1 ################################################################################
2 # inc/partition_check.inc #
5 # Do some basic usability checks on table t1. #
6 # This routine is only useful for the partition_<feature>_<engine> tests. #
9 # It is intended that in many testcases (statements) more than one partition #
10 # or subpartition is affected. #
11 # Without analysis of the partitioning function used during CREATE TABLE #
12 # we cannot be 100% sure that this goal is reached. #
13 # But statements affecting many rows give a good probability that this #
16 # It is expected that the table to be checked contains at the beginning #
17 # of this script records following the scheme #
18 # f_int1 f_int2 f_char1 f_char2 f_charbig #
19 # 1 1 '1' '1' '###1###' #
20 # 2 2 '2' '1' '###2###' #
21 # ... ... ... ... ... #
22 # x x 'x' 'x' '###x###' #
25 # The table content must be equal to the content of the table t0_template. #
26 # Attention: Please be careful when modiying the data. #
27 # Records can be deleted or inserted, but the content of the #
28 # records after a test/testsequence should follow this scheme. #
30 # All checks of preceding statements via Select are so written, #
31 # that they deliver a #
32 # # check <n> success: 1 #
33 # when everything is like expected. #
34 # - f_charbig is typically used for showing if something was changed. #
35 # This is useful for cleanups. #
37 #------------------------------------------------------------------------------#
38 # Original Author: mleich #
39 # Original Date: 2006-03-05 #
40 # Change Author: mleich #
41 # Change Date: 2007-10-08 #
42 # Change: Around fix for #
43 # Bug#31243 Test "partition_basic_myisam" truncates path names#
44 # Adjustments of expected error codes: #
45 # ER_NO_PARTITION_FOR_GIVEN_VALUE is now 1525 #
46 # ER_SAME_NAME_PARTITION is now 1516 #
47 ################################################################################
50 --echo # Start usability
test (inc/partition_check.inc)
51 # Print the CREATE TABLE STATEMENT and store the current layout of the table
52 --source suite/parts/inc/partition_layout_check1.inc
55 #-------------------------------------------------------------------------------
56 ## 1. Check the prerequisites for the following tests
57 # (sideeffect some SELECT functionality is also tested)
58 # Determine if we have PRIMARY KEYs or UNIQUE INDEXes
59 ## 1.1 Check if the content of the records is like expected
60 # Sideeffect: mass SELECT, all records/partitions/subpartitions have to be
61 # read, because at least f_charbig is not part of any
67 let $my_stmt= SELECT COUNT(*) <> 0 INTO @aux FROM t1
68 WHERE f_int1 <> f_int2 OR f_char1 <> CAST(f_int1 AS CHAR) OR f_char1 <> f_char2
69 OR f_charbig <> CONCAT(
'===',f_char1,
'===')
70 OR f_int1 IS NULL OR f_int2 IS NULL OR f_char1 IS NULL OR f_char2 IS NULL
73 let $run= `SELECT @aux`;
77 --echo # Prerequisites
for following tests not fullfilled.
78 --echo # The content of the
table t1 is unexpected
81 --echo # Sorry, have
to abort.
84 # Give a success message like in the other following tests
85 --echo # check prerequisites-1 success: 1
86 #-------------------------------------------------------------------------------
87 ## 1.2 Check if the number of records and the maximum and minimum values are
91 # - MIN/MAX on all columns possibly used in part. function
92 # The optimizer might decide to run on INDEX only, if available.
94 ## 1.2.1 Check COUNT(*)
99 let $my_stmt= SELECT COUNT(*) <> @max_row INTO @aux FROM t1;
100 let $run= `SELECT @aux`;
104 --echo # Prerequisites
for following tests not fullfilled.
105 --echo # The content of the
table t1 is unexpected
108 --echo # Sorry, have
to abort.
111 # Give a success message like in the other following tests
112 --echo # check COUNT(*) success: 1
113 ## 1.2.2 Check MAX(f_int1),MIN(f_int1)
118 let $my_stmt= SELECT MIN(f_int1) <> 1 AND MAX(f_int1) <> @max_row INTO @aux
120 let $run= `SELECT @aux`;
124 --echo # Prerequisites
for following tests not fullfilled.
125 --echo # The content of the
table t1 is unexpected
128 --echo # Sorry, have
to abort.
131 # Give a success message like in the other following tests
132 --echo # check MIN/MAX(f_int1) success: 1
133 ## 1.2.3 Check MAX(f_int2),MIN(f_int2)
138 let $my_stmt= SELECT MIN(f_int2) <> 1 AND MAX(f_int2) <> @max_row INTO @aux
140 let $run= `SELECT @aux`;
144 --echo # Prerequisites
for following tests not fullfilled.
145 --echo # The content of the
table t1 is unexpected
148 --echo # Sorry, have
to abort.
151 # Give a success message like in the other following tests
152 --echo # check MIN/MAX(f_int2) success: 1
154 #-------------------------------------------------------------------------------
155 ## 1.3 Check, if f_int1 and/or f_char2 and/or (f_char1,f_char2) is UNIQUE
156 # by testing if any DUPLICATE KEY might appear
157 # Note: INFORMATION_SCHEMA SELECTs could be also used, but testing the
158 # table via INSERT and SELECT is better because is stresses the
159 # partitioning mechanism.
160 # Sideeffect: Attempt to INSERT one record
161 # DUPLICATE KEY will appear if we have UNIQUE columns
162 # ER_DUP_KEY, ER_DUP_ENTRY
163 --disable_abort_on_error
164 INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig)
165 SELECT f_int1, f_int1, CAST(f_int1 AS CHAR),
166 CAST(f_int1 AS CHAR), 'delete me' FROM t0_template
167 WHERE f_int1 IN (2,3);
168 --enable_abort_on_error
173 eval SET @my_errno = $mysql_errno;
174 let $run_delete= `SELECT @my_errno = 0`;
175 let $any_unique= `SELECT @my_errno IN ($ER_DUP_KEY,$ER_DUP_ENTRY)`;
176 # DEBUG eval SELECT $run_delete AS run_delete, $any_unique AS any_unique,
177 # @my_errno AS sql_errno;
178 if (`SELECT @my_errno NOT IN (0,$ER_DUP_KEY,$ER_DUP_ENTRY)`)
180 --echo # The last command got an unexpected error response.
181 --echo # Expected/handled SQL codes are 0,$ER_DUP_KEY,$ER_DUP_ENTRY
182 SELECT
'# SQL code we got was: ' AS
"", @my_errno AS
"";
183 --echo # Sorry, have
to abort.
187 # Give a success message like in the other following tests
188 --echo # check prerequisites-3 success: 1
190 # DEBUG eval SELECT $run_delete AS run_delete, $any_unique AS any_unique;
193 # INSERT was successful -> DELETE this new record
194 DELETE FROM t1 WHERE f_charbig =
'delete me';
195 --echo # INFO: Neither f_int1 nor f_int2 nor (f_int1,f_int2) is UNIQUE
199 --echo # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE
201 ## 1.3.1 Check, if f_int1 is UNIQUE
202 # Sideeffect: Attempt to INSERT one record
203 # DUPLICATE KEY will appear if we have UNIQUE columns
204 # ER_DUP_KEY, ER_DUP_ENTRY
205 --disable_abort_on_error
206 INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig)
207 SELECT f_int1, 2 * @max_row + f_int1, CAST((2 * @max_row + f_int1) AS CHAR),
208 CAST((2 * @max_row + f_int1) AS CHAR), 'delete me' FROM t0_template
209 WHERE f_int1 IN (2,3);
210 --enable_abort_on_error
215 eval SET @my_errno = $mysql_errno;
216 let $run_delete= `SELECT @my_errno = 0`;
217 let $f_int1_is_unique= `SELECT @my_errno IN ($ER_DUP_KEY,$ER_DUP_ENTRY)`;
218 # DEBUG eval SELECT $run_delete AS run_delete, $f_int1_is_unique AS any_unique,
219 # @my_errno AS sql_errno;
220 if (`SELECT @my_errno NOT IN (0,$ER_DUP_KEY,$ER_DUP_ENTRY)`)
222 --echo # The last command got an unexpected error response.
223 --echo # Expected/handled SQL codes are 0,$ER_DUP_KEY,$ER_DUP_ENTRY
224 SELECT
'# SQL code we got was: ' AS
"", @my_errno AS
"";
225 --echo # Sorry, have
to abort.
230 if ($f_int1_is_unique)
232 --echo # INFO: f_int1 is UNIQUE
236 # INSERT was successful -> DELETE this new record
237 DELETE FROM t1 WHERE f_charbig =
'delete me';
240 ## 1.3.2 Check, if f_int2 is UNIQUE (get ER_DUP_KEY or ER_DUP_ENTRY
241 --disable_abort_on_error
242 INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig)
243 SELECT 2 * @max_row + f_int1, f_int1, CAST((2 * @max_row + f_int1) AS CHAR),
244 CAST((2 * @max_row + f_int1) AS CHAR), 'delete me' FROM t0_template
245 WHERE f_int1 IN (2,3);
246 --enable_abort_on_error
251 eval SET @my_errno = $mysql_errno;
252 let $run_delete= `SELECT @my_errno = 0`;
253 let $f_int1_is_unique= `SELECT @my_errno IN ($ER_DUP_KEY,$ER_DUP_ENTRY)`;
254 # DEBUG eval SELECT $run_delete AS run_delete, $f_int1_is_unique AS any_unique,
255 # @my_errno AS sql_errno;
256 if (`SELECT @my_errno NOT IN (0,$ER_DUP_KEY,$ER_DUP_ENTRY)`)
258 --echo # The last command got an unexpected error response.
259 --echo # Expected/handled SQL codes are 0,$ER_DUP_KEY,$ER_DUP_ENTRY
260 SELECT
'# SQL code we got was: ' AS
"", @my_errno AS
"";
261 --echo # Sorry, have
to abort.
265 if ($f_int2_is_unique)
267 --echo # INFO: f_int2 is UNIQUE
272 # INSERT was successful -> DELETE this new record
273 DELETE FROM t1 WHERE f_charbig =
'delete me';
278 #-------------------------------------------------------------------------------
279 ## 2. Read the table row by row
280 # Note: There were crashes in history when reading a partitioned table
281 # PRIMARY KEY AND/OR UNIQUE INDEXes
282 ## 2.1 Read all existing and some not existing records of table
283 # per f_int1 used in partitioning function
284 let $col_to_check= f_int1;
285 --source suite/parts/inc/partition_check_read.inc
286 ## 2.2 Read all existing and some not existing records of table
287 # per f_int2 used in partitioning function
288 let $col_to_check= f_int2;
289 --source suite/parts/inc/partition_check_read.inc
292 #-------------------------------------------------------------------------------
293 # 3 Some operations with multiple records
294 # 3.1 Select on "full" table
299 SELECT
'# check multiple-1 success: ' AS
"",COUNT(*) = @max_row AS
"" FROM t1;
302 # 3.2 (mass) DELETE of @max_row_div3 records
303 DELETE FROM t1 WHERE MOD(f_int1,3) = 0;
308 SELECT
'# check multiple-2 success: ' AS
"",COUNT(*) = @max_row - @max_row_div3 AS
"" FROM t1;
311 # 3.3 (mass) Insert of @max_row_div3 records
312 # (Insert the records deleted in 3.2)
313 INSERT INTO t1 SELECT * FROM t0_template
314 WHERE MOD(f_int1,3) = 0;
315 # Check of preceding statement via Select
320 SELECT
'# check multiple-3 success: ' AS
"",
321 (COUNT(*) = @max_row) AND (MIN(f_int1) = 1) AND (MAX(f_int1) = @max_row) AS
""
324 # DEBUG SELECT COUNT(*),MIN(f_int1),MAX(f_int1) FROM t1;
326 # 3.4 (mass) Update @max_row_div4 * 2 + 1 records
327 # Bug#18735: Partitions: NDB, UNIQUE INDEX, UPDATE, strange server response
328 UPDATE t1 SET f_int1 = f_int1 + @max_row
329 WHERE f_int1 BETWEEN @max_row_div2 - @max_row_div4
330 AND @max_row_div2 + @max_row_div4;
331 # Check of preceding statement via Select
336 SELECT
'# check multiple-4 success: ' AS
"",(COUNT(*) = @max_row) AND (MIN(f_int1) = 1) AND
337 (MAX(f_int1) = @max_row_div2 + @max_row_div4 + @max_row ) AS
"" FROM t1;
339 # DEBUG SELECT COUNT(*),MIN(f_int1),MAX(f_int1) FROM t1;
341 # 3.5 (mass) Delete @max_row_div4 * 2 + 1 records
342 # (Delete the records updated in 3.4)
344 WHERE f_int1 BETWEEN @max_row_div2 - @max_row_div4 + @max_row
345 AND @max_row_div2 + @max_row_div4 + @max_row;
346 # Check of preceding statement via Select
351 SELECT
'# check multiple-5 success: ' AS
"",
352 (COUNT(*) = @max_row - @max_row_div4 - @max_row_div4 - 1)
353 AND (MIN(f_int1) = 1) AND (MAX(f_int1) = @max_row) AS
"" FROM t1;
355 # DEBUG SELECT COUNT(*),MIN(f_int1),MAX(f_int1) FROM t1;
357 #-------------------------------------------------------------------------------
358 # Attention: After this section all modification on the table have to be reverted !
359 # Current content of t1 follows the rule:
360 # <value>,<value>,'<value>','<value>',===<value>===
361 # <value> contains all INTEGER values
362 # between 1 and @max_row_div2 - @max_row_div4 - 1
364 # between @max_row_div2 + @max_row_div4 + 1 and @max_row
365 # With other words the values between @max_row_div2 - @max_row_div4
366 # and @max_row_div2 + @max_row_div4 are "missing".
367 #-------------------------------------------------------------------------------
368 # The following is only needed for tests of UNIQUE CONSTRAINTs.
371 # Calculate the number of records, where we will try INSERT ..... or REPLACE
372 SELECT COUNT(*) INTO @try_count FROM t0_template
373 WHERE MOD(f_int1,3) = 0
374 AND f_int1 BETWEEN @max_row_div2 AND @max_row;
376 # Calculate the number of records, where we will get DUPLICATE KEY
377 # f_int1 is sufficient for calculating this, because 1.1
378 # checks, that f_int1 = f_int2 is valid for all rows.
379 SELECT COUNT(*) INTO @clash_count
380 FROM t1 INNER
JOIN t0_template USING(f_int1)
381 WHERE MOD(f_int1,3) = 0
382 AND f_int1 BETWEEN @max_row_div2 AND @max_row;
385 SELECT
@try_count, @clash_count;
390 #-------------------------------------------------------------------------------
391 # 4 Some operations with single records
392 # 4.1 Insert one record with a value for f_int1 which is lower than in all
394 SELECT MIN(f_int1) - 1 INTO @cur_value FROM t1;
396 SET f_int1 = @cur_value , f_int2 = @cur_value,
397 f_char1 = CAST(@cur_value AS CHAR), f_char2 = CAST(@cur_value AS CHAR),
398 f_charbig =
'#SINGLE#';
399 # Check of preceding statement via Select
404 SELECT
'# check single-1 success: ' AS
"",COUNT(*) = 1 AS
"" FROM t1
405 WHERE f_int1 = @cur_value AND f_int2 = @cur_value
406 AND f_char1 = CAST(@cur_value AS CHAR)
407 AND f_char2 = CAST(@cur_value AS CHAR) AND f_charbig =
'#SINGLE#';
410 # 4.2 Insert one record with a value for f_int1 which is higher than in all
412 SELECT MAX(f_int1) + 1 INTO @cur_value FROM t1;
414 SET f_int1 = @cur_value , f_int2 = @cur_value,
415 f_char1 = CAST(@cur_value AS CHAR), f_char2 = CAST(@cur_value AS CHAR),
416 f_charbig =
'#SINGLE#';
417 # Check of preceding statement via Select
422 SELECT
'# check single-2 success: ' AS
"",COUNT(*) = 1 AS
"" FROM t1
423 WHERE f_int1 = @cur_value AND f_int2 = @cur_value
424 AND f_char1 = CAST(@cur_value AS CHAR)
425 AND f_char2 = CAST(@cur_value AS CHAR) AND f_charbig =
'#SINGLE#';
428 # 4.3 Update one record. The value of f_int1 is altered from the lowest to
429 # the highest value of all existing records.
430 # If f_int1 is used for the partitioning expression a movement of the
431 # record to another partition/subpartition might appear.
432 SELECT MIN(f_int1) INTO @cur_value1 FROM t1;
433 SELECT MAX(f_int1) + 1 INTO @cur_value2 FROM t1;
434 # Bug#18735: Partitions: NDB, UNIQUE INDEX, UPDATE, strange server response
435 UPDATE t1 SET f_int1 = @cur_value2
436 WHERE f_int1 = @cur_value1 AND f_charbig =
'#SINGLE#';
437 # Check of preceding statement via Select
442 SELECT
'# check single-3 success: ' AS
"",COUNT(*) = 1 AS
"" FROM t1
443 WHERE f_int1 = @cur_value2 AND f_charbig =
'#SINGLE#';
446 # 4.4 Update one record. The value of f_int1 is altered from the highest value
447 # to a value lower than in all existing records.
448 # If f_int1 is used for the partitioning expression a movement of the
449 # record to another partition/subpartition might appear.
450 # f_int1 gets the delicate value '-1'.
452 SELECT MAX(f_int1) INTO @cur_value2 FROM t1;
453 # Bug#15968: Partitions: crash when INSERT with f_int1 = -1 into PARTITION BY HASH(f_int1)
454 # Bug#16385: Partitions: crash when updating a range partitioned NDB table
455 # Bug#18735: Partitions: NDB, UNIQUE INDEX, UPDATE, strange server response
456 UPDATE t1 SET f_int1 = @cur_value1
457 WHERE f_int1 = @cur_value2 AND f_charbig =
'#SINGLE#';
458 # Check of preceding statement via Select
463 SELECT
'# check single-4 success: ' AS
"",COUNT(*) AS "" FROM t1
464 WHERE f_int1 = @cur_value1 AND f_charbig = '
#SINGLE#';
467 # 4.5 Delete the record with the highest value of f_int1.
468 SELECT MAX(f_int1) INTO @cur_value FROM t1;
469 DELETE FROM t1 WHERE f_int1 = @cur_value AND f_charbig = '
#SINGLE#';
470 # Check of preceding statements via Select
475 SELECT
'# check single-5 success: ' AS
"",COUNT(*) = 0 AS
"" FROM t1
476 WHERE f_charbig =
'#SINGLE#' AND f_int1 = f_int1 = @cur_value;
479 # 4.6 Delete the record with f_int1 = -1
480 DELETE FROM t1 WHERE f_int1 = -1 AND f_charbig =
'#SINGLE#';
481 # Check of preceding statements via Select
486 SELECT
'# check single-6 success: ' AS
"",COUNT(*) = 0 AS
"" FROM t1
487 WHERE f_charbig =
'#SINGLE#' AND f_int1 IN (-1,@cur_value);
490 # 4.7 Insert one record with such a big value for f_int1, so that in case
491 # - f_int1 is used within the partitioning algorithm
492 # - we use range partitioning
493 # we get error ER_NO_PARTITION_FOR_GIVEN_VALUE
494 # "Table has no partition for value ...."
495 # or ER_SAME_NAME_PARTITION
496 --disable_abort_on_error
497 eval INSERT INTO t1 SET f_int1 = @max_int_4 , f_int2 = @max_int_4, f_charbig =
'#$max_int_4##';
498 --enable_abort_on_error
503 eval SET @my_errno = $mysql_errno;
504 if (`SELECT @my_errno NOT IN (0,$ER_SAME_NAME_PARTITION,$ER_NO_PARTITION_FOR_GIVEN_VALUE)`)
506 --echo # The last command got an unexpected error response.
507 --echo # Expected/handled SQL codes are 0,$ER_SAME_NAME_PARTITION,$ER_NO_PARTITION_FOR_GIVEN_VALUE
508 SELECT
'# SQL code we got was: ' AS
"", @my_errno AS
"";
509 --echo # Sorry, have
to abort.
513 # Check of preceding statement via Select, if the INSERT was successful
514 let $run= `SELECT @my_errno = 0`;
517 # Attention: There are some tests where the column type is changed from
518 # INTEGER to MEDIUMINT. MEDIUMINT has a smaller range and the
519 # inserted value is automatically adjusted to the maximum value
521 # that's the reason why we cannot use WHERE <column> = @max_int_4 here.
523 eval SELECT
'# check single-7 success: ' AS
"",
524 COUNT(*) = 1 AS
"" FROM t1 WHERE f_charbig =
'#$max_int_4##';
525 # Revert this modification
527 eval DELETE FROM t1 WHERE f_charbig =
'#$max_int_4##';
532 #-------------------------------------------------------------------------------
533 # 5 Experiments with NULL
534 # If the result of the partitioning function IS NULL partitioning treats
535 # this record as if the the result of the partitioning function is
536 # MySQL 5.1 < March 2006 : zero
537 # MySQL 5.1 >= March 2006 : LONGLONG_MIN
538 # Let's INSERT a record where the result of the partitioning function is
539 # probably (depends on function currently used) zero and look if there are
540 # any strange effects during the execution of the next statements.
541 # Bug#17891: Partitions: NDB, crash on select .. where col is null or col = value
542 # Bug#18659: Partitions: wrong result on WHERE <col. used in part. function> IS NULL
543 DELETE FROM t1 WHERE f_int1 IS NULL OR f_int1 = 0;
544 # Attention: Zero should be tested
545 INSERT t1 SET f_int1 = 0 , f_int2 = 0,
546 f_char1 = CAST(0 AS CHAR), f_char2 = CAST(0 AS CHAR),
547 f_charbig =
'#NULL#';
548 # 5.1 Insert one record with f_int1 IS NULL.
549 # f1 "=" NULL is a delicate value which might stress the partitioning
550 # mechanism if the result of the expression in the partitioning algorithm
552 # This INSERT will fail, if f_int1 is PRIMARY KEY or UNIQUE INDEX
553 # with ER_BAD_NULL_ERROR.
554 --disable_abort_on_error
556 SET f_int1 = NULL , f_int2 = -@max_row,
557 f_char1 = CAST(-@max_row AS CHAR), f_char2 = CAST(-@max_row AS CHAR),
558 f_charbig =
'#NULL#';
559 # Some other NULL experiments if preceding INSERT was successfull
560 --enable_abort_on_error
565 eval SET @my_errno = $mysql_errno;
566 let $run= `SELECT @my_errno = 0`;
567 if (`SELECT @my_errno NOT IN (0,$ER_BAD_NULL_ERROR)`)
569 --echo # The last command got an unexpected error response.
570 --echo # Expected/handled SQL codes are 0,$ER_BAD_NULL_ERROR
571 SELECT
'# SQL code we got was: ' AS
"", @my_errno AS
"";
572 --echo # Sorry, have
to abort.
573 --echo # Please check the error
name to number mapping in inc/partition.pre.
578 # Give a success message like in the other following tests
579 --echo # check null success: 1
580 # The following checks do not make sense if f_int1 cannot be NULL
583 # Check of preceding statement via Select
588 # Bug#17432: Partitions: wrong result, SELECT ... where <column> is null
589 SELECT
'# check null-1 success: ' AS
"",COUNT(*) = 1 AS
"" FROM t1
590 WHERE f_int1 IS NULL AND f_charbig =
'#NULL#';
593 # 5.2 Update of f_int1 from NULL to negative value
594 # Bug#17432: Partitions: wrong result, SELECT ... where <column> is null
595 UPDATE t1 SET f_int1 = -@max_row
596 WHERE f_int1 IS NULL AND f_int2 = -@max_row AND f_char1 = CAST(-@max_row AS CHAR)
597 AND f_char2 = CAST(-@max_row AS CHAR) AND f_charbig =
'#NULL#';
602 # Check of preceding statement via Select
603 SELECT
'# check null-2 success: ' AS
"",COUNT(*) = 1 AS
"" FROM t1
604 WHERE f_int1 = -@max_row AND f_charbig =
'#NULL#';
606 # 5.3 Update of f_int1 from negative value to NULL
607 UPDATE t1 SET f_int1 = NULL
608 WHERE f_int1 = -@max_row AND f_int2 = -@max_row AND f_char1 = CAST(-@max_row AS CHAR)
609 AND f_char2 = CAST(-@max_row AS CHAR) AND f_charbig =
'#NULL#';
614 # Check of preceding statement via Select
615 SELECT
'# check null-3 success: ' AS
"",COUNT(*) = 1 AS
"" FROM t1
616 WHERE f_int1 IS NULL AND f_charbig =
'#NULL#';
618 # 5.4 DELETE of the record with f_int1 IS NULL
620 WHERE f_int1 IS NULL AND f_int2 = -@max_row AND f_char1 = CAST(-@max_row AS CHAR)
621 AND f_char2 = CAST(-@max_row AS CHAR) AND f_charbig =
'#NULL#';
622 # Check of preceding statement via Select
627 SELECT
'# check null-4 success: ' AS
"",COUNT(*) = 0 AS
"" FROM t1
628 WHERE f_int1 IS NULL;
631 # Remove the "0" record
633 WHERE f_int1 = 0 AND f_int2 = 0
634 AND f_char1 = CAST(0 AS CHAR) AND f_char2 = CAST(0 AS CHAR)
635 AND f_charbig =
'#NULL#';
638 #-------------------------------------------------------------------------------
639 ## 6. UPDATEs of columns used in the partitioning function and the PRIMARY KEY
640 # the UNIQUE INDEX without using straight forward UPDATE.
641 # INSERT .... ON DUPLICATE KEY UPDATE .... --> update existing record
642 # REPLACE --> delete existing record + insert new record
644 # - This test is skipped for tables without any PRIMARY KEY or
646 # - MOD(<column>,n) with n = prime number, n <> 2 is used to cause
647 # that many records and most probably more than one PARTITION/
648 # SUBPARTITION are affected.
649 # - Under certain circumstanditions a movement of one or more records
650 # to other PARTITIONs/SUBPARTITIONs might appear.
651 # - There are some storage engines, which are unable to revert changes
652 # of a failing statement. This has to be taken into account when
653 # checking if a DUPLICATE KEY might occur.
657 # f_int1 IU f_int1 IU f_int1,f_int2 R
658 # f_int2 IU f_int2 IU f_int1,f_int2 R
659 # f_int1,f_int2 IU f_int1,f_int2 R
661 # IU column = INSERT .. ON DUPLICATE KEY UPDATE column
664 # Current state of the data
665 # 1. f_int1 = f_int2, f_char1 = CAST(f_int1 AS CHAR), f_char2 = f_char1,
666 # f_charbig = CONCAT('===',f_char1,'===);
667 # 2. f_int1 FROM 1 TO @max_row_div4
668 # AND @max_row_div2 + @max_row_div4 TO @max_row
670 # Do not apply the following tests to tables without UNIQUE columns.
674 if ($f_int1_is_unique)
676 ## 6.1 f_int1 is UNIQUE, UPDATE f_int1 when DUPLICATE KEY
677 # Bug#15236 Partitions: crash, if Insert .. on duplicate key causes update of existing row
678 INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig)
679 SELECT f_int1, f_int1, '', '', 'was inserted'
680 FROM t0_template source_tab
681 WHERE MOD(f_int1,3) = 0
682 AND f_int1 BETWEEN @max_row_div2 AND @max_row
684 UPDATE f_int1 = 2 * @max_row + source_tab.f_int1,
685 f_charbig = 'was updated';
686 --source suite/parts/inc/partition_20.inc
689 if ($f_int2_is_unique)
691 ## 6.2 f_int2 is UNIQUE, UPDATE f_int2 when DUPLICATE KEY
692 # Bug#15236 Partitions: crash, if Insert .. on duplicate key causes update of existing row
693 INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig)
694 SELECT f_int1, f_int1, '', '', 'was inserted'
695 FROM t0_template source_tab
696 WHERE MOD(f_int1,3) = 0
697 AND f_int1 BETWEEN @max_row_div2 AND @max_row
699 UPDATE f_int2 = 2 * @max_row + source_tab.f_int1,
700 f_charbig = 'was updated';
701 --source suite/parts/inc/partition_20.inc
704 ## 6.3 f_int1, f_int2 is UNIQUE, UPDATE f_int1, f_int2 when DUPLICATE KEY
705 INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig)
706 SELECT f_int1, f_int1, '', '', 'was inserted'
707 FROM t0_template source_tab
708 WHERE MOD(f_int1,3) = 0
709 AND f_int1 BETWEEN @max_row_div2 AND @max_row
711 UPDATE f_int1 = 2 * @max_row + source_tab.f_int1,
712 f_int2 = 2 * @max_row + source_tab.f_int1,
713 f_charbig = 'was updated';
714 --source suite/parts/inc/partition_20.inc
717 # Bug#16782: Partitions: crash, REPLACE .. on table with PK, DUPLICATE KEY
718 REPLACE INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig)
719 SELECT f_int1, - f_int1, '', '', 'was inserted or replaced'
720 FROM t0_template source_tab
721 WHERE MOD(f_int1,3) = 0 AND f_int1 BETWEEN @max_row_div2 AND @max_row;
722 # DEBUG SELECT * FROM t1 ORDER BY f_int1, f_int2;
723 # Check of preceding statement via Select
728 SELECT
'# check replace success: ' AS
"", COUNT(*) =
@try_count AS
""
729 FROM t1 WHERE f_charbig =
'was inserted or replaced';
731 # Revert the modification
733 WHERE f_int1 BETWEEN @max_row_div2 AND @max_row_div2 + @max_row_div4;
734 # If there is only UNIQUE (f1,f2) we will have pairs f_int1,f_int2
735 # <n>, <n> and <n>, <-n>
736 # where MOD(f_int1,3) = 0
737 # and f_int1 between @max_row_div2 + @max_row_div4 and @max_row.
738 # Delete the <n>, <n> records.
740 WHERE f_int1 = f_int2 AND MOD(f_int1,3) = 0 AND
741 f_int1 BETWEEN @max_row_div2 + @max_row_div4 AND @max_row;
742 UPDATE t1 SET f_int2 = f_int1,
743 f_char1 = CAST(f_int1 AS CHAR),
744 f_char2 = CAST(f_int1 AS CHAR),
745 f_charbig = CONCAT(
'===',CAST(f_int1 AS CHAR),
'===')
746 WHERE f_charbig = 'was inserted or replaced' AND f_int1 = - f_int2;
747 # DEBUG SELECT * FROM t1 ORDER BY f_int1, f_int2;
751 #-------------------------------------------------------------------------------
754 # DEBUG SELECT @max_row_div4 , @max_row_div2 + @max_row_div4;
759 SELECT COUNT(f_int1) INTO @start_count FROM t1
760 WHERE f_int1 BETWEEN @max_row_div4 AND @max_row_div2 + @max_row_div4;
762 let $run= `SELECT @start_count <> 0`;
765 --echo # Prerequisites
for following tests not fullfilled.
766 --echo # The content of the
table t1 is unexpected
767 --echo # There must be no rows BETWEEN @max_row_div4 AND @max_row_div2 + @max_row_div4;
768 SELECT COUNT(f_int1) FROM t1
769 WHERE f_int1 BETWEEN @max_row_div4 AND @max_row_div2 + @max_row_div4;
770 --echo
# Sorry, have to abort.
773 # Number of records to be inserted
778 SELECT @max_row_div2 + @max_row_div4 - @max_row_div4 + 1 INTO @exp_inserted_rows;
780 # 7.1 Successful INSERT + COMMIT
781 INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig)
782 SELECT f_int1, f_int1, '', '', 'was inserted'
783 FROM t0_template source_tab
784 WHERE f_int1 BETWEEN @max_row_div4 AND @max_row_div2 + @max_row_div4;
785 # The inserted records must be visible (at least for our current session)
790 SELECT
'# check transactions-1 success: ' AS
"",
791 COUNT(*) = @exp_inserted_rows AS
""
792 FROM t1 WHERE f_int1 BETWEEN @max_row_div4 AND @max_row_div2 + @max_row_div4;
794 # Make the changes persistent for all storage engines
796 # The inserted records must be visible (for all open and future sessions)
801 SELECT
'# check transactions-2 success: ' AS
"",
802 COUNT(*) = @exp_inserted_rows AS
""
803 FROM t1 WHERE f_int1 BETWEEN @max_row_div4 AND @max_row_div2 + @max_row_div4;
805 # Let's assume we have a transactional engine + COMMIT is ill.
806 # A correct working ROLLBACK might revert the INSERT.
812 SELECT
'# check transactions-3 success: ' AS
"",
813 COUNT(*) = @exp_inserted_rows AS
""
814 FROM t1 WHERE f_int1 BETWEEN @max_row_div4 AND @max_row_div2 + @max_row_div4;
817 DELETE FROM t1 WHERE f_charbig =
'was inserted';
824 SELECT
'# check transactions-4 success: ' AS
"",
826 FROM t1 WHERE f_int1 BETWEEN @max_row_div4 AND @max_row_div2 + @max_row_div4;
829 # 7.2 Successful INSERT + ROLLBACK
830 INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig)
831 SELECT f_int1, f_int1, '', '', 'was inserted'
832 FROM t0_template source_tab
833 WHERE f_int1 BETWEEN @max_row_div4 AND @max_row_div2 + @max_row_div4;
838 SELECT
'# check transactions-5 success: ' AS
"",
839 COUNT(*) = @exp_inserted_rows AS
""
840 FROM t1 WHERE f_int1 BETWEEN @max_row_div4 AND @max_row_div2 + @max_row_div4;
847 SELECT COUNT(*) INTO @my_count
848 FROM t1 WHERE f_int1 BETWEEN @max_row_div4 AND @max_row_div2 + @max_row_div4;
849 SELECT '
# check transactions-6 success: ' AS "",
850 @my_count IN (0,@exp_inserted_rows) AS "";
851 let $run= `SELECT @my_count = 0`;
854 --echo # INFO: Storage engine used
for t1 seems
to be transactional.
856 let $run= `SELECT @my_count = @exp_inserted_rows`;
859 --echo # INFO: Storage engine used
for t1 seems
to be not transactional.
862 # Let's assume we have a transactional engine + ROLLBACK is ill.
863 # A correct working COMMIT might make the inserted records again visible.
869 SELECT
'# check transactions-7 success: ' AS
"",
870 COUNT(*) IN (0,@exp_inserted_rows) AS ""
871 FROM t1 WHERE f_int1 BETWEEN @max_row_div4 AND @max_row_div2 + @max_row_div4;
874 DELETE FROM t1 WHERE f_charbig =
'was inserted';
877 # 7.3 Failing INSERT (in mid of statement processing) + COMMIT
878 SET @@session.sql_mode =
'traditional';
879 # Number of records where a INSERT has to be tried
880 SELECT @max_row_div2 + @max_row_div4 - @max_row_div4 + 1 INTO @exp_inserted_rows;
882 --disable_abort_on_error
883 INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig)
884 SELECT IF(f_int1 = @max_row_div2,f_int1 / 0,f_int1),f_int1,
885 '', '', 'was inserted' FROM t0_template
886 WHERE f_int1 BETWEEN @max_row_div4 AND @max_row_div2 + @max_row_div4;
887 --enable_abort_on_error
889 # How many new records should be now visible ?
890 # 1. storage engine unable to revert changes made by the failing statement
891 # @max_row_div2 - 1 - @max_row_div4 + 1
892 # 2. storage engine able to revert changes made by the failing statement
898 SELECT COUNT(*) INTO @my_count
899 FROM t1 WHERE f_int1 BETWEEN @max_row_div4 AND @max_row_div2 + @max_row_div4;
900 SELECT '
# check transactions-8 success: ' AS "",
901 @my_count IN (@max_row_div2 - 1 - @max_row_div4 + 1,0) AS "";
902 let $run= `SELECT @my_count = @max_row_div2 - 1 - @max_row_div4 + 1`;
905 --echo # INFO: Storage engine used
for t1 seems
to be unable
to revert
906 --echo # changes made by the failing
statement.
908 let $run= `SELECT @my_count = 0`;
911 --echo # INFO: Storage engine used
for t1 seems
to be able
to revert
912 --echo # changes made by the failing
statement.
915 SET @@session.sql_mode =
'';
918 DELETE FROM t1 WHERE f_charbig =
'was inserted';
923 SELECT * FROM t1
ORDER BY f_int1;
927 #-------------------------------------------------------------------------------
928 # 8 Some special cases
929 # 8.1 Dramatic increase of the record/partition/subpartition/table sizes
930 UPDATE t1 SET f_charbig = REPEAT(
'b', 1000);
931 # partial check of preceding statement via Select
936 eval SELECT
'# check special-1 success: ' AS
"",1 AS
"" FROM t1
937 WHERE f_int1 = 1 AND f_charbig = REPEAT(
'b', 1000);
940 # 8.2 Dramatic decrease of the record/partition/subpartition/table sizes
941 UPDATE t1 SET f_charbig =
'';
942 # partial check of preceding statement via Select
947 eval SELECT
'# check special-2 success: ' AS
"",1 AS
"" FROM t1
948 WHERE f_int1 = 1 AND f_charbig =
'';
951 UPDATE t1 SET f_charbig = CONCAT(
'===',CAST(f_int1 AS CHAR),
'===');
955 SELECT * FROM t1
ORDER BY f_int1;
959 #-------------------------------------------------------------------------------
962 # 9.1 BEFORE/AFTER INSERT/UPDATE/DELETE TRIGGER on table t0_aux causes that
963 # column values used in partitioning function of t1 are changed.
964 let $tab_has_trigg= t0_aux;
965 let $tab_in_trigg= t1;
967 # Insert three records, which will be updated by the trigger
968 # Bug#18735: Partitions: NDB, UNIQUE INDEX, UPDATE, strange server response
969 eval INSERT INTO $tab_in_trigg(f_int1,f_int2,f_char1,f_char2,f_charbig)
970 SELECT f_int1,f_int2,f_char1,f_char2,'just inserted' FROM t0_template
971 WHERE f_int1 BETWEEN @max_row_div2 - 1 AND @max_row_div2 + 1;
973 let $statement= INSERT INTO t0_aux(f_int1,f_int2,f_char1,f_char2,f_charbig)
974 SELECT f_int1,f_int2,f_char1,f_char2,NULL FROM t0_template
975 WHERE f_int1 BETWEEN @max_row_div2 - 1 AND @max_row_div2 + 1;
976 let $event= BEFORE INSERT;
977 --source suite/parts/inc/partition_trigg1.inc
978 let $event= AFTER INSERT;
979 --source suite/parts/inc/partition_trigg1.inc
981 let $statement= UPDATE t0_aux SET f_int1 = - f_int1, f_int2 = - f_int2
982 WHERE f_int1 IN (- (@max_row_div2 - 1),- @max_row_div2,- (@max_row_div2 + 1));
983 let $event= BEFORE UPDATE;
984 --source suite/parts/inc/partition_trigg1.inc
985 let $event= AFTER UPDATE;
986 --source suite/parts/inc/partition_trigg1.inc
988 let $statement= DELETE FROM t0_aux
989 WHERE f_int1 IN (- (@max_row_div2 - 1),- @max_row_div2,- (@max_row_div2 + 1));
990 let $event= BEFORE DELETE;
991 --source suite/parts/inc/partition_trigg1.inc
992 let $event= AFTER DELETE;
993 --source suite/parts/inc/partition_trigg1.inc
996 eval DELETE FROM $tab_in_trigg
997 WHERE f_int1 BETWEEN @max_row_div2 - 1 AND @max_row_div2 + 1;
999 # Two currently (February 2006) impossible operations.
1000 # 1442: 'Can't update table 't1' in stored function/trigger because it is
1001 # already used by statement which invoked this stored function/trigger.'
1002 # 1362: 'Updating of OLD row is not allowed in trigger'
1006 SELECT * FROM t1
ORDER BY f_int1;
1009 if ($more_trigger_tests)
1011 # 9.2 BEFORE/AFTER INSERT/UPDATE/DELETE TRIGGER on partitioned table t1 causes
1012 # that column values in not partitioned table t0_aux are changed.
1013 let $tab_has_trigg= t1;
1014 let $tab_in_trigg= t0_aux;
1016 # Insert three records, which will be updated by the trigger
1017 eval INSERT INTO $tab_in_trigg(f_int1,f_int2,f_char1,f_char2,f_charbig)
1018 SELECT f_int1,f_int2,f_char1,f_char2,'just inserted' FROM t0_template
1019 WHERE f_int1 BETWEEN @max_row_div2 - 1 AND @max_row_div2 + 1;
1021 let $statement= INSERT INTO t1(f_int1,f_int2,f_char1,f_char2,f_charbig)
1022 SELECT f_int1,f_int2,f_char1,f_char2,NULL FROM t0_template
1023 WHERE f_int1 BETWEEN @max_row_div2 - 1 AND @max_row_div2 + 1;
1024 let $event= BEFORE INSERT;
1025 --source suite/parts/inc/partition_trigg1.inc
1026 let $event= AFTER INSERT;
1027 --source suite/parts/inc/partition_trigg1.inc
1029 let $statement= UPDATE t1 SET f_int1 = - f_int1, f_int2 = - f_int2
1030 WHERE f_int1 IN (- (@max_row_div2 - 1),- @max_row_div2,- (@max_row_div2 + 1));
1031 let $event= BEFORE UPDATE;
1032 --source suite/parts/inc/partition_trigg1.inc
1033 let $event= AFTER UPDATE;
1034 --source suite/parts/inc/partition_trigg1.inc
1036 let $statement= DELETE FROM t1
1037 WHERE f_int1 IN (- (@max_row_div2 - 1),- @max_row_div2,- (@max_row_div2 + 1));
1038 let $event= BEFORE DELETE;
1039 --source suite/parts/inc/partition_trigg1.inc
1040 let $event= AFTER DELETE;
1041 --source suite/parts/inc/partition_trigg1.inc
1042 eval DELETE FROM $tab_in_trigg
1043 WHERE f_int1 BETWEEN @max_row_div2 - 1 AND @max_row_div2 + 1;
1048 SELECT * FROM t1
ORDER BY f_int1;
1051 # 9.3 BEFORE/AFTER UPDATE TRIGGER on partitioned table causes that the value
1052 # of columns in partitioning function is recalculated
1053 if ($more_trigger_tests)
1055 # 9.3.1 The UPDATE itself changes a column which is not used in the partitioning
1057 # "old" values are used as source within the trigger.
1058 let $statement= UPDATE t1
1059 SET f_charbig =
'####updated per update statement itself####';
1061 let $event= BEFORE UPDATE;
1062 --source suite/parts/inc/partition_trigg2.inc
1063 # FIXME when AFTER TRIGGER can be used
1064 # Currently (2006-02-23) a AFTER TRIGGER is not allowed to modify a row, which
1065 # was just modified: 1362: Updating of NEW row is not allowed in after trigger
1068 # 9.3.2 The UPDATE itself changes a column which is used in the partitioning
1070 let $statement= UPDATE t1
1071 SET f_int1 = f_int1 + @max_row, f_int2 = f_int2 - @max_row,
1072 f_charbig =
'####updated per update statement itself####';
1074 # 9.3.2.1 "old" values are used as source within the trigger.
1076 let $event= BEFORE UPDATE;
1077 --source suite/parts/inc/partition_trigg2.inc
1078 # FIXME when AFTER TRIGGER can be used
1079 # Currently (2006-02-23) a AFTER TRIGGER is not allowed to modify a row, which
1080 # was just modified: 1362: Updating of NEW row is not allowed in after trigger
1081 # 9.3.2.2 "new" values are used as source within the trigger.
1083 let $event= BEFORE UPDATE;
1084 --source suite/parts/inc/partition_trigg2.inc
1085 # FIXME when AFTER TRIGGER can be used
1089 SELECT * FROM t1
ORDER BY f_int1;
1092 # 9.4 BEFORE/AFTER INSERT TRIGGER on partitioned table causes that the value of
1093 # columns in partitioning function is recalculated.
1094 # 9.4.1 INSERT assigns values to the recalculate columns
1095 let $statement= INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig)
1096 SELECT f_int1, f_int1, CAST(f_int1 AS CHAR),
1097 CAST(f_int1 AS CHAR), 'just inserted' FROM t0_template
1098 WHERE f_int1 BETWEEN @max_row_div2 - 1 AND @max_row_div2 + 1
1100 let $event= BEFORE INSERT;
1102 --source suite/parts/inc/partition_trigg3.inc
1103 # FIXME when AFTER TRIGGER can be used
1105 # 9.4.2 INSERT assigns no values to the recalculate columns
1106 let $statement= INSERT INTO t1 (f_char1, f_char2, f_charbig)
1107 SELECT CAST(f_int1 AS CHAR),
1108 CAST(f_int1 AS CHAR), 'just inserted' FROM t0_template
1109 WHERE f_int1 BETWEEN @max_row_div2 - 1 AND @max_row_div2 + 1
1111 let $event= BEFORE INSERT;
1113 --source suite/parts/inc/partition_trigg3.inc
1114 # FIXME when AFTER TRIGGER can be used
1118 SELECT * FROM t1
ORDER BY f_int1;
1122 #-------------------------------------------------------------------------------
1123 # 10 ANALYZE/CHECK/CHECKSUM
1125 CHECK
TABLE t1 EXTENDED;
1126 # Checksum depends on @max_row so we have to unify the value
1127 --replace_column 2 <some_value>
1128 CHECKSUM
TABLE t1 EXTENDED;
1131 #-------------------------------------------------------------------------------
1132 # 11 Some special statements, which may lead to a rebuild of the trees
1133 # depending on the storage engine and some particular conditions
1134 # 11.1 OPTIMIZE TABLE
1135 # Manual about OPTIMIZE <InnoDB table>:
1136 # ... , it is mapped to ALTER TABLE, which rebuilds the table.
1137 # Rebuilding updates index statistics and frees unused space in the
1139 # FIXME What will happen with NDB ?
1141 --source suite/parts/inc/partition_layout_check2.inc
1143 REPAIR
TABLE t1 EXTENDED;
1144 --source suite/parts/inc/partition_layout_check2.inc
1147 # Manual about TRUNCATE on tables ( != InnoDB table with FOREIGN KEY ):
1148 # Truncate operations drop and re-create the table ....
1150 # Check of preceding statement via Select
1155 SELECT
'# check TRUNCATE success: ' AS
"",COUNT(*) = 0 AS
"" FROM t1;
1157 --source suite/parts/inc/partition_layout_check2.inc
1158 --echo # End usability
test (inc/partition_check.inc)