From 455352b0b892252fdb060a1da71bd008da36f4ac Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 17 May 2007 19:38:34 +0300 Subject: [PATCH 01/15] Bug#22855: Conversion errors when constructing the condition for an IN predicates were treated as if the affected column contains NULL. If such a IN predicate is inside NOT we get wrong results. Corrected the handling of conversion errors in an IN predicate that is resolved by unique_subquery (through subselect_uniquesubquery_engine). mysql-test/r/subselect3.result: Bug#22855: test case mysql-test/t/subselect3.test: Bug#22855: test case sql/item_subselect.cc: Bug#22855: corrected the handling of conversion errors and NULL key values in IN predicate that is resolved by index lookup. --- mysql-test/r/bdb_notembedded.result | 35 +++++++++++++ mysql-test/r/subselect3.result | 18 +++++++ mysql-test/t/bdb_notembedded.test | 38 ++++++++++++++ mysql-test/t/subselect3.test | 18 +++++++ sql/item_subselect.cc | 81 ++++++++++++++++++++++++++--- 5 files changed, 183 insertions(+), 7 deletions(-) create mode 100644 mysql-test/r/bdb_notembedded.result create mode 100644 mysql-test/t/bdb_notembedded.test diff --git a/mysql-test/r/bdb_notembedded.result b/mysql-test/r/bdb_notembedded.result new file mode 100644 index 00000000000..14cb5fad915 --- /dev/null +++ b/mysql-test/r/bdb_notembedded.result @@ -0,0 +1,35 @@ +set autocommit=1; +reset master; +create table bug16206 (a int); +insert into bug16206 values(1); +start transaction; +insert into bug16206 values(2); +commit; +show binlog events; +Log_name Pos Event_type Server_id End_log_pos Info +f n Format_desc 1 n Server ver: VERSION, Binlog ver: 4 +f n Query 1 n use `test`; create table bug16206 (a int) +f n Query 1 n use `test`; insert into bug16206 values(1) +f n Query 1 n use `test`; insert into bug16206 values(2) +drop table bug16206; +reset master; +create table bug16206 (a int) engine= bdb; +insert into bug16206 values(0); +insert into bug16206 values(1); +start transaction; +insert into bug16206 values(2); +commit; +insert into bug16206 values(3); +show binlog events; +Log_name Pos Event_type Server_id End_log_pos Info +f n Format_desc 1 n Server ver: VERSION, Binlog ver: 4 +f n Query 1 n use `test`; create table bug16206 (a int) engine= bdb +f n Query 1 n use `test`; insert into bug16206 values(0) +f n Query 1 n use `test`; insert into bug16206 values(1) +f n Query 1 n use `test`; BEGIN +f n Query 1 n use `test`; insert into bug16206 values(2) +f n Query 1 n use `test`; COMMIT +f n Query 1 n use `test`; insert into bug16206 values(3) +drop table bug16206; +set autocommit=0; +End of 5.0 tests diff --git a/mysql-test/r/subselect3.result b/mysql-test/r/subselect3.result index 96a3ee00a59..65637a2d0db 100644 --- a/mysql-test/r/subselect3.result +++ b/mysql-test/r/subselect3.result @@ -692,3 +692,21 @@ a MAX(b) test 2 3 h 3 4 i DROP TABLE t1, t2; +CREATE TABLE t1 (a INT NOT NULL); +INSERT INTO t1 VALUES (1),(-1), (65),(66); +CREATE TABLE t2 (a INT UNSIGNED NOT NULL PRIMARY KEY); +INSERT INTO t2 VALUES (65),(66); +SELECT a FROM t1 WHERE a NOT IN (65,66); +a +1 +-1 +SELECT a FROM t1 WHERE a NOT IN (SELECT a FROM t2); +a +1 +-1 +EXPLAIN SELECT a FROM t1 WHERE a NOT IN (SELECT a FROM t2); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 4 Using where +2 DEPENDENT SUBQUERY t2 unique_subquery PRIMARY PRIMARY 4 func 1 Using index +DROP TABLE t1; +End of 5.0 tests diff --git a/mysql-test/t/bdb_notembedded.test b/mysql-test/t/bdb_notembedded.test new file mode 100644 index 00000000000..24e64ebbfb2 --- /dev/null +++ b/mysql-test/t/bdb_notembedded.test @@ -0,0 +1,38 @@ +-- source include/not_embedded.inc +-- source include/have_bdb.inc + +# +# Bug #16206: Superfluous COMMIT event in binlog when updating BDB in autocommit mode +# +set autocommit=1; + +let $VERSION=`select version()`; + +reset master; +create table bug16206 (a int); +insert into bug16206 values(1); +start transaction; +insert into bug16206 values(2); +commit; +--replace_result $VERSION VERSION +--replace_column 1 f 2 n 5 n +show binlog events; +drop table bug16206; + +reset master; +create table bug16206 (a int) engine= bdb; +insert into bug16206 values(0); +insert into bug16206 values(1); +start transaction; +insert into bug16206 values(2); +commit; +insert into bug16206 values(3); +--replace_result $VERSION VERSION +--replace_column 1 f 2 n 5 n +show binlog events; +drop table bug16206; + +set autocommit=0; + + +--echo End of 5.0 tests diff --git a/mysql-test/t/subselect3.test b/mysql-test/t/subselect3.test index e8eae3e2452..178d95dfff9 100644 --- a/mysql-test/t/subselect3.test +++ b/mysql-test/t/subselect3.test @@ -531,3 +531,21 @@ SELECT a, MAX(b), DROP TABLE t1, t2; + +# +# Bug #22855: Optimizer doesn't rewrite NOT IN subselects to a correlated +# subquery +# +CREATE TABLE t1 (a INT NOT NULL); +INSERT INTO t1 VALUES (1),(-1), (65),(66); + +CREATE TABLE t2 (a INT UNSIGNED NOT NULL PRIMARY KEY); +INSERT INTO t2 VALUES (65),(66); + +SELECT a FROM t1 WHERE a NOT IN (65,66); +SELECT a FROM t1 WHERE a NOT IN (SELECT a FROM t2); +EXPLAIN SELECT a FROM t1 WHERE a NOT IN (SELECT a FROM t2); + +DROP TABLE t1; + +--echo End of 5.0 tests diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc index b3744d6eb96..2491acc0150 100644 --- a/sql/item_subselect.cc +++ b/sql/item_subselect.cc @@ -775,6 +775,11 @@ bool Item_in_subselect::val_bool() if (exec()) { reset(); + /* + Must mark the IN predicate as NULL so as to make sure an enclosing NOT + predicate will return FALSE. See the comments in + subselect_uniquesubquery_engine::copy_ref_key for further details. + */ null_value= 1; return 0; } @@ -1919,10 +1924,38 @@ int subselect_uniquesubquery_engine::scan_table() DESCRIPTION Copy ref key and check for null parts in it. + Depending on the nullability and conversion problems this function + recognizes and processes the following states : + 1. Partial match on top level. This means IN has a value of FALSE + regardless of the data in the subquery table. + Detected by finding a NULL in the left IN operand of a top level + expression. + We may actually skip reading the subquery, so return TRUE to skip + the table scan in subselect_uniquesubquery_engine::exec and make + the value of the IN predicate a NULL (that is equal to FALSE on + top level). + 2. No exact match when IN is nested inside another predicate. + Detected by finding a NULL in the left IN operand when IN is not + a top level predicate. + We cannot have an exact match. But we must proceed further with a + table scan to find out if it's a partial match (and IN has a value + of NULL) or no match (and IN has a value of FALSE). + So we return FALSE to continue with the scan and see if there are + any record that would constitute a partial match (as we cannot + determine that from the index). + 3. Error converting the left IN operand to the column type of the + right IN operand. This counts as no match (and IN has the value of + FALSE). We mark the subquery table cursor as having no more rows + (to ensure that the processing that follows will not find a match) + and return FALSE, so IN is not treated as returning NULL. + RETURN - FALSE - ok, index lookup key without keys copied. - TRUE - an error occured while copying the key + FALSE - The value of the IN predicate is not known. Proceed to find the + value of the IN predicate using the determined values of + null_keypart and table->status. + TRUE - IN predicate has a value of NULL. Stop the processing right there + and return NULL to the outer predicates. */ bool subselect_uniquesubquery_engine::copy_ref_key() @@ -1942,13 +1975,37 @@ bool subselect_uniquesubquery_engine::copy_ref_key() function. */ null_keypart= (*copy)->null_key; - bool top_level= ((Item_in_subselect *) item)->is_top_level_item(); - if (null_keypart && !top_level) - break; - if ((tab->ref.key_err) & 1 || (null_keypart && top_level)) + if (null_keypart) { + bool top_level= ((Item_in_subselect *) item)->is_top_level_item(); + if (top_level) + { + /* Partial match on top level */ + DBUG_RETURN(1); + } + else + { + /* No exact match when IN is nested inside another predicate */ + break; + } + } + + /* + Check if the error is equal to STORE_KEY_FATAL. This is not expressed + using the store_key::store_key_result enum because ref.key_err is a + boolean and we want to detect both TRUE and STORE_KEY_FATAL from the + space of the union of the values of [TRUE, FALSE] and + store_key::store_key_result. + TODO: fix the variable an return types. + */ + if (tab->ref.key_err & 1) + { + /* + Error converting the left IN operand to the column type of the right + IN operand. + */ tab->table->status= STATUS_NOT_FOUND; - DBUG_RETURN(1); + break; } } DBUG_RETURN(0); @@ -1991,10 +2048,20 @@ int subselect_uniquesubquery_engine::exec() int error; TABLE *table= tab->table; empty_result_set= TRUE; + table->status= 0; /* TODO: change to use of 'full_scan' here? */ if (copy_ref_key()) DBUG_RETURN(1); + if (table->status) + { + /* + We know that there will be no rows even if we scan. + Can be set in copy_ref_key. + */ + ((Item_in_subselect *) item)->value= 0; + DBUG_RETURN(0); + } if (null_keypart) DBUG_RETURN(scan_table()); From 59a7e066e3a86bb4371ce5027b4ad6b79ac91ce2 Mon Sep 17 00:00:00 2001 From: unknown Date: Sun, 20 May 2007 21:22:57 +0500 Subject: [PATCH 02/15] bug #28361 Buffer overflow in DECIMAL code on Windows my_decimal in some cases can contain more decimal digits than is officially supported (DECIMAL_MAX_PRECISION), so we need to prepare bigger buffer for the resulting string. mysql-test/r/type_newdecimal.result: bug #28361 Buffer overflow in DECIMAL code on Windows test result mysql-test/t/type_newdecimal.test: bug #28361 Buffer overflow in DECIMAL code on Windows test case This test case doesn't fall in most cases even without the fix Still valgrind shows the problemn sql/my_decimal.h: bug #28361 Buffer overflow in DECIMAL code on Windows DECIMAL_MAX_POSSIBLE_PRECISION introduced to be used in places, when we need to check for the number of digits technicaly possible in my_decimal. DECIMAL_MAX_STR_LENGTH fixed as it has to fit for the MAX_POSSIBLE_PRECISION --- mysql-test/r/type_newdecimal.result | 3 +++ mysql-test/t/type_newdecimal.test | 8 ++++++++ sql/my_decimal.h | 10 +++++++--- 3 files changed, 18 insertions(+), 3 deletions(-) diff --git a/mysql-test/r/type_newdecimal.result b/mysql-test/r/type_newdecimal.result index cbcab126439..d91baaa0394 100644 --- a/mysql-test/r/type_newdecimal.result +++ b/mysql-test/r/type_newdecimal.result @@ -1465,4 +1465,7 @@ Error 1264 Out of range value adjusted for column 'cast(a as DECIMAL(3,2))' at r Error 1264 Out of range value adjusted for column 'cast(a as DECIMAL(3,2))' at row 1 Error 1264 Out of range value adjusted for column 'cast(a as DECIMAL(3,2))' at row 1 Error 1264 Out of range value adjusted for column 'cast(a as DECIMAL(3,2))' at row 1 +create table t1 (s varchar(100)); +insert into t1 values (0.00000000010000000000000000364321973154977415791655470655996396089904010295867919921875); +drop table t1; End of 5.0 tests diff --git a/mysql-test/t/type_newdecimal.test b/mysql-test/t/type_newdecimal.test index a7906be79d4..09b20fb14d3 100644 --- a/mysql-test/t/type_newdecimal.test +++ b/mysql-test/t/type_newdecimal.test @@ -1149,4 +1149,12 @@ select cast(a as DECIMAL(3,2)), count(*) UNION select 12.1234 ) t group by 1; +# +# Bug #28361 Buffer overflow in DECIMAL code on Windows +# + +create table t1 (s varchar(100)); +insert into t1 values (0.00000000010000000000000000364321973154977415791655470655996396089904010295867919921875); +drop table t1; + --echo End of 5.0 tests diff --git a/sql/my_decimal.h b/sql/my_decimal.h index 9558b00f0cf..0affa07557e 100644 --- a/sql/my_decimal.h +++ b/sql/my_decimal.h @@ -36,13 +36,17 @@ C_MODE_END /* maximum length of buffer in our big digits (uint32) */ #define DECIMAL_BUFF_LENGTH 9 + +/* the number of digits that my_decimal can possibly contain */ +#define DECIMAL_MAX_POSSIBLE_PRECISION (DECIMAL_BUFF_LENGTH * 9) + /* maximum guaranteed precision of number in decimal digits (number of our digits * number of decimal digits in one our big digit - number of decimal - digits in one our big digit decreased on 1 (because we always put decimal + digits in one our big digit decreased by 1 (because we always put decimal point on the border of our big digits)) */ -#define DECIMAL_MAX_PRECISION ((DECIMAL_BUFF_LENGTH * 9) - 8*2) +#define DECIMAL_MAX_PRECISION (DECIMAL_MAX_POSSIBLE_PRECISION - 8*2) #define DECIMAL_MAX_SCALE 30 #define DECIMAL_NOT_SPECIFIED 31 @@ -50,7 +54,7 @@ C_MODE_END maximum length of string representation (number of maximum decimal digits + 1 position for sign + 1 position for decimal point) */ -#define DECIMAL_MAX_STR_LENGTH (DECIMAL_MAX_PRECISION + 2) +#define DECIMAL_MAX_STR_LENGTH (DECIMAL_MAX_POSSIBLE_PRECISION + 2) /* maximum size of packet length */ From d2c985e3543194436c836fa6bad2b45c27ea5060 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 21 May 2007 13:02:03 +0500 Subject: [PATCH 03/15] Bug #28361 Buffer overflow in DECIMAL code on Windows result max length changed for the 'decimal' fields so test results have to be fixed mysql-test/r/ps_2myisam.result: Bug #28361 Buffer overflow in DECIMAL code on Windows test result fixed mysql-test/r/ps_3innodb.result: Bug #28361 Buffer overflow in DECIMAL code on Windows test result fixed mysql-test/r/ps_4heap.result: Bug #28361 Buffer overflow in DECIMAL code on Windows test result fixed mysql-test/r/ps_5merge.result: Bug #28361 Buffer overflow in DECIMAL code on Windows test result fixed mysql-test/r/ps_7ndb.result: Bug #28361 Buffer overflow in DECIMAL code on Windows test result fixed --- mysql-test/r/ps_2myisam.result | 32 ++++++++--------- mysql-test/r/ps_3innodb.result | 32 ++++++++--------- mysql-test/r/ps_4heap.result | 32 ++++++++--------- mysql-test/r/ps_5merge.result | 64 +++++++++++++++++----------------- mysql-test/r/ps_7ndb.result | 32 ++++++++--------- 5 files changed, 96 insertions(+), 96 deletions(-) diff --git a/mysql-test/r/ps_2myisam.result b/mysql-test/r/ps_2myisam.result index 2b2a29b2122..a2f0fff086e 100644 --- a/mysql-test/r/ps_2myisam.result +++ b/mysql-test/r/ps_2myisam.result @@ -1927,8 +1927,8 @@ def @arg07 253 23 1 Y 128 31 63 def @arg08 253 23 1 Y 128 31 63 def @arg09 253 23 1 Y 128 31 63 def @arg10 253 23 1 Y 128 31 63 -def @arg11 253 67 6 Y 128 30 63 -def @arg12 253 67 6 Y 128 30 63 +def @arg11 253 83 6 Y 128 30 63 +def @arg12 253 83 6 Y 128 30 63 def @arg13 253 8192 10 Y 128 31 63 def @arg14 253 8192 19 Y 128 31 63 def @arg15 253 8192 19 Y 128 31 63 @@ -1974,8 +1974,8 @@ def @arg07 253 23 0 Y 128 31 63 def @arg08 253 23 0 Y 128 31 63 def @arg09 253 23 0 Y 128 31 63 def @arg10 253 23 0 Y 128 31 63 -def @arg11 253 67 0 Y 128 30 63 -def @arg12 253 67 0 Y 128 30 63 +def @arg11 253 83 0 Y 128 30 63 +def @arg12 253 83 0 Y 128 30 63 def @arg13 253 8192 0 Y 128 31 63 def @arg14 253 8192 0 Y 128 31 63 def @arg15 253 8192 19 Y 128 31 63 @@ -2024,8 +2024,8 @@ def @arg07 253 23 1 Y 128 31 63 def @arg08 253 23 1 Y 128 31 63 def @arg09 253 23 1 Y 128 31 63 def @arg10 253 23 1 Y 128 31 63 -def @arg11 253 67 6 Y 128 30 63 -def @arg12 253 67 6 Y 128 30 63 +def @arg11 253 83 6 Y 128 30 63 +def @arg12 253 83 6 Y 128 30 63 def @arg13 253 8192 10 Y 128 31 63 def @arg14 253 8192 19 Y 128 31 63 def @arg15 253 8192 19 Y 128 31 63 @@ -2064,8 +2064,8 @@ def @arg07 253 23 0 Y 128 31 63 def @arg08 253 23 0 Y 128 31 63 def @arg09 253 23 0 Y 128 31 63 def @arg10 253 23 0 Y 128 31 63 -def @arg11 253 67 0 Y 128 30 63 -def @arg12 253 67 0 Y 128 30 63 +def @arg11 253 83 0 Y 128 30 63 +def @arg12 253 83 0 Y 128 30 63 def @arg13 253 8192 0 Y 128 31 63 def @arg14 253 8192 0 Y 128 31 63 def @arg15 253 8192 19 Y 128 31 63 @@ -2112,8 +2112,8 @@ def @arg07 253 23 1 Y 128 31 63 def @arg08 253 23 1 Y 128 31 63 def @arg09 253 23 1 Y 128 31 63 def @arg10 253 23 1 Y 128 31 63 -def @arg11 253 67 6 Y 128 30 63 -def @arg12 253 67 6 Y 128 30 63 +def @arg11 253 83 6 Y 128 30 63 +def @arg12 253 83 6 Y 128 30 63 def @arg13 253 8192 10 Y 128 31 63 def @arg14 253 8192 19 Y 128 31 63 def @arg15 253 8192 19 Y 128 31 63 @@ -2156,8 +2156,8 @@ def @arg07 253 23 0 Y 128 31 63 def @arg08 253 23 0 Y 128 31 63 def @arg09 253 23 0 Y 128 31 63 def @arg10 253 23 0 Y 128 31 63 -def @arg11 253 67 0 Y 128 30 63 -def @arg12 253 67 0 Y 128 30 63 +def @arg11 253 83 0 Y 128 30 63 +def @arg12 253 83 0 Y 128 30 63 def @arg13 253 8192 0 Y 128 31 63 def @arg14 253 8192 0 Y 128 31 63 def @arg15 253 8192 19 Y 128 31 63 @@ -2202,8 +2202,8 @@ def @arg07 253 23 1 Y 128 31 63 def @arg08 253 23 1 Y 128 31 63 def @arg09 253 23 1 Y 128 31 63 def @arg10 253 23 1 Y 128 31 63 -def @arg11 253 67 6 Y 128 30 63 -def @arg12 253 67 6 Y 128 30 63 +def @arg11 253 83 6 Y 128 30 63 +def @arg12 253 83 6 Y 128 30 63 def @arg13 253 8192 10 Y 128 31 63 def @arg14 253 8192 19 Y 128 31 63 def @arg15 253 8192 19 Y 128 31 63 @@ -2240,8 +2240,8 @@ def @arg07 253 23 0 Y 128 31 63 def @arg08 253 23 0 Y 128 31 63 def @arg09 253 23 0 Y 128 31 63 def @arg10 253 23 0 Y 128 31 63 -def @arg11 253 67 0 Y 128 30 63 -def @arg12 253 67 0 Y 128 30 63 +def @arg11 253 83 0 Y 128 30 63 +def @arg12 253 83 0 Y 128 30 63 def @arg13 253 8192 0 Y 128 31 63 def @arg14 253 8192 0 Y 128 31 63 def @arg15 253 8192 19 Y 128 31 63 diff --git a/mysql-test/r/ps_3innodb.result b/mysql-test/r/ps_3innodb.result index f30262ef219..17c83bdc87a 100644 --- a/mysql-test/r/ps_3innodb.result +++ b/mysql-test/r/ps_3innodb.result @@ -1910,8 +1910,8 @@ def @arg07 253 23 1 Y 128 31 63 def @arg08 253 23 1 Y 128 31 63 def @arg09 253 23 1 Y 128 31 63 def @arg10 253 23 1 Y 128 31 63 -def @arg11 253 67 6 Y 128 30 63 -def @arg12 253 67 6 Y 128 30 63 +def @arg11 253 83 6 Y 128 30 63 +def @arg12 253 83 6 Y 128 30 63 def @arg13 253 8192 10 Y 128 31 63 def @arg14 253 8192 19 Y 128 31 63 def @arg15 253 8192 19 Y 128 31 63 @@ -1957,8 +1957,8 @@ def @arg07 253 23 0 Y 128 31 63 def @arg08 253 23 0 Y 128 31 63 def @arg09 253 23 0 Y 128 31 63 def @arg10 253 23 0 Y 128 31 63 -def @arg11 253 67 0 Y 128 30 63 -def @arg12 253 67 0 Y 128 30 63 +def @arg11 253 83 0 Y 128 30 63 +def @arg12 253 83 0 Y 128 30 63 def @arg13 253 8192 0 Y 128 31 63 def @arg14 253 8192 0 Y 128 31 63 def @arg15 253 8192 19 Y 128 31 63 @@ -2007,8 +2007,8 @@ def @arg07 253 23 1 Y 128 31 63 def @arg08 253 23 1 Y 128 31 63 def @arg09 253 23 1 Y 128 31 63 def @arg10 253 23 1 Y 128 31 63 -def @arg11 253 67 6 Y 128 30 63 -def @arg12 253 67 6 Y 128 30 63 +def @arg11 253 83 6 Y 128 30 63 +def @arg12 253 83 6 Y 128 30 63 def @arg13 253 8192 10 Y 128 31 63 def @arg14 253 8192 19 Y 128 31 63 def @arg15 253 8192 19 Y 128 31 63 @@ -2047,8 +2047,8 @@ def @arg07 253 23 0 Y 128 31 63 def @arg08 253 23 0 Y 128 31 63 def @arg09 253 23 0 Y 128 31 63 def @arg10 253 23 0 Y 128 31 63 -def @arg11 253 67 0 Y 128 30 63 -def @arg12 253 67 0 Y 128 30 63 +def @arg11 253 83 0 Y 128 30 63 +def @arg12 253 83 0 Y 128 30 63 def @arg13 253 8192 0 Y 128 31 63 def @arg14 253 8192 0 Y 128 31 63 def @arg15 253 8192 19 Y 128 31 63 @@ -2095,8 +2095,8 @@ def @arg07 253 23 1 Y 128 31 63 def @arg08 253 23 1 Y 128 31 63 def @arg09 253 23 1 Y 128 31 63 def @arg10 253 23 1 Y 128 31 63 -def @arg11 253 67 6 Y 128 30 63 -def @arg12 253 67 6 Y 128 30 63 +def @arg11 253 83 6 Y 128 30 63 +def @arg12 253 83 6 Y 128 30 63 def @arg13 253 8192 10 Y 128 31 63 def @arg14 253 8192 19 Y 128 31 63 def @arg15 253 8192 19 Y 128 31 63 @@ -2139,8 +2139,8 @@ def @arg07 253 23 0 Y 128 31 63 def @arg08 253 23 0 Y 128 31 63 def @arg09 253 23 0 Y 128 31 63 def @arg10 253 23 0 Y 128 31 63 -def @arg11 253 67 0 Y 128 30 63 -def @arg12 253 67 0 Y 128 30 63 +def @arg11 253 83 0 Y 128 30 63 +def @arg12 253 83 0 Y 128 30 63 def @arg13 253 8192 0 Y 128 31 63 def @arg14 253 8192 0 Y 128 31 63 def @arg15 253 8192 19 Y 128 31 63 @@ -2185,8 +2185,8 @@ def @arg07 253 23 1 Y 128 31 63 def @arg08 253 23 1 Y 128 31 63 def @arg09 253 23 1 Y 128 31 63 def @arg10 253 23 1 Y 128 31 63 -def @arg11 253 67 6 Y 128 30 63 -def @arg12 253 67 6 Y 128 30 63 +def @arg11 253 83 6 Y 128 30 63 +def @arg12 253 83 6 Y 128 30 63 def @arg13 253 8192 10 Y 128 31 63 def @arg14 253 8192 19 Y 128 31 63 def @arg15 253 8192 19 Y 128 31 63 @@ -2223,8 +2223,8 @@ def @arg07 253 23 0 Y 128 31 63 def @arg08 253 23 0 Y 128 31 63 def @arg09 253 23 0 Y 128 31 63 def @arg10 253 23 0 Y 128 31 63 -def @arg11 253 67 0 Y 128 30 63 -def @arg12 253 67 0 Y 128 30 63 +def @arg11 253 83 0 Y 128 30 63 +def @arg12 253 83 0 Y 128 30 63 def @arg13 253 8192 0 Y 128 31 63 def @arg14 253 8192 0 Y 128 31 63 def @arg15 253 8192 19 Y 128 31 63 diff --git a/mysql-test/r/ps_4heap.result b/mysql-test/r/ps_4heap.result index a012e516404..114891f1145 100644 --- a/mysql-test/r/ps_4heap.result +++ b/mysql-test/r/ps_4heap.result @@ -1911,8 +1911,8 @@ def @arg07 253 23 1 Y 128 31 63 def @arg08 253 23 1 Y 128 31 63 def @arg09 253 23 1 Y 128 31 63 def @arg10 253 23 1 Y 128 31 63 -def @arg11 253 67 6 Y 128 30 63 -def @arg12 253 67 6 Y 128 30 63 +def @arg11 253 83 6 Y 128 30 63 +def @arg12 253 83 6 Y 128 30 63 def @arg13 253 8192 10 Y 128 31 63 def @arg14 253 8192 19 Y 128 31 63 def @arg15 253 8192 19 Y 128 31 63 @@ -1958,8 +1958,8 @@ def @arg07 253 23 0 Y 128 31 63 def @arg08 253 23 0 Y 128 31 63 def @arg09 253 23 0 Y 128 31 63 def @arg10 253 23 0 Y 128 31 63 -def @arg11 253 67 0 Y 128 30 63 -def @arg12 253 67 0 Y 128 30 63 +def @arg11 253 83 0 Y 128 30 63 +def @arg12 253 83 0 Y 128 30 63 def @arg13 253 8192 0 Y 128 31 63 def @arg14 253 8192 0 Y 128 31 63 def @arg15 253 8192 19 Y 128 31 63 @@ -2008,8 +2008,8 @@ def @arg07 253 23 1 Y 128 31 63 def @arg08 253 23 1 Y 128 31 63 def @arg09 253 23 1 Y 128 31 63 def @arg10 253 23 1 Y 128 31 63 -def @arg11 253 67 6 Y 128 30 63 -def @arg12 253 67 6 Y 128 30 63 +def @arg11 253 83 6 Y 128 30 63 +def @arg12 253 83 6 Y 128 30 63 def @arg13 253 8192 10 Y 128 31 63 def @arg14 253 8192 19 Y 128 31 63 def @arg15 253 8192 19 Y 128 31 63 @@ -2048,8 +2048,8 @@ def @arg07 253 23 0 Y 128 31 63 def @arg08 253 23 0 Y 128 31 63 def @arg09 253 23 0 Y 128 31 63 def @arg10 253 23 0 Y 128 31 63 -def @arg11 253 67 0 Y 128 30 63 -def @arg12 253 67 0 Y 128 30 63 +def @arg11 253 83 0 Y 128 30 63 +def @arg12 253 83 0 Y 128 30 63 def @arg13 253 8192 0 Y 128 31 63 def @arg14 253 8192 0 Y 128 31 63 def @arg15 253 8192 19 Y 128 31 63 @@ -2096,8 +2096,8 @@ def @arg07 253 23 1 Y 128 31 63 def @arg08 253 23 1 Y 128 31 63 def @arg09 253 23 1 Y 128 31 63 def @arg10 253 23 1 Y 128 31 63 -def @arg11 253 67 6 Y 128 30 63 -def @arg12 253 67 6 Y 128 30 63 +def @arg11 253 83 6 Y 128 30 63 +def @arg12 253 83 6 Y 128 30 63 def @arg13 253 8192 10 Y 128 31 63 def @arg14 253 8192 19 Y 128 31 63 def @arg15 253 8192 19 Y 128 31 63 @@ -2140,8 +2140,8 @@ def @arg07 253 23 0 Y 128 31 63 def @arg08 253 23 0 Y 128 31 63 def @arg09 253 23 0 Y 128 31 63 def @arg10 253 23 0 Y 128 31 63 -def @arg11 253 67 0 Y 128 30 63 -def @arg12 253 67 0 Y 128 30 63 +def @arg11 253 83 0 Y 128 30 63 +def @arg12 253 83 0 Y 128 30 63 def @arg13 253 8192 0 Y 128 31 63 def @arg14 253 8192 0 Y 128 31 63 def @arg15 253 8192 19 Y 128 31 63 @@ -2186,8 +2186,8 @@ def @arg07 253 23 1 Y 128 31 63 def @arg08 253 23 1 Y 128 31 63 def @arg09 253 23 1 Y 128 31 63 def @arg10 253 23 1 Y 128 31 63 -def @arg11 253 67 6 Y 128 30 63 -def @arg12 253 67 6 Y 128 30 63 +def @arg11 253 83 6 Y 128 30 63 +def @arg12 253 83 6 Y 128 30 63 def @arg13 253 8192 10 Y 128 31 63 def @arg14 253 8192 19 Y 128 31 63 def @arg15 253 8192 19 Y 128 31 63 @@ -2224,8 +2224,8 @@ def @arg07 253 23 0 Y 128 31 63 def @arg08 253 23 0 Y 128 31 63 def @arg09 253 23 0 Y 128 31 63 def @arg10 253 23 0 Y 128 31 63 -def @arg11 253 67 0 Y 128 30 63 -def @arg12 253 67 0 Y 128 30 63 +def @arg11 253 83 0 Y 128 30 63 +def @arg12 253 83 0 Y 128 30 63 def @arg13 253 8192 0 Y 128 31 63 def @arg14 253 8192 0 Y 128 31 63 def @arg15 253 8192 19 Y 128 31 63 diff --git a/mysql-test/r/ps_5merge.result b/mysql-test/r/ps_5merge.result index ac9c8ae55ff..245d5766efd 100644 --- a/mysql-test/r/ps_5merge.result +++ b/mysql-test/r/ps_5merge.result @@ -1847,8 +1847,8 @@ def @arg07 253 23 1 Y 128 31 63 def @arg08 253 23 1 Y 128 31 63 def @arg09 253 23 1 Y 128 31 63 def @arg10 253 23 1 Y 128 31 63 -def @arg11 253 67 6 Y 128 30 63 -def @arg12 253 67 6 Y 128 30 63 +def @arg11 253 83 6 Y 128 30 63 +def @arg12 253 83 6 Y 128 30 63 def @arg13 253 8192 10 Y 128 31 63 def @arg14 253 8192 19 Y 128 31 63 def @arg15 253 8192 19 Y 128 31 63 @@ -1894,8 +1894,8 @@ def @arg07 253 23 0 Y 128 31 63 def @arg08 253 23 0 Y 128 31 63 def @arg09 253 23 0 Y 128 31 63 def @arg10 253 23 0 Y 128 31 63 -def @arg11 253 67 0 Y 128 30 63 -def @arg12 253 67 0 Y 128 30 63 +def @arg11 253 83 0 Y 128 30 63 +def @arg12 253 83 0 Y 128 30 63 def @arg13 253 8192 0 Y 128 31 63 def @arg14 253 8192 0 Y 128 31 63 def @arg15 253 8192 19 Y 128 31 63 @@ -1944,8 +1944,8 @@ def @arg07 253 23 1 Y 128 31 63 def @arg08 253 23 1 Y 128 31 63 def @arg09 253 23 1 Y 128 31 63 def @arg10 253 23 1 Y 128 31 63 -def @arg11 253 67 6 Y 128 30 63 -def @arg12 253 67 6 Y 128 30 63 +def @arg11 253 83 6 Y 128 30 63 +def @arg12 253 83 6 Y 128 30 63 def @arg13 253 8192 10 Y 128 31 63 def @arg14 253 8192 19 Y 128 31 63 def @arg15 253 8192 19 Y 128 31 63 @@ -1984,8 +1984,8 @@ def @arg07 253 23 0 Y 128 31 63 def @arg08 253 23 0 Y 128 31 63 def @arg09 253 23 0 Y 128 31 63 def @arg10 253 23 0 Y 128 31 63 -def @arg11 253 67 0 Y 128 30 63 -def @arg12 253 67 0 Y 128 30 63 +def @arg11 253 83 0 Y 128 30 63 +def @arg12 253 83 0 Y 128 30 63 def @arg13 253 8192 0 Y 128 31 63 def @arg14 253 8192 0 Y 128 31 63 def @arg15 253 8192 19 Y 128 31 63 @@ -2032,8 +2032,8 @@ def @arg07 253 23 1 Y 128 31 63 def @arg08 253 23 1 Y 128 31 63 def @arg09 253 23 1 Y 128 31 63 def @arg10 253 23 1 Y 128 31 63 -def @arg11 253 67 6 Y 128 30 63 -def @arg12 253 67 6 Y 128 30 63 +def @arg11 253 83 6 Y 128 30 63 +def @arg12 253 83 6 Y 128 30 63 def @arg13 253 8192 10 Y 128 31 63 def @arg14 253 8192 19 Y 128 31 63 def @arg15 253 8192 19 Y 128 31 63 @@ -2076,8 +2076,8 @@ def @arg07 253 23 0 Y 128 31 63 def @arg08 253 23 0 Y 128 31 63 def @arg09 253 23 0 Y 128 31 63 def @arg10 253 23 0 Y 128 31 63 -def @arg11 253 67 0 Y 128 30 63 -def @arg12 253 67 0 Y 128 30 63 +def @arg11 253 83 0 Y 128 30 63 +def @arg12 253 83 0 Y 128 30 63 def @arg13 253 8192 0 Y 128 31 63 def @arg14 253 8192 0 Y 128 31 63 def @arg15 253 8192 19 Y 128 31 63 @@ -2122,8 +2122,8 @@ def @arg07 253 23 1 Y 128 31 63 def @arg08 253 23 1 Y 128 31 63 def @arg09 253 23 1 Y 128 31 63 def @arg10 253 23 1 Y 128 31 63 -def @arg11 253 67 6 Y 128 30 63 -def @arg12 253 67 6 Y 128 30 63 +def @arg11 253 83 6 Y 128 30 63 +def @arg12 253 83 6 Y 128 30 63 def @arg13 253 8192 10 Y 128 31 63 def @arg14 253 8192 19 Y 128 31 63 def @arg15 253 8192 19 Y 128 31 63 @@ -2160,8 +2160,8 @@ def @arg07 253 23 0 Y 128 31 63 def @arg08 253 23 0 Y 128 31 63 def @arg09 253 23 0 Y 128 31 63 def @arg10 253 23 0 Y 128 31 63 -def @arg11 253 67 0 Y 128 30 63 -def @arg12 253 67 0 Y 128 30 63 +def @arg11 253 83 0 Y 128 30 63 +def @arg12 253 83 0 Y 128 30 63 def @arg13 253 8192 0 Y 128 31 63 def @arg14 253 8192 0 Y 128 31 63 def @arg15 253 8192 19 Y 128 31 63 @@ -4861,8 +4861,8 @@ def @arg07 253 23 1 Y 128 31 63 def @arg08 253 23 1 Y 128 31 63 def @arg09 253 23 1 Y 128 31 63 def @arg10 253 23 1 Y 128 31 63 -def @arg11 253 67 6 Y 128 30 63 -def @arg12 253 67 6 Y 128 30 63 +def @arg11 253 83 6 Y 128 30 63 +def @arg12 253 83 6 Y 128 30 63 def @arg13 253 8192 10 Y 128 31 63 def @arg14 253 8192 19 Y 128 31 63 def @arg15 253 8192 19 Y 128 31 63 @@ -4908,8 +4908,8 @@ def @arg07 253 23 0 Y 128 31 63 def @arg08 253 23 0 Y 128 31 63 def @arg09 253 23 0 Y 128 31 63 def @arg10 253 23 0 Y 128 31 63 -def @arg11 253 67 0 Y 128 30 63 -def @arg12 253 67 0 Y 128 30 63 +def @arg11 253 83 0 Y 128 30 63 +def @arg12 253 83 0 Y 128 30 63 def @arg13 253 8192 0 Y 128 31 63 def @arg14 253 8192 0 Y 128 31 63 def @arg15 253 8192 19 Y 128 31 63 @@ -4958,8 +4958,8 @@ def @arg07 253 23 1 Y 128 31 63 def @arg08 253 23 1 Y 128 31 63 def @arg09 253 23 1 Y 128 31 63 def @arg10 253 23 1 Y 128 31 63 -def @arg11 253 67 6 Y 128 30 63 -def @arg12 253 67 6 Y 128 30 63 +def @arg11 253 83 6 Y 128 30 63 +def @arg12 253 83 6 Y 128 30 63 def @arg13 253 8192 10 Y 128 31 63 def @arg14 253 8192 19 Y 128 31 63 def @arg15 253 8192 19 Y 128 31 63 @@ -4998,8 +4998,8 @@ def @arg07 253 23 0 Y 128 31 63 def @arg08 253 23 0 Y 128 31 63 def @arg09 253 23 0 Y 128 31 63 def @arg10 253 23 0 Y 128 31 63 -def @arg11 253 67 0 Y 128 30 63 -def @arg12 253 67 0 Y 128 30 63 +def @arg11 253 83 0 Y 128 30 63 +def @arg12 253 83 0 Y 128 30 63 def @arg13 253 8192 0 Y 128 31 63 def @arg14 253 8192 0 Y 128 31 63 def @arg15 253 8192 19 Y 128 31 63 @@ -5046,8 +5046,8 @@ def @arg07 253 23 1 Y 128 31 63 def @arg08 253 23 1 Y 128 31 63 def @arg09 253 23 1 Y 128 31 63 def @arg10 253 23 1 Y 128 31 63 -def @arg11 253 67 6 Y 128 30 63 -def @arg12 253 67 6 Y 128 30 63 +def @arg11 253 83 6 Y 128 30 63 +def @arg12 253 83 6 Y 128 30 63 def @arg13 253 8192 10 Y 128 31 63 def @arg14 253 8192 19 Y 128 31 63 def @arg15 253 8192 19 Y 128 31 63 @@ -5090,8 +5090,8 @@ def @arg07 253 23 0 Y 128 31 63 def @arg08 253 23 0 Y 128 31 63 def @arg09 253 23 0 Y 128 31 63 def @arg10 253 23 0 Y 128 31 63 -def @arg11 253 67 0 Y 128 30 63 -def @arg12 253 67 0 Y 128 30 63 +def @arg11 253 83 0 Y 128 30 63 +def @arg12 253 83 0 Y 128 30 63 def @arg13 253 8192 0 Y 128 31 63 def @arg14 253 8192 0 Y 128 31 63 def @arg15 253 8192 19 Y 128 31 63 @@ -5136,8 +5136,8 @@ def @arg07 253 23 1 Y 128 31 63 def @arg08 253 23 1 Y 128 31 63 def @arg09 253 23 1 Y 128 31 63 def @arg10 253 23 1 Y 128 31 63 -def @arg11 253 67 6 Y 128 30 63 -def @arg12 253 67 6 Y 128 30 63 +def @arg11 253 83 6 Y 128 30 63 +def @arg12 253 83 6 Y 128 30 63 def @arg13 253 8192 10 Y 128 31 63 def @arg14 253 8192 19 Y 128 31 63 def @arg15 253 8192 19 Y 128 31 63 @@ -5174,8 +5174,8 @@ def @arg07 253 23 0 Y 128 31 63 def @arg08 253 23 0 Y 128 31 63 def @arg09 253 23 0 Y 128 31 63 def @arg10 253 23 0 Y 128 31 63 -def @arg11 253 67 0 Y 128 30 63 -def @arg12 253 67 0 Y 128 30 63 +def @arg11 253 83 0 Y 128 30 63 +def @arg12 253 83 0 Y 128 30 63 def @arg13 253 8192 0 Y 128 31 63 def @arg14 253 8192 0 Y 128 31 63 def @arg15 253 8192 19 Y 128 31 63 diff --git a/mysql-test/r/ps_7ndb.result b/mysql-test/r/ps_7ndb.result index 2673448489a..65e9121a35e 100644 --- a/mysql-test/r/ps_7ndb.result +++ b/mysql-test/r/ps_7ndb.result @@ -1910,8 +1910,8 @@ def @arg07 253 23 1 Y 128 31 63 def @arg08 253 23 1 Y 128 31 63 def @arg09 253 23 1 Y 128 31 63 def @arg10 253 23 1 Y 128 31 63 -def @arg11 253 67 6 Y 128 30 63 -def @arg12 253 67 6 Y 128 30 63 +def @arg11 253 83 6 Y 128 30 63 +def @arg12 253 83 6 Y 128 30 63 def @arg13 253 8192 10 Y 128 31 63 def @arg14 253 8192 19 Y 128 31 63 def @arg15 253 8192 19 Y 128 31 63 @@ -1957,8 +1957,8 @@ def @arg07 253 23 0 Y 128 31 63 def @arg08 253 23 0 Y 128 31 63 def @arg09 253 23 0 Y 128 31 63 def @arg10 253 23 0 Y 128 31 63 -def @arg11 253 67 0 Y 128 30 63 -def @arg12 253 67 0 Y 128 30 63 +def @arg11 253 83 0 Y 128 30 63 +def @arg12 253 83 0 Y 128 30 63 def @arg13 253 8192 0 Y 128 31 63 def @arg14 253 8192 0 Y 128 31 63 def @arg15 253 8192 19 Y 128 31 63 @@ -2007,8 +2007,8 @@ def @arg07 253 23 1 Y 128 31 63 def @arg08 253 23 1 Y 128 31 63 def @arg09 253 23 1 Y 128 31 63 def @arg10 253 23 1 Y 128 31 63 -def @arg11 253 67 6 Y 128 30 63 -def @arg12 253 67 6 Y 128 30 63 +def @arg11 253 83 6 Y 128 30 63 +def @arg12 253 83 6 Y 128 30 63 def @arg13 253 8192 10 Y 128 31 63 def @arg14 253 8192 19 Y 128 31 63 def @arg15 253 8192 19 Y 128 31 63 @@ -2047,8 +2047,8 @@ def @arg07 253 23 0 Y 128 31 63 def @arg08 253 23 0 Y 128 31 63 def @arg09 253 23 0 Y 128 31 63 def @arg10 253 23 0 Y 128 31 63 -def @arg11 253 67 0 Y 128 30 63 -def @arg12 253 67 0 Y 128 30 63 +def @arg11 253 83 0 Y 128 30 63 +def @arg12 253 83 0 Y 128 30 63 def @arg13 253 8192 0 Y 128 31 63 def @arg14 253 8192 0 Y 128 31 63 def @arg15 253 8192 19 Y 128 31 63 @@ -2095,8 +2095,8 @@ def @arg07 253 23 1 Y 128 31 63 def @arg08 253 23 1 Y 128 31 63 def @arg09 253 23 1 Y 128 31 63 def @arg10 253 23 1 Y 128 31 63 -def @arg11 253 67 6 Y 128 30 63 -def @arg12 253 67 6 Y 128 30 63 +def @arg11 253 83 6 Y 128 30 63 +def @arg12 253 83 6 Y 128 30 63 def @arg13 253 8192 10 Y 128 31 63 def @arg14 253 8192 19 Y 128 31 63 def @arg15 253 8192 19 Y 128 31 63 @@ -2139,8 +2139,8 @@ def @arg07 253 23 0 Y 128 31 63 def @arg08 253 23 0 Y 128 31 63 def @arg09 253 23 0 Y 128 31 63 def @arg10 253 23 0 Y 128 31 63 -def @arg11 253 67 0 Y 128 30 63 -def @arg12 253 67 0 Y 128 30 63 +def @arg11 253 83 0 Y 128 30 63 +def @arg12 253 83 0 Y 128 30 63 def @arg13 253 8192 0 Y 128 31 63 def @arg14 253 8192 0 Y 128 31 63 def @arg15 253 8192 19 Y 128 31 63 @@ -2185,8 +2185,8 @@ def @arg07 253 23 1 Y 128 31 63 def @arg08 253 23 1 Y 128 31 63 def @arg09 253 23 1 Y 128 31 63 def @arg10 253 23 1 Y 128 31 63 -def @arg11 253 67 6 Y 128 30 63 -def @arg12 253 67 6 Y 128 30 63 +def @arg11 253 83 6 Y 128 30 63 +def @arg12 253 83 6 Y 128 30 63 def @arg13 253 8192 10 Y 128 31 63 def @arg14 253 8192 19 Y 128 31 63 def @arg15 253 8192 19 Y 128 31 63 @@ -2223,8 +2223,8 @@ def @arg07 253 23 0 Y 128 31 63 def @arg08 253 23 0 Y 128 31 63 def @arg09 253 23 0 Y 128 31 63 def @arg10 253 23 0 Y 128 31 63 -def @arg11 253 67 0 Y 128 30 63 -def @arg12 253 67 0 Y 128 30 63 +def @arg11 253 83 0 Y 128 30 63 +def @arg12 253 83 0 Y 128 30 63 def @arg13 253 8192 0 Y 128 31 63 def @arg14 253 8192 0 Y 128 31 63 def @arg15 253 8192 19 Y 128 31 63 From 84966af9fc33a4cfa72f24a57da170db28f1c55a Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 21 May 2007 10:27:33 +0200 Subject: [PATCH 04/15] bug#23856 --- mysql-test/r/func_gconcat.result | 47 ++++++++++++++++++++++++++++++++ mysql-test/t/func_gconcat.test | 32 ++++++++++++++++++++++ sql/field.h | 5 ++++ sql/field_conv.cc | 14 ++++++++++ sql/item_sum.cc | 14 +++++++--- sql/sql_select.cc | 5 ++-- 6 files changed, 111 insertions(+), 6 deletions(-) diff --git a/mysql-test/r/func_gconcat.result b/mysql-test/r/func_gconcat.result index 71419b5b2c3..0f41db3fa84 100644 --- a/mysql-test/r/func_gconcat.result +++ b/mysql-test/r/func_gconcat.result @@ -737,4 +737,51 @@ SELECT GROUP_CONCAT(DISTINCT UCASE(b)) FROM t1; GROUP_CONCAT(DISTINCT UCASE(b)) ONE.1,TWO.2,ONE.3 DROP TABLE t1; +SET group_concat_max_len= 65535; +CREATE TABLE t1( a TEXT, b INTEGER ); +INSERT INTO t1 VALUES ( 'a', 0 ), ( 'b', 1 ); +SELECT GROUP_CONCAT( a ORDER BY b ) FROM t1; +GROUP_CONCAT( a ORDER BY b ) +a,b +SELECT GROUP_CONCAT(DISTINCT a ORDER BY b) FROM t1; +GROUP_CONCAT(DISTINCT a ORDER BY b) +a,b +SELECT GROUP_CONCAT(DISTINCT a) FROM t1; +GROUP_CONCAT(DISTINCT a) +a,b +SET group_concat_max_len= 10; +SELECT GROUP_CONCAT(a ORDER BY b) FROM t1; +GROUP_CONCAT(a ORDER BY b) +a,b +SELECT GROUP_CONCAT(DISTINCT a ORDER BY b) FROM t1; +GROUP_CONCAT(DISTINCT a ORDER BY b) +a,b +SELECT GROUP_CONCAT(DISTINCT a) FROM t1; +GROUP_CONCAT(DISTINCT a) +a,b +SET group_concat_max_len= 65535; +CREATE TABLE t2( a TEXT ); +INSERT INTO t2 VALUES( REPEAT( 'a', 5000 ) ); +INSERT INTO t2 VALUES( REPEAT( 'b', 5000 ) ); +INSERT INTO t2 VALUES( REPEAT( 'a', 5000 ) ); +SELECT LENGTH( GROUP_CONCAT( DISTINCT a ) ) FROM t2; +LENGTH( GROUP_CONCAT( DISTINCT a ) ) +10001 +CREATE TABLE t3( a TEXT, b INT ); +INSERT INTO t3 VALUES( REPEAT( 'a', 65534 ), 1 ); +INSERT INTO t3 VALUES( REPEAT( 'a', 65535 ), 2 ); +INSERT INTO t3 VALUES( REPEAT( 'a', 65536 ), 3 ); +Warnings: +Warning 1265 Data truncated for column 'a' at row 1 +SELECT LENGTH( GROUP_CONCAT( a ) ) FROM t3 WHERE b = 1; +LENGTH( GROUP_CONCAT( a ) ) +65534 +SELECT LENGTH( GROUP_CONCAT( a ) ) FROM t3 WHERE b = 2; +LENGTH( GROUP_CONCAT( a ) ) +65535 +SELECT LENGTH( GROUP_CONCAT( a ) ) FROM t3 WHERE b = 3; +LENGTH( GROUP_CONCAT( a ) ) +65535 +SET group_concat_max_len= DEFAULT; +DROP TABLE t1, t2, t3; End of 5.0 tests diff --git a/mysql-test/t/func_gconcat.test b/mysql-test/t/func_gconcat.test index 0dd82864520..983797f9c4d 100644 --- a/mysql-test/t/func_gconcat.test +++ b/mysql-test/t/func_gconcat.test @@ -507,4 +507,36 @@ SELECT GROUP_CONCAT(DISTINCT UCASE(a)) FROM t1; SELECT GROUP_CONCAT(DISTINCT UCASE(b)) FROM t1; DROP TABLE t1; +# +# Bug #23856:GROUP_CONCAT and ORDER BY: junk from previous rows for query on I_S +# +SET group_concat_max_len= 65535; +CREATE TABLE t1( a TEXT, b INTEGER ); +INSERT INTO t1 VALUES ( 'a', 0 ), ( 'b', 1 ); +SELECT GROUP_CONCAT( a ORDER BY b ) FROM t1; +SELECT GROUP_CONCAT(DISTINCT a ORDER BY b) FROM t1; +SELECT GROUP_CONCAT(DISTINCT a) FROM t1; +SET group_concat_max_len= 10; +SELECT GROUP_CONCAT(a ORDER BY b) FROM t1; +SELECT GROUP_CONCAT(DISTINCT a ORDER BY b) FROM t1; +SELECT GROUP_CONCAT(DISTINCT a) FROM t1; + +SET group_concat_max_len= 65535; +CREATE TABLE t2( a TEXT ); +INSERT INTO t2 VALUES( REPEAT( 'a', 5000 ) ); +INSERT INTO t2 VALUES( REPEAT( 'b', 5000 ) ); +INSERT INTO t2 VALUES( REPEAT( 'a', 5000 ) ); +SELECT LENGTH( GROUP_CONCAT( DISTINCT a ) ) FROM t2; + +CREATE TABLE t3( a TEXT, b INT ); +INSERT INTO t3 VALUES( REPEAT( 'a', 65534 ), 1 ); +INSERT INTO t3 VALUES( REPEAT( 'a', 65535 ), 2 ); +INSERT INTO t3 VALUES( REPEAT( 'a', 65536 ), 3 ); +SELECT LENGTH( GROUP_CONCAT( a ) ) FROM t3 WHERE b = 1; +SELECT LENGTH( GROUP_CONCAT( a ) ) FROM t3 WHERE b = 2; +SELECT LENGTH( GROUP_CONCAT( a ) ) FROM t3 WHERE b = 3; + +SET group_concat_max_len= DEFAULT; +DROP TABLE t1, t2, t3; + --echo End of 5.0 tests diff --git a/sql/field.h b/sql/field.h index 47f61c1fe8b..94c5d94def4 100644 --- a/sql/field.h +++ b/sql/field.h @@ -1108,6 +1108,11 @@ public: class Field_varstring :public Field_longstr { public: + /* + The maximum space available in a Field_varstring, in bytes. See + length_bytes. + */ + static const int MAX_SIZE= UINT_MAX16; /* Store number of bytes used to store length (1 or 2) */ uint32 length_bytes; Field_varstring(char *ptr_arg, diff --git a/sql/field_conv.cc b/sql/field_conv.cc index 5670b1e0676..5c74ea9e49f 100644 --- a/sql/field_conv.cc +++ b/sql/field_conv.cc @@ -530,7 +530,21 @@ void Copy_field::set(char *to,Field *from) } +/* + To do: + If 'save\ is set to true and the 'from' is a blob field, do_copy is set to + do_save_blob rather than do_conv_blob. The only differences between them + appears to be: + + - do_save_blob allocates and uses an intermediate buffer before calling + Field_blob::store. Is this in order to trigger the call to + well_formed_copy_nchars, by changing the pointer copy->tmp.ptr()? + That call will take place anyway in all known cases. + + - The above causes a truncation to MAX_FIELD_WIDTH. Is this the intended + effect? Truncation is handled by well_formed_copy_nchars anyway. + */ void Copy_field::set(Field *to,Field *from,bool save) { if (to->type() == FIELD_TYPE_NULL) diff --git a/sql/item_sum.cc b/sql/item_sum.cc index 4579ecd48ae..443b3782d6b 100644 --- a/sql/item_sum.cc +++ b/sql/item_sum.cc @@ -432,7 +432,7 @@ Field *Item_sum::create_tmp_field(bool group, TABLE *table, 2-byte lenght. */ if (max_length/collation.collation->mbmaxlen > 255 && - convert_blob_length < UINT_MAX16 && convert_blob_length) + convert_blob_length <= Field_varstring::MAX_SIZE && convert_blob_length) return new Field_varstring(convert_blob_length, maybe_null, name, table, collation.collation); @@ -3268,15 +3268,21 @@ bool Item_func_group_concat::setup(THD *thd) count_field_types(tmp_table_param,all_fields,0); tmp_table_param->force_copy_fields= force_copy_fields; DBUG_ASSERT(table == 0); + /* + Currently we have to force conversion of BLOB values to VARCHAR's + if we are to store them in TREE objects used for ORDER BY and + DISTINCT. This leads to truncation if the BLOB's size exceeds + Field_varstring::MAX_SIZE. + */ + if (arg_count_order > 0 || distinct) + set_if_smaller(tmp_table_param->convert_blob_length, + Field_varstring::MAX_SIZE); /* We have to create a temporary table to get descriptions of fields (types, sizes and so on). Note that in the table, we first have the ORDER BY fields, then the field list. - - We need to set set_sum_field in true for storing value of blob in buffer - of a record instead of a pointer of one. */ if (!(table= create_tmp_table(thd, tmp_table_param, all_fields, (ORDER*) 0, 0, TRUE, diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 967322600a7..1d8e10ed84b 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -8794,7 +8794,7 @@ Field* create_tmp_field_from_field(THD *thd, Field* org_field, Make sure that the blob fits into a Field_varstring which has 2-byte lenght. */ - if (convert_blob_length && convert_blob_length < UINT_MAX16 && + if (convert_blob_length && convert_blob_length <= Field_varstring::MAX_SIZE && (org_field->flags & BLOB_FLAG)) new_field= new Field_varstring(convert_blob_length, org_field->maybe_null(), @@ -8885,7 +8885,8 @@ static Field *create_tmp_field_from_item(THD *thd, Item *item, TABLE *table, 2-byte lenght. */ else if (item->max_length/item->collation.collation->mbmaxlen > 255 && - convert_blob_length < UINT_MAX16 && convert_blob_length) + convert_blob_length <= Field_varstring::MAX_SIZE && + convert_blob_length) new_field= new Field_varstring(convert_blob_length, maybe_null, item->name, table, item->collation.collation); From 786adf870b13695b9db5c12283dc475201f3e0e4 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 21 May 2007 17:53:55 +0500 Subject: [PATCH 05/15] test result fixed --- mysql-test/r/ps_6bdb.result | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/mysql-test/r/ps_6bdb.result b/mysql-test/r/ps_6bdb.result index 407dddb6f53..6f6ecbb20b8 100644 --- a/mysql-test/r/ps_6bdb.result +++ b/mysql-test/r/ps_6bdb.result @@ -1910,8 +1910,8 @@ def @arg07 253 23 1 Y 128 31 63 def @arg08 253 23 1 Y 128 31 63 def @arg09 253 23 1 Y 128 31 63 def @arg10 253 23 1 Y 128 31 63 -def @arg11 253 67 6 Y 128 30 63 -def @arg12 253 67 6 Y 128 30 63 +def @arg11 253 83 6 Y 128 30 63 +def @arg12 253 83 6 Y 128 30 63 def @arg13 253 8192 10 Y 128 31 63 def @arg14 253 8192 19 Y 128 31 63 def @arg15 253 8192 19 Y 128 31 63 @@ -1957,8 +1957,8 @@ def @arg07 253 23 0 Y 128 31 63 def @arg08 253 23 0 Y 128 31 63 def @arg09 253 23 0 Y 128 31 63 def @arg10 253 23 0 Y 128 31 63 -def @arg11 253 67 0 Y 128 30 63 -def @arg12 253 67 0 Y 128 30 63 +def @arg11 253 83 0 Y 128 30 63 +def @arg12 253 83 0 Y 128 30 63 def @arg13 253 8192 0 Y 128 31 63 def @arg14 253 8192 0 Y 128 31 63 def @arg15 253 8192 19 Y 128 31 63 @@ -2007,8 +2007,8 @@ def @arg07 253 23 1 Y 128 31 63 def @arg08 253 23 1 Y 128 31 63 def @arg09 253 23 1 Y 128 31 63 def @arg10 253 23 1 Y 128 31 63 -def @arg11 253 67 6 Y 128 30 63 -def @arg12 253 67 6 Y 128 30 63 +def @arg11 253 83 6 Y 128 30 63 +def @arg12 253 83 6 Y 128 30 63 def @arg13 253 8192 10 Y 128 31 63 def @arg14 253 8192 19 Y 128 31 63 def @arg15 253 8192 19 Y 128 31 63 @@ -2047,8 +2047,8 @@ def @arg07 253 23 0 Y 128 31 63 def @arg08 253 23 0 Y 128 31 63 def @arg09 253 23 0 Y 128 31 63 def @arg10 253 23 0 Y 128 31 63 -def @arg11 253 67 0 Y 128 30 63 -def @arg12 253 67 0 Y 128 30 63 +def @arg11 253 83 0 Y 128 30 63 +def @arg12 253 83 0 Y 128 30 63 def @arg13 253 8192 0 Y 128 31 63 def @arg14 253 8192 0 Y 128 31 63 def @arg15 253 8192 19 Y 128 31 63 @@ -2095,8 +2095,8 @@ def @arg07 253 23 1 Y 128 31 63 def @arg08 253 23 1 Y 128 31 63 def @arg09 253 23 1 Y 128 31 63 def @arg10 253 23 1 Y 128 31 63 -def @arg11 253 67 6 Y 128 30 63 -def @arg12 253 67 6 Y 128 30 63 +def @arg11 253 83 6 Y 128 30 63 +def @arg12 253 83 6 Y 128 30 63 def @arg13 253 8192 10 Y 128 31 63 def @arg14 253 8192 19 Y 128 31 63 def @arg15 253 8192 19 Y 128 31 63 @@ -2139,8 +2139,8 @@ def @arg07 253 23 0 Y 128 31 63 def @arg08 253 23 0 Y 128 31 63 def @arg09 253 23 0 Y 128 31 63 def @arg10 253 23 0 Y 128 31 63 -def @arg11 253 67 0 Y 128 30 63 -def @arg12 253 67 0 Y 128 30 63 +def @arg11 253 83 0 Y 128 30 63 +def @arg12 253 83 0 Y 128 30 63 def @arg13 253 8192 0 Y 128 31 63 def @arg14 253 8192 0 Y 128 31 63 def @arg15 253 8192 19 Y 128 31 63 @@ -2185,8 +2185,8 @@ def @arg07 253 23 1 Y 128 31 63 def @arg08 253 23 1 Y 128 31 63 def @arg09 253 23 1 Y 128 31 63 def @arg10 253 23 1 Y 128 31 63 -def @arg11 253 67 6 Y 128 30 63 -def @arg12 253 67 6 Y 128 30 63 +def @arg11 253 83 6 Y 128 30 63 +def @arg12 253 83 6 Y 128 30 63 def @arg13 253 8192 10 Y 128 31 63 def @arg14 253 8192 19 Y 128 31 63 def @arg15 253 8192 19 Y 128 31 63 @@ -2223,8 +2223,8 @@ def @arg07 253 23 0 Y 128 31 63 def @arg08 253 23 0 Y 128 31 63 def @arg09 253 23 0 Y 128 31 63 def @arg10 253 23 0 Y 128 31 63 -def @arg11 253 67 0 Y 128 30 63 -def @arg12 253 67 0 Y 128 30 63 +def @arg11 253 83 0 Y 128 30 63 +def @arg12 253 83 0 Y 128 30 63 def @arg13 253 8192 0 Y 128 31 63 def @arg14 253 8192 0 Y 128 31 63 def @arg15 253 8192 19 Y 128 31 63 From cfb9378b3d7a1041752f0e2099494ec20d970baf Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 21 May 2007 22:22:47 +0500 Subject: [PATCH 06/15] Bug #27984 Long Decimal Maths produces truncated results. decimal_round failed to perform a correct rounding of a decimal number if its first nine digits were '9'. It just sets those digits to 0. mysql-test/r/type_newdecimal.result: Bug #27984 Long Decimal Maths produces truncated results. test result mysql-test/t/type_newdecimal.test: Bug #27984 Long Decimal Maths produces truncated results. test case strings/decimal.c: Bug #27984 Long Decimal Maths produces truncated results. when to == from we break the data if we do to->buf[0]=0 So now doing this after the data is moved and only if we really need to set to->buf[0] to zero --- mysql-test/r/type_newdecimal.result | 3 +++ mysql-test/t/type_newdecimal.test | 5 +++++ strings/decimal.c | 3 ++- 3 files changed, 10 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/type_newdecimal.result b/mysql-test/r/type_newdecimal.result index cbcab126439..92a5e4fc39c 100644 --- a/mysql-test/r/type_newdecimal.result +++ b/mysql-test/r/type_newdecimal.result @@ -1465,4 +1465,7 @@ Error 1264 Out of range value adjusted for column 'cast(a as DECIMAL(3,2))' at r Error 1264 Out of range value adjusted for column 'cast(a as DECIMAL(3,2))' at row 1 Error 1264 Out of range value adjusted for column 'cast(a as DECIMAL(3,2))' at row 1 Error 1264 Out of range value adjusted for column 'cast(a as DECIMAL(3,2))' at row 1 +SELECT 1.000000000000 * 99.999999999998 / 100 a,1.000000000000 * (99.999999999998 / 100) b; +a b +0.9999999999999800000000000000 0.9999999999999800000000000000 End of 5.0 tests diff --git a/mysql-test/t/type_newdecimal.test b/mysql-test/t/type_newdecimal.test index a7906be79d4..3a62db1bfd7 100644 --- a/mysql-test/t/type_newdecimal.test +++ b/mysql-test/t/type_newdecimal.test @@ -1149,4 +1149,9 @@ select cast(a as DECIMAL(3,2)), count(*) UNION select 12.1234 ) t group by 1; +# +# Bug #27984 Long Decimal Maths produces truncated results +# + +SELECT 1.000000000000 * 99.999999999998 / 100 a,1.000000000000 * (99.999999999998 / 100) b; --echo End of 5.0 tests diff --git a/strings/decimal.c b/strings/decimal.c index 1ae75167794..f1f02f3a071 100644 --- a/strings/decimal.c +++ b/strings/decimal.c @@ -1517,9 +1517,10 @@ decimal_round(decimal_t *from, decimal_t *to, int scale, dec1 *p0= buf0+intg0+max(frac1, frac0); dec1 *p1= buf1+intg1+max(frac1, frac0); - to->buf[0]= 0; while (buf0 < p0) *(--p1) = *(--p0); + if (unlikely(intg1 > intg0)) + to->buf[0]= 0; intg0= intg1; buf0=to->buf; From f3b78f34e511305fec193f4cdbc8710f26baf993 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 22 May 2007 00:22:53 +0400 Subject: [PATCH 07/15] Bug#27507: Wrong DATETIME value was allowed by ALTER TABLE in the NO_ZERO_DATE mode. When a new DATE/DATETIME field without default value is being added by the ALTER TABLE the '0000-00-00' value is used as the default one. But it wasn't checked whether such value was allowed by the set sql mode. Due to this '0000-00-00' values was allowed for DATE/DATETIME fields even in the NO_ZERO_DATE mode. Now the mysql_alter_table() function checks whether the '0000-00-00' value is allowed for DATE/DATETIME fields by the set sql mode. The new error_if_not_empty flag is used in the mysql_alter_table() function to indicate that it should abort if the table being altered isn't empty. The new new_datetime_field field is used in the mysql_alter_table() function for error throwing purposes. The new error_if_not_empty parameter is added to the copy_data_between_tables() function to indicate the it should return error if the source table isn't empty. mysql-test/t/alter_table.test: Added a test case for the bug#27507: Wrong DATETIME value was allowed by ALTER TABLE in the NO_ZERO_DATE mode. mysql-test/r/alter_table.result: Added a test case for the bug#27507: Wrong DATETIME value was allowed by ALTER TABLE in the NO_ZERO_DATE mode. sql/sql_table.cc: Bug#27507: Wrong DATETIME value was allowed by ALTER TABLE in the NO_ZERO_DATE mode. Now the mysql_alter_table() function checks whether the '0000-00-00' value is allowed for DATE/DATETIME fields by the set sql mode. The new error_if_not_empty flag is used in the mysql_alter_table() function to indicate that it should abort if the table being altered isn't empty. The new new_datetime_field field is used in the mysql_alter_table() function for error throwing purposes. The new error_if_not_empty parameter is added to the copy_data_between_tables() function to indicate the it should return error if the source table isn't empty. --- mysql-test/r/alter_table.result | 19 +++++++++ mysql-test/t/alter_table.test | 22 ++++++++++ sql/sql_table.cc | 72 +++++++++++++++++++++++++++++++-- 3 files changed, 110 insertions(+), 3 deletions(-) diff --git a/mysql-test/r/alter_table.result b/mysql-test/r/alter_table.result index 280cedb8b89..4eace9ac628 100644 --- a/mysql-test/r/alter_table.result +++ b/mysql-test/r/alter_table.result @@ -884,3 +884,22 @@ id 50 51 drop table t1; +set @orig_sql_mode = @@sql_mode; +set sql_mode="no_zero_date"; +create table t1(f1 int); +alter table t1 add column f2 datetime not null, add column f21 date not null; +insert into t1 values(1,'2000-01-01','2000-01-01'); +alter table t1 add column f3 datetime not null; +ERROR 22007: Incorrect datetime value: '0000-00-00 00:00:00' for column 'f3' at row 1 +alter table t1 add column f3 date not null; +ERROR 22007: Incorrect date value: '0000-00-00' for column 'f3' at row 1 +alter table t1 add column f4 datetime not null default '2002-02-02', +add column f41 date not null; +ERROR 22007: Incorrect date value: '0000-00-00' for column 'f41' at row 1 +alter table t1 add column f4 datetime not null default '2002-02-02', +add column f41 date not null default '2002-02-02'; +select * from t1; +f1 f2 f21 f4 f41 +1 2000-01-01 00:00:00 2000-01-01 2002-02-02 00:00:00 2002-02-02 +drop table t1; +set sql_mode= @orig_sql_mode; diff --git a/mysql-test/t/alter_table.test b/mysql-test/t/alter_table.test index 83686f31e9e..3ced1087757 100644 --- a/mysql-test/t/alter_table.test +++ b/mysql-test/t/alter_table.test @@ -662,3 +662,25 @@ insert into t1 values (null); select * from t1; drop table t1; + +# +# Bug#27507: Wrong DATETIME value was allowed by ALTER TABLE in the +# NO_ZERO_DATE mode. +# +set @orig_sql_mode = @@sql_mode; +set sql_mode="no_zero_date"; +create table t1(f1 int); +alter table t1 add column f2 datetime not null, add column f21 date not null; +insert into t1 values(1,'2000-01-01','2000-01-01'); +--error 1292 +alter table t1 add column f3 datetime not null; +--error 1292 +alter table t1 add column f3 date not null; +--error 1292 +alter table t1 add column f4 datetime not null default '2002-02-02', + add column f41 date not null; +alter table t1 add column f4 datetime not null default '2002-02-02', + add column f41 date not null default '2002-02-02'; +select * from t1; +drop table t1; +set sql_mode= @orig_sql_mode; diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 079cc0d6456..ed1c49d768a 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -37,7 +37,8 @@ static int copy_data_between_tables(TABLE *from,TABLE *to, List &create, bool ignore, uint order_num, ORDER *order, ha_rows *copied,ha_rows *deleted, - enum enum_enable_or_disable keys_onoff); + enum enum_enable_or_disable keys_onoff, + bool error_if_not_empty); static bool prepare_blob_field(THD *thd, create_field *sql_field); static bool check_engine(THD *thd, const char *table_name, @@ -3077,6 +3078,16 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name, bool need_copy_table; bool no_table_reopen= FALSE, varchar= FALSE; frm_type_enum frm_type; + /* + Throw an error if the table to be altered isn't empty. + Used in DATE/DATETIME fields default value checking. + */ + bool error_if_not_empty= FALSE; + /* + A field used for error reporting in DATE/DATETIME fields default + value checking. + */ + create_field *new_datetime_field= 0; DBUG_ENTER("mysql_alter_table"); thd->proc_info="init"; @@ -3445,6 +3456,22 @@ view_err: my_error(ER_BAD_FIELD_ERROR, MYF(0), def->change, table_name); DBUG_RETURN(TRUE); } + /* + Check that the DATE/DATETIME not null field we are going to add is + either has a default value or the '0000-00-00' is allowed by the + set sql mode. + If the '0000-00-00' value isn't allowed then raise the error_if_not_empty + flag to allow ALTER TABLE only if the table to be altered is empty. + */ + if ((def->sql_type == MYSQL_TYPE_DATE || + def->sql_type == MYSQL_TYPE_NEWDATE || + def->sql_type == MYSQL_TYPE_DATETIME) && !new_datetime_field && + !(~def->flags & (NO_DEFAULT_VALUE_FLAG | NOT_NULL_FLAG)) && + thd->variables.sql_mode & MODE_NO_ZERO_DATE) + { + new_datetime_field= def; + error_if_not_empty= TRUE; + } if (!def->after) new_info.create_list.push_back(def); else if (def->after == first_keyword) @@ -3765,7 +3792,8 @@ view_err: new_table->next_number_field=new_table->found_next_number_field; error= copy_data_between_tables(table, new_table, new_info.create_list, ignore, order_num, order, - &copied, &deleted, alter_info->keys_onoff); + &copied, &deleted, alter_info->keys_onoff, + error_if_not_empty); } else if (!new_table) { @@ -3999,6 +4027,37 @@ end_temporary: DBUG_RETURN(FALSE); err: + /* + No default value was provided for a DATE/DATETIME field, the + current sql_mode doesn't allow the '0000-00-00' value and + the table to be altered isn't empty. + Report error here. + */ + if (error_if_not_empty && thd->row_count) + { + const char *f_val; + enum enum_mysql_timestamp_type t_type; + switch (new_datetime_field->sql_type) + { + case MYSQL_TYPE_DATE: + case MYSQL_TYPE_NEWDATE: + f_val= "0000-00-00"; + t_type= MYSQL_TIMESTAMP_DATE; + break; + case MYSQL_TYPE_DATETIME: + f_val= "0000-00-00 00:00:00"; + t_type= MYSQL_TIMESTAMP_DATETIME; + break; + default: + /* Shouldn't get here. */ + DBUG_ASSERT(0); + } + bool save_abort_on_warning= thd->abort_on_warning; + thd->abort_on_warning= TRUE; + make_truncated_value_warning(thd, f_val, strlength(f_val), t_type, + new_datetime_field->field_name); + thd->abort_on_warning= save_abort_on_warning; + } DBUG_RETURN(TRUE); } @@ -4010,7 +4069,8 @@ copy_data_between_tables(TABLE *from,TABLE *to, uint order_num, ORDER *order, ha_rows *copied, ha_rows *deleted, - enum enum_enable_or_disable keys_onoff) + enum enum_enable_or_disable keys_onoff, + bool error_if_not_empty) { int error; Copy_field *copy,*copy_end; @@ -4125,6 +4185,12 @@ copy_data_between_tables(TABLE *from,TABLE *to, break; } thd->row_count++; + /* Return error if source table isn't empty. */ + if (error_if_not_empty) + { + error= 1; + break; + } if (to->next_number_field) { if (auto_increment_field_copied) From 14cb59d8bb0531cec3955fb3718455e7742d5db8 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 21 May 2007 16:44:36 -0700 Subject: [PATCH 08/15] Added initializations to avoid compiler warnings. --- sql/sql_table.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sql/sql_table.cc b/sql/sql_table.cc index ed1c49d768a..a8ed2a53601 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -4035,8 +4035,8 @@ err: */ if (error_if_not_empty && thd->row_count) { - const char *f_val; - enum enum_mysql_timestamp_type t_type; + const char *f_val= 0; + enum enum_mysql_timestamp_type t_type= MYSQL_TIMESTAMP_DATE; switch (new_datetime_field->sql_type) { case MYSQL_TYPE_DATE: From 3332b80130172656c1e483e5bc9aa2bcfe741a8f Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 22 May 2007 15:58:30 +0300 Subject: [PATCH 09/15] Bug #28476: force index on a disabled myisam index gives error 124 When processing the USE/FORCE index hints the optimizer was not checking if the indexes specified are enabled (see ALTER TABLE). Fixed by: Backporting the fix for bug 20604 to 5.0 mysql-test/r/key.result: Test for BUG 20604. The important part of the test is the explain output that tests what indexes are used. mysql-test/r/myisam.result: Bug #28476: test cases mysql-test/t/key.test: Bug 20604: The minimal test case that reveals the bug. The optimizer for aggregates relies on keys disabled with ALTER TABLE ... DISABLE KEYS not being in the set TABLE::keys_in_use_for_query. When the execution engine tries to use a disabled index, MyISAM returns an error. mysql-test/t/myisam.test: Bug #28476: test cases sql/sql_base.cc: Bug #28476: - Ignore disabled indexes in USE/FORCE index sql/sql_select.cc: Bug 20604 : The intersection operation between table->s->keys_in_use and table->keys_in_use_for_query is no longer necessary. We can trust that the latter is a subset of the former. sql/table.h: Bug 20604: Added comments to TABLE_SHARE::keys_in_use and TABLE::keys_in_use_for_query. --- mysql-test/r/key.result | 8 ++++++++ mysql-test/r/myisam.result | 26 ++++++++++++++++++++++++++ mysql-test/t/key.test | 12 ++++++++++++ mysql-test/t/myisam.test | 16 ++++++++++++++++ sql/sql_base.cc | 7 ++++++- sql/sql_select.cc | 7 ++++--- sql/table.h | 23 +++++++++++++++++++++-- 7 files changed, 93 insertions(+), 6 deletions(-) diff --git a/mysql-test/r/key.result b/mysql-test/r/key.result index ec15eaa97f5..3abc95ec3bf 100644 --- a/mysql-test/r/key.result +++ b/mysql-test/r/key.result @@ -455,3 +455,11 @@ ORDER BY c.b, c.d a b c d e f g h i j a b c d 2 2 1 2004-11-30 12:00:00 1 0 0 0 0 0 2 3388000 -553000 NULL DROP TABLE t1, t2; +CREATE TABLE t1( a TINYINT, KEY(a) ) ENGINE=MyISAM; +INSERT INTO t1 VALUES( 1 ); +ALTER TABLE t1 DISABLE KEYS; +EXPLAIN SELECT MAX(a) FROM t1 FORCE INDEX(a); +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 system NULL NULL NULL NULL 1 +DROP TABLE t1; +End of 5.0 tests. diff --git a/mysql-test/r/myisam.result b/mysql-test/r/myisam.result index 94f2f1f72b3..7fc29cd13ca 100644 --- a/mysql-test/r/myisam.result +++ b/mysql-test/r/myisam.result @@ -1780,4 +1780,30 @@ create table t3 (c1 int) engine=myisam pack_keys=default; create table t4 (c1 int) engine=myisam pack_keys=2; ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '2' at line 1 drop table t1, t2, t3; +CREATE TABLE t1(a INT, b INT, KEY inx (a), UNIQUE KEY uinx (b)) ENGINE=MyISAM; +INSERT INTO t1(a,b) VALUES (1,1),(2,2),(3,3),(4,4),(5,5); +SELECT a FROM t1 FORCE INDEX (inx) WHERE a=1; +a +1 +ALTER TABLE t1 DISABLE KEYS; +SELECT a FROM t1 FORCE INDEX (inx) WHERE a=1; +a +1 +SELECT a FROM t1 USE INDEX (inx) WHERE a=1; +a +1 +SELECT b FROM t1 FORCE INDEX (uinx) WHERE b=1; +b +1 +SELECT b FROM t1 USE INDEX (uinx) WHERE b=1; +b +1 +SELECT a FROM t1 FORCE INDEX (inx,uinx) WHERE a=1; +a +1 +ALTER TABLE t1 ENABLE KEYS; +SELECT a FROM t1 FORCE INDEX (inx) WHERE a=1; +a +1 +DROP TABLE t1; End of 5.0 tests diff --git a/mysql-test/t/key.test b/mysql-test/t/key.test index e84b2071ab1..3d0e68dc0f3 100644 --- a/mysql-test/t/key.test +++ b/mysql-test/t/key.test @@ -432,3 +432,15 @@ ORDER BY c.b, c.d ; DROP TABLE t1, t2; + + +# +# Bug #20604: Test for disabled keys with aggregate functions and FORCE INDEX. +# +CREATE TABLE t1( a TINYINT, KEY(a) ) ENGINE=MyISAM; +INSERT INTO t1 VALUES( 1 ); +ALTER TABLE t1 DISABLE KEYS; +EXPLAIN SELECT MAX(a) FROM t1 FORCE INDEX(a); +DROP TABLE t1; + +--echo End of 5.0 tests. diff --git a/mysql-test/t/myisam.test b/mysql-test/t/myisam.test index 82d10059c65..12b9423be21 100644 --- a/mysql-test/t/myisam.test +++ b/mysql-test/t/myisam.test @@ -1145,4 +1145,20 @@ create table t3 (c1 int) engine=myisam pack_keys=default; create table t4 (c1 int) engine=myisam pack_keys=2; drop table t1, t2, t3; +# +# Bug#28476: force index on a disabled myisam index gives error 124 +# +CREATE TABLE t1(a INT, b INT, KEY inx (a), UNIQUE KEY uinx (b)) ENGINE=MyISAM; +INSERT INTO t1(a,b) VALUES (1,1),(2,2),(3,3),(4,4),(5,5); +SELECT a FROM t1 FORCE INDEX (inx) WHERE a=1; +ALTER TABLE t1 DISABLE KEYS; +SELECT a FROM t1 FORCE INDEX (inx) WHERE a=1; +SELECT a FROM t1 USE INDEX (inx) WHERE a=1; +SELECT b FROM t1 FORCE INDEX (uinx) WHERE b=1; +SELECT b FROM t1 USE INDEX (uinx) WHERE b=1; +SELECT a FROM t1 FORCE INDEX (inx,uinx) WHERE a=1; +ALTER TABLE t1 ENABLE KEYS; +SELECT a FROM t1 FORCE INDEX (inx) WHERE a=1; +DROP TABLE t1; + --echo End of 5.0 tests diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 6e6611d54d2..59532b9fe96 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -4811,7 +4811,12 @@ bool setup_tables(THD *thd, Name_resolution_context *context, get_key_map_from_key_list(&map, table, table_list->use_index); if (map.is_set_all()) DBUG_RETURN(1); - table->keys_in_use_for_query=map; + /* + Don't introduce keys in keys_in_use_for_query that weren't there + before. FORCE/USE INDEX should not add keys, it should only remove + all keys except the key(s) specified in the hint. + */ + table->keys_in_use_for_query.intersect(map); } if (table_list->ignore_index) { diff --git a/sql/sql_select.cc b/sql/sql_select.cc index ea59cbbe9f2..607bbdc6cd6 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -12246,10 +12246,11 @@ test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,ha_rows select_limit, LINT_INIT(ref_key_parts); /* - Check which keys can be used to resolve ORDER BY. - We must not try to use disabled keys. + Keys disabled by ALTER TABLE ... DISABLE KEYS should have already + been taken into account. */ - usable_keys= table->s->keys_in_use; + usable_keys= table->keys_in_use_for_query; + DBUG_ASSERT(usable_keys.is_subset(table->s->keys_in_use)); for (ORDER *tmp_order=order; tmp_order ; tmp_order=tmp_order->next) { diff --git a/sql/table.h b/sql/table.h index 61232a39f0e..ebcafbd4dc7 100644 --- a/sql/table.h +++ b/sql/table.h @@ -137,7 +137,12 @@ typedef struct st_table_share const char *table_name; /* Table name (for open) */ const char *path; /* Path to .frm file (from datadir) */ LEX_STRING connect_string; - key_map keys_in_use; /* Keys in use for table */ + + /* + Set of keys in use, implemented as a Bitmap. + Excludes keys disabled by ALTER TABLE ... DISABLE KEYS. + */ + key_map keys_in_use; key_map keys_for_keyread; ulong avg_row_length; /* create information */ ulong raid_chunksize; @@ -206,7 +211,21 @@ struct st_table { byte *record[2]; /* Pointer to records */ byte *insert_values; /* used by INSERT ... UPDATE */ - key_map quick_keys, used_keys, keys_in_use_for_query; + key_map quick_keys, used_keys; + + /* + A set of keys that can be used in the query that references this + table + + All indexes disabled on the table's TABLE_SHARE (see TABLE::s) will be + subtracted from this set upon instantiation. Thus for any TABLE t it holds + that t.keys_in_use_for_query is a subset of t.s.keys_in_use. Generally we + must not introduce any new keys here (see setup_tables). + + The set is implemented as a bitmap. + */ + key_map keys_in_use_for_query; + key_map merge_keys; KEY *key_info; /* data of keys in database */ Field *next_number_field, /* Set if next_number is activated */ From 1734b4e99068a135c0b7d49f8bb3b463b3cb0ef3 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 23 May 2007 23:24:16 +0400 Subject: [PATCH 10/15] Bug#27563: Stored functions and triggers wasn't throwing an error when killed. If a stored function or a trigger was killed it had aborted but no error was thrown. This allows the caller statement to continue without a notice. This may lead to a wrong data being inserted/updated to/deleted as in such cases the correct result of a stored function isn't guaranteed. In the case of triggers it allows the caller statement to ignore kill signal and to waste time because of re-evaluation of triggers that always will fail because thd->killed flag is still on. Now the Item_func_sp::execute() and the sp_head::execute_trigger() functions check whether a function or a trigger were killed during execution and throws an appropriate error if so. Now the fill_record() function stops filling record if an error was reported through thd->net.report_error. sql/item_func.cc: Bug#27563: Stored functions and triggers wasn't throwing an error when killed. Now the Item_func_sp::execute() function checks whether a trigger was killed during execution and throws an appropriate error if so. sql/sp_head.cc: Bug#27563: Stored functions and triggers wasn't throwing an error when killed. Now the sp_head::execute_trigger() function checks whether a function was killed during execution and throws an appropriate error if so. sql/sql_base.cc: Bug#27563: Stored functions and triggers wasn't throwing an error when killed. Now the fill_record() function stops filling record if an error was reported through thd->net.report_error. mysql-test/r/kill.result: Added a test case for the bug#27563: Stored functions and triggers wasn't throwing an error when killed. mysql-test/t/kill.test: Added a test case for the bug#27563: Stored functions and triggers wasn't throwing an error when killed. --- mysql-test/r/kill.result | 82 ++++++++++++++++++++++++ mysql-test/t/kill.test | 132 +++++++++++++++++++++++++++++++++++++++ sql/item_func.cc | 2 + sql/sp_head.cc | 3 + sql/sql_base.cc | 2 +- 5 files changed, 220 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/kill.result b/mysql-test/r/kill.result index cf5486d1091..4bc04c6de3c 100644 --- a/mysql-test/r/kill.result +++ b/mysql-test/r/kill.result @@ -41,3 +41,85 @@ select 1; select RELEASE_LOCK("a"); RELEASE_LOCK("a") 1 +create table t1(f1 int); +create function bug27563() returns int(11) +deterministic +begin +declare continue handler for sqlstate '70100' set @a:= 'killed'; +declare continue handler for sqlexception set @a:= 'exception'; +set @a= get_lock("lock27563", 10); +return 1; +end| +select get_lock("lock27563",10); +get_lock("lock27563",10) +1 +insert into t1 values (bug27563()); +ERROR 70100: Query execution was interrupted +select @a; +@a +NULL +select * from t1; +f1 +insert into t1 values(0); +update t1 set f1= bug27563(); +ERROR 70100: Query execution was interrupted +select @a; +@a +NULL +select * from t1; +f1 +0 +insert into t1 values(1); +delete from t1 where bug27563() is null; +ERROR 70100: Query execution was interrupted +select @a; +@a +NULL +select * from t1; +f1 +0 +1 +select * from t1 where f1= bug27563(); +ERROR 70100: Query execution was interrupted +select @a; +@a +NULL +create procedure proc27563() +begin +declare continue handler for sqlstate '70100' set @a:= 'killed'; +declare continue handler for sqlexception set @a:= 'exception'; +select get_lock("lock27563",10); +select "shouldn't be selected"; +end| +call proc27563(); +get_lock("lock27563",10) +NULL +ERROR 70100: Query execution was interrupted +select @a; +@a +NULL +create table t2 (f2 int); +create trigger trg27563 before insert on t1 for each row +begin +declare continue handler for sqlstate '70100' set @a:= 'killed'; +declare continue handler for sqlexception set @a:= 'exception'; +set @a:= get_lock("lock27563",10); +insert into t2 values(1); +end| +insert into t1 values(2),(3); +ERROR 70100: Query execution was interrupted +select @a; +@a +NULL +select * from t1; +f1 +0 +1 +select * from t2; +f2 +select release_lock("lock27563"); +release_lock("lock27563") +1 +drop table t1, t2; +drop function bug27563; +drop procedure proc27563; diff --git a/mysql-test/t/kill.test b/mysql-test/t/kill.test index 1e99911a7e3..83194e214fb 100644 --- a/mysql-test/t/kill.test +++ b/mysql-test/t/kill.test @@ -117,3 +117,135 @@ reap; select 1; connection con1; select RELEASE_LOCK("a"); + +# +# Bug#27563: Stored functions and triggers wasn't throwing an error when killed. +# +create table t1(f1 int); +delimiter |; +create function bug27563() returns int(11) +deterministic +begin + declare continue handler for sqlstate '70100' set @a:= 'killed'; + declare continue handler for sqlexception set @a:= 'exception'; + set @a= get_lock("lock27563", 10); + return 1; +end| +delimiter ;| +# Test stored functions +# Test INSERT +connection con1; +select get_lock("lock27563",10); +connection con2; +let $ID= `select connection_id()`; +send insert into t1 values (bug27563()); +real_sleep 2; +connection con1; +disable_query_log; +eval kill query $ID; +enable_query_log; +connection con2; +--error 1317 +reap; +select @a; +connection con1; +select * from t1; + +# Test UPDATE +insert into t1 values(0); +connection con2; +send update t1 set f1= bug27563(); +real_sleep 2; +connection con1; +disable_query_log; +eval kill query $ID; +enable_query_log; +connection con2; +--error 1317 +reap; +select @a; +connection con1; +select * from t1; + +# Test DELETE +insert into t1 values(1); +connection con2; +send delete from t1 where bug27563() is null; +real_sleep 2; +connection con1; +disable_query_log; +eval kill query $ID; +enable_query_log; +connection con2; +--error 1317 +reap; +select @a; +connection con1; +select * from t1; + +# Test SELECT +connection con2; +send select * from t1 where f1= bug27563(); +real_sleep 2; +connection con1; +disable_query_log; +eval kill query $ID; +enable_query_log; +connection con2; +--error 1317 +reap; +select @a; + +# Test PROCEDURE +connection con2; +delimiter |; +create procedure proc27563() +begin + declare continue handler for sqlstate '70100' set @a:= 'killed'; + declare continue handler for sqlexception set @a:= 'exception'; + select get_lock("lock27563",10); + select "shouldn't be selected"; +end| +delimiter ;| +send call proc27563(); +real_sleep 2; +connection con1; +disable_query_log; +eval kill query $ID; +enable_query_log; +connection con2; +--error 1317 +reap; +select @a; + +# Test TRIGGERS +connection con2; +create table t2 (f2 int); +delimiter |; +create trigger trg27563 before insert on t1 for each row +begin + declare continue handler for sqlstate '70100' set @a:= 'killed'; + declare continue handler for sqlexception set @a:= 'exception'; + set @a:= get_lock("lock27563",10); + insert into t2 values(1); +end| +delimiter ;| +send insert into t1 values(2),(3); +real_sleep 2; +connection con1; +disable_query_log; +eval kill query $ID; +enable_query_log; +connection con2; +--error 1317 +reap; +select @a; +connection con1; +select * from t1; +select * from t2; + +# Cleanup +select release_lock("lock27563"); +drop table t1, t2; +drop function bug27563; +drop procedure proc27563; diff --git a/sql/item_func.cc b/sql/item_func.cc index c0a9647e382..6aa2337b8d9 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -5347,6 +5347,8 @@ Item_func_sp::execute() { null_value= 1; context->process_error(thd); + if (thd->killed) + thd->send_kill_message(); return TRUE; } diff --git a/sql/sp_head.cc b/sql/sp_head.cc index 338b2eb84bb..9e9c1d7bdda 100644 --- a/sql/sp_head.cc +++ b/sql/sp_head.cc @@ -1318,6 +1318,9 @@ err_with_cleanup: free_root(&call_mem_root, MYF(0)); thd->spcont= octx; + if (thd->killed) + thd->send_kill_message(); + DBUG_RETURN(err_status); } diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 6e6611d54d2..ed081f810fd 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -5444,7 +5444,7 @@ fill_record(THD *thd, Field **ptr, List &values, bool ignore_errors) table= (*ptr)->table; table->auto_increment_field_not_null= FALSE; } - while ((field = *ptr++)) + while ((field = *ptr++) && !thd->net.report_error) { value=v++; table= field->table; From 48af05a8e90d5a81e03257d31ed0f5166559ab88 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 23 May 2007 19:04:12 -0700 Subject: [PATCH 11/15] Fixed bug #28561: assertion abort for update on multi-table view with CHECK OPTION and a subquery in WHERE condition. The abort was triggered by setting the value of join->tables for subqueries in the function JOIN::cleanup. This function was called after an invocation of the JOIN::join_free method for subqueries used in WHERE condition. mysql-test/r/view.result: Added a test case for bug #28561. mysql-test/t/view.test: Added a test case for bug #28561. sql/sql_select.cc: Fixed bug #28561: assertion abort for update on multi-table view with CHECK OPTION and a subquery in WHERE condition. The abort was triggered by setting the value of join->tables for subqueries in the function JOIN::cleanup. This function was called after an invocation of the JOIN::join_free method for subqueries used in WHERE condition. Setting the value of join->tables to for a subquery created serious problems for checking WHERE condition after update of the multi-table view as this check is performed in the do_select function right after a call of the JOIN::join_free method. In fact setting join->tables to 0 in JOIN::cleanup is not needed anywhere in the current code. --- mysql-test/r/view.result | 10 ++++++++++ mysql-test/t/view.test | 19 +++++++++++++++++++ sql/sql_select.cc | 1 - 3 files changed, 29 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/view.result b/mysql-test/r/view.result index 8d9d802949d..13239af41ad 100644 --- a/mysql-test/r/view.result +++ b/mysql-test/r/view.result @@ -3367,4 +3367,14 @@ SHOW CREATE VIEW v1; View Create View v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select cast(1.23456789 as decimal(8,0)) AS `col` DROP VIEW v1; +CREATE TABLE t1 (id int); +CREATE TABLE t2 (id int, c int DEFAULT 0); +INSERT INTO t1 (id) VALUES (1); +INSERT INTO t2 (id) VALUES (1); +CREATE VIEW v1 AS +SELECT t2.c FROM t1, t2 +WHERE t1.id=t2.id AND 1 IN (SELECT id FROM t1) WITH CHECK OPTION; +UPDATE v1 SET c=1; +DROP VIEW v1; +DROP TABLE t1,t2; End of 5.0 tests. diff --git a/mysql-test/t/view.test b/mysql-test/t/view.test index 3275ba0a687..1f6bee8b142 100644 --- a/mysql-test/t/view.test +++ b/mysql-test/t/view.test @@ -3233,4 +3233,23 @@ CREATE VIEW v1 AS SELECT CAST(1.23456789 AS DECIMAL(8,0)) AS col; SHOW CREATE VIEW v1; DROP VIEW v1; +# +# Bug #28561: update on multi-table view with CHECK OPTION and +# a subquery in WHERE condition +# + +CREATE TABLE t1 (id int); +CREATE TABLE t2 (id int, c int DEFAULT 0); +INSERT INTO t1 (id) VALUES (1); +INSERT INTO t2 (id) VALUES (1); + +CREATE VIEW v1 AS + SELECT t2.c FROM t1, t2 + WHERE t1.id=t2.id AND 1 IN (SELECT id FROM t1) WITH CHECK OPTION; + +UPDATE v1 SET c=1; + +DROP VIEW v1; +DROP TABLE t1,t2; + --echo End of 5.0 tests. diff --git a/sql/sql_select.cc b/sql/sql_select.cc index ce8a5b99633..db6c134b203 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -6375,7 +6375,6 @@ void JOIN::cleanup(bool full) for (tab= join_tab, end= tab+tables; tab != end; tab++) tab->cleanup(); table= 0; - tables= 0; } else { From c326457d78af9a27ad58a74c31125594d9fc2a75 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 25 May 2007 17:24:17 +0500 Subject: [PATCH 12/15] Fixed bug #28522: sometimes `mysqldump --hex-blob' overruned output buffer by '\0' byte. The dump_table() function has been fixed to reserve 1 byte more for the last '\0' byte of dumped string. client/mysqldump.c: Fixed bug #28522. The dump_table() function has been fixed to reserve 1 byte more for the last '\0' byte of dumped string. mysql-test/t/mysqldump.test: Updated test case for bug #28522. mysql-test/r/mysqldump.result: Updated test case for bug #28522. --- client/mysqldump.c | 7 +++++-- mysql-test/r/mysqldump.result | 11 +++++++++++ mysql-test/t/mysqldump.test | 7 +++++++ 3 files changed, 23 insertions(+), 2 deletions(-) diff --git a/client/mysqldump.c b/client/mysqldump.c index 4f908b531b1..26235efafce 100644 --- a/client/mysqldump.c +++ b/client/mysqldump.c @@ -2529,15 +2529,18 @@ static void dump_table(char *table, char *db) plus 2 bytes for '0x' prefix. - In non-HEX mode we need up to 2 bytes per character, plus 2 bytes for leading and trailing '\'' characters. + Also we need to reserve 1 byte for terminating '\0'. */ - dynstr_realloc_checked(&extended_row,length * 2+2); + dynstr_realloc_checked(&extended_row,length * 2 + 2 + 1); if (opt_hex_blob && is_blob) { dynstr_append_checked(&extended_row, "0x"); extended_row.length+= mysql_hex_string(extended_row.str + extended_row.length, row[i], length); - extended_row.str[extended_row.length]= '\0'; + DBUG_ASSERT(extended_row.length+1 <= extended_row.max_length); + /* mysql_hex_string() already terminated string by '\0' */ + DBUG_ASSERT(extended_row.str[extended_row.length] == '\0'); } else { diff --git a/mysql-test/r/mysqldump.result b/mysql-test/r/mysqldump.result index d9198ffeb48..25c4199e7a3 100644 --- a/mysql-test/r/mysqldump.result +++ b/mysql-test/r/mysqldump.result @@ -3310,5 +3310,16 @@ drop user user1; drop user user2; drop database mysqldump_test_db; # +# Bug #28522: buffer overrun by '\0' byte using --hex-blob. +# +CREATE TABLE t1 (c1 INT, c2 LONGBLOB); +INSERT INTO t1 SET c1=11, c2=REPEAT('q',509); +CREATE TABLE `t1` ( + `c1` int(11) default NULL, + `c2` longblob +); +INSERT INTO `t1` VALUES (11,0x7171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171); +DROP TABLE t1; +# # End of 5.0 tests # diff --git a/mysql-test/t/mysqldump.test b/mysql-test/t/mysqldump.test index 4c4690520c6..7df65f2b2e1 100644 --- a/mysql-test/t/mysqldump.test +++ b/mysql-test/t/mysqldump.test @@ -1528,7 +1528,14 @@ drop user user2; drop database mysqldump_test_db; +--echo # +--echo # Bug #28522: buffer overrun by '\0' byte using --hex-blob. +--echo # +CREATE TABLE t1 (c1 INT, c2 LONGBLOB); +INSERT INTO t1 SET c1=11, c2=REPEAT('q',509); +--exec $MYSQL_DUMP --skip-create --compact --hex-blob test t1 +DROP TABLE t1; --echo # --echo # End of 5.0 tests From 5a5c256ffdae3f54e722008726987bb681f7d109 Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 26 May 2007 00:44:13 +0500 Subject: [PATCH 13/15] field.h: Warnings elimination. sql/field.h: Warnings elimination. --- sql/field.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql/field.h b/sql/field.h index 94c5d94def4..0d0b1c93a5b 100644 --- a/sql/field.h +++ b/sql/field.h @@ -1112,7 +1112,7 @@ public: The maximum space available in a Field_varstring, in bytes. See length_bytes. */ - static const int MAX_SIZE= UINT_MAX16; + static const uint MAX_SIZE= UINT_MAX16; /* Store number of bytes used to store length (1 or 2) */ uint32 length_bytes; Field_varstring(char *ptr_arg, From 90484de3f73cb943fd6e31b974e3a13a709dac08 Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 26 May 2007 10:33:01 -0700 Subject: [PATCH 14/15] Fixed bug #28571. Outer join queries with ON conditions over constant outer tables did not return null complemented rows when conditions were evaluated to FALSE. Wrong results were returned because the conditions over constant outer tables, when being pushed down, were erroneously enclosed into the guard function used for WHERE conditions. mysql-test/r/join_outer.result: Added a test case for bug #28571. mysql-test/t/join_outer.test: Added a test case for bug #28571. sql/sql_select.cc: Fixed bug #28571. Outer join queries with ON conditions over constant outer tables did not return null complemented rows when conditions were evaluated to FALSE. Wrong results were returned because the conditions over constant outer tables, when being pushed down, were erroneously enclosed into the guard function used for WHERE conditions. The problem is fixed in the function make_join_select. Now the conditions over constant tables from ON expressions are pushed down after the conditions from WHERE has been pushed down. --- mysql-test/r/join_outer.result | 15 ++++++++++ mysql-test/t/join_outer.test | 16 ++++++++++ sql/sql_select.cc | 54 ++++++++++++++++++---------------- 3 files changed, 60 insertions(+), 25 deletions(-) diff --git a/mysql-test/r/join_outer.result b/mysql-test/r/join_outer.result index c62601946c2..1366a8fe97a 100644 --- a/mysql-test/r/join_outer.result +++ b/mysql-test/r/join_outer.result @@ -1239,3 +1239,18 @@ Handler_read_prev 0 Handler_read_rnd 0 Handler_read_rnd_next 6 DROP TABLE t1,t2; +CREATE TABLE t1 (c int PRIMARY KEY, e int NOT NULL); +INSERT INTO t1 VALUES (1,0), (2,1); +CREATE TABLE t2 (d int PRIMARY KEY); +INSERT INTO t2 VALUES (1), (2), (3); +EXPLAIN SELECT * FROM t1 LEFT JOIN t2 ON e<>0 WHERE c=1 AND d IS NULL; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 const PRIMARY PRIMARY 4 const 1 +1 SIMPLE t2 index NULL PRIMARY 4 NULL 3 Using where; Using index; Not exists +SELECT * FROM t1 LEFT JOIN t2 ON e<>0 WHERE c=1 AND d IS NULL; +c e d +1 0 NULL +SELECT * FROM t1 LEFT JOIN t2 ON e<>0 WHERE c=1 AND d<=>NULL; +c e d +1 0 NULL +DROP TABLE t1,t2; diff --git a/mysql-test/t/join_outer.test b/mysql-test/t/join_outer.test index 51e79a20d65..1a59dbf8fc2 100644 --- a/mysql-test/t/join_outer.test +++ b/mysql-test/t/join_outer.test @@ -845,3 +845,19 @@ SELECT t1.id, a FROM t1 LEFT JOIN t2 ON t1.id=t2.id WHERE t2.b IS NULL; show status like 'Handler_read%'; DROP TABLE t1,t2; + +# +# Bug 28571: outer join with false on condition over constant tables +# + +CREATE TABLE t1 (c int PRIMARY KEY, e int NOT NULL); +INSERT INTO t1 VALUES (1,0), (2,1); +CREATE TABLE t2 (d int PRIMARY KEY); +INSERT INTO t2 VALUES (1), (2), (3); + +EXPLAIN SELECT * FROM t1 LEFT JOIN t2 ON e<>0 WHERE c=1 AND d IS NULL; +SELECT * FROM t1 LEFT JOIN t2 ON e<>0 WHERE c=1 AND d IS NULL; +SELECT * FROM t1 LEFT JOIN t2 ON e<>0 WHERE c=1 AND d<=>NULL; + +DROP TABLE t1,t2; + diff --git a/sql/sql_select.cc b/sql/sql_select.cc index db6c134b203..ecdb727bcb4 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -5666,28 +5666,6 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond) join->const_table_map, (table_map) 0); DBUG_EXECUTE("where",print_where(const_cond,"constants");); - for (JOIN_TAB *tab= join->join_tab+join->const_tables; - tab < join->join_tab+join->tables ; tab++) - { - if (*tab->on_expr_ref) - { - JOIN_TAB *cond_tab= tab->first_inner; - COND *tmp= make_cond_for_table(*tab->on_expr_ref, - join->const_table_map, - ( table_map) 0); - if (!tmp) - continue; - tmp= new Item_func_trig_cond(tmp, &cond_tab->not_null_compl); - if (!tmp) - DBUG_RETURN(1); - tmp->quick_fix_field(); - cond_tab->select_cond= !cond_tab->select_cond ? tmp : - new Item_cond_and(cond_tab->select_cond,tmp); - if (!cond_tab->select_cond) - DBUG_RETURN(1); - cond_tab->select_cond->quick_fix_field(); - } - } if (const_cond && !const_cond->val_int()) { DBUG_PRINT("info",("Found impossible WHERE condition")); @@ -5918,13 +5896,39 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond) } /* - Push down all predicates from on expressions. - Each of these predicated are guarded by a variable + Push down conditions from all on expressions. + Each of these conditions are guarded by a variable that turns if off just before null complemented row for - outer joins is formed. Thus, the predicates from an + outer joins is formed. Thus, the condition from an 'on expression' are guaranteed not to be checked for the null complemented row. */ + + /* First push down constant conditions from on expressions */ + for (JOIN_TAB *tab= join->join_tab+join->const_tables; + tab < join->join_tab+join->tables ; tab++) + { + if (*tab->on_expr_ref) + { + JOIN_TAB *cond_tab= tab->first_inner; + COND *tmp= make_cond_for_table(*tab->on_expr_ref, + join->const_table_map, + (table_map) 0); + if (!tmp) + continue; + tmp= new Item_func_trig_cond(tmp, &cond_tab->not_null_compl); + if (!tmp) + DBUG_RETURN(1); + tmp->quick_fix_field(); + cond_tab->select_cond= !cond_tab->select_cond ? tmp : + new Item_cond_and(cond_tab->select_cond,tmp); + if (!cond_tab->select_cond) + DBUG_RETURN(1); + cond_tab->select_cond->quick_fix_field(); + } + } + + /* Push down non-constant conditions from on expressions */ JOIN_TAB *last_tab= tab; while (first_inner_tab && first_inner_tab->last_inner == last_tab) { From 5f99cf963ea4138fd7adb70ec4a9add55388c281 Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 26 May 2007 13:19:36 -0700 Subject: [PATCH 15/15] Avoided warnings on Windows. --- sql/sql_select.cc | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/sql/sql_select.cc b/sql/sql_select.cc index ecdb727bcb4..57dff4b23a5 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -5905,13 +5905,13 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond) */ /* First push down constant conditions from on expressions */ - for (JOIN_TAB *tab= join->join_tab+join->const_tables; - tab < join->join_tab+join->tables ; tab++) + for (JOIN_TAB *join_tab= join->join_tab+join->const_tables; + join_tab < join->join_tab+join->tables ; join_tab++) { - if (*tab->on_expr_ref) + if (*join_tab->on_expr_ref) { - JOIN_TAB *cond_tab= tab->first_inner; - COND *tmp= make_cond_for_table(*tab->on_expr_ref, + JOIN_TAB *cond_tab= join_tab->first_inner; + COND *tmp= make_cond_for_table(*join_tab->on_expr_ref, join->const_table_map, (table_map) 0); if (!tmp)