This file is indexed.

/usr/lib/mysql-testsuite/include/gtid_utils.inc is in percona-server-test-5.6 5.6.22-rel71.0-0ubuntu4.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
# ==== Purpose ====
#
# Define the auxiliary stored functions operating on sets of GTIDs.
# The functions are typically useful to check assertions related to
# GTIDs. The following functions are defined:
#
#   GTID_IS_EQUAL(gtid_set_1, gtid_set_2)
#     True if gtid_set_1 and gtid_set_2 are the same set
#   GTID_IS_DISJOINT(gtid_set_1, gtid_set_2)
#     True if gtid_set_1 and gtid_set_2 are disjoint
#   GTID_IS_DISJOINT_UNION(gtid_set_1, gtid_set_2, sum)
#     True if sum is the disjoint union of gtid_set_1 and gtid_set_2
#   GTID_NORMALIZE(gtid_set)
#     Return the gtid set in a normalized form: all uuids in alphabetic
#     order, all intervals compressed and in order, no whitespace, all
#     lowercase.
#   GTID_UNION(gtid_set_1, gtid_set_2)
#     Return the union of gtid_set_1 and gtid_set_2
#   GTID_INTERSECTION(gtid_set_1, gtid_set_2)
#     Return the intersection of gtid_set_1 and gtid_set_2
#   GTID_SYMMETRIC_DIFFERENCE(gtid_set_1, gtid_set_2)
#     Return the symmetric difference of gtid_set_1 and gtid_set_2
#   GTID_SUBTRACT_UUID(gtid_set, uuid)
#     Remove the UUID from the GTID set
#   GTID_INTERSECTION_WITH_UUID(gtid_set, uuid)
#     Return only the gtids with the given uuid from the GTID set
#   GTID_COUNT(gtid_set)
#     Return the number of gtids in the gtid_set.
#   GTID_NEXT_GENERATED(gtid_set, uuid)
#     Return the next GNO that will be generated for the given uuid.
#   GTID_NEXT_GENERATED_SET(gtid_set, uuid, count)
#     Return the GTID set consisting of the next 'count' GTIDs that will
#     be generated for the given uuid.
#   GTID_COMPARE(old, diff, new)
#     The same as GTID_IS_DISJOINT_UNION, except it has the following
#     additional feature: if diff begins by '~', then it returns true
#     if 'old' is the disjoint union of 'new' and 'diff' (where the
#     tilde is removed).
#   NUMBER_TO_UUID(N)
#     Given a number N between 0 and 99, returns a uuid consisting of the
#     number repeated, like:
#       NUMBER_TO_UUID(1) -> '01010101-0101-0101-0101-010101010101'
#     This works also if N is a GTID set, like:
#       NUMBER_TO_UUID('1:4-5,97:1') ->
#         '01010101-0101-0101-0101-010101010101:4-5,
#          97979797-9797-9797-9797-979797979797:1'
#   UUID_TO_NUMBER(UUID)
#     The inverse of NUMBER_TO_UUID.
#
# ==== Usage ====
#
# You should not normally source this file directly; instead set
# $rpl_gtid_utils=1 before sourcing master-slave.inc or rpl_init.inc.
# Then, the functions are automatically dropped in rpl_end.inc, and
# RESET MASTER is executed so that the functions do not pollute the
# binary log.
#
# If you really need to use this file manually, do this:
#
#  1. Create the stored functions at the beginning of the test script:
#
#       --source include/gtid_utils.inc
#
#  2. Use the functions as you like during the test script.
#
#  3. Delete the stored functions at the end of the test script:
#
#       --source include/gtid_utils_end.inc


--let $include_filename= gtid_utils.inc
--source include/begin_include_file.inc

if (!$rpl_debug)
{
  --disable_query_log
}

--delimiter |

# For convenience, declare these human-readable, deterministic uuids here
--let $uuid0= 00000000-0000-0000-0000-000000000000
--let $uuid1= 11111111-1111-1111-1111-111111111111
--let $uuid2= 22222222-2222-2222-2222-222222222222
--let $uuid3= 33333333-3333-3333-3333-333333333333
--let $uuid4= 44444444-4444-4444-4444-444444444444
--let $uuid5= 55555555-5555-5555-5555-555555555555
--let $uuid6= 66666666-6666-6666-6666-666666666666
--let $uuid7= 77777777-7777-7777-7777-777777777777
--let $uuid8= 88888888-8888-8888-8888-888888888888
--let $uuid9= 99999999-9999-9999-9999-999999999999
--let $uuida= aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa
--let $uuidb= bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb
--let $uuidc= cccccccc-cccc-cccc-cccc-cccccccccccc
--let $uuidd= dddddddd-dddd-dddd-dddd-dddddddddddd
--let $uuide= eeeeeeee-eeee-eeee-eeee-eeeeeeeeeeee
--let $uuidf= ffffffff-ffff-ffff-ffff-ffffffffffff

