MySQL 5.6.14 Source Code Document
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
gtid_utils.inc
1 # ==== Purpose ====
2 #
3 # Define the auxiliary stored functions operating on sets of GTIDs.
4 # The functions are typically useful to check assertions related to
5 # GTIDs. The following functions are defined:
6 #
7 # GTID_IS_EQUAL(g1, g2)
8 # True if g1 and g2 are the same set
9 # GTID_IS_DISJOINT(g1, g2)
10 # True if g1 and g2 are disjoint
11 # GTID_IS_DISJOINT_UNION(g1, g2, sum)
12 # True if sum is the disjoint union of g1 and g2
13 # GTID_UNION(g1, g2)
14 # Return the union of g1 and g2
15 # GTID_INTERSECTION(g1, g2)
16 # Return the union of g1 and g2
17 # GTID_SYMMETRIC_DIFFERENCE(g1, g2)
18 # Return the symmetric difference of g1 and g2
19 # GTID_SUBTRACT_UUID(gtid, uuid)
20 # Remove the UUID from the GTID set
21 # GTID_INTERSECTION_WITH_UUID(gtid, uuid)
22 # Return only the gtids with the given uuid from the GTID set
23 # GTID_COMPARE(old, diff, new)
24 # The same as GTID_IS_DISJOINT_UNION, except it has the following
25 # additional feature: if diff begins by '~', then it returns true
26 # if 'old' is the disjoint union of 'new' and 'diff' (where the
27 # tilde is removed).
28 # NUMBER_TO_UUID(N)
29 # Given a number N between 0 and 99, returns a uuid consisting of the
30 # number repeated, like:
31 # NUMBER_TO_UUID(1) -> '01010101-0101-0101-0101-010101010101'
32 # This works also if N is a GTID set, like:
33 # NUMBER_TO_UUID('1:4-5,97:1') ->
34 # '01010101-0101-0101-0101-010101010101:4-5,
35 # 97979797-9797-9797-9797-979797979797:1'
36 # UUID_TO_NUMBER(UUID)
37 # The inverse of NUMBER_TO_UUID.
38 #
39 # ==== Usage ====
40 #
41 # 1. Create the stored functions at the beginning of the test script:
42 #
43 # --source include/gtid_utils.inc
44 #
45 # 2. Use the functions as you like during the test script.
46 #
47 # 3. Delete the stored functions at the end of the test script:
48 #
49 # --source include/gtid_utils_end.inc
50 
51 
52 --let $include_filename= gtid_utils.inc
53 --source include/begin_include_file.inc
54 
55 --disable_query_log
56 
57 --delimiter |
58 
59 # For convenience, declare these human-readable, deterministic uuids here
60 --let $uuid0= 00000000-0000-0000-0000-000000000000
61 --let $uuid1= 11111111-1111-1111-1111-111111111111
62 --let $uuid2= 22222222-2222-2222-2222-222222222222
63 --let $uuid3= 33333333-3333-3333-3333-333333333333
64 --let $uuid4= 44444444-4444-4444-4444-444444444444
65 --let $uuid5= 55555555-5555-5555-5555-555555555555
66 --let $uuid6= 66666666-6666-6666-6666-666666666666
67 --let $uuid7= 77777777-7777-7777-7777-777777777777
68 --let $uuid8= 88888888-8888-8888-8888-888888888888
69 --let $uuid9= 99999999-9999-9999-9999-999999999999
70 --let $uuida= aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa
71 --let $uuidb= bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb
72 --let $uuidc= cccccccc-cccc-cccc-cccc-cccccccccccc
73 --let $uuidd= dddddddd-dddd-dddd-dddd-dddddddddddd
74 --let $uuide= eeeeeeee-eeee-eeee-eeee-eeeeeeeeeeee
75 --let $uuidf= ffffffff-ffff-ffff-ffff-ffffffffffff
76 
77 # Return nonzero if the two gtid_sets are equal.
78 CREATE FUNCTION GTID_IS_EQUAL(g1 TEXT(10000), g2 TEXT(10000))
79 RETURNS INT
80 BEGIN
81  RETURN GTID_SUBSET(g1, g2) AND GTID_SUBSET(g2, g1);
82 END|
83 
84 # Return nonzero if the two gtid_sets are disjoint.
85 CREATE FUNCTION GTID_IS_DISJOINT(g1 TEXT(10000), g2 TEXT(10000))
86 RETURNS INT
87 BEGIN
88  RETURN GTID_SUBSET(g1, GTID_SUBTRACT(g1, g2));
89 END|
90 
91 # Return true if g1 union g2 = sum, and g1 and g2 are disjoint.
92 CREATE FUNCTION GTID_IS_DISJOINT_UNION(g1 TEXT(10000), g2 TEXT(10000), sum TEXT(10000))
93 RETURNS INT
94 BEGIN
95  RETURN GTID_IS_EQUAL(GTID_SUBTRACT(sum, g1), g2) AND
96  GTID_IS_EQUAL(GTID_SUBTRACT(sum, g2), g1);
97 END|
98 
99 # Return the union of g1 and g2.
100 CREATE FUNCTION GTID_UNION(g1 TEXT(10000), g2 TEXT(10000))
101 RETURNS TEXT(10000)
102 BEGIN
103  RETURN GTID_SUBTRACT(CONCAT(g1, ',', g2), '');
104 END|
105 
106 # Return the intersection of g1 and g2.
107 CREATE FUNCTION GTID_INTERSECT(g1 TEXT(10000), g2 TEXT(10000))
108 RETURNS TEXT(10000)
109 BEGIN
110  RETURN GTID_SUBTRACT(g1, GTID_SUBTRACT(g1, g2));
111 END|
112 
113 # Return the symmetric difference between g1 and g2.
114 CREATE FUNCTION GTID_SYMMETRIC_DIFFERENCE(g1 TEXT(10000), g2 TEXT(10000))
115 RETURNS TEXT(10000)
116 BEGIN
117  RETURN SUBTRACT(CONCAT(g1, ',', g2), GTID_INTERSECTION(g1, g2));
118 END|
119 
120 # Return the gtid with uuid removed.
121 CREATE FUNCTION GTID_SUBTRACT_UUID(gtid TEXT(10000), uuid TEXT(10000))
122 RETURNS TEXT(10000)
123 BEGIN
124  RETURN GTID_SUBTRACT(gtid, CONCAT(UUID, ':1-', 1 << 62));
125 END|
126 
127 # Return the intersection of gtid and uuid.
128 CREATE FUNCTION GTID_INTERSECT_UUID(gtid TEXT(10000), uuid TEXT(10000))
129 RETURNS TEXT(10000)
130 BEGIN
131  RETURN GTID_SUBTRACT(gtid, GTID_SUBTRACT_UUID(gtid, uuid));
132 END|
133 
134 # Return true if gtid_set 'new' is obtained by adding 'diff' to 'old',
135 # and all three are disjoint. If 'diff' is prefixed by a tilde, then
136 # returns true if 'old' is obtained by adding 'diff' (with the tilde
137 # removed) from 'new'.
138 CREATE FUNCTION GTID_COMPARE(old TEXT(10000), diff TEXT(10000), new TEXT(10000))
139 RETURNS INT
140 BEGIN
141  DECLARE tilde_pos INT DEFAULT LOCATE('~', diff);
142  DECLARE to_add TEXT(10000);
143  DECLARE to_remove TEXT(10000);
144  IF tilde_pos != 0 THEN
145  RETURN GTID_IS_DISJOINT_UNION(new, SUBSTR(diff, 2), old);
146  ELSE
147  RETURN GTID_IS_DISJOINT_UNION(old, diff, new);
148  END IF;
149 END|
150 
151 # convert strings like '1:4-5,97:1' to
152 # '01010101-0101-0101-0101-010101010101:4-5,97979797-9797-9797-9797-979797979797:1'
153 CREATE FUNCTION NUMBER_TO_UUID(str TEXT(10000))
154 RETURNS TEXT(10000)
155 BEGIN
156  DECLARE pos INT DEFAULT 0;# pos. before next number to replace by UUID in str
157  DECLARE colon INT; # position of next ':' after pos in str
158  DECLARE n TEXT(3); # number between comma and colon
159  DECLARE nn TEXT(5); # n, zero-padded to 2 digits, repeated twice
160  DECLARE _uuid TEXT(37); # UUID generated from nn
161  DECLARE comma INT; # position of next ',' after pos
162  DECLARE tilde INT; # position of next '~' after pos
163  IF str = '' or str IS NULL THEN
164  RETURN str;
165  END IF;
166  IF SUBSTR(str, 1, 1) = '~' THEN
167  SET pos = 1;
168  END IF;
169  REPEAT
170  # find end of number
171  SET colon = LOCATE(':', str, pos + 1);
172  # get number
173  SET n = SUBSTR(str, pos + 1, colon - pos - 1);
174  # convert number to uuid
175  SET nn = REPEAT(LPAD(n, 2, '0'), 2);
176  SET _uuid = CONCAT(nn, nn, '-', nn, '-', nn, '-', nn, '-', nn, nn, nn);
177  # replace number by uuid
178  SET str = CONCAT(SUBSTR(str, 1, pos), _uuid, SUBSTR(str, colon));
179  # find next substring to replace
180  SET comma = LOCATE(',', str, pos + 1), tilde = LOCATE('~', str, pos + 1);
181  SET pos = IF(comma != 0 AND (tilde = 0 OR comma < tilde), comma, tilde);
182  UNTIL pos = 0 END REPEAT;
183  RETURN str;
184 END|
185 
186 # convert strings like '01010101-0101-0101-0101-010101010101:4-5,
187 # 97979797-9797-9797-9797-979797979797:1'
188 # to '1:4-5,97:1'
189 CREATE FUNCTION UUID_TO_NUMBER(str TEXT(10000))
190 RETURNS TEXT(10000)
191 BEGIN
192  DECLARE pos INT DEFAULT 0; # position before next UUID in str
193  DECLARE colon INT; # position of first ':' after pos in str
194  DECLARE _uuid TEXT(37); # UUID between ',' and ':'
195  DECLARE n TEXT(5); # the two digits that are repeated in UUID
196  DECLARE comma INT; # position of next ',' after pos
197  DECLARE tilde INT; # position of next '~' after pos
198  IF str = '' or str IS NULL THEN
199  RETURN str;
200  END IF;
201  IF SUBSTR(str, 1, 1) = '~' THEN
202  SET pos = 1;
203  END IF;
204  # trim newlines
205  SET str = REPLACE(str, '\n', '');
206  REPEAT
207  # find end of substring of the form ",uuid:"
208  SET colon = LOCATE(':', str, pos + 1);
209  # get the uuid
210  SET _uuid = SUBSTR(str, pos + 1, colon - pos - 1);
211  IF _uuid = @@GLOBAL.SERVER_UUID THEN
212  # strip server_uuid from string. make sure we dont strip ~
213  # before or after server_uuid.
214  SET comma = LOCATE(',', str, pos + 1), tilde = LOCATE('~', str, pos + 1);
215  IF comma != 0 AND (tilde = 0 OR tilde > comma) THEN
216  SET str = CONCAT(SUBSTR(str, 1, pos), SUBSTR(str, comma + 1));
217  ELSEIF tilde != 0 THEN
218  SET str = CONCAT(SUBSTR(str, 1, pos - 1), SUBSTR(str, tilde));
219  ELSE
220  SET str = SUBSTR(str, 1, pos - 1);
221  END IF;
222  ELSE
223  # get the number that repeats in UUID and remove leading zero
224  SET n = SUBSTR(str, pos + 1, 2);
225  IF SUBSTR(n, 1, 1) = '0' THEN
226  SET n = SUBSTR(n, 2, 1);
227  END IF;
228  # replace UUID by number
229  SET str = CONCAT(SUBSTR(str, 1, pos), n, SUBSTR(str, colon));
230  END IF;
231  # find next substring
232  SET comma = LOCATE(',', str, pos + 1), tilde = LOCATE('~', str, pos + 1);
233  SET pos = IF(comma != 0 AND (tilde = 0 OR comma < tilde), comma, tilde);
234  UNTIL pos = 0 END REPEAT;
235  RETURN str;
236 END|
237 
238 --delimiter ;
239 
240 --let $include_filename= gtid_utils.inc
241 --source include/end_include_file.inc