summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--meta-oe/recipes-dbs/mysql/mariadb.inc4
-rw-r--r--meta-oe/recipes-dbs/mysql/mariadb/CVE-2023-52969-CVE-20230-52970-0001.patch502
-rw-r--r--meta-oe/recipes-dbs/mysql/mariadb/CVE-2023-52969-CVE-20230-52970-0002.patch168
-rw-r--r--meta-oe/recipes-dbs/mysql/mariadb/CVE-2023-52969-CVE-20230-52970-0003.patch470
-rw-r--r--meta-oe/recipes-dbs/mysql/mariadb/CVE-2023-52969-CVE-20230-52970-0004.patch1785
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 "
28SRC_URI:append:libc-musl = " file://ppc-remove-glibc-dep.patch" 32SRC_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 @@
1From e6403733897483bed249875f0f3e5e9937ca2b38 Mon Sep 17 00:00:00 2001
2From: Oleg Smirnov <olernov@gmail.com>
3Date: Fri, 25 Oct 2024 14:35:22 +0700
4Subject: [PATCH] Revert "MDEV-26427 MariaDB Server SEGV on INSERT .. SELECT"
5
6This reverts commit 49e14000eeb245ea27e9207d2f63cb0a28be1ca9
7as it introduces regression MDEV-29935 and has to be reconsidered
8in general
9
10CVE: CVE-2023-52969 and CVE-2023-52970
11Upstream-Status: Backport [https://github.com/MariaDB/server/commit/e6403733897483bed249875f0f3e5e9937ca2b38]
12
13Signed-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
25diff --git a/mysql-test/main/insert_select.result b/mysql-test/main/insert_select.result
26index 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
106diff --git a/mysql-test/main/insert_select.test b/mysql-test/main/insert_select.test
107index 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 #
171diff --git a/mysql-test/main/view.result b/mysql-test/main/view.result
172index 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);
199diff --git a/mysql-test/main/view.test b/mysql-test/main/view.test
200index 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
212diff --git a/sql/sql_base.cc b/sql/sql_base.cc
213index 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
437diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc
438index 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;
459diff --git a/sql/sql_select.cc b/sql/sql_select.cc
460index 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)
488diff --git a/sql/sql_select.h b/sql/sql_select.h
489index 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--
5012.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 @@
1From d98ac8511e39770ef3d8b42937c84e876d1459e7 Mon Sep 17 00:00:00 2001
2From: Oleg Smirnov <olernov@gmail.com>
3Date: Sat, 26 Oct 2024 20:29:56 +0700
4Subject: [PATCH] MDEV-26247 MariaDB Server SEGV on INSERT .. SELECT
5
6This problem occured for statements like `INSERT INTO t1 SELECT 1`,
7which do not have tables in the SELECT part. In such scenarios
8SELECT_LEX::insert_tables was not properly set at `setup_tables()`,
9and this led to either incorrect execution or a crash
10
11Reviewer: Oleksandr Byelkin <sanja@mariadb.com>
12
13CVE: CVE-2023-52969 and CVE-2023-52970
14Upstream-Status: Backport [https://github.com/MariaDB/server/commit/d98ac8511e39770ef3d8b42937c84e876d1459e7]
15
16Signed-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
23diff --git a/mysql-test/main/insert_select.result b/mysql-test/main/insert_select.result
24index 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+#
80diff --git a/mysql-test/main/insert_select.test b/mysql-test/main/insert_select.test
81index 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 #
123diff --git a/sql/sql_base.cc b/sql/sql_base.cc
124index 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--
1672.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 @@
1From 9b313d2de1df65626abb3b1d6c973f74addb12fb Mon Sep 17 00:00:00 2001
2From: Oleksandr Byelkin <sanja@mariadb.com>
3Date: Tue, 1 Apr 2025 20:57:29 +0200
4Subject: [PATCH] MDEV-32086 Server crash when inserting from derived table
5 containing insert target table
6
7Use original solution for INSERT ... SELECT - select result buferisation.
8
9Also fix MDEV-36447 and MDEV-33139
10
11CVE: CVE-2023-52969 and CVE-2023-52970
12Upstream-Status: Backport [https://github.com/MariaDB/server/commit/9b313d2de1df65626abb3b1d6c973f74addb12fb]
13
14Signed-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
25diff --git a/mysql-test/main/derived_cond_pushdown.result b/mysql-test/main/derived_cond_pushdown.result
26index 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 }
181diff --git a/mysql-test/main/derived_view.result b/mysql-test/main/derived_view.result
182index 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 #
194diff --git a/mysql-test/main/insert_select.result b/mysql-test/main/insert_select.result
195index 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
333diff --git a/mysql-test/main/insert_select.test b/mysql-test/main/insert_select.test
334index 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
399diff --git a/sql/sql_base.cc b/sql/sql_base.cc
400index 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 */
427diff --git a/sql/sql_base.h b/sql/sql_base.h
428index 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,
439diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc
440index 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--
4692.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 @@
1From 4fc9dc84b017cf9f30585bcdef0663f9425fe460 Mon Sep 17 00:00:00 2001
2From: Oleksandr Byelkin <sanja@mariadb.com>
3Date: Fri, 18 Apr 2025 12:14:23 +0200
4Subject: [PATCH] MDEV-32086 (part 2) Server crash when inserting from derived
5 table containing insert target table
6
7Get rid of need of matherialization for usual INSERT (cache results in
8Item_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
14Changes:
15- subselect_elimination.result and subselect_elimination.test files
16are not presented so skip those changes.
17
18CVE: CVE-2023-52969 and CVE-2023-52970
19Upstream-Status: Backport [https://github.com/MariaDB/server/commit/4fc9dc84b017cf9f30585bcdef0663f9425fe460]
20
21Signed-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
56diff --git a/mysql-test/main/insert.result b/mysql-test/main/insert.result
57index 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
137diff --git a/mysql-test/main/insert.test b/mysql-test/main/insert.test
138index 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
202diff --git a/mysql-test/main/insert_returning.result b/mysql-test/main/insert_returning.result
203index 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 #
215diff --git a/mysql-test/main/insert_returning.test b/mysql-test/main/insert_returning.test
216index 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
228diff --git a/mysql-test/main/lowercase_view.result b/mysql-test/main/lowercase_view.result
229index 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);
262diff --git a/mysql-test/main/lowercase_view.test b/mysql-test/main/lowercase_view.test
263index 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;
296diff --git a/mysql-test/main/merge.result b/mysql-test/main/merge.result
297index 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;
337diff --git a/mysql-test/main/merge.test b/mysql-test/main/merge.test
338index 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;
381diff --git a/mysql-test/main/subselect.result b/mysql-test/main/subselect.result
382index 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);
460diff --git a/mysql-test/main/subselect.test b/mysql-test/main/subselect.test
461index 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);
497diff --git a/mysql-test/main/subselect_no_exists_to_in.result b/mysql-test/main/subselect_no_exists_to_in.result
498index 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
572diff --git a/mysql-test/main/subselect_no_mat.result b/mysql-test/main/subselect_no_mat.result
573index 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);
651diff --git a/mysql-test/main/subselect_no_opts.result b/mysql-test/main/subselect_no_opts.result
652index 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);
730diff --git a/mysql-test/main/subselect_no_scache.result b/mysql-test/main/subselect_no_scache.result
731index 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);
809diff --git a/mysql-test/main/subselect_no_semijoin.result b/mysql-test/main/subselect_no_semijoin.result
810index 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);
888diff --git a/mysql-test/main/view.result b/mysql-test/main/view.result
889index 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;
974diff --git a/mysql-test/main/view.test b/mysql-test/main/view.test
975index 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 #
1036diff --git a/mysql-test/suite/sql_sequence/other.result b/mysql-test/suite/sql_sequence/other.result
1037index 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);
1048diff --git a/mysql-test/suite/sql_sequence/other.test b/mysql-test/suite/sql_sequence/other.test
1049index 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);
1060diff --git a/sql/item.h b/sql/item.h
1061index 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
1090diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc
1091index 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, &param->find->db,
1114+ &param->find->table_name)))
1115+ {
1116+ param->dup= dup;
1117+ return TRUE;
1118+ }
1119+ }
1120+ return FALSE;
1121+};
1122diff --git a/sql/item_subselect.h b/sql/item_subselect.h
1123index 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);
1134diff --git a/sql/sql_base.cc b/sql/sql_base.cc
1135index 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, &param))
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
1271diff --git a/sql/sql_base.h b/sql/sql_base.h
1272index 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);
1292diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc
1293index 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;
1493diff --git a/sql/sql_insert.h b/sql/sql_insert.h
1494index 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,
1506diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc
1507index 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+}
1556diff --git a/sql/sql_lex.h b/sql/sql_lex.h
1557index 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
1571diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc
1572index 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;
1593diff --git a/sql/table.h b/sql/table.h
1594index 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 /*
1606diff --git a/tests/mysql_client_test.c b/tests/mysql_client_test.c
1607index 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--
17842.40.0
1785