# Return nonzero if the two gtid_sets are equal.
CREATE FUNCTION GTID_IS_EQUAL(gtid_set_1 TEXT(10000), gtid_set_2 TEXT(10000))
RETURNS INT
RETURN GTID_SUBSET(gtid_set_1, gtid_set_2) AND GTID_SUBSET(gtid_set_2, gtid_set_1)|

# Return nonzero if the two gtid_sets are disjoint.
CREATE FUNCTION GTID_IS_DISJOINT(gtid_set_1 TEXT(10000), gtid_set_2 TEXT(10000))
RETURNS INT
RETURN GTID_SUBSET(gtid_set_1, GTID_SUBTRACT(gtid_set_1, gtid_set_2))|

# Return true if gtid_set_1 union gtid_set_2 = sum, and gtid_set_1 and gtid_set_2 are disjoint.
CREATE FUNCTION GTID_IS_DISJOINT_UNION(gtid_set_1 TEXT(10000), gtid_set_2 TEXT(10000), sum TEXT(10000))
RETURNS INT
RETURN GTID_IS_EQUAL(GTID_SUBTRACT(sum, gtid_set_1), gtid_set_2) AND
       GTID_IS_EQUAL(GTID_SUBTRACT(sum, gtid_set_2), gtid_set_1)|

# Return a normalized form of the GTID (all uppercase, no whitespace,
# no duplicates, uuids in alphabetic order, intervals in numeric
# order).
CREATE FUNCTION GTID_NORMALIZE(g TEXT(10000))
RETURNS TEXT(10000)
RETURN GTID_SUBTRACT(g, '')|

# Return the union of gtid_set_1 and gtid_set_2.
CREATE FUNCTION GTID_UNION(gtid_set_1 TEXT(10000), gtid_set_2 TEXT(10000))
RETURNS TEXT(10000)
RETURN GTID_NORMALIZE(CONCAT(gtid_set_1, ',', gtid_set_2))|

# Return the intersection of gtid_set_1 and gtid_set_2.
CREATE FUNCTION GTID_INTERSECTION(gtid_set_1 TEXT(10000), gtid_set_2 TEXT(10000))
RETURNS TEXT(10000)
RETURN GTID_SUBTRACT(gtid_set_1, GTID_SUBTRACT(gtid_set_1, gtid_set_2))|

# Return the symmetric difference between gtid_set_1 and gtid_set_2.
CREATE FUNCTION GTID_SYMMETRIC_DIFFERENCE(gtid_set_1 TEXT(10000), gtid_set_2 TEXT(10000))
RETURNS TEXT(10000)
RETURN GTID_SUBTRACT(CONCAT(gtid_set_1, ',', gtid_set_2), GTID_INTERSECTION(gtid_set_1, gtid_set_2))|

# Return the gtid with uuid removed.
CREATE FUNCTION GTID_SUBTRACT_UUID(gtid_set TEXT(10000), uuid TEXT(100))
RETURNS TEXT(10000)
RETURN GTID_SUBTRACT(gtid_set, CONCAT(UUID, ':1-', 1 << 63 - 1))|

# Return the intersection of gtid and uuid.
CREATE FUNCTION GTID_INTERSECTION_WITH_UUID(gtid_set TEXT(10000), uuid TEXT(100))
RETURNS TEXT(10000)
RETURN GTID_SUBTRACT(gtid_set, GTID_SUBTRACT_UUID(gtid_set, uuid))|

# If the first argument is nonzero, return it, else return the second argument
CREATE FUNCTION IFZERO(a INT, b INT)
RETURNS INT
RETURN IF(a = 0, b, a)|

# Like the builtin LOCATE, but returns length+1 rather than 0 if nothing found.
CREATE FUNCTION LOCATE2(needle TEXT(10000), haystack TEXT(10000), offset INT)
RETURNS INT
RETURN IFZERO(LOCATE(needle, haystack, offset), LENGTH(haystack) + 1)|

