diff options
5 files changed, 2929 insertions, 0 deletions
diff --git a/meta-oe/recipes-dbs/mysql/mariadb.inc b/meta-oe/recipes-dbs/mysql/mariadb.inc index 6a8ff05039..951d3a28e8 100644 --- a/meta-oe/recipes-dbs/mysql/mariadb.inc +++ b/meta-oe/recipes-dbs/mysql/mariadb.inc | |||
| @@ -24,6 +24,10 @@ SRC_URI = "https://archive.mariadb.org/${BP}/source/${BP}.tar.gz \ | |||
| 24 | file://0001-MDEV-29644-a-potential-bug-of-null-pointer-dereferen.patch \ | 24 | file://0001-MDEV-29644-a-potential-bug-of-null-pointer-dereferen.patch \ |
| 25 | file://CVE-2023-22084.patch \ | 25 | file://CVE-2023-22084.patch \ |
| 26 | file://CVE-2023-52968.patch \ | 26 | file://CVE-2023-52968.patch \ |
| 27 | file://CVE-2023-52969-CVE-20230-52970-0001.patch \ | ||
| 28 | file://CVE-2023-52969-CVE-20230-52970-0002.patch \ | ||
| 29 | file://CVE-2023-52969-CVE-20230-52970-0003.patch \ | ||
| 30 | file://CVE-2023-52969-CVE-20230-52970-0004.patch \ | ||
| 27 | " | 31 | " |
| 28 | SRC_URI:append:libc-musl = " file://ppc-remove-glibc-dep.patch" | 32 | SRC_URI:append:libc-musl = " file://ppc-remove-glibc-dep.patch" |
| 29 | 33 | ||
diff --git a/meta-oe/recipes-dbs/mysql/mariadb/CVE-2023-52969-CVE-20230-52970-0001.patch b/meta-oe/recipes-dbs/mysql/mariadb/CVE-2023-52969-CVE-20230-52970-0001.patch new file mode 100644 index 0000000000..99e98b19f9 --- /dev/null +++ b/meta-oe/recipes-dbs/mysql/mariadb/CVE-2023-52969-CVE-20230-52970-0001.patch | |||
| @@ -0,0 +1,502 @@ | |||
| 1 | From e6403733897483bed249875f0f3e5e9937ca2b38 Mon Sep 17 00:00:00 2001 | ||
| 2 | From: Oleg Smirnov <olernov@gmail.com> | ||
| 3 | Date: Fri, 25 Oct 2024 14:35:22 +0700 | ||
| 4 | Subject: [PATCH] Revert "MDEV-26427 MariaDB Server SEGV on INSERT .. SELECT" | ||
| 5 | |||
| 6 | This reverts commit 49e14000eeb245ea27e9207d2f63cb0a28be1ca9 | ||
| 7 | as it introduces regression MDEV-29935 and has to be reconsidered | ||
| 8 | in general | ||
| 9 | |||
| 10 | CVE: CVE-2023-52969 and CVE-2023-52970 | ||
| 11 | Upstream-Status: Backport [https://github.com/MariaDB/server/commit/e6403733897483bed249875f0f3e5e9937ca2b38] | ||
| 12 | |||
| 13 | Signed-off-by: Yogita Urade <yogita.urade@windriver.com> | ||
| 14 | --- | ||
| 15 | mysql-test/main/insert_select.result | 70 ----------- | ||
| 16 | mysql-test/main/insert_select.test | 54 -------- | ||
| 17 | mysql-test/main/view.result | 10 -- | ||
| 18 | mysql-test/main/view.test | 2 - | ||
| 19 | sql/sql_base.cc | 178 ++++++++------------------- | ||
| 20 | sql/sql_insert.cc | 4 +- | ||
| 21 | sql/sql_select.cc | 4 + | ||
| 22 | sql/sql_select.h | 1 + | ||
| 23 | 8 files changed, 59 insertions(+), 264 deletions(-) | ||
| 24 | |||
| 25 | diff --git a/mysql-test/main/insert_select.result b/mysql-test/main/insert_select.result | ||
| 26 | index 29618c6d..10c87271 100644 | ||
| 27 | --- a/mysql-test/main/insert_select.result | ||
| 28 | +++ b/mysql-test/main/insert_select.result | ||
| 29 | @@ -883,76 +883,6 @@ INSERT INTO t1 SELECT a*2 FROM t1 ORDER BY a; | ||
| 30 | Warnings: | ||
| 31 | Warning 1264 Out of range value for column 'a' at row 4 | ||
| 32 | DROP TABLE t1; | ||
| 33 | -CREATE TABLE t1 (a INT, b INT); | ||
| 34 | -INSERT INTO t1 (a) SELECT SUM(1); | ||
| 35 | -INSERT INTO t1 (a, b) SELECT AVG(2), MIN(3); | ||
| 36 | -INSERT INTO t1 (b) SELECT AVG('x') OVER (); | ||
| 37 | -ERROR 22007: Truncated incorrect DOUBLE value: 'x' | ||
| 38 | -INSERT INTO t1 SELECT MIN(7) OVER (), MAX(8) OVER(); | ||
| 39 | -SELECT * FROM t1; | ||
| 40 | -a b | ||
| 41 | -1 NULL | ||
| 42 | -2 3 | ||
| 43 | -7 8 | ||
| 44 | -PREPARE stmt FROM 'INSERT INTO t1 (a) SELECT AVG(?)'; | ||
| 45 | -EXECUTE stmt USING 9; | ||
| 46 | -EXECUTE stmt USING 10; | ||
| 47 | -PREPARE stmt FROM 'INSERT INTO t1 SELECT MIN(?), MAX(?)'; | ||
| 48 | -EXECUTE stmt USING 11, 12; | ||
| 49 | -EXECUTE stmt USING 13, 14; | ||
| 50 | -DEALLOCATE PREPARE stmt; | ||
| 51 | -SELECT * FROM t1; | ||
| 52 | -a b | ||
| 53 | -1 NULL | ||
| 54 | -2 3 | ||
| 55 | -7 8 | ||
| 56 | -9 NULL | ||
| 57 | -10 NULL | ||
| 58 | -11 12 | ||
| 59 | -13 14 | ||
| 60 | -CREATE PROCEDURE p1(param_a INT, param_b INT) | ||
| 61 | -BEGIN | ||
| 62 | -INSERT INTO t1 SELECT MIN(param_a) OVER (), MAX(param_b); | ||
| 63 | -END// | ||
| 64 | -CALL p1(21, 22); | ||
| 65 | -CALL p1(23, 24); | ||
| 66 | -SELECT * FROM t1; | ||
| 67 | -a b | ||
| 68 | -1 NULL | ||
| 69 | -2 3 | ||
| 70 | -7 8 | ||
| 71 | -9 NULL | ||
| 72 | -10 NULL | ||
| 73 | -11 12 | ||
| 74 | -13 14 | ||
| 75 | -21 22 | ||
| 76 | -23 24 | ||
| 77 | -CREATE TABLE t2 ( | ||
| 78 | -a DECIMAL UNIQUE CHECK (CASE 0 * 27302337.000000 WHEN 34 THEN | ||
| 79 | -+ 'x' LIKE 'x' OR a NOT IN (-1 / TRUE ^ 2) ELSE 7105743.000000 END)); | ||
| 80 | -INSERT INTO t2 VALUES (90),( -1),(31152443.000000),(-32768),(NULL),(NULL); | ||
| 81 | -INSERT INTO t2 SELECT AVG('x') OVER ( | ||
| 82 | -PARTITION BY ((NOT AVG(76698761.000000))) IS NOT NULL); | ||
| 83 | -ERROR 22007: Truncated incorrect DOUBLE value: 'x' | ||
| 84 | -INSERT IGNORE INTO t2 () VALUES (0),('x'),(3751286.000000), | ||
| 85 | -('x'),((a = 'x' AND 0 AND 0)); | ||
| 86 | -Warnings: | ||
| 87 | -Warning 1366 Incorrect decimal value: 'x' for column `test`.`t2`.`a` at row 2 | ||
| 88 | -Warning 1062 Duplicate entry '0' for key 'a' | ||
| 89 | -Warning 1366 Incorrect decimal value: 'x' for column `test`.`t2`.`a` at row 4 | ||
| 90 | -Warning 1062 Duplicate entry '0' for key 'a' | ||
| 91 | -Warning 1062 Duplicate entry '0' for key 'a' | ||
| 92 | -INSERT INTO t2 VALUES (127); | ||
| 93 | -INSERT INTO t2 SELECT -2147483648 END FROM t2 AS TEXT JOIN t2 JOIN t2 TABLES; | ||
| 94 | -ERROR 23000: Duplicate entry '-2147483648' for key 'a' | ||
| 95 | -ALTER TABLE t2 ADD ( | ||
| 96 | -b INT UNIQUE CHECK ((a = 'x' AND ((-(+(BINARY 49730460.000000)))) = 'x' | ||
| 97 | -BETWEEN 'x' AND 'x'))); | ||
| 98 | -ERROR 22007: Truncated incorrect DECIMAL value: 'x' | ||
| 99 | -UPDATE t2 SET a = -128 WHERE a IS NULL ORDER BY 78 IN ('x','x'),a; | ||
| 100 | -ERROR 23000: Duplicate entry '-128' for key 'a' | ||
| 101 | -DROP TABLE t1, t2; | ||
| 102 | -DROP PROCEDURE p1; | ||
| 103 | # End of 10.2 test | ||
| 104 | # | ||
| 105 | # MDEV-28617: INSERT ... SELECT with redundant IN subquery in GROUP BY | ||
| 106 | diff --git a/mysql-test/main/insert_select.test b/mysql-test/main/insert_select.test | ||
| 107 | index a3604e38..7417bab9 100644 | ||
| 108 | --- a/mysql-test/main/insert_select.test | ||
| 109 | +++ b/mysql-test/main/insert_select.test | ||
| 110 | @@ -459,60 +459,6 @@ INSERT INTO t1 SELECT a*2 FROM t1 ORDER BY a; | ||
| 111 | |||
| 112 | DROP TABLE t1; | ||
| 113 | |||
| 114 | -# | ||
| 115 | -# MDEV-26427 MariaDB Server SEGV on INSERT .. SELECT | ||
| 116 | -# | ||
| 117 | -CREATE TABLE t1 (a INT, b INT); | ||
| 118 | -INSERT INTO t1 (a) SELECT SUM(1); | ||
| 119 | -INSERT INTO t1 (a, b) SELECT AVG(2), MIN(3); | ||
| 120 | - | ||
| 121 | ---error ER_TRUNCATED_WRONG_VALUE | ||
| 122 | -INSERT INTO t1 (b) SELECT AVG('x') OVER (); | ||
| 123 | -INSERT INTO t1 SELECT MIN(7) OVER (), MAX(8) OVER(); | ||
| 124 | -SELECT * FROM t1; | ||
| 125 | - | ||
| 126 | -PREPARE stmt FROM 'INSERT INTO t1 (a) SELECT AVG(?)'; | ||
| 127 | -EXECUTE stmt USING 9; | ||
| 128 | -EXECUTE stmt USING 10; | ||
| 129 | - | ||
| 130 | -PREPARE stmt FROM 'INSERT INTO t1 SELECT MIN(?), MAX(?)'; | ||
| 131 | -EXECUTE stmt USING 11, 12; | ||
| 132 | -EXECUTE stmt USING 13, 14; | ||
| 133 | -DEALLOCATE PREPARE stmt; | ||
| 134 | -SELECT * FROM t1; | ||
| 135 | - | ||
| 136 | -DELIMITER //; | ||
| 137 | -CREATE PROCEDURE p1(param_a INT, param_b INT) | ||
| 138 | -BEGIN | ||
| 139 | -INSERT INTO t1 SELECT MIN(param_a) OVER (), MAX(param_b); | ||
| 140 | -END// | ||
| 141 | -DELIMITER ;// | ||
| 142 | -CALL p1(21, 22); | ||
| 143 | -CALL p1(23, 24); | ||
| 144 | -SELECT * FROM t1; | ||
| 145 | - | ||
| 146 | -CREATE TABLE t2 ( | ||
| 147 | - a DECIMAL UNIQUE CHECK (CASE 0 * 27302337.000000 WHEN 34 THEN | ||
| 148 | - + 'x' LIKE 'x' OR a NOT IN (-1 / TRUE ^ 2) ELSE 7105743.000000 END)); | ||
| 149 | -INSERT INTO t2 VALUES (90),( -1),(31152443.000000),(-32768),(NULL),(NULL); | ||
| 150 | ---error ER_TRUNCATED_WRONG_VALUE | ||
| 151 | -INSERT INTO t2 SELECT AVG('x') OVER ( | ||
| 152 | - PARTITION BY ((NOT AVG(76698761.000000))) IS NOT NULL); | ||
| 153 | -INSERT IGNORE INTO t2 () VALUES (0),('x'),(3751286.000000), | ||
| 154 | - ('x'),((a = 'x' AND 0 AND 0)); | ||
| 155 | -INSERT INTO t2 VALUES (127); | ||
| 156 | ---error ER_DUP_ENTRY | ||
| 157 | -INSERT INTO t2 SELECT -2147483648 END FROM t2 AS TEXT JOIN t2 JOIN t2 TABLES; | ||
| 158 | ---error ER_TRUNCATED_WRONG_VALUE | ||
| 159 | -ALTER TABLE t2 ADD ( | ||
| 160 | - b INT UNIQUE CHECK ((a = 'x' AND ((-(+(BINARY 49730460.000000)))) = 'x' | ||
| 161 | - BETWEEN 'x' AND 'x'))); | ||
| 162 | ---error ER_DUP_ENTRY | ||
| 163 | -UPDATE t2 SET a = -128 WHERE a IS NULL ORDER BY 78 IN ('x','x'),a; | ||
| 164 | - | ||
| 165 | -DROP TABLE t1, t2; | ||
| 166 | -DROP PROCEDURE p1; | ||
| 167 | - | ||
| 168 | --echo # End of 10.2 test | ||
| 169 | |||
| 170 | --echo # | ||
| 171 | diff --git a/mysql-test/main/view.result b/mysql-test/main/view.result | ||
| 172 | index aec4a5d0..69e850cd 100644 | ||
| 173 | --- a/mysql-test/main/view.result | ||
| 174 | +++ b/mysql-test/main/view.result | ||
| 175 | @@ -1503,8 +1503,6 @@ execute stmt1 using @a; | ||
| 176 | set @a= 301; | ||
| 177 | execute stmt1 using @a; | ||
| 178 | deallocate prepare stmt1; | ||
| 179 | -insert into v3(a) select sum(302); | ||
| 180 | -insert into v3(a) select sum(303) over (); | ||
| 181 | select * from v3; | ||
| 182 | a b | ||
| 183 | 100 0 | ||
| 184 | @@ -1523,14 +1521,6 @@ a b | ||
| 185 | 301 10 | ||
| 186 | 301 1000 | ||
| 187 | 301 2000 | ||
| 188 | -302 0 | ||
| 189 | -302 10 | ||
| 190 | -302 1000 | ||
| 191 | -302 2000 | ||
| 192 | -303 0 | ||
| 193 | -303 10 | ||
| 194 | -303 1000 | ||
| 195 | -303 2000 | ||
| 196 | drop view v3; | ||
| 197 | drop tables t1,t2; | ||
| 198 | create table t1(f1 int); | ||
| 199 | diff --git a/mysql-test/main/view.test b/mysql-test/main/view.test | ||
| 200 | index c6cc9a69..f32b148b 100644 | ||
| 201 | --- a/mysql-test/main/view.test | ||
| 202 | +++ b/mysql-test/main/view.test | ||
| 203 | @@ -1334,8 +1334,6 @@ execute stmt1 using @a; | ||
| 204 | set @a= 301; | ||
| 205 | execute stmt1 using @a; | ||
| 206 | deallocate prepare stmt1; | ||
| 207 | -insert into v3(a) select sum(302); | ||
| 208 | -insert into v3(a) select sum(303) over (); | ||
| 209 | --sorted_result | ||
| 210 | select * from v3; | ||
| 211 | |||
| 212 | diff --git a/sql/sql_base.cc b/sql/sql_base.cc | ||
| 213 | index 4142540f..59c13009 100644 | ||
| 214 | --- a/sql/sql_base.cc | ||
| 215 | +++ b/sql/sql_base.cc | ||
| 216 | @@ -7750,39 +7750,6 @@ bool setup_fields(THD *thd, Ref_ptr_array ref_pointer_array, | ||
| 217 | DBUG_RETURN(MY_TEST(thd->is_error())); | ||
| 218 | } | ||
| 219 | |||
| 220 | -/* | ||
| 221 | - make list of leaves for a single TABLE_LIST | ||
| 222 | - | ||
| 223 | - SYNOPSIS | ||
| 224 | - make_leaves_for_single_table() | ||
| 225 | - thd Thread handler | ||
| 226 | - leaves List of leaf tables to be filled | ||
| 227 | - table TABLE_LIST object to process | ||
| 228 | - full_table_list Whether to include tables from mergeable derived table/view | ||
| 229 | -*/ | ||
| 230 | -void make_leaves_for_single_table(THD *thd, List<TABLE_LIST> &leaves, | ||
| 231 | - TABLE_LIST *table, bool& full_table_list, | ||
| 232 | - TABLE_LIST *boundary) | ||
| 233 | -{ | ||
| 234 | - if (table == boundary) | ||
| 235 | - full_table_list= !full_table_list; | ||
| 236 | - if (full_table_list && table->is_merged_derived()) | ||
| 237 | - { | ||
| 238 | - SELECT_LEX *select_lex= table->get_single_select(); | ||
| 239 | - /* | ||
| 240 | - It's safe to use select_lex->leaf_tables because all derived | ||
| 241 | - tables/views were already prepared and has their leaf_tables | ||
| 242 | - set properly. | ||
| 243 | - */ | ||
| 244 | - make_leaves_list(thd, leaves, select_lex->get_table_list(), | ||
| 245 | - full_table_list, boundary); | ||
| 246 | - } | ||
| 247 | - else | ||
| 248 | - { | ||
| 249 | - leaves.push_back(table, thd->mem_root); | ||
| 250 | - } | ||
| 251 | -} | ||
| 252 | - | ||
| 253 | |||
| 254 | /* | ||
| 255 | Perform checks like all given fields exists, if exists fill struct with | ||
| 256 | @@ -7809,79 +7776,40 @@ int setup_returning_fields(THD* thd, TABLE_LIST* table_list) | ||
| 257 | |||
| 258 | SYNOPSIS | ||
| 259 | make_leaves_list() | ||
| 260 | - leaves List of leaf tables to be filled | ||
| 261 | - tables Table list | ||
| 262 | - full_table_list Whether to include tables from mergeable derived table/view. | ||
| 263 | - We need them for checks for INSERT/UPDATE statements only. | ||
| 264 | + list pointer to pointer on list first element | ||
| 265 | + tables table list | ||
| 266 | + full_table_list whether to include tables from mergeable derived table/view. | ||
| 267 | + we need them for checks for INSERT/UPDATE statements only. | ||
| 268 | + | ||
| 269 | + RETURN pointer on pointer to next_leaf of last element | ||
| 270 | */ | ||
| 271 | |||
| 272 | -void make_leaves_list(THD *thd, List<TABLE_LIST> &leaves, TABLE_LIST *tables, | ||
| 273 | +void make_leaves_list(THD *thd, List<TABLE_LIST> &list, TABLE_LIST *tables, | ||
| 274 | bool full_table_list, TABLE_LIST *boundary) | ||
| 275 | |||
| 276 | { | ||
| 277 | for (TABLE_LIST *table= tables; table; table= table->next_local) | ||
| 278 | { | ||
| 279 | - make_leaves_for_single_table(thd, leaves, table, full_table_list, | ||
| 280 | - boundary); | ||
| 281 | - } | ||
| 282 | -} | ||
| 283 | - | ||
| 284 | - | ||
| 285 | -/* | ||
| 286 | - Setup the map and other attributes for a single TABLE_LIST object | ||
| 287 | - | ||
| 288 | - SYNOPSIS | ||
| 289 | - setup_table_attributes() | ||
| 290 | - thd Thread handler | ||
| 291 | - table_list TABLE_LIST object to process | ||
| 292 | - first_select_table First table participating in SELECT for INSERT..SELECT | ||
| 293 | - statements, NULL for other cases | ||
| 294 | - tablenr Serial number of the table in the SQL statement | ||
| 295 | - | ||
| 296 | - RETURN | ||
| 297 | - false Success | ||
| 298 | - true Failure | ||
| 299 | -*/ | ||
| 300 | -bool setup_table_attributes(THD *thd, TABLE_LIST *table_list, | ||
| 301 | - TABLE_LIST *first_select_table, | ||
| 302 | - uint &tablenr) | ||
| 303 | -{ | ||
| 304 | - TABLE *table= table_list->table; | ||
| 305 | - if (table) | ||
| 306 | - table->pos_in_table_list= table_list; | ||
| 307 | - if (first_select_table && table_list->top_table() == first_select_table) | ||
| 308 | - { | ||
| 309 | - /* new counting for SELECT of INSERT ... SELECT command */ | ||
| 310 | - first_select_table= 0; | ||
| 311 | - thd->lex->first_select_lex()->insert_tables= tablenr; | ||
| 312 | - tablenr= 0; | ||
| 313 | - } | ||
| 314 | - if (table_list->jtbm_subselect) | ||
| 315 | - { | ||
| 316 | - table_list->jtbm_table_no= tablenr; | ||
| 317 | - } | ||
| 318 | - else if (table) | ||
| 319 | - { | ||
| 320 | - table->pos_in_table_list= table_list; | ||
| 321 | - setup_table_map(table, table_list, tablenr); | ||
| 322 | - | ||
| 323 | - if (table_list->process_index_hints(table)) | ||
| 324 | - return true; | ||
| 325 | - } | ||
| 326 | - tablenr++; | ||
| 327 | - /* | ||
| 328 | - We test the max tables here as we setup_table_map() should not be called | ||
| 329 | - with tablenr >= 64 | ||
| 330 | - */ | ||
| 331 | - if (tablenr > MAX_TABLES) | ||
| 332 | - { | ||
| 333 | - my_error(ER_TOO_MANY_TABLES, MYF(0), static_cast<int>(MAX_TABLES)); | ||
| 334 | - return true; | ||
| 335 | + if (table == boundary) | ||
| 336 | + full_table_list= !full_table_list; | ||
| 337 | + if (full_table_list && table->is_merged_derived()) | ||
| 338 | + { | ||
| 339 | + SELECT_LEX *select_lex= table->get_single_select(); | ||
| 340 | + /* | ||
| 341 | + It's safe to use select_lex->leaf_tables because all derived | ||
| 342 | + tables/views were already prepared and has their leaf_tables | ||
| 343 | + set properly. | ||
| 344 | + */ | ||
| 345 | + make_leaves_list(thd, list, select_lex->get_table_list(), | ||
| 346 | + full_table_list, boundary); | ||
| 347 | + } | ||
| 348 | + else | ||
| 349 | + { | ||
| 350 | + list.push_back(table, thd->mem_root); | ||
| 351 | + } | ||
| 352 | } | ||
| 353 | - return false; | ||
| 354 | } | ||
| 355 | |||
| 356 | - | ||
| 357 | /* | ||
| 358 | prepare tables | ||
| 359 | |||
| 360 | @@ -7938,14 +7866,7 @@ bool setup_tables(THD *thd, Name_resolution_context *context, | ||
| 361 | leaves.empty(); | ||
| 362 | if (select_lex->prep_leaf_list_state != SELECT_LEX::SAVED) | ||
| 363 | { | ||
| 364 | - /* | ||
| 365 | - For INSERT ... SELECT statements we must not include the first table | ||
| 366 | - (where the data is being inserted into) in the list of leaves | ||
| 367 | - */ | ||
| 368 | - TABLE_LIST *tables_for_leaves= | ||
| 369 | - select_insert ? first_select_table : tables; | ||
| 370 | - make_leaves_list(thd, leaves, tables_for_leaves, full_table_list, | ||
| 371 | - first_select_table); | ||
| 372 | + make_leaves_list(thd, leaves, tables, full_table_list, first_select_table); | ||
| 373 | select_lex->prep_leaf_list_state= SELECT_LEX::READY; | ||
| 374 | select_lex->leaf_tables_exec.empty(); | ||
| 375 | } | ||
| 376 | @@ -7956,34 +7877,37 @@ bool setup_tables(THD *thd, Name_resolution_context *context, | ||
| 377 | leaves.push_back(table_list, thd->mem_root); | ||
| 378 | } | ||
| 379 | |||
| 380 | - List_iterator<TABLE_LIST> ti(leaves); | ||
| 381 | while ((table_list= ti++)) | ||
| 382 | { | ||
| 383 | - if (setup_table_attributes(thd, table_list, first_select_table, tablenr)) | ||
| 384 | - DBUG_RETURN(1); | ||
| 385 | - } | ||
| 386 | - | ||
| 387 | - if (select_insert) | ||
| 388 | - { | ||
| 389 | - /* | ||
| 390 | - The table/view in which the data is inserted must not be included into | ||
| 391 | - the leaf_tables list. But we need this table/view to setup attributes | ||
| 392 | - for it. So build a temporary list of leaves and setup attributes for | ||
| 393 | - the tables included | ||
| 394 | - */ | ||
| 395 | - List<TABLE_LIST> leaves; | ||
| 396 | - TABLE_LIST *table= tables; | ||
| 397 | - | ||
| 398 | - make_leaves_for_single_table(thd, leaves, table, full_table_list, | ||
| 399 | - first_select_table); | ||
| 400 | - | ||
| 401 | - List_iterator<TABLE_LIST> ti(leaves); | ||
| 402 | - while ((table_list= ti++)) | ||
| 403 | + TABLE *table= table_list->table; | ||
| 404 | + if (table) | ||
| 405 | + table->pos_in_table_list= table_list; | ||
| 406 | + if (first_select_table && | ||
| 407 | + table_list->top_table() == first_select_table) | ||
| 408 | { | ||
| 409 | - if (setup_table_attributes(thd, table_list, first_select_table, | ||
| 410 | - tablenr)) | ||
| 411 | + /* new counting for SELECT of INSERT ... SELECT command */ | ||
| 412 | + first_select_table= 0; | ||
| 413 | + thd->lex->first_select_lex()->insert_tables= tablenr; | ||
| 414 | + tablenr= 0; | ||
| 415 | + } | ||
| 416 | + if(table_list->jtbm_subselect) | ||
| 417 | + { | ||
| 418 | + table_list->jtbm_table_no= tablenr; | ||
| 419 | + } | ||
| 420 | + else if (table) | ||
| 421 | + { | ||
| 422 | + table->pos_in_table_list= table_list; | ||
| 423 | + setup_table_map(table, table_list, tablenr); | ||
| 424 | + | ||
| 425 | + if (table_list->process_index_hints(table)) | ||
| 426 | DBUG_RETURN(1); | ||
| 427 | } | ||
| 428 | + tablenr++; | ||
| 429 | + } | ||
| 430 | + if (tablenr > MAX_TABLES) | ||
| 431 | + { | ||
| 432 | + my_error(ER_TOO_MANY_TABLES,MYF(0), static_cast<int>(MAX_TABLES)); | ||
| 433 | + DBUG_RETURN(1); | ||
| 434 | } | ||
| 435 | } | ||
| 436 | else | ||
| 437 | diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc | ||
| 438 | index af2c4606..460c552f 100644 | ||
| 439 | --- a/sql/sql_insert.cc | ||
| 440 | +++ b/sql/sql_insert.cc | ||
| 441 | @@ -1570,7 +1570,8 @@ static bool mysql_prepare_insert_check_table(THD *thd, TABLE_LIST *table_list, | ||
| 442 | if (insert_into_view && !fields.elements) | ||
| 443 | { | ||
| 444 | thd->lex->empty_field_list_on_rset= 1; | ||
| 445 | - if (!table_list->table || table_list->is_multitable()) | ||
| 446 | + if (!thd->lex->first_select_lex()->leaf_tables.head()->table || | ||
| 447 | + table_list->is_multitable()) | ||
| 448 | { | ||
| 449 | my_error(ER_VIEW_NO_INSERT_FIELD_LIST, MYF(0), | ||
| 450 | table_list->view_db.str, table_list->view_name.str); | ||
| 451 | @@ -3828,6 +3829,7 @@ int mysql_insert_select_prepare(THD *thd, select_result *sel_res) | ||
| 452 | if (sel_res) | ||
| 453 | sel_res->prepare(lex->returning()->item_list, NULL); | ||
| 454 | |||
| 455 | + DBUG_ASSERT(select_lex->leaf_tables.elements != 0); | ||
| 456 | List_iterator<TABLE_LIST> ti(select_lex->leaf_tables); | ||
| 457 | TABLE_LIST *table; | ||
| 458 | uint insert_tables; | ||
| 459 | diff --git a/sql/sql_select.cc b/sql/sql_select.cc | ||
| 460 | index 21cc4806..8a7060c3 100644 | ||
| 461 | --- a/sql/sql_select.cc | ||
| 462 | +++ b/sql/sql_select.cc | ||
| 463 | @@ -2037,6 +2037,7 @@ JOIN::optimize_inner() | ||
| 464 | /* Merge all mergeable derived tables/views in this SELECT. */ | ||
| 465 | if (select_lex->handle_derived(thd->lex, DT_MERGE)) | ||
| 466 | DBUG_RETURN(TRUE); | ||
| 467 | + table_count= select_lex->leaf_tables.elements; | ||
| 468 | } | ||
| 469 | |||
| 470 | if (select_lex->first_cond_optimization && | ||
| 471 | @@ -2084,6 +2085,8 @@ JOIN::optimize_inner() | ||
| 472 | |||
| 473 | eval_select_list_used_tables(); | ||
| 474 | |||
| 475 | + table_count= select_lex->leaf_tables.elements; | ||
| 476 | + | ||
| 477 | if (select_lex->options & OPTION_SCHEMA_TABLE && | ||
| 478 | optimize_schema_tables_memory_usage(select_lex->leaf_tables)) | ||
| 479 | DBUG_RETURN(1); | ||
| 480 | @@ -14549,6 +14552,7 @@ void JOIN::cleanup(bool full) | ||
| 481 | /* Free the original optimized join created for the group_by_handler */ | ||
| 482 | join_tab= original_join_tab; | ||
| 483 | original_join_tab= 0; | ||
| 484 | + table_count= original_table_count; | ||
| 485 | } | ||
| 486 | |||
| 487 | if (join_tab) | ||
| 488 | diff --git a/sql/sql_select.h b/sql/sql_select.h | ||
| 489 | index 6efdcafd..e1e06e73 100644 | ||
| 490 | --- a/sql/sql_select.h | ||
| 491 | +++ b/sql/sql_select.h | ||
| 492 | @@ -1291,6 +1291,7 @@ class JOIN :public Sql_alloc | ||
| 493 | |||
| 494 | Pushdown_query *pushdown_query; | ||
| 495 | JOIN_TAB *original_join_tab; | ||
| 496 | + uint original_table_count; | ||
| 497 | |||
| 498 | /******* Join optimization state members start *******/ | ||
| 499 | /* | ||
| 500 | -- | ||
| 501 | 2.40.0 | ||
| 502 | |||
diff --git a/meta-oe/recipes-dbs/mysql/mariadb/CVE-2023-52969-CVE-20230-52970-0002.patch b/meta-oe/recipes-dbs/mysql/mariadb/CVE-2023-52969-CVE-20230-52970-0002.patch new file mode 100644 index 0000000000..75cae12305 --- /dev/null +++ b/meta-oe/recipes-dbs/mysql/mariadb/CVE-2023-52969-CVE-20230-52970-0002.patch | |||
| @@ -0,0 +1,168 @@ | |||
| 1 | From d98ac8511e39770ef3d8b42937c84e876d1459e7 Mon Sep 17 00:00:00 2001 | ||
| 2 | From: Oleg Smirnov <olernov@gmail.com> | ||
| 3 | Date: Sat, 26 Oct 2024 20:29:56 +0700 | ||
| 4 | Subject: [PATCH] MDEV-26247 MariaDB Server SEGV on INSERT .. SELECT | ||
| 5 | |||
| 6 | This problem occured for statements like `INSERT INTO t1 SELECT 1`, | ||
| 7 | which do not have tables in the SELECT part. In such scenarios | ||
| 8 | SELECT_LEX::insert_tables was not properly set at `setup_tables()`, | ||
| 9 | and this led to either incorrect execution or a crash | ||
| 10 | |||
| 11 | Reviewer: Oleksandr Byelkin <sanja@mariadb.com> | ||
| 12 | |||
| 13 | CVE: CVE-2023-52969 and CVE-2023-52970 | ||
| 14 | Upstream-Status: Backport [https://github.com/MariaDB/server/commit/d98ac8511e39770ef3d8b42937c84e876d1459e7] | ||
| 15 | |||
| 16 | Signed-off-by: Yogita Urade <yogita.urade@windriver.com> | ||
| 17 | --- | ||
| 18 | mysql-test/main/insert_select.result | 49 ++++++++++++++++++++++++++++ | ||
| 19 | mysql-test/main/insert_select.test | 35 ++++++++++++++++++++ | ||
| 20 | sql/sql_base.cc | 16 +++++++-- | ||
| 21 | 3 files changed, 97 insertions(+), 3 deletions(-) | ||
| 22 | |||
| 23 | diff --git a/mysql-test/main/insert_select.result b/mysql-test/main/insert_select.result | ||
| 24 | index 10c87271..79f8c519 100644 | ||
| 25 | --- a/mysql-test/main/insert_select.result | ||
| 26 | +++ b/mysql-test/main/insert_select.result | ||
| 27 | @@ -986,3 +986,52 @@ drop table t1, t2; | ||
| 28 | # | ||
| 29 | # End of 10.3 test | ||
| 30 | # | ||
| 31 | +# | ||
| 32 | +# MDEV-26427 MariaDB Server SEGV on INSERT .. SELECT | ||
| 33 | +# | ||
| 34 | +CREATE TABLE t1 (a int); | ||
| 35 | +INSERT INTO t1 SELECT AVG(1); | ||
| 36 | +SELECT * FROM t1; | ||
| 37 | +a | ||
| 38 | +1 | ||
| 39 | +INSERT INTO t1 SELECT MIN(2) OVER (); | ||
| 40 | +SELECT * FROM t1; | ||
| 41 | +a | ||
| 42 | +1 | ||
| 43 | +2 | ||
| 44 | +CREATE VIEW v1 AS SELECT * FROM t1 ORDER BY a; | ||
| 45 | +INSERT INTO v1 SELECT SUM(3); | ||
| 46 | +SELECT * FROM v1; | ||
| 47 | +a | ||
| 48 | +1 | ||
| 49 | +2 | ||
| 50 | +3 | ||
| 51 | +INSERT INTO v1 SELECT * FROM v1; | ||
| 52 | +SELECT * FROM t1; | ||
| 53 | +a | ||
| 54 | +1 | ||
| 55 | +1 | ||
| 56 | +2 | ||
| 57 | +2 | ||
| 58 | +3 | ||
| 59 | +3 | ||
| 60 | +INSERT INTO t1 SELECT * FROM v1; | ||
| 61 | +SELECT * FROM t1; | ||
| 62 | +a | ||
| 63 | +1 | ||
| 64 | +1 | ||
| 65 | +1 | ||
| 66 | +1 | ||
| 67 | +2 | ||
| 68 | +2 | ||
| 69 | +2 | ||
| 70 | +2 | ||
| 71 | +3 | ||
| 72 | +3 | ||
| 73 | +3 | ||
| 74 | +3 | ||
| 75 | +DROP VIEW v1; | ||
| 76 | +DROP TABLE t1; | ||
| 77 | +# | ||
| 78 | +# End of 10.5 test | ||
| 79 | +# | ||
| 80 | diff --git a/mysql-test/main/insert_select.test b/mysql-test/main/insert_select.test | ||
| 81 | index 7417bab9..0e9bd05a 100644 | ||
| 82 | --- a/mysql-test/main/insert_select.test | ||
| 83 | +++ b/mysql-test/main/insert_select.test | ||
| 84 | @@ -559,3 +559,38 @@ drop table t1, t2; | ||
| 85 | --echo # | ||
| 86 | --echo # End of 10.3 test | ||
| 87 | --echo # | ||
| 88 | + | ||
| 89 | +--echo # | ||
| 90 | +--echo # MDEV-26427 MariaDB Server SEGV on INSERT .. SELECT | ||
| 91 | +--echo # | ||
| 92 | + | ||
| 93 | +CREATE TABLE t1 (a int); | ||
| 94 | + | ||
| 95 | +INSERT INTO t1 SELECT AVG(1); | ||
| 96 | +--sorted_result | ||
| 97 | +SELECT * FROM t1; | ||
| 98 | + | ||
| 99 | +INSERT INTO t1 SELECT MIN(2) OVER (); | ||
| 100 | +--sorted_result | ||
| 101 | +SELECT * FROM t1; | ||
| 102 | + | ||
| 103 | +CREATE VIEW v1 AS SELECT * FROM t1 ORDER BY a; | ||
| 104 | + | ||
| 105 | +INSERT INTO v1 SELECT SUM(3); | ||
| 106 | +--sorted_result | ||
| 107 | +SELECT * FROM v1; | ||
| 108 | + | ||
| 109 | +INSERT INTO v1 SELECT * FROM v1; | ||
| 110 | +--sorted_result | ||
| 111 | +SELECT * FROM t1; | ||
| 112 | + | ||
| 113 | +INSERT INTO t1 SELECT * FROM v1; | ||
| 114 | +--sorted_result | ||
| 115 | +SELECT * FROM t1; | ||
| 116 | + | ||
| 117 | +DROP VIEW v1; | ||
| 118 | +DROP TABLE t1; | ||
| 119 | + | ||
| 120 | +--echo # | ||
| 121 | +--echo # End of 10.5 test | ||
| 122 | +--echo # | ||
| 123 | diff --git a/sql/sql_base.cc b/sql/sql_base.cc | ||
| 124 | index 4f04f23d..d50f3407 100644 | ||
| 125 | --- a/sql/sql_base.cc | ||
| 126 | +++ b/sql/sql_base.cc | ||
| 127 | @@ -7876,18 +7876,19 @@ bool setup_tables(THD *thd, Name_resolution_context *context, | ||
| 128 | while ((table_list= ti++)) | ||
| 129 | leaves.push_back(table_list, thd->mem_root); | ||
| 130 | } | ||
| 131 | - | ||
| 132 | + | ||
| 133 | + bool is_insert_tables_num_set= false; | ||
| 134 | while ((table_list= ti++)) | ||
| 135 | { | ||
| 136 | TABLE *table= table_list->table; | ||
| 137 | if (table) | ||
| 138 | table->pos_in_table_list= table_list; | ||
| 139 | - if (first_select_table && | ||
| 140 | + if (select_insert && !is_insert_tables_num_set && | ||
| 141 | table_list->top_table() == first_select_table) | ||
| 142 | { | ||
| 143 | /* new counting for SELECT of INSERT ... SELECT command */ | ||
| 144 | - first_select_table= 0; | ||
| 145 | thd->lex->first_select_lex()->insert_tables= tablenr; | ||
| 146 | + is_insert_tables_num_set= true; | ||
| 147 | tablenr= 0; | ||
| 148 | } | ||
| 149 | if(table_list->jtbm_subselect) | ||
| 150 | @@ -7909,6 +7910,15 @@ bool setup_tables(THD *thd, Name_resolution_context *context, | ||
| 151 | my_error(ER_TOO_MANY_TABLES,MYF(0), static_cast<int>(MAX_TABLES)); | ||
| 152 | DBUG_RETURN(1); | ||
| 153 | } | ||
| 154 | + if (select_insert && !is_insert_tables_num_set) | ||
| 155 | + { | ||
| 156 | + /* | ||
| 157 | + This happens for statements like `INSERT INTO t1 SELECT 1`, | ||
| 158 | + when there are no tables in the SELECT part. | ||
| 159 | + In this case all leaf tables belong to the INSERT part | ||
| 160 | + */ | ||
| 161 | + thd->lex->first_select_lex()->insert_tables= tablenr; | ||
| 162 | + } | ||
| 163 | } | ||
| 164 | else | ||
| 165 | { | ||
| 166 | -- | ||
| 167 | 2.40.0 | ||
| 168 | |||
diff --git a/meta-oe/recipes-dbs/mysql/mariadb/CVE-2023-52969-CVE-20230-52970-0003.patch b/meta-oe/recipes-dbs/mysql/mariadb/CVE-2023-52969-CVE-20230-52970-0003.patch new file mode 100644 index 0000000000..a00820c156 --- /dev/null +++ b/meta-oe/recipes-dbs/mysql/mariadb/CVE-2023-52969-CVE-20230-52970-0003.patch | |||
| @@ -0,0 +1,470 @@ | |||
| 1 | From 9b313d2de1df65626abb3b1d6c973f74addb12fb Mon Sep 17 00:00:00 2001 | ||
| 2 | From: Oleksandr Byelkin <sanja@mariadb.com> | ||
| 3 | Date: Tue, 1 Apr 2025 20:57:29 +0200 | ||
| 4 | Subject: [PATCH] MDEV-32086 Server crash when inserting from derived table | ||
| 5 | containing insert target table | ||
| 6 | |||
| 7 | Use original solution for INSERT ... SELECT - select result buferisation. | ||
| 8 | |||
| 9 | Also fix MDEV-36447 and MDEV-33139 | ||
| 10 | |||
| 11 | CVE: CVE-2023-52969 and CVE-2023-52970 | ||
| 12 | Upstream-Status: Backport [https://github.com/MariaDB/server/commit/9b313d2de1df65626abb3b1d6c973f74addb12fb] | ||
| 13 | |||
| 14 | Signed-off-by: Yogita Urade <yogita.urade@windriver.com> | ||
| 15 | --- | ||
| 16 | mysql-test/main/derived_cond_pushdown.result | 125 ++++++++---------- | ||
| 17 | mysql-test/main/derived_view.result | 2 + | ||
| 18 | mysql-test/main/insert_select.result | 129 ++++++++++++++++++- | ||
| 19 | mysql-test/main/insert_select.test | 56 +++++++- | ||
| 20 | sql/sql_base.cc | 15 ++- | ||
| 21 | sql/sql_base.h | 1 + | ||
| 22 | sql/sql_insert.cc | 11 +- | ||
| 23 | 7 files changed, 260 insertions(+), 79 deletions(-) | ||
| 24 | |||
| 25 | diff --git a/mysql-test/main/derived_cond_pushdown.result b/mysql-test/main/derived_cond_pushdown.result | ||
| 26 | index f47920c0..9eac511e 100644 | ||
| 27 | --- a/mysql-test/main/derived_cond_pushdown.result | ||
| 28 | +++ b/mysql-test/main/derived_cond_pushdown.result | ||
| 29 | @@ -10223,9 +10223,8 @@ SELECT * FROM ( SELECT t1.f FROM v1 JOIN t1 ) AS t WHERE f IS NOT NULL; | ||
| 30 | EXPLAIN INSERT INTO t1 | ||
| 31 | SELECT * FROM ( SELECT t1.f FROM v1 JOIN t1 ) AS t WHERE f IS NOT NULL; | ||
| 32 | id select_type table type possible_keys key key_len ref rows Extra | ||
| 33 | -1 PRIMARY <derived2> ALL NULL NULL NULL NULL 144 Using where | ||
| 34 | -2 DERIVED <derived4> ALL NULL NULL NULL NULL 12 | ||
| 35 | -2 DERIVED t1 ALL NULL NULL NULL NULL 12 Using where; Using join buffer (flat, BNL join) | ||
| 36 | +1 PRIMARY <derived4> ALL NULL NULL NULL NULL 12 Using temporary | ||
| 37 | +1 PRIMARY t1 ALL NULL NULL NULL NULL 12 Using where; Using join buffer (flat, BNL join) | ||
| 38 | 4 DERIVED t1 ALL NULL NULL NULL NULL 12 | ||
| 39 | EXPLAIN FORMAT=JSON INSERT INTO t1 | ||
| 40 | SELECT * FROM ( SELECT t1.f FROM v1 JOIN t1 ) AS t WHERE f IS NOT NULL; | ||
| 41 | @@ -10233,45 +10232,35 @@ EXPLAIN | ||
| 42 | { | ||
| 43 | "query_block": { | ||
| 44 | "select_id": 1, | ||
| 45 | - "table": { | ||
| 46 | - "table_name": "<derived2>", | ||
| 47 | - "access_type": "ALL", | ||
| 48 | - "rows": 144, | ||
| 49 | - "filtered": 100, | ||
| 50 | - "attached_condition": "t.f is not null", | ||
| 51 | - "materialized": { | ||
| 52 | - "query_block": { | ||
| 53 | - "select_id": 2, | ||
| 54 | - "table": { | ||
| 55 | - "table_name": "<derived4>", | ||
| 56 | - "access_type": "ALL", | ||
| 57 | - "rows": 12, | ||
| 58 | - "filtered": 100, | ||
| 59 | - "materialized": { | ||
| 60 | - "query_block": { | ||
| 61 | - "select_id": 4, | ||
| 62 | - "table": { | ||
| 63 | - "table_name": "t1", | ||
| 64 | - "access_type": "ALL", | ||
| 65 | - "rows": 12, | ||
| 66 | - "filtered": 100 | ||
| 67 | - } | ||
| 68 | - } | ||
| 69 | - } | ||
| 70 | - }, | ||
| 71 | - "block-nl-join": { | ||
| 72 | + "temporary_table": { | ||
| 73 | + "table": { | ||
| 74 | + "table_name": "<derived4>", | ||
| 75 | + "access_type": "ALL", | ||
| 76 | + "rows": 12, | ||
| 77 | + "filtered": 100, | ||
| 78 | + "materialized": { | ||
| 79 | + "query_block": { | ||
| 80 | + "select_id": 4, | ||
| 81 | "table": { | ||
| 82 | "table_name": "t1", | ||
| 83 | "access_type": "ALL", | ||
| 84 | "rows": 12, | ||
| 85 | - "filtered": 100, | ||
| 86 | - "attached_condition": "t1.f is not null" | ||
| 87 | - }, | ||
| 88 | - "buffer_type": "flat", | ||
| 89 | - "buffer_size": "64", | ||
| 90 | - "join_type": "BNL" | ||
| 91 | + "filtered": 100 | ||
| 92 | + } | ||
| 93 | } | ||
| 94 | } | ||
| 95 | + }, | ||
| 96 | + "block-nl-join": { | ||
| 97 | + "table": { | ||
| 98 | + "table_name": "t1", | ||
| 99 | + "access_type": "ALL", | ||
| 100 | + "rows": 12, | ||
| 101 | + "filtered": 100, | ||
| 102 | + "attached_condition": "t1.f is not null" | ||
| 103 | + }, | ||
| 104 | + "buffer_type": "flat", | ||
| 105 | + "buffer_size": "64", | ||
| 106 | + "join_type": "BNL" | ||
| 107 | } | ||
| 108 | } | ||
| 109 | } | ||
| 110 | @@ -10302,43 +10291,33 @@ EXPLAIN | ||
| 111 | { | ||
| 112 | "query_block": { | ||
| 113 | "select_id": 1, | ||
| 114 | - "table": { | ||
| 115 | - "table_name": "<derived2>", | ||
| 116 | - "access_type": "ALL", | ||
| 117 | - "rows": 16, | ||
| 118 | - "filtered": 100, | ||
| 119 | - "attached_condition": "t.f is not null", | ||
| 120 | - "materialized": { | ||
| 121 | - "query_block": { | ||
| 122 | - "select_id": 2, | ||
| 123 | - "table": { | ||
| 124 | - "table_name": "t1", | ||
| 125 | - "access_type": "ALL", | ||
| 126 | - "rows": 8, | ||
| 127 | - "filtered": 100, | ||
| 128 | - "attached_condition": "t1.f is not null" | ||
| 129 | - }, | ||
| 130 | - "table": { | ||
| 131 | - "table_name": "<derived4>", | ||
| 132 | - "access_type": "ref", | ||
| 133 | - "possible_keys": ["key0"], | ||
| 134 | - "key": "key0", | ||
| 135 | - "key_length": "4", | ||
| 136 | - "used_key_parts": ["f"], | ||
| 137 | - "ref": ["test.t1.f"], | ||
| 138 | - "rows": 2, | ||
| 139 | - "filtered": 100, | ||
| 140 | - "materialized": { | ||
| 141 | - "query_block": { | ||
| 142 | - "select_id": 4, | ||
| 143 | - "table": { | ||
| 144 | - "table_name": "t1", | ||
| 145 | - "access_type": "ALL", | ||
| 146 | - "rows": 8, | ||
| 147 | - "filtered": 100, | ||
| 148 | - "attached_condition": "t1.f is not null" | ||
| 149 | - } | ||
| 150 | - } | ||
| 151 | + "temporary_table": { | ||
| 152 | + "table": { | ||
| 153 | + "table_name": "t1", | ||
| 154 | + "access_type": "ALL", | ||
| 155 | + "rows": 8, | ||
| 156 | + "filtered": 100, | ||
| 157 | + "attached_condition": "t1.f is not null" | ||
| 158 | + }, | ||
| 159 | + "table": { | ||
| 160 | + "table_name": "<derived4>", | ||
| 161 | + "access_type": "ref", | ||
| 162 | + "possible_keys": ["key0"], | ||
| 163 | + "key": "key0", | ||
| 164 | + "key_length": "4", | ||
| 165 | + "used_key_parts": ["f"], | ||
| 166 | + "ref": ["test.t1.f"], | ||
| 167 | + "rows": 2, | ||
| 168 | + "filtered": 100, | ||
| 169 | + "materialized": { | ||
| 170 | + "query_block": { | ||
| 171 | + "select_id": 4, | ||
| 172 | + "table": { | ||
| 173 | + "table_name": "t1", | ||
| 174 | + "access_type": "ALL", | ||
| 175 | + "rows": 8, | ||
| 176 | + "filtered": 100, | ||
| 177 | + "attached_condition": "t1.f is not null" | ||
| 178 | } | ||
| 179 | } | ||
| 180 | } | ||
| 181 | diff --git a/mysql-test/main/derived_view.result b/mysql-test/main/derived_view.result | ||
| 182 | index 15a7784c..3df1acc6 100644 | ||
| 183 | --- a/mysql-test/main/derived_view.result | ||
| 184 | +++ b/mysql-test/main/derived_view.result | ||
| 185 | @@ -2383,6 +2383,8 @@ SELECT * FROM t1; | ||
| 186 | a | ||
| 187 | 1 | ||
| 188 | 1 | ||
| 189 | +1 | ||
| 190 | +1 | ||
| 191 | drop table t1,t2; | ||
| 192 | set optimizer_switch=@save968720_optimizer_switch; | ||
| 193 | # | ||
| 194 | diff --git a/mysql-test/main/insert_select.result b/mysql-test/main/insert_select.result | ||
| 195 | index 79f8c519..ceb2fb8f 100644 | ||
| 196 | --- a/mysql-test/main/insert_select.result | ||
| 197 | +++ b/mysql-test/main/insert_select.result | ||
| 198 | @@ -1032,6 +1032,133 @@ a | ||
| 199 | 3 | ||
| 200 | DROP VIEW v1; | ||
| 201 | DROP TABLE t1; | ||
| 202 | +create table t1 (pk int, id int); | ||
| 203 | +insert into t1 values (2,2), (3,3), (4,4); | ||
| 204 | +insert into t1 | ||
| 205 | +select 1,10 | ||
| 206 | +from | ||
| 207 | +( | ||
| 208 | +select dt2.id from (select id from t1) dt2, t1 t where t.id=dt2.id | ||
| 209 | +) dt | ||
| 210 | +where dt.id=3; | ||
| 211 | +select * from t1; | ||
| 212 | +pk id | ||
| 213 | +2 2 | ||
| 214 | +3 3 | ||
| 215 | +4 4 | ||
| 216 | +1 10 | ||
| 217 | +explain insert into t1 | ||
| 218 | +select 1,10 | ||
| 219 | +from | ||
| 220 | +( | ||
| 221 | +select dt2.id from (select id from t1) dt2, t1 t where t.id=dt2.id | ||
| 222 | +) dt | ||
| 223 | +where dt.id=3; | ||
| 224 | +id select_type table type possible_keys key key_len ref rows Extra | ||
| 225 | +1 SIMPLE t1 ALL NULL NULL NULL NULL 4 Using where; Using temporary | ||
| 226 | +1 SIMPLE t ALL NULL NULL NULL NULL 4 Using where; Using join buffer (flat, BNL join) | ||
| 227 | +explain format=json insert into t1 | ||
| 228 | +select 1,10 | ||
| 229 | +from | ||
| 230 | +( | ||
| 231 | +select dt2.id from (select id from t1) dt2, t1 t where t.id=dt2.id | ||
| 232 | +) dt | ||
| 233 | +where dt.id=3; | ||
| 234 | +EXPLAIN | ||
| 235 | +{ | ||
| 236 | + "query_block": { | ||
| 237 | + "select_id": 1, | ||
| 238 | + "temporary_table": { | ||
| 239 | + "table": { | ||
| 240 | + "table_name": "t1", | ||
| 241 | + "access_type": "ALL", | ||
| 242 | + "rows": 4, | ||
| 243 | + "filtered": 100, | ||
| 244 | + "attached_condition": "t1.`id` = 3" | ||
| 245 | + }, | ||
| 246 | + "block-nl-join": { | ||
| 247 | + "table": { | ||
| 248 | + "table_name": "t", | ||
| 249 | + "access_type": "ALL", | ||
| 250 | + "rows": 4, | ||
| 251 | + "filtered": 100, | ||
| 252 | + "attached_condition": "t.`id` = 3" | ||
| 253 | + }, | ||
| 254 | + "buffer_type": "flat", | ||
| 255 | + "buffer_size": "65", | ||
| 256 | + "join_type": "BNL" | ||
| 257 | + } | ||
| 258 | + } | ||
| 259 | + } | ||
| 260 | +} | ||
| 261 | +prepare stmt from "insert into t1 | ||
| 262 | +select 1,10 | ||
| 263 | +from | ||
| 264 | +( | ||
| 265 | +select dt2.id from (select id from t1) dt2, t1 t where t.id=dt2.id | ||
| 266 | +) dt | ||
| 267 | +where dt.id=3"; | ||
| 268 | +execute stmt; | ||
| 269 | +select * from t1; | ||
| 270 | +pk id | ||
| 271 | +2 2 | ||
| 272 | +3 3 | ||
| 273 | +4 4 | ||
| 274 | +1 10 | ||
| 275 | +1 10 | ||
| 276 | +execute stmt; | ||
| 277 | +select * from t1; | ||
| 278 | +pk id | ||
| 279 | +2 2 | ||
| 280 | +3 3 | ||
| 281 | +4 4 | ||
| 282 | +1 10 | ||
| 283 | +1 10 | ||
| 284 | +1 10 | ||
| 285 | +deallocate prepare stmt; | ||
| 286 | +create procedure p() insert into t1 | ||
| 287 | +select 1,10 | ||
| 288 | +from | ||
| 289 | +( | ||
| 290 | +select dt2.id from (select id from t1) dt2, t1 t where t.id=dt2.id | ||
| 291 | +) dt | ||
| 292 | +where dt.id=3; | ||
| 293 | +call p(); | ||
| 294 | +select * from t1; | ||
| 295 | +pk id | ||
| 296 | +2 2 | ||
| 297 | +3 3 | ||
| 298 | +4 4 | ||
| 299 | +1 10 | ||
| 300 | +1 10 | ||
| 301 | +1 10 | ||
| 302 | +1 10 | ||
| 303 | +call p(); | ||
| 304 | +select * from t1; | ||
| 305 | +pk id | ||
| 306 | +2 2 | ||
| 307 | +3 3 | ||
| 308 | +4 4 | ||
| 309 | +1 10 | ||
| 310 | +1 10 | ||
| 311 | +1 10 | ||
| 312 | +1 10 | ||
| 313 | +1 10 | ||
| 314 | +drop procedure p; | ||
| 315 | +drop table t1; | ||
| 316 | # | ||
| 317 | -# End of 10.5 test | ||
| 318 | +# MDEV-33139: Crash of INSERT SELECT when preparing structures for | ||
| 319 | +# split optimization | ||
| 320 | # | ||
| 321 | +CREATE TABLE v0 ( v1 INT UNIQUE ) ; | ||
| 322 | +INSERT INTO v0 ( v1 ) VALUES | ||
| 323 | +( ( SELECT | ||
| 324 | +FROM | ||
| 325 | +( SELECT v1 | ||
| 326 | +FROM v0 GROUP BY v1 ) AS v6 NATURAL JOIN | ||
| 327 | +v0 AS v2 NATURAL JOIN | ||
| 328 | +v0 AS v4 NATURAL JOIN | ||
| 329 | +v0 AS v3 NATURAL JOIN | ||
| 330 | +( SELECT v1 FROM v0 ) AS v7 ) ) ; | ||
| 331 | +DROP TABLE v0; | ||
| 332 | +# End of 10.5 tests | ||
| 333 | diff --git a/mysql-test/main/insert_select.test b/mysql-test/main/insert_select.test | ||
| 334 | index 0e9bd05a..5c2691c9 100644 | ||
| 335 | --- a/mysql-test/main/insert_select.test | ||
| 336 | +++ b/mysql-test/main/insert_select.test | ||
| 337 | @@ -591,6 +591,60 @@ SELECT * FROM t1; | ||
| 338 | DROP VIEW v1; | ||
| 339 | DROP TABLE t1; | ||
| 340 | |||
| 341 | +# | ||
| 342 | +# MDEV-32086: condition pushdown into two mergeable derived tables, | ||
| 343 | +# one containing the other, when they are forced to be | ||
| 344 | +# materialized in INSERT | ||
| 345 | +# | ||
| 346 | +create table t1 (pk int, id int); | ||
| 347 | +insert into t1 values (2,2), (3,3), (4,4); | ||
| 348 | + | ||
| 349 | +let $q= | ||
| 350 | +insert into t1 | ||
| 351 | + select 1,10 | ||
| 352 | + from | ||
| 353 | + ( | ||
| 354 | + select dt2.id from (select id from t1) dt2, t1 t where t.id=dt2.id | ||
| 355 | + ) dt | ||
| 356 | + where dt.id=3; | ||
| 357 | + | ||
| 358 | +eval $q; | ||
| 359 | +select * from t1; | ||
| 360 | + | ||
| 361 | +eval explain $q; | ||
| 362 | +eval explain format=json $q; | ||
| 363 | + | ||
| 364 | +eval prepare stmt from "$q"; | ||
| 365 | +execute stmt; | ||
| 366 | +select * from t1; | ||
| 367 | +execute stmt; | ||
| 368 | +select * from t1; | ||
| 369 | +deallocate prepare stmt; | ||
| 370 | + | ||
| 371 | +eval create procedure p() $q; | ||
| 372 | +call p(); | ||
| 373 | +select * from t1; | ||
| 374 | +call p(); | ||
| 375 | +select * from t1; | ||
| 376 | +drop procedure p; | ||
| 377 | + | ||
| 378 | +drop table t1; | ||
| 379 | + | ||
| 380 | --echo # | ||
| 381 | ---echo # End of 10.5 test | ||
| 382 | +--echo # MDEV-33139: Crash of INSERT SELECT when preparing structures for | ||
| 383 | +--echo # split optimization | ||
| 384 | --echo # | ||
| 385 | + | ||
| 386 | +CREATE TABLE v0 ( v1 INT UNIQUE ) ; | ||
| 387 | +INSERT INTO v0 ( v1 ) VALUES | ||
| 388 | + ( ( SELECT 1 | ||
| 389 | + FROM | ||
| 390 | + ( SELECT v1 | ||
| 391 | + FROM v0 GROUP BY v1 ) AS v6 NATURAL JOIN | ||
| 392 | + v0 AS v2 NATURAL JOIN | ||
| 393 | + v0 AS v4 NATURAL JOIN | ||
| 394 | + v0 AS v3 NATURAL JOIN | ||
| 395 | + ( SELECT v1 FROM v0 ) AS v7 ) ) ; | ||
| 396 | +DROP TABLE v0; | ||
| 397 | + | ||
| 398 | +--echo # End of 10.5 tests | ||
| 399 | diff --git a/sql/sql_base.cc b/sql/sql_base.cc | ||
| 400 | index d50f3407..15a9882b 100644 | ||
| 401 | --- a/sql/sql_base.cc | ||
| 402 | +++ b/sql/sql_base.cc | ||
| 403 | @@ -1176,11 +1176,20 @@ TABLE_LIST* find_dup_table(THD *thd, TABLE_LIST *table, TABLE_LIST *table_list, | ||
| 404 | DBUG_PRINT("info", | ||
| 405 | ("found same copy of table or table which we should skip")); | ||
| 406 | } | ||
| 407 | - if (res && res->belong_to_derived) | ||
| 408 | + /* | ||
| 409 | + If we've found a duplicate in a derived table, try to work around that. | ||
| 410 | + | ||
| 411 | + For INSERT...SELECT, do not do any workarounds, return the duplicate. The | ||
| 412 | + caller will enable buffering to handle this. | ||
| 413 | + */ | ||
| 414 | + if (res && res->belong_to_derived && | ||
| 415 | + !(check_flag & CHECK_DUP_FOR_INSERT_SELECT)) | ||
| 416 | { | ||
| 417 | /* | ||
| 418 | - We come here for queries of type: | ||
| 419 | - INSERT INTO t1 (SELECT tmp.a FROM (select * FROM t1) as tmp); | ||
| 420 | + We come here for queries like this: | ||
| 421 | + | ||
| 422 | + INSERT INTO t1 VALUES ((SELECT tmp.a FROM (select * FROM t1))); | ||
| 423 | + DELETE FROM t1 WHERE ( ... (SELECT ... FROM t1) ) ; | ||
| 424 | |||
| 425 | Try to fix by materializing the derived table | ||
| 426 | */ | ||
| 427 | diff --git a/sql/sql_base.h b/sql/sql_base.h | ||
| 428 | index 5b449fdd..da9b1575 100644 | ||
| 429 | --- a/sql/sql_base.h | ||
| 430 | +++ b/sql/sql_base.h | ||
| 431 | @@ -72,6 +72,7 @@ enum find_item_error_report_type {REPORT_ALL_ERRORS, REPORT_EXCEPT_NOT_FOUND, | ||
| 432 | #define CHECK_DUP_ALLOW_DIFFERENT_ALIAS 1 | ||
| 433 | #define CHECK_DUP_FOR_CREATE 2 | ||
| 434 | #define CHECK_DUP_SKIP_TEMP_TABLE 4 | ||
| 435 | +#define CHECK_DUP_FOR_INSERT_SELECT 8 | ||
| 436 | |||
| 437 | uint get_table_def_key(const TABLE_LIST *table_list, const char **key); | ||
| 438 | TABLE *open_ltable(THD *thd, TABLE_LIST *table_list, thr_lock_type update, | ||
| 439 | diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc | ||
| 440 | index 50e3bcd3..d9813660 100644 | ||
| 441 | --- a/sql/sql_insert.cc | ||
| 442 | +++ b/sql/sql_insert.cc | ||
| 443 | @@ -1741,6 +1741,14 @@ int mysql_prepare_insert(THD *thd, TABLE_LIST *table_list, | ||
| 444 | DBUG_RETURN(1); | ||
| 445 | } | ||
| 446 | |||
| 447 | + /* | ||
| 448 | + Check if we read from the same table we're inserting into. | ||
| 449 | + Queries like INSERT INTO t1 VALUES ((SELECT ... FROM t1...)) are not | ||
| 450 | + allowed. | ||
| 451 | + | ||
| 452 | + INSERT...SELECT is an exception: it will detect this case and use | ||
| 453 | + buffering to handle it correctly. | ||
| 454 | + */ | ||
| 455 | if (!select_insert) | ||
| 456 | { | ||
| 457 | Item *fake_conds= 0; | ||
| 458 | @@ -4021,7 +4029,8 @@ select_insert::prepare(List<Item> &values, SELECT_LEX_UNIT *u) | ||
| 459 | Is table which we are changing used somewhere in other parts of | ||
| 460 | query | ||
| 461 | */ | ||
| 462 | - if (unique_table(thd, table_list, table_list->next_global, 0)) | ||
| 463 | + if (unique_table(thd, table_list, table_list->next_global, | ||
| 464 | + CHECK_DUP_FOR_INSERT_SELECT)) | ||
| 465 | { | ||
| 466 | /* Using same table for INSERT and SELECT */ | ||
| 467 | lex->current_select->options|= OPTION_BUFFER_RESULT; | ||
| 468 | -- | ||
| 469 | 2.40.0 | ||
| 470 | |||
diff --git a/meta-oe/recipes-dbs/mysql/mariadb/CVE-2023-52969-CVE-20230-52970-0004.patch b/meta-oe/recipes-dbs/mysql/mariadb/CVE-2023-52969-CVE-20230-52970-0004.patch new file mode 100644 index 0000000000..476bee127a --- /dev/null +++ b/meta-oe/recipes-dbs/mysql/mariadb/CVE-2023-52969-CVE-20230-52970-0004.patch | |||
| @@ -0,0 +1,1785 @@ | |||
| 1 | From 4fc9dc84b017cf9f30585bcdef0663f9425fe460 Mon Sep 17 00:00:00 2001 | ||
| 2 | From: Oleksandr Byelkin <sanja@mariadb.com> | ||
| 3 | Date: Fri, 18 Apr 2025 12:14:23 +0200 | ||
| 4 | Subject: [PATCH] MDEV-32086 (part 2) Server crash when inserting from derived | ||
| 5 | table containing insert target table | ||
| 6 | |||
| 7 | Get rid of need of matherialization for usual INSERT (cache results in | ||
| 8 | Item_cache* if needed) | ||
| 9 | |||
| 10 | - subqueries in VALUE do not see new records in the table we are | ||
| 11 | inserting to | ||
| 12 | - subqueries in RETIRNING prohibited to use the table we are inserting to | ||
| 13 | |||
| 14 | Changes: | ||
| 15 | - subselect_elimination.result and subselect_elimination.test files | ||
| 16 | are not presented so skip those changes. | ||
| 17 | |||
| 18 | CVE: CVE-2023-52969 and CVE-2023-52970 | ||
| 19 | Upstream-Status: Backport [https://github.com/MariaDB/server/commit/4fc9dc84b017cf9f30585bcdef0663f9425fe460] | ||
| 20 | |||
| 21 | Signed-off-by: Yogita Urade <yogita.urade@windriver.com> | ||
| 22 | --- | ||
| 23 | mysql-test/main/insert.result | 72 +++++++- | ||
| 24 | mysql-test/main/insert.test | 56 +++++- | ||
| 25 | mysql-test/main/insert_returning.result | 2 + | ||
| 26 | mysql-test/main/insert_returning.test | 2 + | ||
| 27 | mysql-test/main/lowercase_view.result | 12 -- | ||
| 28 | mysql-test/main/lowercase_view.test | 12 -- | ||
| 29 | mysql-test/main/merge.result | 17 +- | ||
| 30 | mysql-test/main/merge.test | 17 +- | ||
| 31 | mysql-test/main/subselect.result | 20 ++- | ||
| 32 | mysql-test/main/subselect.test | 10 +- | ||
| 33 | .../main/subselect_no_exists_to_in.result | 20 ++- | ||
| 34 | mysql-test/main/subselect_no_mat.result | 20 ++- | ||
| 35 | mysql-test/main/subselect_no_opts.result | 20 ++- | ||
| 36 | mysql-test/main/subselect_no_scache.result | 20 ++- | ||
| 37 | mysql-test/main/subselect_no_semijoin.result | 20 ++- | ||
| 38 | mysql-test/main/view.result | 49 ++++-- | ||
| 39 | mysql-test/main/view.test | 30 ++-- | ||
| 40 | mysql-test/suite/sql_sequence/other.result | 1 - | ||
| 41 | mysql-test/suite/sql_sequence/other.test | 1 - | ||
| 42 | sql/item.h | 12 ++ | ||
| 43 | sql/item_subselect.cc | 24 +++ | ||
| 44 | sql/item_subselect.h | 1 + | ||
| 45 | sql/sql_base.cc | 86 +++++++--- | ||
| 46 | sql/sql_base.h | 3 +- | ||
| 47 | sql/sql_insert.cc | 101 +++++++++-- | ||
| 48 | sql/sql_insert.h | 2 +- | ||
| 49 | sql/sql_lex.cc | 42 +++++ | ||
| 50 | sql/sql_lex.h | 4 + | ||
| 51 | sql/sql_prepare.cc | 4 +- | ||
| 52 | sql/table.h | 2 + | ||
| 53 | tests/mysql_client_test.c | 159 ++++++++++++++++++ | ||
| 54 | 31 files changed, 682 insertions(+), 159 deletions(-) | ||
| 55 | |||
| 56 | diff --git a/mysql-test/main/insert.result b/mysql-test/main/insert.result | ||
| 57 | index 586dbbff..49ebd740 100644 | ||
| 58 | --- a/mysql-test/main/insert.result | ||
| 59 | +++ b/mysql-test/main/insert.result | ||
| 60 | @@ -806,5 +806,75 @@ a | ||
| 61 | 8 | ||
| 62 | drop table t1; | ||
| 63 | # | ||
| 64 | -# End of 10.5 tests | ||
| 65 | +# MDEV-32086 Server crash when inserting from derived table containing insert target table | ||
| 66 | +# (part 2) | ||
| 67 | # | ||
| 68 | +create table t1 (pk int, id int); | ||
| 69 | +insert into t1 values (2,2), (3,3), (4,4); | ||
| 70 | +select * from t1; | ||
| 71 | +pk id | ||
| 72 | +2 2 | ||
| 73 | +3 3 | ||
| 74 | +4 4 | ||
| 75 | +select 101+count(*) | ||
| 76 | +from | ||
| 77 | +( | ||
| 78 | +select dt2.id | ||
| 79 | +from (select id from t1) dt2, t1 t where t.id=dt2.id | ||
| 80 | +) dt | ||
| 81 | +where dt.id<1000; | ||
| 82 | +101+count(*) | ||
| 83 | +104 | ||
| 84 | +prepare s from ' | ||
| 85 | +insert into t1 values( | ||
| 86 | + (select 101+count(*) | ||
| 87 | + from | ||
| 88 | + ( | ||
| 89 | + select dt2.id | ||
| 90 | + from (select id from t1) dt2, t1 t where t.id=dt2.id | ||
| 91 | + ) dt | ||
| 92 | + where dt.id<1000 | ||
| 93 | + ), 123 | ||
| 94 | +) | ||
| 95 | +'; | ||
| 96 | +execute s; | ||
| 97 | +select * from t1; | ||
| 98 | +pk id | ||
| 99 | +2 2 | ||
| 100 | +3 3 | ||
| 101 | +4 4 | ||
| 102 | +104 123 | ||
| 103 | +select 101+count(*) | ||
| 104 | +from | ||
| 105 | +( | ||
| 106 | +select dt2.id | ||
| 107 | +from (select id from t1) dt2, t1 t where t.id=dt2.id | ||
| 108 | +) dt | ||
| 109 | +where dt.id<1000; | ||
| 110 | +101+count(*) | ||
| 111 | +105 | ||
| 112 | +execute s; | ||
| 113 | +select * from t1; | ||
| 114 | +pk id | ||
| 115 | +2 2 | ||
| 116 | +3 3 | ||
| 117 | +4 4 | ||
| 118 | +104 123 | ||
| 119 | +105 123 | ||
| 120 | +drop table t1; | ||
| 121 | +# | ||
| 122 | +# Try this: INSERT INTO t1 VALUES ... reference to t1 | ||
| 123 | +# RETURNING (subquery not touching t1) | ||
| 124 | +create table t1 (a int, b int); | ||
| 125 | +create table t2 (a int, b int); | ||
| 126 | +# This is accepted: | ||
| 127 | +insert into t1 (a) values | ||
| 128 | +(3), | ||
| 129 | +((select max(a) from t1)) | ||
| 130 | +returning | ||
| 131 | +a, b, (select max(a) from t2); | ||
| 132 | +a b (select max(a) from t2) | ||
| 133 | +3 NULL NULL | ||
| 134 | +NULL NULL NULL | ||
| 135 | +drop table t1,t2; | ||
| 136 | +# End of 10.5 tests | ||
| 137 | diff --git a/mysql-test/main/insert.test b/mysql-test/main/insert.test | ||
| 138 | index e5cb2bac..c1661c27 100644 | ||
| 139 | --- a/mysql-test/main/insert.test | ||
| 140 | +++ b/mysql-test/main/insert.test | ||
| 141 | @@ -667,5 +667,59 @@ select * from t1; | ||
| 142 | drop table t1; | ||
| 143 | |||
| 144 | --echo # | ||
| 145 | ---echo # End of 10.5 tests | ||
| 146 | +--echo # MDEV-32086 Server crash when inserting from derived table containing insert target table | ||
| 147 | +--echo # (part 2) | ||
| 148 | --echo # | ||
| 149 | + | ||
| 150 | +create table t1 (pk int, id int); | ||
| 151 | +insert into t1 values (2,2), (3,3), (4,4); | ||
| 152 | +select * from t1; | ||
| 153 | +select 101+count(*) | ||
| 154 | + from | ||
| 155 | + ( | ||
| 156 | + select dt2.id | ||
| 157 | + from (select id from t1) dt2, t1 t where t.id=dt2.id | ||
| 158 | + ) dt | ||
| 159 | + where dt.id<1000; | ||
| 160 | +prepare s from ' | ||
| 161 | +insert into t1 values( | ||
| 162 | + (select 101+count(*) | ||
| 163 | + from | ||
| 164 | + ( | ||
| 165 | + select dt2.id | ||
| 166 | + from (select id from t1) dt2, t1 t where t.id=dt2.id | ||
| 167 | + ) dt | ||
| 168 | + where dt.id<1000 | ||
| 169 | + ), 123 | ||
| 170 | +) | ||
| 171 | +'; | ||
| 172 | +execute s; | ||
| 173 | +select * from t1; | ||
| 174 | +select 101+count(*) | ||
| 175 | + from | ||
| 176 | + ( | ||
| 177 | + select dt2.id | ||
| 178 | + from (select id from t1) dt2, t1 t where t.id=dt2.id | ||
| 179 | + ) dt | ||
| 180 | + where dt.id<1000; | ||
| 181 | +execute s; | ||
| 182 | +select * from t1; | ||
| 183 | + | ||
| 184 | +drop table t1; | ||
| 185 | + | ||
| 186 | +--echo # | ||
| 187 | +--echo # Try this: INSERT INTO t1 VALUES ... reference to t1 | ||
| 188 | +--echo # RETURNING (subquery not touching t1) | ||
| 189 | +create table t1 (a int, b int); | ||
| 190 | +create table t2 (a int, b int); | ||
| 191 | + | ||
| 192 | +--echo # This is accepted: | ||
| 193 | +insert into t1 (a) values | ||
| 194 | + (3), | ||
| 195 | + ((select max(a) from t1)) | ||
| 196 | +returning | ||
| 197 | + a, b, (select max(a) from t2); | ||
| 198 | + | ||
| 199 | +drop table t1,t2; | ||
| 200 | + | ||
| 201 | +--echo # End of 10.5 tests | ||
| 202 | diff --git a/mysql-test/main/insert_returning.result b/mysql-test/main/insert_returning.result | ||
| 203 | index 1976c1ca..d05c5704 100644 | ||
| 204 | --- a/mysql-test/main/insert_returning.result | ||
| 205 | +++ b/mysql-test/main/insert_returning.result | ||
| 206 | @@ -488,6 +488,8 @@ t1 WHERE id1=1) | ||
| 207 | 5 6 | ||
| 208 | INSERT INTO t2(id2,val2) VALUES(5,'f') RETURNING (SELECT id2 FROM t2); | ||
| 209 | ERROR HY000: Table 't2' is specified twice, both as a target for 'INSERT' and as a separate source for data | ||
| 210 | +INSERT INTO t2(id2,val2) VALUES(5,'f') RETURNING (SELECT 1 UNION SELECT id2 FROM t2); | ||
| 211 | +ERROR HY000: Table 't2' is specified twice, both as a target for 'INSERT' and as a separate source for data | ||
| 212 | INSERT INTO t2 (id2, val2) VALUES (6,'f') RETURNING t1.*; | ||
| 213 | ERROR 42S02: Unknown table 'test.t1' | ||
| 214 | # | ||
| 215 | diff --git a/mysql-test/main/insert_returning.test b/mysql-test/main/insert_returning.test | ||
| 216 | index 837d61d2..c2ad613a 100644 | ||
| 217 | --- a/mysql-test/main/insert_returning.test | ||
| 218 | +++ b/mysql-test/main/insert_returning.test | ||
| 219 | @@ -199,6 +199,8 @@ INSERT INTO t2(id2,val2) VALUES(5,'e') RETURNING id2, (SELECT id1+id2 FROM | ||
| 220 | t1 WHERE id1=1); | ||
| 221 | --error ER_UPDATE_TABLE_USED | ||
| 222 | INSERT INTO t2(id2,val2) VALUES(5,'f') RETURNING (SELECT id2 FROM t2); | ||
| 223 | +--error ER_UPDATE_TABLE_USED | ||
| 224 | +INSERT INTO t2(id2,val2) VALUES(5,'f') RETURNING (SELECT 1 UNION SELECT id2 FROM t2); | ||
| 225 | --error ER_BAD_TABLE_ERROR | ||
| 226 | INSERT INTO t2 (id2, val2) VALUES (6,'f') RETURNING t1.*; | ||
| 227 | |||
| 228 | diff --git a/mysql-test/main/lowercase_view.result b/mysql-test/main/lowercase_view.result | ||
| 229 | index af53f678..845df4d6 100644 | ||
| 230 | --- a/mysql-test/main/lowercase_view.result | ||
| 231 | +++ b/mysql-test/main/lowercase_view.result | ||
| 232 | @@ -16,29 +16,17 @@ create view v1Aa as select * from t1aA; | ||
| 233 | create view v2aA as select * from v1aA; | ||
| 234 | create view v3Aa as select v2Aa.col1 from v2aA,t2Aa where v2Aa.col1 = t2aA.col1; | ||
| 235 | insert into v2Aa values ((select max(col1) from v1aA)); | ||
| 236 | -ERROR HY000: The definition of table 'v1aA' prevents operation INSERT on table 'v2Aa' | ||
| 237 | insert into t1aA values ((select max(col1) from v1Aa)); | ||
| 238 | -ERROR HY000: The definition of table 'v1Aa' prevents operation INSERT on table 't1aA' | ||
| 239 | insert into v2aA values ((select max(col1) from v1aA)); | ||
| 240 | -ERROR HY000: The definition of table 'v1aA' prevents operation INSERT on table 'v2aA' | ||
| 241 | insert into v2Aa values ((select max(col1) from t1Aa)); | ||
| 242 | -ERROR HY000: The definition of table 'v2Aa' prevents operation INSERT on table 'v2Aa' | ||
| 243 | insert into t1aA values ((select max(col1) from t1Aa)); | ||
| 244 | -ERROR HY000: Table 't1aA' is specified twice, both as a target for 'INSERT' and as a separate source for data | ||
| 245 | insert into v2aA values ((select max(col1) from t1aA)); | ||
| 246 | -ERROR HY000: The definition of table 'v2aA' prevents operation INSERT on table 'v2aA' | ||
| 247 | insert into v2Aa values ((select max(col1) from v2aA)); | ||
| 248 | -ERROR HY000: Table 'v2Aa' is specified twice, both as a target for 'INSERT' and as a separate source for data | ||
| 249 | insert into t1Aa values ((select max(col1) from v2Aa)); | ||
| 250 | -ERROR HY000: The definition of table 'v2Aa' prevents operation INSERT on table 't1Aa' | ||
| 251 | insert into v2aA values ((select max(col1) from v2Aa)); | ||
| 252 | -ERROR HY000: Table 'v2aA' is specified twice, both as a target for 'INSERT' and as a separate source for data | ||
| 253 | insert into v3Aa (col1) values ((select max(col1) from v1Aa)); | ||
| 254 | -ERROR HY000: The definition of table 'v1Aa' prevents operation INSERT on table 'v3Aa' | ||
| 255 | insert into v3aA (col1) values ((select max(col1) from t1aA)); | ||
| 256 | -ERROR HY000: The definition of table 'v3aA' prevents operation INSERT on table 'v3aA' | ||
| 257 | insert into v3Aa (col1) values ((select max(col1) from v2aA)); | ||
| 258 | -ERROR HY000: The definition of table 'v2aA' prevents operation INSERT on table 'v3Aa' | ||
| 259 | drop view v3aA,v2Aa,v1aA; | ||
| 260 | drop table t1Aa,t2Aa; | ||
| 261 | create table t1Aa (col1 int); | ||
| 262 | diff --git a/mysql-test/main/lowercase_view.test b/mysql-test/main/lowercase_view.test | ||
| 263 | index cdd0256d..52aae7b2 100644 | ||
| 264 | --- a/mysql-test/main/lowercase_view.test | ||
| 265 | +++ b/mysql-test/main/lowercase_view.test | ||
| 266 | @@ -23,29 +23,17 @@ create table t2aA (col1 int); | ||
| 267 | create view v1Aa as select * from t1aA; | ||
| 268 | create view v2aA as select * from v1aA; | ||
| 269 | create view v3Aa as select v2Aa.col1 from v2aA,t2Aa where v2Aa.col1 = t2aA.col1; | ||
| 270 | --- error 1443 | ||
| 271 | insert into v2Aa values ((select max(col1) from v1aA)); | ||
| 272 | --- error 1443 | ||
| 273 | insert into t1aA values ((select max(col1) from v1Aa)); | ||
| 274 | --- error 1443 | ||
| 275 | insert into v2aA values ((select max(col1) from v1aA)); | ||
| 276 | --- error 1443 | ||
| 277 | insert into v2Aa values ((select max(col1) from t1Aa)); | ||
| 278 | --- error 1093 | ||
| 279 | insert into t1aA values ((select max(col1) from t1Aa)); | ||
| 280 | --- error 1443 | ||
| 281 | insert into v2aA values ((select max(col1) from t1aA)); | ||
| 282 | --- error 1093 | ||
| 283 | insert into v2Aa values ((select max(col1) from v2aA)); | ||
| 284 | --- error 1443 | ||
| 285 | insert into t1Aa values ((select max(col1) from v2Aa)); | ||
| 286 | --- error 1093 | ||
| 287 | insert into v2aA values ((select max(col1) from v2Aa)); | ||
| 288 | --- error 1443 | ||
| 289 | insert into v3Aa (col1) values ((select max(col1) from v1Aa)); | ||
| 290 | --- error 1443 | ||
| 291 | insert into v3aA (col1) values ((select max(col1) from t1aA)); | ||
| 292 | --- error 1443 | ||
| 293 | insert into v3Aa (col1) values ((select max(col1) from v2aA)); | ||
| 294 | drop view v3aA,v2Aa,v1aA; | ||
| 295 | drop table t1Aa,t2Aa; | ||
| 296 | diff --git a/mysql-test/main/merge.result b/mysql-test/main/merge.result | ||
| 297 | index 1e671e25..d10f0b67 100644 | ||
| 298 | --- a/mysql-test/main/merge.result | ||
| 299 | +++ b/mysql-test/main/merge.result | ||
| 300 | @@ -3689,33 +3689,22 @@ insert into tmp (b) values (1); | ||
| 301 | insert into t1 (a) values (1); | ||
| 302 | insert into t3 (b) values (1); | ||
| 303 | insert into m1 (a) values ((select max(a) from m1)); | ||
| 304 | -ERROR HY000: Table 'm1' is specified twice, both as a target for 'INSERT' and as a separate source for data | ||
| 305 | insert into m1 (a) values ((select max(a) from m2)); | ||
| 306 | -ERROR HY000: Table 'm1' is specified twice, both as a target for 'INSERT' and as a separate source for data | ||
| 307 | insert into m1 (a) values ((select max(a) from t1)); | ||
| 308 | -ERROR HY000: Table 'm1' is specified twice, both as a target for 'INSERT' and as a separate source for data | ||
| 309 | insert into m1 (a) values ((select max(a) from t2)); | ||
| 310 | -ERROR HY000: Table 'm1' is specified twice, both as a target for 'INSERT' and as a separate source for data | ||
| 311 | insert into m1 (a) values ((select max(a) from t3, m1)); | ||
| 312 | -ERROR HY000: Table 'm1' is specified twice, both as a target for 'INSERT' and as a separate source for data | ||
| 313 | insert into m1 (a) values ((select max(a) from t3, m2)); | ||
| 314 | -ERROR HY000: Table 'm1' is specified twice, both as a target for 'INSERT' and as a separate source for data | ||
| 315 | insert into m1 (a) values ((select max(a) from t3, t1)); | ||
| 316 | -ERROR HY000: Table 'm1' is specified twice, both as a target for 'INSERT' and as a separate source for data | ||
| 317 | insert into m1 (a) values ((select max(a) from t3, t2)); | ||
| 318 | -ERROR HY000: Table 'm1' is specified twice, both as a target for 'INSERT' and as a separate source for data | ||
| 319 | insert into m1 (a) values ((select max(a) from tmp, m1)); | ||
| 320 | -ERROR HY000: Table 'm1' is specified twice, both as a target for 'INSERT' and as a separate source for data | ||
| 321 | insert into m1 (a) values ((select max(a) from tmp, m2)); | ||
| 322 | -ERROR HY000: Table 'm1' is specified twice, both as a target for 'INSERT' and as a separate source for data | ||
| 323 | insert into m1 (a) values ((select max(a) from tmp, t1)); | ||
| 324 | -ERROR HY000: Table 'm1' is specified twice, both as a target for 'INSERT' and as a separate source for data | ||
| 325 | insert into m1 (a) values ((select max(a) from tmp, t2)); | ||
| 326 | -ERROR HY000: Table 'm1' is specified twice, both as a target for 'INSERT' and as a separate source for data | ||
| 327 | insert into m1 (a) values ((select max(a) from v1)); | ||
| 328 | -ERROR HY000: The definition of table 'v1' prevents operation INSERT on table 'm1' | ||
| 329 | insert into m1 (a) values ((select max(a) from tmp, v1)); | ||
| 330 | -ERROR HY000: The definition of table 'v1' prevents operation INSERT on table 'm1' | ||
| 331 | +select count(*) from m1; | ||
| 332 | +count(*) | ||
| 333 | +15 | ||
| 334 | drop view v1; | ||
| 335 | drop temporary table tmp; | ||
| 336 | drop table t1, t2, t3, m1, m2; | ||
| 337 | diff --git a/mysql-test/main/merge.test b/mysql-test/main/merge.test | ||
| 338 | index 99cce370..9e76515c 100644 | ||
| 339 | --- a/mysql-test/main/merge.test | ||
| 340 | +++ b/mysql-test/main/merge.test | ||
| 341 | @@ -2706,37 +2706,24 @@ insert into tmp (b) values (1); | ||
| 342 | |||
| 343 | insert into t1 (a) values (1); | ||
| 344 | insert into t3 (b) values (1); | ||
| 345 | ---error ER_UPDATE_TABLE_USED | ||
| 346 | insert into m1 (a) values ((select max(a) from m1)); | ||
| 347 | ---error ER_UPDATE_TABLE_USED | ||
| 348 | insert into m1 (a) values ((select max(a) from m2)); | ||
| 349 | ---error ER_UPDATE_TABLE_USED | ||
| 350 | insert into m1 (a) values ((select max(a) from t1)); | ||
| 351 | ---error ER_UPDATE_TABLE_USED | ||
| 352 | insert into m1 (a) values ((select max(a) from t2)); | ||
| 353 | |||
| 354 | ---error ER_UPDATE_TABLE_USED | ||
| 355 | insert into m1 (a) values ((select max(a) from t3, m1)); | ||
| 356 | ---error ER_UPDATE_TABLE_USED | ||
| 357 | insert into m1 (a) values ((select max(a) from t3, m2)); | ||
| 358 | ---error ER_UPDATE_TABLE_USED | ||
| 359 | insert into m1 (a) values ((select max(a) from t3, t1)); | ||
| 360 | ---error ER_UPDATE_TABLE_USED | ||
| 361 | insert into m1 (a) values ((select max(a) from t3, t2)); | ||
| 362 | |||
| 363 | ---error ER_UPDATE_TABLE_USED | ||
| 364 | insert into m1 (a) values ((select max(a) from tmp, m1)); | ||
| 365 | ---error ER_UPDATE_TABLE_USED | ||
| 366 | insert into m1 (a) values ((select max(a) from tmp, m2)); | ||
| 367 | ---error ER_UPDATE_TABLE_USED | ||
| 368 | insert into m1 (a) values ((select max(a) from tmp, t1)); | ||
| 369 | ---error ER_UPDATE_TABLE_USED | ||
| 370 | insert into m1 (a) values ((select max(a) from tmp, t2)); | ||
| 371 | - | ||
| 372 | ---error ER_VIEW_PREVENT_UPDATE | ||
| 373 | + | ||
| 374 | insert into m1 (a) values ((select max(a) from v1)); | ||
| 375 | ---error ER_VIEW_PREVENT_UPDATE | ||
| 376 | insert into m1 (a) values ((select max(a) from tmp, v1)); | ||
| 377 | +select count(*) from m1; | ||
| 378 | |||
| 379 | |||
| 380 | drop view v1; | ||
| 381 | diff --git a/mysql-test/main/subselect.result b/mysql-test/main/subselect.result | ||
| 382 | index 4209e2bc..dcbc2023 100644 | ||
| 383 | --- a/mysql-test/main/subselect.result | ||
| 384 | +++ b/mysql-test/main/subselect.result | ||
| 385 | @@ -653,22 +653,24 @@ create table t3 (b int); | ||
| 386 | insert into t2 values (1); | ||
| 387 | insert into t3 values (1),(2); | ||
| 388 | INSERT INTO t1 (x) VALUES ((SELECT x FROM t1)); | ||
| 389 | -ERROR HY000: Table 't1' is specified twice, both as a target for 'INSERT' and as a separate source for data | ||
| 390 | INSERT INTO t1 (x) VALUES ((SELECT b FROM t3)); | ||
| 391 | ERROR 21000: Subquery returns more than 1 row | ||
| 392 | INSERT INTO t1 (x) VALUES ((SELECT a FROM t2)); | ||
| 393 | select * from t1; | ||
| 394 | x | ||
| 395 | +NULL | ||
| 396 | 1 | ||
| 397 | insert into t2 values (1); | ||
| 398 | INSERT DELAYED INTO t1 (x) VALUES ((SELECT SUM(a) FROM t2)); | ||
| 399 | select * from t1; | ||
| 400 | x | ||
| 401 | +NULL | ||
| 402 | 1 | ||
| 403 | 2 | ||
| 404 | INSERT INTO t1 (x) select (SELECT SUM(a)+1 FROM t2) FROM t2; | ||
| 405 | select * from t1; | ||
| 406 | x | ||
| 407 | +NULL | ||
| 408 | 1 | ||
| 409 | 2 | ||
| 410 | 3 | ||
| 411 | @@ -676,6 +678,7 @@ x | ||
| 412 | INSERT INTO t1 (x) select (SELECT SUM(x)+2 FROM t1) FROM t2; | ||
| 413 | select * from t1; | ||
| 414 | x | ||
| 415 | +NULL | ||
| 416 | 1 | ||
| 417 | 2 | ||
| 418 | 3 | ||
| 419 | @@ -685,6 +688,7 @@ x | ||
| 420 | INSERT DELAYED INTO t1 (x) VALUES ((SELECT SUM(a) FROM t2)); | ||
| 421 | select * from t1; | ||
| 422 | x | ||
| 423 | +NULL | ||
| 424 | 1 | ||
| 425 | 2 | ||
| 426 | 3 | ||
| 427 | @@ -701,7 +705,7 @@ insert into t3 values (1),(2); | ||
| 428 | select * from t1; | ||
| 429 | x y | ||
| 430 | replace into t1 (x, y) VALUES ((SELECT x FROM t1), (SELECT a+1 FROM t2)); | ||
| 431 | -ERROR HY000: Table 't1' is specified twice, both as a target for 'INSERT' and as a separate source for data | ||
| 432 | +ERROR 23000: Column 'x' cannot be null | ||
| 433 | replace into t1 (x, y) VALUES ((SELECT a FROM t3), (SELECT a+1 FROM t2)); | ||
| 434 | ERROR 21000: Subquery returns more than 1 row | ||
| 435 | replace into t1 (x, y) VALUES ((SELECT a FROM t2), (SELECT a+1 FROM t2)); | ||
| 436 | @@ -769,13 +773,21 @@ SELECT * FROM t2 WHERE id IN (SELECT 5 UNION SELECT 2); | ||
| 437 | id | ||
| 438 | 2 | ||
| 439 | INSERT INTO t2 VALUES ((SELECT * FROM t2)); | ||
| 440 | -ERROR HY000: Table 't2' is specified twice, both as a target for 'INSERT' and as a separate source for data | ||
| 441 | +ERROR 21000: Subquery returns more than 1 row | ||
| 442 | INSERT INTO t2 VALUES ((SELECT id FROM t2)); | ||
| 443 | -ERROR HY000: Table 't2' is specified twice, both as a target for 'INSERT' and as a separate source for data | ||
| 444 | +ERROR 21000: Subquery returns more than 1 row | ||
| 445 | +select * from t2; | ||
| 446 | +id | ||
| 447 | +1 | ||
| 448 | +2 | ||
| 449 | +INSERT INTO t2 VALUES ((SELECT count(*) FROM t2)); | ||
| 450 | +INSERT INTO t2 VALUES ((SELECT max(id) FROM t2)); | ||
| 451 | SELECT * FROM t2; | ||
| 452 | id | ||
| 453 | 1 | ||
| 454 | 2 | ||
| 455 | +2 | ||
| 456 | +2 | ||
| 457 | CREATE TABLE t1 (id int(11) default NULL, KEY id (id)) ENGINE=MyISAM CHARSET=latin1; | ||
| 458 | INSERT INTO t1 values (1),(1); | ||
| 459 | UPDATE t2 SET id=(SELECT * FROM t1); | ||
| 460 | diff --git a/mysql-test/main/subselect.test b/mysql-test/main/subselect.test | ||
| 461 | index be22169a..f4394f08 100644 | ||
| 462 | --- a/mysql-test/main/subselect.test | ||
| 463 | +++ b/mysql-test/main/subselect.test | ||
| 464 | @@ -400,7 +400,6 @@ create table t2 (a int) ENGINE=MyISAM; | ||
| 465 | create table t3 (b int); | ||
| 466 | insert into t2 values (1); | ||
| 467 | insert into t3 values (1),(2); | ||
| 468 | --- error ER_UPDATE_TABLE_USED | ||
| 469 | INSERT INTO t1 (x) VALUES ((SELECT x FROM t1)); | ||
| 470 | -- error ER_SUBQUERY_NO_1_ROW | ||
| 471 | INSERT INTO t1 (x) VALUES ((SELECT b FROM t3)); | ||
| 472 | @@ -435,7 +434,7 @@ create table t3 (a int); | ||
| 473 | insert into t2 values (1); | ||
| 474 | insert into t3 values (1),(2); | ||
| 475 | select * from t1; | ||
| 476 | --- error ER_UPDATE_TABLE_USED | ||
| 477 | +-- error ER_BAD_NULL_ERROR | ||
| 478 | replace into t1 (x, y) VALUES ((SELECT x FROM t1), (SELECT a+1 FROM t2)); | ||
| 479 | -- error ER_SUBQUERY_NO_1_ROW | ||
| 480 | replace into t1 (x, y) VALUES ((SELECT a FROM t3), (SELECT a+1 FROM t2)); | ||
| 481 | @@ -475,10 +474,13 @@ EXPLAIN EXTENDED SELECT * FROM t2 WHERE id IN (SELECT 1 UNION SELECT 3); | ||
| 482 | --disable_prepare_warnings | ||
| 483 | SELECT * FROM t2 WHERE id IN (SELECT 5 UNION SELECT 3); | ||
| 484 | SELECT * FROM t2 WHERE id IN (SELECT 5 UNION SELECT 2); | ||
| 485 | --- error ER_UPDATE_TABLE_USED | ||
| 486 | +-- error ER_SUBQUERY_NO_1_ROW | ||
| 487 | INSERT INTO t2 VALUES ((SELECT * FROM t2)); | ||
| 488 | --- error ER_UPDATE_TABLE_USED | ||
| 489 | +-- error ER_SUBQUERY_NO_1_ROW | ||
| 490 | INSERT INTO t2 VALUES ((SELECT id FROM t2)); | ||
| 491 | +select * from t2; | ||
| 492 | +INSERT INTO t2 VALUES ((SELECT count(*) FROM t2)); | ||
| 493 | +INSERT INTO t2 VALUES ((SELECT max(id) FROM t2)); | ||
| 494 | SELECT * FROM t2; | ||
| 495 | CREATE TABLE t1 (id int(11) default NULL, KEY id (id)) ENGINE=MyISAM CHARSET=latin1; | ||
| 496 | INSERT INTO t1 values (1),(1); | ||
| 497 | diff --git a/mysql-test/main/subselect_no_exists_to_in.result b/mysql-test/main/subselect_no_exists_to_in.result | ||
| 498 | index e32e6007..5c9e493a 100644 | ||
| 499 | --- a/mysql-test/main/subselect_no_exists_to_in.result | ||
| 500 | +++ b/mysql-test/main/subselect_no_exists_to_in.result | ||
| 501 | @@ -657,22 +657,24 @@ create table t3 (b int); | ||
| 502 | insert into t2 values (1); | ||
| 503 | insert into t3 values (1),(2); | ||
| 504 | INSERT INTO t1 (x) VALUES ((SELECT x FROM t1)); | ||
| 505 | -ERROR HY000: Table 't1' is specified twice, both as a target for 'INSERT' and as a separate source for data | ||
| 506 | INSERT INTO t1 (x) VALUES ((SELECT b FROM t3)); | ||
| 507 | ERROR 21000: Subquery returns more than 1 row | ||
| 508 | INSERT INTO t1 (x) VALUES ((SELECT a FROM t2)); | ||
| 509 | select * from t1; | ||
| 510 | x | ||
| 511 | +NULL | ||
| 512 | 1 | ||
| 513 | insert into t2 values (1); | ||
| 514 | INSERT DELAYED INTO t1 (x) VALUES ((SELECT SUM(a) FROM t2)); | ||
| 515 | select * from t1; | ||
| 516 | x | ||
| 517 | +NULL | ||
| 518 | 1 | ||
| 519 | 2 | ||
| 520 | INSERT INTO t1 (x) select (SELECT SUM(a)+1 FROM t2) FROM t2; | ||
| 521 | select * from t1; | ||
| 522 | x | ||
| 523 | +NULL | ||
| 524 | 1 | ||
| 525 | 2 | ||
| 526 | 3 | ||
| 527 | @@ -680,6 +682,7 @@ x | ||
| 528 | INSERT INTO t1 (x) select (SELECT SUM(x)+2 FROM t1) FROM t2; | ||
| 529 | select * from t1; | ||
| 530 | x | ||
| 531 | +NULL | ||
| 532 | 1 | ||
| 533 | 2 | ||
| 534 | 3 | ||
| 535 | @@ -689,6 +692,7 @@ x | ||
| 536 | INSERT DELAYED INTO t1 (x) VALUES ((SELECT SUM(a) FROM t2)); | ||
| 537 | select * from t1; | ||
| 538 | x | ||
| 539 | +NULL | ||
| 540 | 1 | ||
| 541 | 2 | ||
| 542 | 3 | ||
| 543 | @@ -705,7 +709,7 @@ insert into t3 values (1),(2); | ||
| 544 | select * from t1; | ||
| 545 | x y | ||
| 546 | replace into t1 (x, y) VALUES ((SELECT x FROM t1), (SELECT a+1 FROM t2)); | ||
| 547 | -ERROR HY000: Table 't1' is specified twice, both as a target for 'INSERT' and as a separate source for data | ||
| 548 | +ERROR 23000: Column 'x' cannot be null | ||
| 549 | replace into t1 (x, y) VALUES ((SELECT a FROM t3), (SELECT a+1 FROM t2)); | ||
| 550 | ERROR 21000: Subquery returns more than 1 row | ||
| 551 | replace into t1 (x, y) VALUES ((SELECT a FROM t2), (SELECT a+1 FROM t2)); | ||
| 552 | @@ -773,9 +777,17 @@ SELECT * FROM t2 WHERE id IN (SELECT 5 UNION SELECT 2); | ||
| 553 | id | ||
| 554 | 2 | ||
| 555 | INSERT INTO t2 VALUES ((SELECT * FROM t2)); | ||
| 556 | -ERROR HY000: Table 't2' is specified twice, both as a target for 'INSERT' and as a separate source for data | ||
| 557 | +ERROR 21000: Subquery returns more than 1 row | ||
| 558 | INSERT INTO t2 VALUES ((SELECT id FROM t2)); | ||
| 559 | -ERROR HY000: Table 't2' is specified twice, both as a target for 'INSERT' and as a separate source for data | ||
| 560 | +ERROR 21000: Subquery returns more than 1 row | ||
| 561 | +select * from t2; | ||
| 562 | +id | ||
| 563 | +1 | ||
| 564 | +2 | ||
| 565 | +2 | ||
| 566 | +2 | ||
| 567 | +INSERT INTO t2 VALUES ((SELECT count(*) FROM t2)); | ||
| 568 | +INSERT INTO t2 VALUES ((SELECT max(id) FROM t2)); | ||
| 569 | SELECT * FROM t2; | ||
| 570 | id | ||
| 571 | 1 | ||
| 572 | diff --git a/mysql-test/main/subselect_no_mat.result b/mysql-test/main/subselect_no_mat.result | ||
| 573 | index 07755a51..8c24edcc 100644 | ||
| 574 | --- a/mysql-test/main/subselect_no_mat.result | ||
| 575 | +++ b/mysql-test/main/subselect_no_mat.result | ||
| 576 | @@ -660,22 +660,24 @@ create table t3 (b int); | ||
| 577 | insert into t2 values (1); | ||
| 578 | insert into t3 values (1),(2); | ||
| 579 | INSERT INTO t1 (x) VALUES ((SELECT x FROM t1)); | ||
| 580 | -ERROR HY000: Table 't1' is specified twice, both as a target for 'INSERT' and as a separate source for data | ||
| 581 | INSERT INTO t1 (x) VALUES ((SELECT b FROM t3)); | ||
| 582 | ERROR 21000: Subquery returns more than 1 row | ||
| 583 | INSERT INTO t1 (x) VALUES ((SELECT a FROM t2)); | ||
| 584 | select * from t1; | ||
| 585 | x | ||
| 586 | +NULL | ||
| 587 | 1 | ||
| 588 | insert into t2 values (1); | ||
| 589 | INSERT DELAYED INTO t1 (x) VALUES ((SELECT SUM(a) FROM t2)); | ||
| 590 | select * from t1; | ||
| 591 | x | ||
| 592 | +NULL | ||
| 593 | 1 | ||
| 594 | 2 | ||
| 595 | INSERT INTO t1 (x) select (SELECT SUM(a)+1 FROM t2) FROM t2; | ||
| 596 | select * from t1; | ||
| 597 | x | ||
| 598 | +NULL | ||
| 599 | 1 | ||
| 600 | 2 | ||
| 601 | 3 | ||
| 602 | @@ -683,6 +685,7 @@ x | ||
| 603 | INSERT INTO t1 (x) select (SELECT SUM(x)+2 FROM t1) FROM t2; | ||
| 604 | select * from t1; | ||
| 605 | x | ||
| 606 | +NULL | ||
| 607 | 1 | ||
| 608 | 2 | ||
| 609 | 3 | ||
| 610 | @@ -692,6 +695,7 @@ x | ||
| 611 | INSERT DELAYED INTO t1 (x) VALUES ((SELECT SUM(a) FROM t2)); | ||
| 612 | select * from t1; | ||
| 613 | x | ||
| 614 | +NULL | ||
| 615 | 1 | ||
| 616 | 2 | ||
| 617 | 3 | ||
| 618 | @@ -708,7 +712,7 @@ insert into t3 values (1),(2); | ||
| 619 | select * from t1; | ||
| 620 | x y | ||
| 621 | replace into t1 (x, y) VALUES ((SELECT x FROM t1), (SELECT a+1 FROM t2)); | ||
| 622 | -ERROR HY000: Table 't1' is specified twice, both as a target for 'INSERT' and as a separate source for data | ||
| 623 | +ERROR 23000: Column 'x' cannot be null | ||
| 624 | replace into t1 (x, y) VALUES ((SELECT a FROM t3), (SELECT a+1 FROM t2)); | ||
| 625 | ERROR 21000: Subquery returns more than 1 row | ||
| 626 | replace into t1 (x, y) VALUES ((SELECT a FROM t2), (SELECT a+1 FROM t2)); | ||
| 627 | @@ -776,13 +780,21 @@ SELECT * FROM t2 WHERE id IN (SELECT 5 UNION SELECT 2); | ||
| 628 | id | ||
| 629 | 2 | ||
| 630 | INSERT INTO t2 VALUES ((SELECT * FROM t2)); | ||
| 631 | -ERROR HY000: Table 't2' is specified twice, both as a target for 'INSERT' and as a separate source for data | ||
| 632 | +ERROR 21000: Subquery returns more than 1 row | ||
| 633 | INSERT INTO t2 VALUES ((SELECT id FROM t2)); | ||
| 634 | -ERROR HY000: Table 't2' is specified twice, both as a target for 'INSERT' and as a separate source for data | ||
| 635 | +ERROR 21000: Subquery returns more than 1 row | ||
| 636 | +select * from t2; | ||
| 637 | +id | ||
| 638 | +1 | ||
| 639 | +2 | ||
| 640 | +INSERT INTO t2 VALUES ((SELECT count(*) FROM t2)); | ||
| 641 | +INSERT INTO t2 VALUES ((SELECT max(id) FROM t2)); | ||
| 642 | SELECT * FROM t2; | ||
| 643 | id | ||
| 644 | 1 | ||
| 645 | 2 | ||
| 646 | +2 | ||
| 647 | +2 | ||
| 648 | CREATE TABLE t1 (id int(11) default NULL, KEY id (id)) ENGINE=MyISAM CHARSET=latin1; | ||
| 649 | INSERT INTO t1 values (1),(1); | ||
| 650 | UPDATE t2 SET id=(SELECT * FROM t1); | ||
| 651 | diff --git a/mysql-test/main/subselect_no_opts.result b/mysql-test/main/subselect_no_opts.result | ||
| 652 | index 15688fc1..897ec5be 100644 | ||
| 653 | --- a/mysql-test/main/subselect_no_opts.result | ||
| 654 | +++ b/mysql-test/main/subselect_no_opts.result | ||
| 655 | @@ -656,22 +656,24 @@ create table t3 (b int); | ||
| 656 | insert into t2 values (1); | ||
| 657 | insert into t3 values (1),(2); | ||
| 658 | INSERT INTO t1 (x) VALUES ((SELECT x FROM t1)); | ||
| 659 | -ERROR HY000: Table 't1' is specified twice, both as a target for 'INSERT' and as a separate source for data | ||
| 660 | INSERT INTO t1 (x) VALUES ((SELECT b FROM t3)); | ||
| 661 | ERROR 21000: Subquery returns more than 1 row | ||
| 662 | INSERT INTO t1 (x) VALUES ((SELECT a FROM t2)); | ||
| 663 | select * from t1; | ||
| 664 | x | ||
| 665 | +NULL | ||
| 666 | 1 | ||
| 667 | insert into t2 values (1); | ||
| 668 | INSERT DELAYED INTO t1 (x) VALUES ((SELECT SUM(a) FROM t2)); | ||
| 669 | select * from t1; | ||
| 670 | x | ||
| 671 | +NULL | ||
| 672 | 1 | ||
| 673 | 2 | ||
| 674 | INSERT INTO t1 (x) select (SELECT SUM(a)+1 FROM t2) FROM t2; | ||
| 675 | select * from t1; | ||
| 676 | x | ||
| 677 | +NULL | ||
| 678 | 1 | ||
| 679 | 2 | ||
| 680 | 3 | ||
| 681 | @@ -679,6 +681,7 @@ x | ||
| 682 | INSERT INTO t1 (x) select (SELECT SUM(x)+2 FROM t1) FROM t2; | ||
| 683 | select * from t1; | ||
| 684 | x | ||
| 685 | +NULL | ||
| 686 | 1 | ||
| 687 | 2 | ||
| 688 | 3 | ||
| 689 | @@ -688,6 +691,7 @@ x | ||
| 690 | INSERT DELAYED INTO t1 (x) VALUES ((SELECT SUM(a) FROM t2)); | ||
| 691 | select * from t1; | ||
| 692 | x | ||
| 693 | +NULL | ||
| 694 | 1 | ||
| 695 | 2 | ||
| 696 | 3 | ||
| 697 | @@ -704,7 +708,7 @@ insert into t3 values (1),(2); | ||
| 698 | select * from t1; | ||
| 699 | x y | ||
| 700 | replace into t1 (x, y) VALUES ((SELECT x FROM t1), (SELECT a+1 FROM t2)); | ||
| 701 | -ERROR HY000: Table 't1' is specified twice, both as a target for 'INSERT' and as a separate source for data | ||
| 702 | +ERROR 23000: Column 'x' cannot be null | ||
| 703 | replace into t1 (x, y) VALUES ((SELECT a FROM t3), (SELECT a+1 FROM t2)); | ||
| 704 | ERROR 21000: Subquery returns more than 1 row | ||
| 705 | replace into t1 (x, y) VALUES ((SELECT a FROM t2), (SELECT a+1 FROM t2)); | ||
| 706 | @@ -772,13 +776,21 @@ SELECT * FROM t2 WHERE id IN (SELECT 5 UNION SELECT 2); | ||
| 707 | id | ||
| 708 | 2 | ||
| 709 | INSERT INTO t2 VALUES ((SELECT * FROM t2)); | ||
| 710 | -ERROR HY000: Table 't2' is specified twice, both as a target for 'INSERT' and as a separate source for data | ||
| 711 | +ERROR 21000: Subquery returns more than 1 row | ||
| 712 | INSERT INTO t2 VALUES ((SELECT id FROM t2)); | ||
| 713 | -ERROR HY000: Table 't2' is specified twice, both as a target for 'INSERT' and as a separate source for data | ||
| 714 | +ERROR 21000: Subquery returns more than 1 row | ||
| 715 | +select * from t2; | ||
| 716 | +id | ||
| 717 | +1 | ||
| 718 | +2 | ||
| 719 | +INSERT INTO t2 VALUES ((SELECT count(*) FROM t2)); | ||
| 720 | +INSERT INTO t2 VALUES ((SELECT max(id) FROM t2)); | ||
| 721 | SELECT * FROM t2; | ||
| 722 | id | ||
| 723 | 1 | ||
| 724 | 2 | ||
| 725 | +2 | ||
| 726 | +2 | ||
| 727 | CREATE TABLE t1 (id int(11) default NULL, KEY id (id)) ENGINE=MyISAM CHARSET=latin1; | ||
| 728 | INSERT INTO t1 values (1),(1); | ||
| 729 | UPDATE t2 SET id=(SELECT * FROM t1); | ||
| 730 | diff --git a/mysql-test/main/subselect_no_scache.result b/mysql-test/main/subselect_no_scache.result | ||
| 731 | index e3bdddbf..df43d4e5 100644 | ||
| 732 | --- a/mysql-test/main/subselect_no_scache.result | ||
| 733 | +++ b/mysql-test/main/subselect_no_scache.result | ||
| 734 | @@ -659,22 +659,24 @@ create table t3 (b int); | ||
| 735 | insert into t2 values (1); | ||
| 736 | insert into t3 values (1),(2); | ||
| 737 | INSERT INTO t1 (x) VALUES ((SELECT x FROM t1)); | ||
| 738 | -ERROR HY000: Table 't1' is specified twice, both as a target for 'INSERT' and as a separate source for data | ||
| 739 | INSERT INTO t1 (x) VALUES ((SELECT b FROM t3)); | ||
| 740 | ERROR 21000: Subquery returns more than 1 row | ||
| 741 | INSERT INTO t1 (x) VALUES ((SELECT a FROM t2)); | ||
| 742 | select * from t1; | ||
| 743 | x | ||
| 744 | +NULL | ||
| 745 | 1 | ||
| 746 | insert into t2 values (1); | ||
| 747 | INSERT DELAYED INTO t1 (x) VALUES ((SELECT SUM(a) FROM t2)); | ||
| 748 | select * from t1; | ||
| 749 | x | ||
| 750 | +NULL | ||
| 751 | 1 | ||
| 752 | 2 | ||
| 753 | INSERT INTO t1 (x) select (SELECT SUM(a)+1 FROM t2) FROM t2; | ||
| 754 | select * from t1; | ||
| 755 | x | ||
| 756 | +NULL | ||
| 757 | 1 | ||
| 758 | 2 | ||
| 759 | 3 | ||
| 760 | @@ -682,6 +684,7 @@ x | ||
| 761 | INSERT INTO t1 (x) select (SELECT SUM(x)+2 FROM t1) FROM t2; | ||
| 762 | select * from t1; | ||
| 763 | x | ||
| 764 | +NULL | ||
| 765 | 1 | ||
| 766 | 2 | ||
| 767 | 3 | ||
| 768 | @@ -691,6 +694,7 @@ x | ||
| 769 | INSERT DELAYED INTO t1 (x) VALUES ((SELECT SUM(a) FROM t2)); | ||
| 770 | select * from t1; | ||
| 771 | x | ||
| 772 | +NULL | ||
| 773 | 1 | ||
| 774 | 2 | ||
| 775 | 3 | ||
| 776 | @@ -707,7 +711,7 @@ insert into t3 values (1),(2); | ||
| 777 | select * from t1; | ||
| 778 | x y | ||
| 779 | replace into t1 (x, y) VALUES ((SELECT x FROM t1), (SELECT a+1 FROM t2)); | ||
| 780 | -ERROR HY000: Table 't1' is specified twice, both as a target for 'INSERT' and as a separate source for data | ||
| 781 | +ERROR 23000: Column 'x' cannot be null | ||
| 782 | replace into t1 (x, y) VALUES ((SELECT a FROM t3), (SELECT a+1 FROM t2)); | ||
| 783 | ERROR 21000: Subquery returns more than 1 row | ||
| 784 | replace into t1 (x, y) VALUES ((SELECT a FROM t2), (SELECT a+1 FROM t2)); | ||
| 785 | @@ -775,13 +779,21 @@ SELECT * FROM t2 WHERE id IN (SELECT 5 UNION SELECT 2); | ||
| 786 | id | ||
| 787 | 2 | ||
| 788 | INSERT INTO t2 VALUES ((SELECT * FROM t2)); | ||
| 789 | -ERROR HY000: Table 't2' is specified twice, both as a target for 'INSERT' and as a separate source for data | ||
| 790 | +ERROR 21000: Subquery returns more than 1 row | ||
| 791 | INSERT INTO t2 VALUES ((SELECT id FROM t2)); | ||
| 792 | -ERROR HY000: Table 't2' is specified twice, both as a target for 'INSERT' and as a separate source for data | ||
| 793 | +ERROR 21000: Subquery returns more than 1 row | ||
| 794 | +select * from t2; | ||
| 795 | +id | ||
| 796 | +1 | ||
| 797 | +2 | ||
| 798 | +INSERT INTO t2 VALUES ((SELECT count(*) FROM t2)); | ||
| 799 | +INSERT INTO t2 VALUES ((SELECT max(id) FROM t2)); | ||
| 800 | SELECT * FROM t2; | ||
| 801 | id | ||
| 802 | 1 | ||
| 803 | 2 | ||
| 804 | +2 | ||
| 805 | +2 | ||
| 806 | CREATE TABLE t1 (id int(11) default NULL, KEY id (id)) ENGINE=MyISAM CHARSET=latin1; | ||
| 807 | INSERT INTO t1 values (1),(1); | ||
| 808 | UPDATE t2 SET id=(SELECT * FROM t1); | ||
| 809 | diff --git a/mysql-test/main/subselect_no_semijoin.result b/mysql-test/main/subselect_no_semijoin.result | ||
| 810 | index a06a4aef..b43cf744 100644 | ||
| 811 | --- a/mysql-test/main/subselect_no_semijoin.result | ||
| 812 | +++ b/mysql-test/main/subselect_no_semijoin.result | ||
| 813 | @@ -656,22 +656,24 @@ create table t3 (b int); | ||
| 814 | insert into t2 values (1); | ||
| 815 | insert into t3 values (1),(2); | ||
| 816 | INSERT INTO t1 (x) VALUES ((SELECT x FROM t1)); | ||
| 817 | -ERROR HY000: Table 't1' is specified twice, both as a target for 'INSERT' and as a separate source for data | ||
| 818 | INSERT INTO t1 (x) VALUES ((SELECT b FROM t3)); | ||
| 819 | ERROR 21000: Subquery returns more than 1 row | ||
| 820 | INSERT INTO t1 (x) VALUES ((SELECT a FROM t2)); | ||
| 821 | select * from t1; | ||
| 822 | x | ||
| 823 | +NULL | ||
| 824 | 1 | ||
| 825 | insert into t2 values (1); | ||
| 826 | INSERT DELAYED INTO t1 (x) VALUES ((SELECT SUM(a) FROM t2)); | ||
| 827 | select * from t1; | ||
| 828 | x | ||
| 829 | +NULL | ||
| 830 | 1 | ||
| 831 | 2 | ||
| 832 | INSERT INTO t1 (x) select (SELECT SUM(a)+1 FROM t2) FROM t2; | ||
| 833 | select * from t1; | ||
| 834 | x | ||
| 835 | +NULL | ||
| 836 | 1 | ||
| 837 | 2 | ||
| 838 | 3 | ||
| 839 | @@ -679,6 +681,7 @@ x | ||
| 840 | INSERT INTO t1 (x) select (SELECT SUM(x)+2 FROM t1) FROM t2; | ||
| 841 | select * from t1; | ||
| 842 | x | ||
| 843 | +NULL | ||
| 844 | 1 | ||
| 845 | 2 | ||
| 846 | 3 | ||
| 847 | @@ -688,6 +691,7 @@ x | ||
| 848 | INSERT DELAYED INTO t1 (x) VALUES ((SELECT SUM(a) FROM t2)); | ||
| 849 | select * from t1; | ||
| 850 | x | ||
| 851 | +NULL | ||
| 852 | 1 | ||
| 853 | 2 | ||
| 854 | 3 | ||
| 855 | @@ -704,7 +708,7 @@ insert into t3 values (1),(2); | ||
| 856 | select * from t1; | ||
| 857 | x y | ||
| 858 | replace into t1 (x, y) VALUES ((SELECT x FROM t1), (SELECT a+1 FROM t2)); | ||
| 859 | -ERROR HY000: Table 't1' is specified twice, both as a target for 'INSERT' and as a separate source for data | ||
| 860 | +ERROR 23000: Column 'x' cannot be null | ||
| 861 | replace into t1 (x, y) VALUES ((SELECT a FROM t3), (SELECT a+1 FROM t2)); | ||
| 862 | ERROR 21000: Subquery returns more than 1 row | ||
| 863 | replace into t1 (x, y) VALUES ((SELECT a FROM t2), (SELECT a+1 FROM t2)); | ||
| 864 | @@ -772,13 +776,21 @@ SELECT * FROM t2 WHERE id IN (SELECT 5 UNION SELECT 2); | ||
| 865 | id | ||
| 866 | 2 | ||
| 867 | INSERT INTO t2 VALUES ((SELECT * FROM t2)); | ||
| 868 | -ERROR HY000: Table 't2' is specified twice, both as a target for 'INSERT' and as a separate source for data | ||
| 869 | +ERROR 21000: Subquery returns more than 1 row | ||
| 870 | INSERT INTO t2 VALUES ((SELECT id FROM t2)); | ||
| 871 | -ERROR HY000: Table 't2' is specified twice, both as a target for 'INSERT' and as a separate source for data | ||
| 872 | +ERROR 21000: Subquery returns more than 1 row | ||
| 873 | +select * from t2; | ||
| 874 | +id | ||
| 875 | +1 | ||
| 876 | +2 | ||
| 877 | +INSERT INTO t2 VALUES ((SELECT count(*) FROM t2)); | ||
| 878 | +INSERT INTO t2 VALUES ((SELECT max(id) FROM t2)); | ||
| 879 | SELECT * FROM t2; | ||
| 880 | id | ||
| 881 | 1 | ||
| 882 | 2 | ||
| 883 | +2 | ||
| 884 | +2 | ||
| 885 | CREATE TABLE t1 (id int(11) default NULL, KEY id (id)) ENGINE=MyISAM CHARSET=latin1; | ||
| 886 | INSERT INTO t1 values (1),(1); | ||
| 887 | UPDATE t2 SET id=(SELECT * FROM t1); | ||
| 888 | diff --git a/mysql-test/main/view.result b/mysql-test/main/view.result | ||
| 889 | index 69e850cd..41ec8f43 100644 | ||
| 890 | --- a/mysql-test/main/view.result | ||
| 891 | +++ b/mysql-test/main/view.result | ||
| 892 | @@ -944,31 +944,19 @@ create view v1 as select * from t1; | ||
| 893 | create view v2 as select * from v1; | ||
| 894 | create view v3 as select v2.col1 from v2,t2 where v2.col1 = t2.col1; | ||
| 895 | insert into v2 values ((select max(col1) from v1)); | ||
| 896 | -ERROR HY000: The definition of table 'v1' prevents operation INSERT on table 'v2' | ||
| 897 | insert into t1 values ((select max(col1) from v1)); | ||
| 898 | -ERROR HY000: The definition of table 'v1' prevents operation INSERT on table 't1' | ||
| 899 | insert into v2 values ((select max(col1) from v1)); | ||
| 900 | -ERROR HY000: The definition of table 'v1' prevents operation INSERT on table 'v2' | ||
| 901 | insert into v2 values ((select max(col1) from t1)); | ||
| 902 | -ERROR HY000: The definition of table 'v2' prevents operation INSERT on table 'v2' | ||
| 903 | insert into t1 values ((select max(col1) from t1)); | ||
| 904 | -ERROR HY000: Table 't1' is specified twice, both as a target for 'INSERT' and as a separate source for data | ||
| 905 | insert into v2 values ((select max(col1) from t1)); | ||
| 906 | -ERROR HY000: The definition of table 'v2' prevents operation INSERT on table 'v2' | ||
| 907 | insert into v2 values ((select max(col1) from v2)); | ||
| 908 | -ERROR HY000: Table 'v2' is specified twice, both as a target for 'INSERT' and as a separate source for data | ||
| 909 | insert into t1 values ((select max(col1) from v2)); | ||
| 910 | -ERROR HY000: The definition of table 'v2' prevents operation INSERT on table 't1' | ||
| 911 | insert into v2 values ((select max(col1) from v2)); | ||
| 912 | -ERROR HY000: Table 'v2' is specified twice, both as a target for 'INSERT' and as a separate source for data | ||
| 913 | insert into v3 (col1) values ((select max(col1) from v1)); | ||
| 914 | -ERROR HY000: The definition of table 'v1' prevents operation INSERT on table 'v3' | ||
| 915 | insert into v3 (col1) values ((select max(col1) from t1)); | ||
| 916 | -ERROR HY000: The definition of table 'v3' prevents operation INSERT on table 'v3' | ||
| 917 | insert into v3 (col1) values ((select max(col1) from v2)); | ||
| 918 | -ERROR HY000: The definition of table 'v2' prevents operation INSERT on table 'v3' | ||
| 919 | -insert into v3 (col1) values ((select CONVERT_TZ('20050101000000','UTC','MET') from v2)); | ||
| 920 | -ERROR HY000: The definition of table 'v2' prevents operation INSERT on table 'v3' | ||
| 921 | +insert into v3 (col1) values ((select CONVERT_TZ('20050101000000','UTC','MET') from v2 LIMIT 1)); | ||
| 922 | +ERROR 22003: Out of range value for column 'col1' at row 2 | ||
| 923 | insert into v3 (col1) values ((select CONVERT_TZ('20050101000000','UTC','MET') from t2)); | ||
| 924 | insert into t3 values ((select CONVERT_TZ('20050101000000','UTC','MET') from t2)); | ||
| 925 | ERROR 23000: Column 'col1' cannot be null | ||
| 926 | @@ -978,6 +966,18 @@ insert into t1 (col1) values ((select max(col1) from v4)); | ||
| 927 | select * from t1; | ||
| 928 | col1 | ||
| 929 | NULL | ||
| 930 | +NULL | ||
| 931 | +NULL | ||
| 932 | +NULL | ||
| 933 | +NULL | ||
| 934 | +NULL | ||
| 935 | +NULL | ||
| 936 | +NULL | ||
| 937 | +NULL | ||
| 938 | +NULL | ||
| 939 | +NULL | ||
| 940 | +NULL | ||
| 941 | +NULL | ||
| 942 | 1 | ||
| 943 | 2 | ||
| 944 | 3 | ||
| 945 | @@ -1332,9 +1332,26 @@ create view v3 as select * from t1 where 20 < (select (s1) from v2); | ||
| 946 | insert into v3 values (30); | ||
| 947 | ERROR HY000: The target table v3 of the INSERT is not insertable-into | ||
| 948 | create view v4 as select * from v2 where 20 < (select (s1) from t1); | ||
| 949 | +select * from t1; | ||
| 950 | +s1 | ||
| 951 | insert into v4 values (30); | ||
| 952 | -ERROR HY000: The target table v4 of the INSERT is not insertable-into | ||
| 953 | -drop view v4, v3, v2, v1; | ||
| 954 | +select * from t1; | ||
| 955 | +s1 | ||
| 956 | +30 | ||
| 957 | +create view v5 as select * from v2 where s1 < (select min(s1) from t1) WITH CHECK OPTION; | ||
| 958 | +# can't insert only less then minimum | ||
| 959 | +insert into v5 values (40); | ||
| 960 | +ERROR 44000: CHECK OPTION failed `test`.`v5` | ||
| 961 | +# allow insert the new minimum | ||
| 962 | +insert into v5 values (10); | ||
| 963 | +# always emply view (can't be something less than minimum) | ||
| 964 | +select * from v5; | ||
| 965 | +s1 | ||
| 966 | +select * from t1; | ||
| 967 | +s1 | ||
| 968 | +30 | ||
| 969 | +10 | ||
| 970 | +drop view v5, v4, v3, v2, v1; | ||
| 971 | drop table t1; | ||
| 972 | create table t1 (a int); | ||
| 973 | create view v1 as select * from t1; | ||
| 974 | diff --git a/mysql-test/main/view.test b/mysql-test/main/view.test | ||
| 975 | index f32b148b..4e1dc911 100644 | ||
| 976 | --- a/mysql-test/main/view.test | ||
| 977 | +++ b/mysql-test/main/view.test | ||
| 978 | @@ -865,33 +865,21 @@ create table t3 (col1 datetime not null); | ||
| 979 | create view v1 as select * from t1; | ||
| 980 | create view v2 as select * from v1; | ||
| 981 | create view v3 as select v2.col1 from v2,t2 where v2.col1 = t2.col1; | ||
| 982 | --- error ER_VIEW_PREVENT_UPDATE | ||
| 983 | insert into v2 values ((select max(col1) from v1)); | ||
| 984 | --- error ER_VIEW_PREVENT_UPDATE | ||
| 985 | insert into t1 values ((select max(col1) from v1)); | ||
| 986 | --- error ER_VIEW_PREVENT_UPDATE | ||
| 987 | insert into v2 values ((select max(col1) from v1)); | ||
| 988 | --- error ER_VIEW_PREVENT_UPDATE | ||
| 989 | insert into v2 values ((select max(col1) from t1)); | ||
| 990 | --- error ER_UPDATE_TABLE_USED | ||
| 991 | insert into t1 values ((select max(col1) from t1)); | ||
| 992 | --- error ER_VIEW_PREVENT_UPDATE | ||
| 993 | insert into v2 values ((select max(col1) from t1)); | ||
| 994 | --- error ER_UPDATE_TABLE_USED | ||
| 995 | insert into v2 values ((select max(col1) from v2)); | ||
| 996 | --- error ER_VIEW_PREVENT_UPDATE | ||
| 997 | insert into t1 values ((select max(col1) from v2)); | ||
| 998 | --- error ER_UPDATE_TABLE_USED | ||
| 999 | insert into v2 values ((select max(col1) from v2)); | ||
| 1000 | --- error ER_VIEW_PREVENT_UPDATE | ||
| 1001 | insert into v3 (col1) values ((select max(col1) from v1)); | ||
| 1002 | --- error ER_VIEW_PREVENT_UPDATE | ||
| 1003 | insert into v3 (col1) values ((select max(col1) from t1)); | ||
| 1004 | --- error ER_VIEW_PREVENT_UPDATE | ||
| 1005 | insert into v3 (col1) values ((select max(col1) from v2)); | ||
| 1006 | # check with TZ tables in list | ||
| 1007 | --- error ER_VIEW_PREVENT_UPDATE | ||
| 1008 | -insert into v3 (col1) values ((select CONVERT_TZ('20050101000000','UTC','MET') from v2)); | ||
| 1009 | +--error ER_WARN_DATA_OUT_OF_RANGE | ||
| 1010 | +insert into v3 (col1) values ((select CONVERT_TZ('20050101000000','UTC','MET') from v2 LIMIT 1)); | ||
| 1011 | insert into v3 (col1) values ((select CONVERT_TZ('20050101000000','UTC','MET') from t2)); | ||
| 1012 | -- error ER_BAD_NULL_ERROR | ||
| 1013 | insert into t3 values ((select CONVERT_TZ('20050101000000','UTC','MET') from t2)); | ||
| 1014 | @@ -1209,9 +1197,19 @@ create view v3 as select * from t1 where 20 < (select (s1) from v2); | ||
| 1015 | -- error ER_NON_INSERTABLE_TABLE | ||
| 1016 | insert into v3 values (30); | ||
| 1017 | create view v4 as select * from v2 where 20 < (select (s1) from t1); | ||
| 1018 | --- error ER_NON_INSERTABLE_TABLE | ||
| 1019 | +select * from t1; | ||
| 1020 | insert into v4 values (30); | ||
| 1021 | -drop view v4, v3, v2, v1; | ||
| 1022 | +select * from t1; | ||
| 1023 | +create view v5 as select * from v2 where s1 < (select min(s1) from t1) WITH CHECK OPTION; | ||
| 1024 | +--echo # can't insert only less then minimum | ||
| 1025 | +--error ER_VIEW_CHECK_FAILED | ||
| 1026 | +insert into v5 values (40); | ||
| 1027 | +--echo # allow insert the new minimum | ||
| 1028 | +insert into v5 values (10); | ||
| 1029 | +--echo # always emply view (can't be something less than minimum) | ||
| 1030 | +select * from v5; | ||
| 1031 | +select * from t1; | ||
| 1032 | +drop view v5, v4, v3, v2, v1; | ||
| 1033 | drop table t1; | ||
| 1034 | |||
| 1035 | # | ||
| 1036 | diff --git a/mysql-test/suite/sql_sequence/other.result b/mysql-test/suite/sql_sequence/other.result | ||
| 1037 | index d237be63..a2a93d11 100644 | ||
| 1038 | --- a/mysql-test/suite/sql_sequence/other.result | ||
| 1039 | +++ b/mysql-test/suite/sql_sequence/other.result | ||
| 1040 | @@ -48,7 +48,6 @@ create sequence s2; | ||
| 1041 | insert into s1 (next_not_cached_value, minimum_value) values (100,1000); | ||
| 1042 | ERROR HY000: Field 'maximum_value' doesn't have a default value | ||
| 1043 | insert into s1 values (next value for s1, 1,9223372036854775806,1,1,1000,0,0); | ||
| 1044 | -ERROR HY000: Table 's1' is specified twice, both as a target for 'INSERT' and as a separate source for data | ||
| 1045 | insert into s1 values(1000,9223372036854775806,1,1,1,1000,0,0); | ||
| 1046 | ERROR HY000: Sequence 'test.s1' has out of range value for options | ||
| 1047 | insert into s1 values(0,9223372036854775806,1,1,1,1000,0,0); | ||
| 1048 | diff --git a/mysql-test/suite/sql_sequence/other.test b/mysql-test/suite/sql_sequence/other.test | ||
| 1049 | index 639cc5c3..69d51b3a 100644 | ||
| 1050 | --- a/mysql-test/suite/sql_sequence/other.test | ||
| 1051 | +++ b/mysql-test/suite/sql_sequence/other.test | ||
| 1052 | @@ -36,7 +36,6 @@ create sequence s1; | ||
| 1053 | create sequence s2; | ||
| 1054 | --error ER_NO_DEFAULT_FOR_FIELD | ||
| 1055 | insert into s1 (next_not_cached_value, minimum_value) values (100,1000); | ||
| 1056 | ---error ER_UPDATE_TABLE_USED | ||
| 1057 | insert into s1 values (next value for s1, 1,9223372036854775806,1,1,1000,0,0); | ||
| 1058 | --error ER_SEQUENCE_INVALID_DATA | ||
| 1059 | insert into s1 values(1000,9223372036854775806,1,1,1,1000,0,0); | ||
| 1060 | diff --git a/sql/item.h b/sql/item.h | ||
| 1061 | index 6c3b73df..cec075b4 100644 | ||
| 1062 | --- a/sql/item.h | ||
| 1063 | +++ b/sql/item.h | ||
| 1064 | @@ -753,6 +753,17 @@ class Item_const | ||
| 1065 | virtual const String *const_ptr_string() const { return NULL; } | ||
| 1066 | }; | ||
| 1067 | |||
| 1068 | +struct subselect_table_finder_param | ||
| 1069 | +{ | ||
| 1070 | + THD *thd; | ||
| 1071 | + /* | ||
| 1072 | + We're searching for different TABLE_LIST objects referring to the same | ||
| 1073 | + table as this one | ||
| 1074 | + */ | ||
| 1075 | + const TABLE_LIST *find; | ||
| 1076 | + /* NUL - not found, ERROR_TABLE - search error, or the found table reference */ | ||
| 1077 | + TABLE_LIST *dup; | ||
| 1078 | +}; | ||
| 1079 | |||
| 1080 | /****************************************************************************/ | ||
| 1081 | |||
| 1082 | @@ -2216,6 +2227,7 @@ class Item :public Value_source, | ||
| 1083 | set_extraction_flag(*(int16*)arg); | ||
| 1084 | return 0; | ||
| 1085 | } | ||
| 1086 | + virtual bool subselect_table_finder_processor(void *arg) { return 0; }; | ||
| 1087 | |||
| 1088 | /** | ||
| 1089 | Check db/table_name if they defined in item and match arg values | ||
| 1090 | diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc | ||
| 1091 | index f509e00b..4d579f09 100644 | ||
| 1092 | --- a/sql/item_subselect.cc | ||
| 1093 | +++ b/sql/item_subselect.cc | ||
| 1094 | @@ -7001,3 +7001,27 @@ void Item_subselect::init_expr_cache_tracker(THD *thd) | ||
| 1095 | DBUG_ASSERT(expr_cache->type() == Item::EXPR_CACHE_ITEM); | ||
| 1096 | node->cache_tracker= ((Item_cache_wrapper *)expr_cache)->init_tracker(qw->mem_root); | ||
| 1097 | } | ||
| 1098 | + | ||
| 1099 | + | ||
| 1100 | +/* | ||
| 1101 | + Check if somewhere inside this subselect we read the table. This means a | ||
| 1102 | + full read "(SELECT ... FROM tbl)", outside reference to tbl.column does not | ||
| 1103 | + count | ||
| 1104 | +*/ | ||
| 1105 | + | ||
| 1106 | +bool | ||
| 1107 | +Item_subselect::subselect_table_finder_processor(void *arg) | ||
| 1108 | +{ | ||
| 1109 | + subselect_table_finder_param *param= (subselect_table_finder_param *)arg; | ||
| 1110 | + for (SELECT_LEX *sl= unit->first_select(); sl; sl= sl->next_select()) | ||
| 1111 | + { | ||
| 1112 | + TABLE_LIST *dup; | ||
| 1113 | + if ((dup= sl->find_table(param->thd, ¶m->find->db, | ||
| 1114 | + ¶m->find->table_name))) | ||
| 1115 | + { | ||
| 1116 | + param->dup= dup; | ||
| 1117 | + return TRUE; | ||
| 1118 | + } | ||
| 1119 | + } | ||
| 1120 | + return FALSE; | ||
| 1121 | +}; | ||
| 1122 | diff --git a/sql/item_subselect.h b/sql/item_subselect.h | ||
| 1123 | index fdd0333a..b03ad835 100644 | ||
| 1124 | --- a/sql/item_subselect.h | ||
| 1125 | +++ b/sql/item_subselect.h | ||
| 1126 | @@ -270,6 +270,7 @@ class Item_subselect :public Item_result_field, | ||
| 1127 | { | ||
| 1128 | return TRUE; | ||
| 1129 | } | ||
| 1130 | + bool subselect_table_finder_processor(void *arg) override; | ||
| 1131 | |||
| 1132 | void register_as_with_rec_ref(With_element *with_elem); | ||
| 1133 | void init_expr_cache_tracker(THD *thd); | ||
| 1134 | diff --git a/sql/sql_base.cc b/sql/sql_base.cc | ||
| 1135 | index 15a9882b..6374d0be 100644 | ||
| 1136 | --- a/sql/sql_base.cc | ||
| 1137 | +++ b/sql/sql_base.cc | ||
| 1138 | @@ -19,6 +19,7 @@ | ||
| 1139 | |||
| 1140 | #include "mariadb.h" | ||
| 1141 | #include "sql_base.h" // setup_table_map | ||
| 1142 | +#include "sql_list.h" | ||
| 1143 | #include "sql_priv.h" | ||
| 1144 | #include "unireg.h" | ||
| 1145 | #include "debug_sync.h" | ||
| 1146 | @@ -1114,7 +1115,6 @@ TABLE_LIST* find_dup_table(THD *thd, TABLE_LIST *table, TABLE_LIST *table_list, | ||
| 1147 | t_name= &table->table_name; | ||
| 1148 | t_alias= &table->alias; | ||
| 1149 | |||
| 1150 | -retry: | ||
| 1151 | DBUG_PRINT("info", ("real table: %s.%s", d_name->str, t_name->str)); | ||
| 1152 | for (TABLE_LIST *tl= table_list; tl ; tl= tl->next_global, res= 0) | ||
| 1153 | { | ||
| 1154 | @@ -1176,37 +1176,52 @@ TABLE_LIST* find_dup_table(THD *thd, TABLE_LIST *table, TABLE_LIST *table_list, | ||
| 1155 | DBUG_PRINT("info", | ||
| 1156 | ("found same copy of table or table which we should skip")); | ||
| 1157 | } | ||
| 1158 | - /* | ||
| 1159 | - If we've found a duplicate in a derived table, try to work around that. | ||
| 1160 | - | ||
| 1161 | - For INSERT...SELECT, do not do any workarounds, return the duplicate. The | ||
| 1162 | - caller will enable buffering to handle this. | ||
| 1163 | - */ | ||
| 1164 | - if (res && res->belong_to_derived && | ||
| 1165 | - !(check_flag & CHECK_DUP_FOR_INSERT_SELECT)) | ||
| 1166 | - { | ||
| 1167 | - /* | ||
| 1168 | - We come here for queries like this: | ||
| 1169 | + DBUG_RETURN(res); | ||
| 1170 | +} | ||
| 1171 | |||
| 1172 | - INSERT INTO t1 VALUES ((SELECT tmp.a FROM (select * FROM t1))); | ||
| 1173 | - DELETE FROM t1 WHERE ( ... (SELECT ... FROM t1) ) ; | ||
| 1174 | |||
| 1175 | - Try to fix by materializing the derived table | ||
| 1176 | - */ | ||
| 1177 | - TABLE_LIST *derived= res->belong_to_derived; | ||
| 1178 | - if (derived->is_merged_derived() && !derived->derived->is_excluded()) | ||
| 1179 | +TABLE_LIST* unique_table_in_select_list(THD *thd, TABLE_LIST *table, SELECT_LEX *sel) | ||
| 1180 | +{ | ||
| 1181 | + subselect_table_finder_param param= {thd, table, NULL}; | ||
| 1182 | + List_iterator_fast<Item> it(sel->item_list); | ||
| 1183 | + Item *item; | ||
| 1184 | + while ((item= it++)) | ||
| 1185 | + { | ||
| 1186 | + if (item->walk(&Item::subselect_table_finder_processor, FALSE, ¶m)) | ||
| 1187 | { | ||
| 1188 | - DBUG_PRINT("info", | ||
| 1189 | - ("convert merged to materialization to resolve the conflict")); | ||
| 1190 | - derived->change_refs_to_fields(); | ||
| 1191 | - derived->set_materialized_derived(); | ||
| 1192 | - goto retry; | ||
| 1193 | + if (param.dup == NULL) | ||
| 1194 | + return ERROR_TABLE; | ||
| 1195 | + return param.dup; | ||
| 1196 | } | ||
| 1197 | + DBUG_ASSERT(param.dup == NULL); | ||
| 1198 | } | ||
| 1199 | - DBUG_RETURN(res); | ||
| 1200 | + return NULL; | ||
| 1201 | } | ||
| 1202 | |||
| 1203 | |||
| 1204 | +typedef TABLE_LIST* (*find_table_callback)(THD *thd, TABLE_LIST *table, | ||
| 1205 | + TABLE_LIST *table_list, | ||
| 1206 | + uint check_flag, SELECT_LEX *sel); | ||
| 1207 | + | ||
| 1208 | +static | ||
| 1209 | +TABLE_LIST* | ||
| 1210 | +find_table(THD *thd, TABLE_LIST *table, TABLE_LIST *table_list, | ||
| 1211 | + uint check_flag, SELECT_LEX *sel, find_table_callback callback ); | ||
| 1212 | + | ||
| 1213 | +TABLE_LIST* unique_table_callback(THD *thd, TABLE_LIST *table, | ||
| 1214 | + TABLE_LIST *table_list, | ||
| 1215 | + uint check_flag, SELECT_LEX *sel) | ||
| 1216 | +{ | ||
| 1217 | + return find_dup_table(thd, table, table_list, check_flag); | ||
| 1218 | +} | ||
| 1219 | + | ||
| 1220 | + | ||
| 1221 | +TABLE_LIST* unique_in_sel_table_callback(THD *thd, TABLE_LIST *table, | ||
| 1222 | + TABLE_LIST *table_list, | ||
| 1223 | + uint check_flag, SELECT_LEX *sel) | ||
| 1224 | +{ | ||
| 1225 | + return unique_table_in_select_list(thd, table, sel); | ||
| 1226 | +} | ||
| 1227 | /** | ||
| 1228 | Test that the subject table of INSERT/UPDATE/DELETE/CREATE | ||
| 1229 | or (in case of MyISAMMRG) one of its children are not used later | ||
| 1230 | @@ -1225,6 +1240,25 @@ TABLE_LIST* find_dup_table(THD *thd, TABLE_LIST *table, TABLE_LIST *table_list, | ||
| 1231 | TABLE_LIST* | ||
| 1232 | unique_table(THD *thd, TABLE_LIST *table, TABLE_LIST *table_list, | ||
| 1233 | uint check_flag) | ||
| 1234 | +{ | ||
| 1235 | + return find_table(thd, table, table_list, check_flag, NULL, | ||
| 1236 | + &unique_table_callback); | ||
| 1237 | +} | ||
| 1238 | + | ||
| 1239 | + | ||
| 1240 | +TABLE_LIST* | ||
| 1241 | +unique_table_in_insert_returning_subselect(THD *thd, TABLE_LIST *table, SELECT_LEX *sel) | ||
| 1242 | +{ | ||
| 1243 | + return find_table(thd, table, NULL, 0, sel, | ||
| 1244 | + &unique_in_sel_table_callback); | ||
| 1245 | + | ||
| 1246 | +} | ||
| 1247 | + | ||
| 1248 | + | ||
| 1249 | +static | ||
| 1250 | +TABLE_LIST* | ||
| 1251 | +find_table(THD *thd, TABLE_LIST *table, TABLE_LIST *table_list, | ||
| 1252 | + uint check_flag, SELECT_LEX *sel, find_table_callback callback ) | ||
| 1253 | { | ||
| 1254 | TABLE_LIST *dup; | ||
| 1255 | |||
| 1256 | @@ -1256,12 +1290,12 @@ unique_table(THD *thd, TABLE_LIST *table, TABLE_LIST *table_list, | ||
| 1257 | if (!tmp_parent) | ||
| 1258 | break; | ||
| 1259 | |||
| 1260 | - if ((dup= find_dup_table(thd, child, child->next_global, check_flag))) | ||
| 1261 | + if ((dup= (*callback)(thd, child, child->next_global, check_flag, sel))) | ||
| 1262 | break; | ||
| 1263 | } | ||
| 1264 | } | ||
| 1265 | else | ||
| 1266 | - dup= find_dup_table(thd, table, table_list, check_flag); | ||
| 1267 | + dup= (*callback)(thd, table, table_list, check_flag, sel); | ||
| 1268 | return dup; | ||
| 1269 | } | ||
| 1270 | |||
| 1271 | diff --git a/sql/sql_base.h b/sql/sql_base.h | ||
| 1272 | index da9b1575..6de4d2b8 100644 | ||
| 1273 | --- a/sql/sql_base.h | ||
| 1274 | +++ b/sql/sql_base.h | ||
| 1275 | @@ -72,7 +72,6 @@ enum find_item_error_report_type {REPORT_ALL_ERRORS, REPORT_EXCEPT_NOT_FOUND, | ||
| 1276 | #define CHECK_DUP_ALLOW_DIFFERENT_ALIAS 1 | ||
| 1277 | #define CHECK_DUP_FOR_CREATE 2 | ||
| 1278 | #define CHECK_DUP_SKIP_TEMP_TABLE 4 | ||
| 1279 | -#define CHECK_DUP_FOR_INSERT_SELECT 8 | ||
| 1280 | |||
| 1281 | uint get_table_def_key(const TABLE_LIST *table_list, const char **key); | ||
| 1282 | TABLE *open_ltable(THD *thd, TABLE_LIST *table_list, thr_lock_type update, | ||
| 1283 | @@ -291,6 +290,8 @@ bool open_and_lock_internal_tables(TABLE *table, bool lock); | ||
| 1284 | bool lock_tables(THD *thd, TABLE_LIST *tables, uint counter, uint flags); | ||
| 1285 | int decide_logging_format(THD *thd, TABLE_LIST *tables); | ||
| 1286 | void close_thread_table(THD *thd, TABLE **table_ptr); | ||
| 1287 | +TABLE_LIST* | ||
| 1288 | +unique_table_in_insert_returning_subselect(THD *thd, TABLE_LIST *table, SELECT_LEX *sel); | ||
| 1289 | TABLE_LIST *unique_table(THD *thd, TABLE_LIST *table, TABLE_LIST *table_list, | ||
| 1290 | uint check_flag); | ||
| 1291 | bool is_equal(const LEX_CSTRING *a, const LEX_CSTRING *b); | ||
| 1292 | diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc | ||
| 1293 | index d9813660..91bd6e93 100644 | ||
| 1294 | --- a/sql/sql_insert.cc | ||
| 1295 | +++ b/sql/sql_insert.cc | ||
| 1296 | @@ -57,6 +57,7 @@ | ||
| 1297 | */ | ||
| 1298 | |||
| 1299 | #include "mariadb.h" /* NO_EMBEDDED_ACCESS_CHECKS */ | ||
| 1300 | +#include "sql_list.h" | ||
| 1301 | #include "sql_priv.h" | ||
| 1302 | #include "sql_insert.h" | ||
| 1303 | #include "sql_update.h" // compare_record | ||
| 1304 | @@ -712,6 +713,8 @@ bool mysql_insert(THD *thd, TABLE_LIST *table_list, | ||
| 1305 | Name_resolution_context_state ctx_state; | ||
| 1306 | SELECT_LEX *returning= thd->lex->has_returning() ? thd->lex->returning() : 0; | ||
| 1307 | unsigned char *readbuff= NULL; | ||
| 1308 | + List<List_item> insert_values_cache; | ||
| 1309 | + bool cache_insert_values= FALSE; | ||
| 1310 | |||
| 1311 | #ifndef EMBEDDED_LIBRARY | ||
| 1312 | char *query= thd->query(); | ||
| 1313 | @@ -769,7 +772,7 @@ bool mysql_insert(THD *thd, TABLE_LIST *table_list, | ||
| 1314 | |||
| 1315 | if ((res= mysql_prepare_insert(thd, table_list, fields, values, | ||
| 1316 | update_fields, update_values, duplic, ignore, | ||
| 1317 | - &unused_conds, FALSE))) | ||
| 1318 | + &unused_conds, FALSE, &cache_insert_values))) | ||
| 1319 | { | ||
| 1320 | retval= thd->is_error(); | ||
| 1321 | if (res < 0) | ||
| 1322 | @@ -1019,8 +1022,41 @@ bool mysql_insert(THD *thd, TABLE_LIST *table_list, | ||
| 1323 | if (returning) | ||
| 1324 | fix_rownum_pointers(thd, thd->lex->returning(), &info.accepted_rows); | ||
| 1325 | |||
| 1326 | + if (cache_insert_values) | ||
| 1327 | + { | ||
| 1328 | + insert_values_cache.empty(); | ||
| 1329 | + while ((values= its++)) | ||
| 1330 | + { | ||
| 1331 | + List<Item> *caches= new (thd->mem_root) List_item; | ||
| 1332 | + List_iterator_fast<Item> iv(*values); | ||
| 1333 | + Item *item; | ||
| 1334 | + if (caches == 0) | ||
| 1335 | + { | ||
| 1336 | + error= 1; | ||
| 1337 | + goto values_loop_end; | ||
| 1338 | + } | ||
| 1339 | + caches->empty(); | ||
| 1340 | + while((item= iv++)) | ||
| 1341 | + { | ||
| 1342 | + Item_cache *cache= item->get_cache(thd); | ||
| 1343 | + if (!cache) | ||
| 1344 | + { | ||
| 1345 | + error= 1; | ||
| 1346 | + goto values_loop_end; | ||
| 1347 | + } | ||
| 1348 | + cache->setup(thd, item); | ||
| 1349 | + caches->push_back(cache); | ||
| 1350 | + } | ||
| 1351 | + insert_values_cache.push_back(caches); | ||
| 1352 | + } | ||
| 1353 | + its.rewind(); | ||
| 1354 | + } | ||
| 1355 | + | ||
| 1356 | do | ||
| 1357 | { | ||
| 1358 | + List_iterator_fast<List_item> itc(insert_values_cache); | ||
| 1359 | + List_iterator_fast<List_item> *itr; | ||
| 1360 | + | ||
| 1361 | DBUG_PRINT("info", ("iteration %llu", iteration)); | ||
| 1362 | if (iteration && bulk_parameters_set(thd)) | ||
| 1363 | { | ||
| 1364 | @@ -1028,7 +1064,24 @@ bool mysql_insert(THD *thd, TABLE_LIST *table_list, | ||
| 1365 | goto values_loop_end; | ||
| 1366 | } | ||
| 1367 | |||
| 1368 | - while ((values= its++)) | ||
| 1369 | + if (cache_insert_values) | ||
| 1370 | + { | ||
| 1371 | + List_item *caches; | ||
| 1372 | + while ((caches= itc++)) | ||
| 1373 | + { | ||
| 1374 | + List_iterator_fast<Item> ic(*caches); | ||
| 1375 | + Item_cache *cache; | ||
| 1376 | + while((cache= (Item_cache*) ic++)) | ||
| 1377 | + { | ||
| 1378 | + cache->cache_value(); | ||
| 1379 | + } | ||
| 1380 | + } | ||
| 1381 | + itc.rewind(); | ||
| 1382 | + itr= &itc; | ||
| 1383 | + } | ||
| 1384 | + else | ||
| 1385 | + itr= &its; | ||
| 1386 | + while ((values= (*itr)++)) | ||
| 1387 | { | ||
| 1388 | thd->get_stmt_da()->inc_current_row_for_warning(); | ||
| 1389 | if (fields.elements || !value_count) | ||
| 1390 | @@ -1148,7 +1201,7 @@ bool mysql_insert(THD *thd, TABLE_LIST *table_list, | ||
| 1391 | break; | ||
| 1392 | info.accepted_rows++; | ||
| 1393 | } | ||
| 1394 | - its.rewind(); | ||
| 1395 | + itr->rewind(); | ||
| 1396 | iteration++; | ||
| 1397 | } while (bulk_parameters_iterations(thd)); | ||
| 1398 | |||
| 1399 | @@ -1620,6 +1673,7 @@ static void prepare_for_positional_update(TABLE *table, TABLE_LIST *tables) | ||
| 1400 | table_list Global/local table list | ||
| 1401 | where Where clause (for insert ... select) | ||
| 1402 | select_insert TRUE if INSERT ... SELECT statement | ||
| 1403 | + cache_insert_values insert's VALUES(...) has to be pre-computed | ||
| 1404 | |||
| 1405 | TODO (in far future) | ||
| 1406 | In cases of: | ||
| 1407 | @@ -1642,7 +1696,7 @@ int mysql_prepare_insert(THD *thd, TABLE_LIST *table_list, | ||
| 1408 | List<Item> &update_fields, List<Item> &update_values, | ||
| 1409 | enum_duplicates duplic, bool ignore, | ||
| 1410 | COND **where, | ||
| 1411 | - bool select_insert) | ||
| 1412 | + bool select_insert, bool * const cache_insert_values) | ||
| 1413 | { | ||
| 1414 | SELECT_LEX *select_lex= thd->lex->first_select_lex(); | ||
| 1415 | Name_resolution_context *context= &select_lex->context; | ||
| 1416 | @@ -1743,11 +1797,12 @@ int mysql_prepare_insert(THD *thd, TABLE_LIST *table_list, | ||
| 1417 | |||
| 1418 | /* | ||
| 1419 | Check if we read from the same table we're inserting into. | ||
| 1420 | - Queries like INSERT INTO t1 VALUES ((SELECT ... FROM t1...)) are not | ||
| 1421 | - allowed. | ||
| 1422 | + Queries like INSERT INTO t1 VALUES ((SELECT ... FROM t1...)) have | ||
| 1423 | + to pre-compute the VALUES part. | ||
| 1424 | + Reading from the same table in the RETURNING clause is not allowed. | ||
| 1425 | |||
| 1426 | - INSERT...SELECT is an exception: it will detect this case and use | ||
| 1427 | - buffering to handle it correctly. | ||
| 1428 | + INSERT...SELECT detects this case in select_insert::prepare and also | ||
| 1429 | + uses buffering to handle it correcly. | ||
| 1430 | */ | ||
| 1431 | if (!select_insert) | ||
| 1432 | { | ||
| 1433 | @@ -1756,10 +1811,30 @@ int mysql_prepare_insert(THD *thd, TABLE_LIST *table_list, | ||
| 1434 | if ((duplicate= unique_table(thd, table_list, table_list->next_global, | ||
| 1435 | CHECK_DUP_ALLOW_DIFFERENT_ALIAS))) | ||
| 1436 | { | ||
| 1437 | - update_non_unique_table_error(table_list, "INSERT", duplicate); | ||
| 1438 | - DBUG_RETURN(1); | ||
| 1439 | + /* | ||
| 1440 | + This is INSERT INTO ... VALUES (...) and it must pre-compute the | ||
| 1441 | + values to be inserted. | ||
| 1442 | + */ | ||
| 1443 | + (*cache_insert_values)= true; | ||
| 1444 | } | ||
| 1445 | + else | ||
| 1446 | + (*cache_insert_values)= false; | ||
| 1447 | + | ||
| 1448 | select_lex->fix_prepare_information(thd, &fake_conds, &fake_conds); | ||
| 1449 | + | ||
| 1450 | + if ((*cache_insert_values) && thd->lex->has_returning()) | ||
| 1451 | + { | ||
| 1452 | + // Check if the table we're inserting into is also in RETURNING clause | ||
| 1453 | + TABLE_LIST *dup= | ||
| 1454 | + unique_table_in_insert_returning_subselect(thd, table_list, | ||
| 1455 | + thd->lex->returning()); | ||
| 1456 | + if (dup) | ||
| 1457 | + { | ||
| 1458 | + if (dup != ERROR_TABLE) | ||
| 1459 | + update_non_unique_table_error(table_list, "INSERT", duplicate); | ||
| 1460 | + DBUG_RETURN(1); | ||
| 1461 | + } | ||
| 1462 | + } | ||
| 1463 | } | ||
| 1464 | /* | ||
| 1465 | Only call prepare_for_posistion() if we are not performing a DELAYED | ||
| 1466 | @@ -3817,6 +3892,7 @@ int mysql_insert_select_prepare(THD *thd, select_result *sel_res) | ||
| 1467 | int res; | ||
| 1468 | LEX *lex= thd->lex; | ||
| 1469 | SELECT_LEX *select_lex= lex->first_select_lex(); | ||
| 1470 | + bool cache_insert_values= false; | ||
| 1471 | DBUG_ENTER("mysql_insert_select_prepare"); | ||
| 1472 | |||
| 1473 | /* | ||
| 1474 | @@ -3827,7 +3903,7 @@ int mysql_insert_select_prepare(THD *thd, select_result *sel_res) | ||
| 1475 | if ((res= mysql_prepare_insert(thd, lex->query_tables, lex->field_list, 0, | ||
| 1476 | lex->update_list, lex->value_list, | ||
| 1477 | lex->duplicates, lex->ignore, | ||
| 1478 | - &select_lex->where, TRUE))) | ||
| 1479 | + &select_lex->where, TRUE, &cache_insert_values))) | ||
| 1480 | DBUG_RETURN(res); | ||
| 1481 | |||
| 1482 | /* | ||
| 1483 | @@ -4029,8 +4105,7 @@ select_insert::prepare(List<Item> &values, SELECT_LEX_UNIT *u) | ||
| 1484 | Is table which we are changing used somewhere in other parts of | ||
| 1485 | query | ||
| 1486 | */ | ||
| 1487 | - if (unique_table(thd, table_list, table_list->next_global, | ||
| 1488 | - CHECK_DUP_FOR_INSERT_SELECT)) | ||
| 1489 | + if (unique_table(thd, table_list, table_list->next_global, 0)) | ||
| 1490 | { | ||
| 1491 | /* Using same table for INSERT and SELECT */ | ||
| 1492 | lex->current_select->options|= OPTION_BUFFER_RESULT; | ||
| 1493 | diff --git a/sql/sql_insert.h b/sql/sql_insert.h | ||
| 1494 | index 8b034c25..656da557 100644 | ||
| 1495 | --- a/sql/sql_insert.h | ||
| 1496 | +++ b/sql/sql_insert.h | ||
| 1497 | @@ -28,7 +28,7 @@ int mysql_prepare_insert(THD *thd, TABLE_LIST *table_list, | ||
| 1498 | List<Item> &update_fields, | ||
| 1499 | List<Item> &update_values, enum_duplicates duplic, | ||
| 1500 | bool ignore, | ||
| 1501 | - COND **where, bool select_insert); | ||
| 1502 | + COND **where, bool select_insert, bool * const cache_results); | ||
| 1503 | bool mysql_insert(THD *thd,TABLE_LIST *table,List<Item> &fields, | ||
| 1504 | List<List_item> &values, List<Item> &update_fields, | ||
| 1505 | List<Item> &update_values, enum_duplicates flag, | ||
| 1506 | diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc | ||
| 1507 | index b3aef010..51678f76 100644 | ||
| 1508 | --- a/sql/sql_lex.cc | ||
| 1509 | +++ b/sql/sql_lex.cc | ||
| 1510 | @@ -11872,3 +11872,45 @@ bool SELECT_LEX_UNIT::explainable() const | ||
| 1511 | derived->is_materialized_derived() : // (3) | ||
| 1512 | false; | ||
| 1513 | } | ||
| 1514 | + | ||
| 1515 | +/** | ||
| 1516 | + Find the real table in prepared SELECT tree | ||
| 1517 | + | ||
| 1518 | + NOTE: all SELECT must be prepared (to have leaf table list). | ||
| 1519 | + | ||
| 1520 | + NOTE: it looks only for real tables (not view or derived) | ||
| 1521 | + | ||
| 1522 | + @param thd the current thread handle | ||
| 1523 | + @param db_name name of db of the table to look for | ||
| 1524 | + @param db_name name of db of the table to look for | ||
| 1525 | + | ||
| 1526 | + @return first found table, NULL or ERROR_TABLE | ||
| 1527 | +*/ | ||
| 1528 | + | ||
| 1529 | +TABLE_LIST *SELECT_LEX::find_table(THD *thd, | ||
| 1530 | + const LEX_CSTRING *db_name, | ||
| 1531 | + const LEX_CSTRING *table_name) | ||
| 1532 | +{ | ||
| 1533 | + uchar buff[STACK_BUFF_ALLOC]; // Max argument in function | ||
| 1534 | + if (check_stack_overrun(thd, STACK_MIN_SIZE, buff)) | ||
| 1535 | + return NULL; | ||
| 1536 | + | ||
| 1537 | + List_iterator_fast <TABLE_LIST> ti(leaf_tables); | ||
| 1538 | + TABLE_LIST *table; | ||
| 1539 | + while ((table= ti++)) | ||
| 1540 | + { | ||
| 1541 | + if (cmp(&table->db, db_name) == 0 && | ||
| 1542 | + cmp(&table->table_name, table_name) == 0) | ||
| 1543 | + return table; | ||
| 1544 | + } | ||
| 1545 | + | ||
| 1546 | + for (SELECT_LEX_UNIT *u= first_inner_unit(); u; u= u->next_unit()) | ||
| 1547 | + { | ||
| 1548 | + for (st_select_lex *sl= u->first_select(); sl; sl=sl->next_select()) | ||
| 1549 | + { | ||
| 1550 | + if ((table= sl->find_table(thd, db_name, table_name))) | ||
| 1551 | + return table; | ||
| 1552 | + } | ||
| 1553 | + } | ||
| 1554 | + return NULL; | ||
| 1555 | +} | ||
| 1556 | diff --git a/sql/sql_lex.h b/sql/sql_lex.h | ||
| 1557 | index 9d2912c8..2300a772 100644 | ||
| 1558 | --- a/sql/sql_lex.h | ||
| 1559 | +++ b/sql/sql_lex.h | ||
| 1560 | @@ -1641,6 +1641,10 @@ class st_select_lex: public st_select_lex_node | ||
| 1561 | void lex_start(LEX *plex); | ||
| 1562 | bool is_unit_nest() { return (nest_flags & UNIT_NEST_FL); } | ||
| 1563 | void mark_as_unit_nest() { nest_flags= UNIT_NEST_FL; } | ||
| 1564 | + | ||
| 1565 | + TABLE_LIST *find_table(THD *thd, | ||
| 1566 | + const LEX_CSTRING *db_name, | ||
| 1567 | + const LEX_CSTRING *table_name); | ||
| 1568 | }; | ||
| 1569 | typedef class st_select_lex SELECT_LEX; | ||
| 1570 | |||
| 1571 | diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc | ||
| 1572 | index 65d515d3..ec5d1692 100644 | ||
| 1573 | --- a/sql/sql_prepare.cc | ||
| 1574 | +++ b/sql/sql_prepare.cc | ||
| 1575 | @@ -1294,6 +1294,7 @@ static bool mysql_test_insert_common(Prepared_statement *stmt, | ||
| 1576 | THD *thd= stmt->thd; | ||
| 1577 | List_iterator_fast<List_item> its(values_list); | ||
| 1578 | List_item *values; | ||
| 1579 | + bool cache_results= FALSE; | ||
| 1580 | DBUG_ENTER("mysql_test_insert_common"); | ||
| 1581 | |||
| 1582 | if (insert_precheck(thd, table_list)) | ||
| 1583 | @@ -1326,7 +1327,8 @@ static bool mysql_test_insert_common(Prepared_statement *stmt, | ||
| 1584 | |||
| 1585 | if (mysql_prepare_insert(thd, table_list, fields, values, update_fields, | ||
| 1586 | update_values, duplic, ignore, | ||
| 1587 | - &unused_conds, FALSE)) | ||
| 1588 | + &unused_conds, FALSE, | ||
| 1589 | + &cache_results)) | ||
| 1590 | goto error; | ||
| 1591 | |||
| 1592 | value_count= values->elements; | ||
| 1593 | diff --git a/sql/table.h b/sql/table.h | ||
| 1594 | index d0f61eb0..5493412d 100644 | ||
| 1595 | --- a/sql/table.h | ||
| 1596 | +++ b/sql/table.h | ||
| 1597 | @@ -2973,6 +2973,8 @@ struct TABLE_LIST | ||
| 1598 | ulong m_table_ref_version; | ||
| 1599 | }; | ||
| 1600 | |||
| 1601 | +#define ERROR_TABLE ((TABLE_LIST*) 0x1) | ||
| 1602 | + | ||
| 1603 | class Item; | ||
| 1604 | |||
| 1605 | /* | ||
| 1606 | diff --git a/tests/mysql_client_test.c b/tests/mysql_client_test.c | ||
| 1607 | index 528eece5..0bcb1e98 100644 | ||
| 1608 | --- a/tests/mysql_client_test.c | ||
| 1609 | +++ b/tests/mysql_client_test.c | ||
| 1610 | @@ -21535,6 +21535,164 @@ static void test_mdev19838() | ||
| 1611 | rc = mysql_query(mysql, "drop table mdev19838"); | ||
| 1612 | myquery(rc); | ||
| 1613 | } | ||
| 1614 | + | ||
| 1615 | +/* Server crash when inserting from derived table containing insert target table */ | ||
| 1616 | +static void test_mdev_32086() | ||
| 1617 | +{ | ||
| 1618 | + int rc; | ||
| 1619 | + MYSQL_STMT *stmt_insert; | ||
| 1620 | + MYSQL_BIND bind[2]; | ||
| 1621 | + MYSQL_RES *result; | ||
| 1622 | + MYSQL_ROW row; | ||
| 1623 | + unsigned int vals[] = { 123, 124}; | ||
| 1624 | + unsigned int vals_array_len = 2; | ||
| 1625 | + const char *insert_stmt= "\ | ||
| 1626 | +insert into t1 values(\ | ||
| 1627 | + (select 101+count(*)\ | ||
| 1628 | + from\ | ||
| 1629 | + (\ | ||
| 1630 | + select dt2.id\ | ||
| 1631 | + from (select id from t1) dt2, t1 t where t.id=dt2.id\ | ||
| 1632 | + ) dt\ | ||
| 1633 | + where dt.id<1000\ | ||
| 1634 | + ), ?\ | ||
| 1635 | +)"; | ||
| 1636 | + | ||
| 1637 | + /* Set up test's environment */ | ||
| 1638 | + | ||
| 1639 | + | ||
| 1640 | + rc= mysql_query(mysql, "create table t1 (pk int, id int);"); | ||
| 1641 | + myquery(rc); | ||
| 1642 | + | ||
| 1643 | + rc= mysql_query(mysql, "insert into t1 values (2,2), (3,3), (4,4);"); | ||
| 1644 | + myquery(rc); | ||
| 1645 | + | ||
| 1646 | + stmt_insert = mysql_stmt_init(mysql); | ||
| 1647 | + if (!stmt_insert) | ||
| 1648 | + { | ||
| 1649 | + fprintf(stderr, "mysql_stmt_init failed: Error: %s\n", | ||
| 1650 | + mysql_error(mysql)); | ||
| 1651 | + exit(1); | ||
| 1652 | + } | ||
| 1653 | + | ||
| 1654 | + rc= mysql_stmt_prepare(stmt_insert, insert_stmt, strlen(insert_stmt)); | ||
| 1655 | + if (rc) | ||
| 1656 | + { | ||
| 1657 | + fprintf(stderr, "mysql_stmt_prepare failed: %s\n", | ||
| 1658 | + mysql_stmt_error(stmt_insert)); | ||
| 1659 | + exit(1); | ||
| 1660 | + } | ||
| 1661 | + | ||
| 1662 | + memset(&bind[0], 0, sizeof(MYSQL_BIND)); | ||
| 1663 | + | ||
| 1664 | + bind[0].buffer_type= MYSQL_TYPE_LONG; | ||
| 1665 | + bind[0].buffer= vals; | ||
| 1666 | + | ||
| 1667 | + rc= mysql_stmt_attr_set(stmt_insert, STMT_ATTR_ARRAY_SIZE, &vals_array_len); | ||
| 1668 | + if (rc) | ||
| 1669 | + { | ||
| 1670 | + fprintf(stderr, "mysql_stmt_prepare failed: %s\n", | ||
| 1671 | + mysql_stmt_error(stmt_insert)); | ||
| 1672 | + exit(1); | ||
| 1673 | + } | ||
| 1674 | + | ||
| 1675 | + rc= mysql_stmt_bind_param(stmt_insert, bind); | ||
| 1676 | + if (rc) | ||
| 1677 | + { | ||
| 1678 | + fprintf(stderr, "mysql_stmt_bind_param failed: %s\n", | ||
| 1679 | + mysql_stmt_error(stmt_insert)); | ||
| 1680 | + exit(1); | ||
| 1681 | + } | ||
| 1682 | + | ||
| 1683 | + rc= mysql_stmt_execute(stmt_insert); | ||
| 1684 | + if (rc) | ||
| 1685 | + { | ||
| 1686 | + fprintf(stderr, "mysql_stmt_execute failed: %s\n", | ||
| 1687 | + mysql_stmt_error(stmt_insert)); | ||
| 1688 | + exit(1); | ||
| 1689 | + } | ||
| 1690 | + | ||
| 1691 | + /* | ||
| 1692 | + pk id | ||
| 1693 | + 2 2 | ||
| 1694 | + 3 3 | ||
| 1695 | + 4 4 | ||
| 1696 | + 104 123 | ||
| 1697 | + 104 124 | ||
| 1698 | + */ | ||
| 1699 | + rc= mysql_query(mysql, "select * from t1"); | ||
| 1700 | + if (rc) | ||
| 1701 | + { | ||
| 1702 | + fprintf(stderr, "Query failed: %s\n", mysql_error(mysql)); | ||
| 1703 | + } | ||
| 1704 | + result= mysql_store_result(mysql); | ||
| 1705 | + row= mysql_fetch_row(result); | ||
| 1706 | + DIE_UNLESS(atoi(row[0]) == 2 && atoi(row[1]) == 2); | ||
| 1707 | + row= mysql_fetch_row(result); | ||
| 1708 | + DIE_UNLESS(atoi(row[0]) == 3 && atoi(row[1]) == 3); | ||
| 1709 | + row= mysql_fetch_row(result); | ||
| 1710 | + DIE_UNLESS(atoi(row[0]) == 4 && atoi(row[1]) == 4); | ||
| 1711 | + row= mysql_fetch_row(result); | ||
| 1712 | + printf("\n %d, %d \n", atoi(row[0]), atoi(row[1])); | ||
| 1713 | + DIE_UNLESS(atoi(row[0]) == 104 && atoi(row[1]) == 123); | ||
| 1714 | + row= mysql_fetch_row(result); | ||
| 1715 | + printf("\n %d, %d \n", atoi(row[0]), atoi(row[1])); | ||
| 1716 | + DIE_UNLESS(atoi(row[0]) == 104 && atoi(row[1]) == 124); | ||
| 1717 | + row= mysql_fetch_row(result); | ||
| 1718 | + DIE_UNLESS(row == NULL); | ||
| 1719 | + | ||
| 1720 | + mysql_free_result(result); | ||
| 1721 | + | ||
| 1722 | + rc= mysql_stmt_execute(stmt_insert); | ||
| 1723 | + if (rc) | ||
| 1724 | + { | ||
| 1725 | + fprintf(stderr, "mysql_stmt_execute failed: %s\n", | ||
| 1726 | + mysql_stmt_error(stmt_insert)); | ||
| 1727 | + exit(1); | ||
| 1728 | + } | ||
| 1729 | + /* | ||
| 1730 | + pk id | ||
| 1731 | + 2 2 | ||
| 1732 | + 3 3 | ||
| 1733 | + 4 4 | ||
| 1734 | + 104 123 | ||
| 1735 | + 104 124 | ||
| 1736 | + 106 123 | ||
| 1737 | + 106 124 | ||
| 1738 | + */ | ||
| 1739 | + rc= mysql_query(mysql, "select * from t1"); | ||
| 1740 | + if (rc) | ||
| 1741 | + { | ||
| 1742 | + fprintf(stderr, "Query failed: %s\n", mysql_error(mysql)); | ||
| 1743 | + } | ||
| 1744 | + result= mysql_store_result(mysql); | ||
| 1745 | + row= mysql_fetch_row(result); | ||
| 1746 | + DIE_UNLESS(atoi(row[0]) == 2 && atoi(row[1]) == 2); | ||
| 1747 | + row= mysql_fetch_row(result); | ||
| 1748 | + DIE_UNLESS(atoi(row[0]) == 3 && atoi(row[1]) == 3); | ||
| 1749 | + row= mysql_fetch_row(result); | ||
| 1750 | + DIE_UNLESS(atoi(row[0]) == 4 && atoi(row[1]) == 4); | ||
| 1751 | + row= mysql_fetch_row(result); | ||
| 1752 | + DIE_UNLESS(atoi(row[0]) == 104 && atoi(row[1]) == 123); | ||
| 1753 | + row= mysql_fetch_row(result); | ||
| 1754 | + DIE_UNLESS(atoi(row[0]) == 104 && atoi(row[1]) == 124); | ||
| 1755 | + row= mysql_fetch_row(result); | ||
| 1756 | + printf("\n %d, %d \n", atoi(row[0]), atoi(row[1])); | ||
| 1757 | + DIE_UNLESS(atoi(row[0]) == 106 && atoi(row[1]) == 123); | ||
| 1758 | + row= mysql_fetch_row(result); | ||
| 1759 | + printf("\n %d, %d \n", atoi(row[0]), atoi(row[1])); | ||
| 1760 | + DIE_UNLESS(atoi(row[0]) == 106 && atoi(row[1]) == 124); | ||
| 1761 | + row= mysql_fetch_row(result); | ||
| 1762 | + DIE_UNLESS(row == NULL); | ||
| 1763 | + | ||
| 1764 | + mysql_free_result(result); | ||
| 1765 | + | ||
| 1766 | + mysql_stmt_close(stmt_insert); | ||
| 1767 | + | ||
| 1768 | + /* Clean up */ | ||
| 1769 | + rc= mysql_query(mysql, "DROP TABLE t1"); | ||
| 1770 | + myquery(rc); | ||
| 1771 | +} | ||
| 1772 | #endif // EMBEDDED_LIBRARY | ||
| 1773 | |||
| 1774 | |||
| 1775 | @@ -22102,6 +22260,7 @@ static struct my_tests_st my_tests[]= { | ||
| 1776 | { "test_explain_meta", test_explain_meta }, | ||
| 1777 | #ifndef EMBEDDED_LIBRARY | ||
| 1778 | { "test_mdev19838", test_mdev19838 }, | ||
| 1779 | + { "test_mdev_32086", test_mdev_32086 }, | ||
| 1780 | #endif | ||
| 1781 | { "test_mdev_16128", test_mdev_16128 }, | ||
| 1782 | { "test_mdev18408", test_mdev18408 }, | ||
| 1783 | -- | ||
| 1784 | 2.40.0 | ||
| 1785 | |||
