/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
|