# Return the number of GTIDs in the given GTID set.
CREATE FUNCTION GTID_COUNT(gtid_set TEXT(10000))
RETURNS INT
BEGIN
  DECLARE result BIGINT DEFAULT 0;
  DECLARE colon_pos INT;
  DECLARE next_dash_pos INT;
  DECLARE next_colon_pos INT;
  DECLARE next_comma_pos INT;
  SET gtid_set = GTID_NORMALIZE(gtid_set);
  SET colon_pos = LOCATE2(':', gtid_set, 1);
  WHILE colon_pos != LENGTH(gtid_set) + 1 DO
     SET next_dash_pos = LOCATE2('-', gtid_set, colon_pos + 1);
     SET next_colon_pos = LOCATE2(':', gtid_set, colon_pos + 1);
     SET next_comma_pos = LOCATE2(',', gtid_set, colon_pos + 1);
     IF next_dash_pos < next_colon_pos AND next_dash_pos < next_comma_pos THEN
       SET result = result +
         SUBSTR(gtid_set, next_dash_pos + 1,
                LEAST(next_colon_pos, next_comma_pos) - (next_dash_pos + 1)) -
         SUBSTR(gtid_set, colon_pos + 1, next_dash_pos - (colon_pos + 1)) + 1;
     ELSE
       SET result = result + 1;
     END IF;
     SET colon_pos = next_colon_pos;
  END WHILE;
  RETURN result;
END|

# Return the next GNO (numeric component) to be generated for the given UUID
CREATE FUNCTION GTID_NEXT_GENERATED(gtid_set TEXT(10000), uuid TEXT(100))
RETURNS INT
BEGIN
  DECLARE gtid_uuid TEXT(10000) DEFAULT GTID_INTERSECTION_WITH_UUID(gtid_set, uuid);
  DECLARE colon_pos INT DEFAULT LOCATE2(':', gtid_uuid, 1);
  DECLARE next_dash_pos INT DEFAULT LOCATE2('-', gtid_uuid, colon_pos + 1);
  DECLARE next_comma_pos INT DEFAULT LOCATE2(',', gtid_uuid, colon_pos + 1);
  DECLARE next_colon_pos INT DEFAULT LOCATE2(':', gtid_uuid, colon_pos + 1);
  IF gtid_uuid = '' THEN
    RETURN 1;
  ELSEIF SUBSTR(gtid_uuid, colon_pos + 1,
                 LEAST(next_dash_pos, next_comma_pos, next_colon_pos) -
                 (colon_pos + 1)) != '1' THEN
    RETURN 1;
  ELSEIF next_dash_pos < LEAST(next_comma_pos, next_colon_pos) THEN
    RETURN SUBSTR(gtid_uuid, next_dash_pos + 1,
                  LEAST(next_comma_pos, next_colon_pos) -
                  (next_dash_pos + 1)) + 1;
  ELSE
    RETURN 2;
  END IF;
END|

# Return a GTID set consisting of the the next 'count' GTIDs that will
# be generated for the given UUID.
# This is inefficient if count is big, consider optimizing it if needed.
CREATE FUNCTION GTID_NEXT_GENERATED_SET(gtid_set TEXT(10000), uuid TEXT(100), count INT)
RETURNS TEXT(10000)
BEGIN
  DECLARE result TEXT(10000) DEFAULT '';
  DECLARE number INT;
  DECLARE new_gtid VARCHAR(100);
  WHILE count > 0 DO
    SET new_gtid = CONCAT(uuid, ':', GTID_NEXT_GENERATED(gtid_set, uuid));
    SET result = GTID_UNION(result, new_gtid);
    SET gtid_set = GTID_UNION(gtid_set, new_gtid);
    SET count = count - 1;
  END WHILE;
  RETURN result;
END|

# Return true if gtid_set 'new' is obtained by adding 'diff' to 'old',
# and all three are disjoint.  If 'diff' is prefixed by a tilde, then
# returns true if 'old' is obtained by adding 'diff' (with the tilde
# removed) from 'new'.
CREATE FUNCTION GTID_COMPARE(old TEXT(10000), diff TEXT(10000), new TEXT(10000))
RETURNS INT
RETURN IF(SUBSTR(diff, 1, 1) != '~', GTID_IS_DISJOINT_UNION(old, diff, new), GTID_IS_DISJOINT_UNION(new, SUBSTR(diff, 2), old))|

# convert strings like '1:4-5,97:1' to
# '01010101-0101-0101-0101-010101010101:4-5,97979797-9797-9797-9797-979797979797:1'
CREATE FUNCTION NUMBER_TO_UUID(str TEXT(10000))
RETURNS TEXT(10000)
BEGIN
  DECLARE pos INT DEFAULT 0;# pos. before next number to replace by UUID in str
  DECLARE colon INT;               # position of next ':' after pos in str
  DECLARE n TEXT(3);               # number between comma and colon
  DECLARE nn TEXT(5);              # n, zero-padded to 2 digits, repeated twice
  DECLARE _uuid TEXT(37);          # UUID generated from nn
  DECLARE comma INT;               # position of next ',' after pos
  DECLARE tilde INT;               # position of next '~' after pos
  IF str = '' or str IS NULL THEN
    RETURN str;
  END IF;
  IF SUBSTR(str, 1, 1) = '~' THEN
    SET pos = 1;
  END IF;
  REPEAT
    # find end of number
    SET colon = LOCATE(':', str, pos + 1);
    # get number
    SET n = SUBSTR(str, pos + 1, colon - pos - 1);
    # convert number to uuid
    SET nn = REPEAT(LPAD(n, 2, '0'), 2);
    SET _uuid = CONCAT(nn, nn, '-', nn, '-', nn, '-', nn, '-', nn, nn, nn);
    # replace number by uuid
    SET str = CONCAT(SUBSTR(str, 1, pos), _uuid, SUBSTR(str, colon));
    # find next substring to replace
    SET comma = LOCATE(',', str, pos + 1), tilde = LOCATE('~', str, pos + 1);
    SET pos = IF(comma != 0 AND (tilde = 0 OR comma < tilde), comma, tilde);
  UNTIL pos = 0 END REPEAT;
  RETURN str;
END|

# convert strings like '01010101-0101-0101-0101-010101010101:4-5,
# 97979797-9797-9797-9797-979797979797:1'
# to '1:4-5,97:1'
CREATE FUNCTION UUID_TO_NUMBER(str TEXT(10000))
RETURNS TEXT(10000)
BEGIN
  DECLARE pos INT DEFAULT 0;       # position before next UUID in str
  DECLARE colon INT;               # position of first ':' after pos in str
  DECLARE _uuid TEXT(37);          # UUID between ',' and ':'
  DECLARE n TEXT(5);               # the two digits that are repeated in UUID
  DECLARE comma INT;               # position of next ',' after pos
  DECLARE tilde INT;               # position of next '~' after pos
  IF str = '' or str IS NULL THEN
    RETURN str;
  END IF;
  IF SUBSTR(str, 1, 1) = '~' THEN
    SET pos = 1;
  END IF;
  # trim newlines
  SET str = REPLACE(str, '\n', '');
  REPEAT
    # find end of substring of the form ",uuid:"
    SET colon = LOCATE(':', str, pos + 1);
    # get the uuid
    SET _uuid = SUBSTR(str, pos + 1, colon - pos - 1);
    IF _uuid = @@GLOBAL.SERVER_UUID THEN
      # strip server_uuid from string. make sure we dont strip ~
      # before or after server_uuid.
      SET comma = LOCATE(',', str, pos + 1), tilde = LOCATE('~', str, pos + 1);
      IF comma != 0 AND (tilde = 0 OR tilde > comma) THEN
        SET str = CONCAT(SUBSTR(str, 1, pos), SUBSTR(str, comma + 1));
      ELSEIF tilde != 0 THEN
        SET str = CONCAT(SUBSTR(str, 1, pos - 1), SUBSTR(str, tilde));
      ELSE
        SET str = SUBSTR(str, 1, pos - 1);
      END IF;
    ELSE
      # get the number that repeats in UUID and remove leading zero
      SET n = SUBSTR(str, pos + 1, 2);
      IF SUBSTR(n, 1, 1) = '0' THEN
        SET n = SUBSTR(n, 2, 1);
      END IF;
      # replace UUID by number
      SET str = CONCAT(SUBSTR(str, 1, pos), n, SUBSTR(str, colon));
    END IF;
    # find next substring
    SET comma = LOCATE(',', str, pos + 1), tilde = LOCATE('~', str, pos + 1);
    SET pos = IF(comma != 0 AND (tilde = 0 OR comma < tilde), comma, tilde);
  UNTIL pos = 0 END REPEAT;
  RETURN str;
END|

--delimiter ;

--let $include_filename= gtid_utils.inc
--source include/end_include_file.inc