mirror of
https://github.com/openembedded/meta-openembedded.git
synced 2026-04-20 11:38:34 +00:00
mariadb: fix CVE-2023-52969 and CVE-2023-52970
CVE-2023-52969: MariaDB Server 10.4 through 10.5., 10.6 through 10.6., 10.7 through 10.11., and 11.0 through 11.0. can sometimes crash with an empty backtrace log. This may be related to make_aggr_tables_info and optimize_stage2. CVE-2023-52970: MariaDB Server 10.4 through 10.5., 10.6 through 10.6., 10.7 through 10.11., 11.0 through 11.0., and 11.1 through 11.4.* crashes in Item_direct_view_ref::derived_field_transformer_for_where. CVE-2023-52969-CVE-20230-52970-0001 and CVE-2023-52969-CVE-20230-52970-0002 are dependent commits while CVE-2023-52969-CVE-20230-52970-0003 and CVE-2023-52969-CVE-20230-52970-0004 are actual CVE fixes. References: https://nvd.nist.gov/vuln/detail/CVE-2023-52969 https://nvd.nist.gov/vuln/detail/CVE-2023-52970 Upstream patches:e640373389https://github.com/MariaDB/server/commit/d98ac8511e39770ef3d8b42937c84e876d1459e9b313d2de14fc9dc84b0Signed-off-by: Yogita Urade <yogita.urade@windriver.com> Signed-off-by: Armin Kuster <akuster808@gmail.com>
This commit is contained in:
committed by
Armin Kuster
parent
c2140f3f2a
commit
5bc652be7a
@@ -24,6 +24,10 @@ SRC_URI = "https://archive.mariadb.org/${BP}/source/${BP}.tar.gz \
|
||||
file://0001-MDEV-29644-a-potential-bug-of-null-pointer-dereferen.patch \
|
||||
file://CVE-2023-22084.patch \
|
||||
file://CVE-2023-52968.patch \
|
||||
file://CVE-2023-52969-CVE-20230-52970-0001.patch \
|
||||
file://CVE-2023-52969-CVE-20230-52970-0002.patch \
|
||||
file://CVE-2023-52969-CVE-20230-52970-0003.patch \
|
||||
file://CVE-2023-52969-CVE-20230-52970-0004.patch \
|
||||
"
|
||||
SRC_URI:append:libc-musl = " file://ppc-remove-glibc-dep.patch"
|
||||
|
||||
|
||||
@@ -0,0 +1,502 @@
|
||||
From e6403733897483bed249875f0f3e5e9937ca2b38 Mon Sep 17 00:00:00 2001
|
||||
From: Oleg Smirnov <olernov@gmail.com>
|
||||
Date: Fri, 25 Oct 2024 14:35:22 +0700
|
||||
Subject: [PATCH] Revert "MDEV-26427 MariaDB Server SEGV on INSERT .. SELECT"
|
||||
|
||||
This reverts commit 49e14000eeb245ea27e9207d2f63cb0a28be1ca9
|
||||
as it introduces regression MDEV-29935 and has to be reconsidered
|
||||
in general
|
||||
|
||||
CVE: CVE-2023-52969 and CVE-2023-52970
|
||||
Upstream-Status: Backport [https://github.com/MariaDB/server/commit/e6403733897483bed249875f0f3e5e9937ca2b38]
|
||||
|
||||
Signed-off-by: Yogita Urade <yogita.urade@windriver.com>
|
||||
---
|
||||
mysql-test/main/insert_select.result | 70 -----------
|
||||
mysql-test/main/insert_select.test | 54 --------
|
||||
mysql-test/main/view.result | 10 --
|
||||
mysql-test/main/view.test | 2 -
|
||||
sql/sql_base.cc | 178 ++++++++-------------------
|
||||
sql/sql_insert.cc | 4 +-
|
||||
sql/sql_select.cc | 4 +
|
||||
sql/sql_select.h | 1 +
|
||||
8 files changed, 59 insertions(+), 264 deletions(-)
|
||||
|
||||
diff --git a/mysql-test/main/insert_select.result b/mysql-test/main/insert_select.result
|
||||
index 29618c6d..10c87271 100644
|
||||
--- a/mysql-test/main/insert_select.result
|
||||
+++ b/mysql-test/main/insert_select.result
|
||||
@@ -883,76 +883,6 @@ INSERT INTO t1 SELECT a*2 FROM t1 ORDER BY a;
|
||||
Warnings:
|
||||
Warning 1264 Out of range value for column 'a' at row 4
|
||||
DROP TABLE t1;
|
||||
-CREATE TABLE t1 (a INT, b INT);
|
||||
-INSERT INTO t1 (a) SELECT SUM(1);
|
||||
-INSERT INTO t1 (a, b) SELECT AVG(2), MIN(3);
|
||||
-INSERT INTO t1 (b) SELECT AVG('x') OVER ();
|
||||
-ERROR 22007: Truncated incorrect DOUBLE value: 'x'
|
||||
-INSERT INTO t1 SELECT MIN(7) OVER (), MAX(8) OVER();
|
||||
-SELECT * FROM t1;
|
||||
-a b
|
||||
-1 NULL
|
||||
-2 3
|
||||
-7 8
|
||||
-PREPARE stmt FROM 'INSERT INTO t1 (a) SELECT AVG(?)';
|
||||
-EXECUTE stmt USING 9;
|
||||
-EXECUTE stmt USING 10;
|
||||
-PREPARE stmt FROM 'INSERT INTO t1 SELECT MIN(?), MAX(?)';
|
||||
-EXECUTE stmt USING 11, 12;
|
||||
-EXECUTE stmt USING 13, 14;
|
||||
-DEALLOCATE PREPARE stmt;
|
||||
-SELECT * FROM t1;
|
||||
-a b
|
||||
-1 NULL
|
||||
-2 3
|
||||
-7 8
|
||||
-9 NULL
|
||||
-10 NULL
|
||||
-11 12
|
||||
-13 14
|
||||
-CREATE PROCEDURE p1(param_a INT, param_b INT)
|
||||
-BEGIN
|
||||
-INSERT INTO t1 SELECT MIN(param_a) OVER (), MAX(param_b);
|
||||
-END//
|
||||
-CALL p1(21, 22);
|
||||
-CALL p1(23, 24);
|
||||
-SELECT * FROM t1;
|
||||
-a b
|
||||
-1 NULL
|
||||
-2 3
|
||||
-7 8
|
||||
-9 NULL
|
||||
-10 NULL
|
||||
-11 12
|
||||
-13 14
|
||||
-21 22
|
||||
-23 24
|
||||
-CREATE TABLE t2 (
|
||||
-a DECIMAL UNIQUE CHECK (CASE 0 * 27302337.000000 WHEN 34 THEN
|
||||
-+ 'x' LIKE 'x' OR a NOT IN (-1 / TRUE ^ 2) ELSE 7105743.000000 END));
|
||||
-INSERT INTO t2 VALUES (90),( -1),(31152443.000000),(-32768),(NULL),(NULL);
|
||||
-INSERT INTO t2 SELECT AVG('x') OVER (
|
||||
-PARTITION BY ((NOT AVG(76698761.000000))) IS NOT NULL);
|
||||
-ERROR 22007: Truncated incorrect DOUBLE value: 'x'
|
||||
-INSERT IGNORE INTO t2 () VALUES (0),('x'),(3751286.000000),
|
||||
-('x'),((a = 'x' AND 0 AND 0));
|
||||
-Warnings:
|
||||
-Warning 1366 Incorrect decimal value: 'x' for column `test`.`t2`.`a` at row 2
|
||||
-Warning 1062 Duplicate entry '0' for key 'a'
|
||||
-Warning 1366 Incorrect decimal value: 'x' for column `test`.`t2`.`a` at row 4
|
||||
-Warning 1062 Duplicate entry '0' for key 'a'
|
||||
-Warning 1062 Duplicate entry '0' for key 'a'
|
||||
-INSERT INTO t2 VALUES (127);
|
||||
-INSERT INTO t2 SELECT -2147483648 END FROM t2 AS TEXT JOIN t2 JOIN t2 TABLES;
|
||||
-ERROR 23000: Duplicate entry '-2147483648' for key 'a'
|
||||
-ALTER TABLE t2 ADD (
|
||||
-b INT UNIQUE CHECK ((a = 'x' AND ((-(+(BINARY 49730460.000000)))) = 'x'
|
||||
-BETWEEN 'x' AND 'x')));
|
||||
-ERROR 22007: Truncated incorrect DECIMAL value: 'x'
|
||||
-UPDATE t2 SET a = -128 WHERE a IS NULL ORDER BY 78 IN ('x','x'),a;
|
||||
-ERROR 23000: Duplicate entry '-128' for key 'a'
|
||||
-DROP TABLE t1, t2;
|
||||
-DROP PROCEDURE p1;
|
||||
# End of 10.2 test
|
||||
#
|
||||
# MDEV-28617: INSERT ... SELECT with redundant IN subquery in GROUP BY
|
||||
diff --git a/mysql-test/main/insert_select.test b/mysql-test/main/insert_select.test
|
||||
index a3604e38..7417bab9 100644
|
||||
--- a/mysql-test/main/insert_select.test
|
||||
+++ b/mysql-test/main/insert_select.test
|
||||
@@ -459,60 +459,6 @@ INSERT INTO t1 SELECT a*2 FROM t1 ORDER BY a;
|
||||
|
||||
DROP TABLE t1;
|
||||
|
||||
-#
|
||||
-# MDEV-26427 MariaDB Server SEGV on INSERT .. SELECT
|
||||
-#
|
||||
-CREATE TABLE t1 (a INT, b INT);
|
||||
-INSERT INTO t1 (a) SELECT SUM(1);
|
||||
-INSERT INTO t1 (a, b) SELECT AVG(2), MIN(3);
|
||||
-
|
||||
---error ER_TRUNCATED_WRONG_VALUE
|
||||
-INSERT INTO t1 (b) SELECT AVG('x') OVER ();
|
||||
-INSERT INTO t1 SELECT MIN(7) OVER (), MAX(8) OVER();
|
||||
-SELECT * FROM t1;
|
||||
-
|
||||
-PREPARE stmt FROM 'INSERT INTO t1 (a) SELECT AVG(?)';
|
||||
-EXECUTE stmt USING 9;
|
||||
-EXECUTE stmt USING 10;
|
||||
-
|
||||
-PREPARE stmt FROM 'INSERT INTO t1 SELECT MIN(?), MAX(?)';
|
||||
-EXECUTE stmt USING 11, 12;
|
||||
-EXECUTE stmt USING 13, 14;
|
||||
-DEALLOCATE PREPARE stmt;
|
||||
-SELECT * FROM t1;
|
||||
-
|
||||
-DELIMITER //;
|
||||
-CREATE PROCEDURE p1(param_a INT, param_b INT)
|
||||
-BEGIN
|
||||
-INSERT INTO t1 SELECT MIN(param_a) OVER (), MAX(param_b);
|
||||
-END//
|
||||
-DELIMITER ;//
|
||||
-CALL p1(21, 22);
|
||||
-CALL p1(23, 24);
|
||||
-SELECT * FROM t1;
|
||||
-
|
||||
-CREATE TABLE t2 (
|
||||
- a DECIMAL UNIQUE CHECK (CASE 0 * 27302337.000000 WHEN 34 THEN
|
||||
- + 'x' LIKE 'x' OR a NOT IN (-1 / TRUE ^ 2) ELSE 7105743.000000 END));
|
||||
-INSERT INTO t2 VALUES (90),( -1),(31152443.000000),(-32768),(NULL),(NULL);
|
||||
---error ER_TRUNCATED_WRONG_VALUE
|
||||
-INSERT INTO t2 SELECT AVG('x') OVER (
|
||||
- PARTITION BY ((NOT AVG(76698761.000000))) IS NOT NULL);
|
||||
-INSERT IGNORE INTO t2 () VALUES (0),('x'),(3751286.000000),
|
||||
- ('x'),((a = 'x' AND 0 AND 0));
|
||||
-INSERT INTO t2 VALUES (127);
|
||||
---error ER_DUP_ENTRY
|
||||
-INSERT INTO t2 SELECT -2147483648 END FROM t2 AS TEXT JOIN t2 JOIN t2 TABLES;
|
||||
---error ER_TRUNCATED_WRONG_VALUE
|
||||
-ALTER TABLE t2 ADD (
|
||||
- b INT UNIQUE CHECK ((a = 'x' AND ((-(+(BINARY 49730460.000000)))) = 'x'
|
||||
- BETWEEN 'x' AND 'x')));
|
||||
---error ER_DUP_ENTRY
|
||||
-UPDATE t2 SET a = -128 WHERE a IS NULL ORDER BY 78 IN ('x','x'),a;
|
||||
-
|
||||
-DROP TABLE t1, t2;
|
||||
-DROP PROCEDURE p1;
|
||||
-
|
||||
--echo # End of 10.2 test
|
||||
|
||||
--echo #
|
||||
diff --git a/mysql-test/main/view.result b/mysql-test/main/view.result
|
||||
index aec4a5d0..69e850cd 100644
|
||||
--- a/mysql-test/main/view.result
|
||||
+++ b/mysql-test/main/view.result
|
||||
@@ -1503,8 +1503,6 @@ execute stmt1 using @a;
|
||||
set @a= 301;
|
||||
execute stmt1 using @a;
|
||||
deallocate prepare stmt1;
|
||||
-insert into v3(a) select sum(302);
|
||||
-insert into v3(a) select sum(303) over ();
|
||||
select * from v3;
|
||||
a b
|
||||
100 0
|
||||
@@ -1523,14 +1521,6 @@ a b
|
||||
301 10
|
||||
301 1000
|
||||
301 2000
|
||||
-302 0
|
||||
-302 10
|
||||
-302 1000
|
||||
-302 2000
|
||||
-303 0
|
||||
-303 10
|
||||
-303 1000
|
||||
-303 2000
|
||||
drop view v3;
|
||||
drop tables t1,t2;
|
||||
create table t1(f1 int);
|
||||
diff --git a/mysql-test/main/view.test b/mysql-test/main/view.test
|
||||
index c6cc9a69..f32b148b 100644
|
||||
--- a/mysql-test/main/view.test
|
||||
+++ b/mysql-test/main/view.test
|
||||
@@ -1334,8 +1334,6 @@ execute stmt1 using @a;
|
||||
set @a= 301;
|
||||
execute stmt1 using @a;
|
||||
deallocate prepare stmt1;
|
||||
-insert into v3(a) select sum(302);
|
||||
-insert into v3(a) select sum(303) over ();
|
||||
--sorted_result
|
||||
select * from v3;
|
||||
|
||||
diff --git a/sql/sql_base.cc b/sql/sql_base.cc
|
||||
index 4142540f..59c13009 100644
|
||||
--- a/sql/sql_base.cc
|
||||
+++ b/sql/sql_base.cc
|
||||
@@ -7750,39 +7750,6 @@ bool setup_fields(THD *thd, Ref_ptr_array ref_pointer_array,
|
||||
DBUG_RETURN(MY_TEST(thd->is_error()));
|
||||
}
|
||||
|
||||
-/*
|
||||
- make list of leaves for a single TABLE_LIST
|
||||
-
|
||||
- SYNOPSIS
|
||||
- make_leaves_for_single_table()
|
||||
- thd Thread handler
|
||||
- leaves List of leaf tables to be filled
|
||||
- table TABLE_LIST object to process
|
||||
- full_table_list Whether to include tables from mergeable derived table/view
|
||||
-*/
|
||||
-void make_leaves_for_single_table(THD *thd, List<TABLE_LIST> &leaves,
|
||||
- TABLE_LIST *table, bool& full_table_list,
|
||||
- TABLE_LIST *boundary)
|
||||
-{
|
||||
- if (table == boundary)
|
||||
- full_table_list= !full_table_list;
|
||||
- if (full_table_list && table->is_merged_derived())
|
||||
- {
|
||||
- SELECT_LEX *select_lex= table->get_single_select();
|
||||
- /*
|
||||
- It's safe to use select_lex->leaf_tables because all derived
|
||||
- tables/views were already prepared and has their leaf_tables
|
||||
- set properly.
|
||||
- */
|
||||
- make_leaves_list(thd, leaves, select_lex->get_table_list(),
|
||||
- full_table_list, boundary);
|
||||
- }
|
||||
- else
|
||||
- {
|
||||
- leaves.push_back(table, thd->mem_root);
|
||||
- }
|
||||
-}
|
||||
-
|
||||
|
||||
/*
|
||||
Perform checks like all given fields exists, if exists fill struct with
|
||||
@@ -7809,79 +7776,40 @@ int setup_returning_fields(THD* thd, TABLE_LIST* table_list)
|
||||
|
||||
SYNOPSIS
|
||||
make_leaves_list()
|
||||
- leaves List of leaf tables to be filled
|
||||
- tables Table list
|
||||
- full_table_list Whether to include tables from mergeable derived table/view.
|
||||
- We need them for checks for INSERT/UPDATE statements only.
|
||||
+ list pointer to pointer on list first element
|
||||
+ tables table list
|
||||
+ full_table_list whether to include tables from mergeable derived table/view.
|
||||
+ we need them for checks for INSERT/UPDATE statements only.
|
||||
+
|
||||
+ RETURN pointer on pointer to next_leaf of last element
|
||||
*/
|
||||
|
||||
-void make_leaves_list(THD *thd, List<TABLE_LIST> &leaves, TABLE_LIST *tables,
|
||||
+void make_leaves_list(THD *thd, List<TABLE_LIST> &list, TABLE_LIST *tables,
|
||||
bool full_table_list, TABLE_LIST *boundary)
|
||||
|
||||
{
|
||||
for (TABLE_LIST *table= tables; table; table= table->next_local)
|
||||
{
|
||||
- make_leaves_for_single_table(thd, leaves, table, full_table_list,
|
||||
- boundary);
|
||||
- }
|
||||
-}
|
||||
-
|
||||
-
|
||||
-/*
|
||||
- Setup the map and other attributes for a single TABLE_LIST object
|
||||
-
|
||||
- SYNOPSIS
|
||||
- setup_table_attributes()
|
||||
- thd Thread handler
|
||||
- table_list TABLE_LIST object to process
|
||||
- first_select_table First table participating in SELECT for INSERT..SELECT
|
||||
- statements, NULL for other cases
|
||||
- tablenr Serial number of the table in the SQL statement
|
||||
-
|
||||
- RETURN
|
||||
- false Success
|
||||
- true Failure
|
||||
-*/
|
||||
-bool setup_table_attributes(THD *thd, TABLE_LIST *table_list,
|
||||
- TABLE_LIST *first_select_table,
|
||||
- uint &tablenr)
|
||||
-{
|
||||
- TABLE *table= table_list->table;
|
||||
- if (table)
|
||||
- table->pos_in_table_list= table_list;
|
||||
- if (first_select_table && table_list->top_table() == first_select_table)
|
||||
- {
|
||||
- /* new counting for SELECT of INSERT ... SELECT command */
|
||||
- first_select_table= 0;
|
||||
- thd->lex->first_select_lex()->insert_tables= tablenr;
|
||||
- tablenr= 0;
|
||||
- }
|
||||
- if (table_list->jtbm_subselect)
|
||||
- {
|
||||
- table_list->jtbm_table_no= tablenr;
|
||||
- }
|
||||
- else if (table)
|
||||
- {
|
||||
- table->pos_in_table_list= table_list;
|
||||
- setup_table_map(table, table_list, tablenr);
|
||||
-
|
||||
- if (table_list->process_index_hints(table))
|
||||
- return true;
|
||||
- }
|
||||
- tablenr++;
|
||||
- /*
|
||||
- We test the max tables here as we setup_table_map() should not be called
|
||||
- with tablenr >= 64
|
||||
- */
|
||||
- if (tablenr > MAX_TABLES)
|
||||
- {
|
||||
- my_error(ER_TOO_MANY_TABLES, MYF(0), static_cast<int>(MAX_TABLES));
|
||||
- return true;
|
||||
+ if (table == boundary)
|
||||
+ full_table_list= !full_table_list;
|
||||
+ if (full_table_list && table->is_merged_derived())
|
||||
+ {
|
||||
+ SELECT_LEX *select_lex= table->get_single_select();
|
||||
+ /*
|
||||
+ It's safe to use select_lex->leaf_tables because all derived
|
||||
+ tables/views were already prepared and has their leaf_tables
|
||||
+ set properly.
|
||||
+ */
|
||||
+ make_leaves_list(thd, list, select_lex->get_table_list(),
|
||||
+ full_table_list, boundary);
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ list.push_back(table, thd->mem_root);
|
||||
+ }
|
||||
}
|
||||
- return false;
|
||||
}
|
||||
|
||||
-
|
||||
/*
|
||||
prepare tables
|
||||
|
||||
@@ -7938,14 +7866,7 @@ bool setup_tables(THD *thd, Name_resolution_context *context,
|
||||
leaves.empty();
|
||||
if (select_lex->prep_leaf_list_state != SELECT_LEX::SAVED)
|
||||
{
|
||||
- /*
|
||||
- For INSERT ... SELECT statements we must not include the first table
|
||||
- (where the data is being inserted into) in the list of leaves
|
||||
- */
|
||||
- TABLE_LIST *tables_for_leaves=
|
||||
- select_insert ? first_select_table : tables;
|
||||
- make_leaves_list(thd, leaves, tables_for_leaves, full_table_list,
|
||||
- first_select_table);
|
||||
+ make_leaves_list(thd, leaves, tables, full_table_list, first_select_table);
|
||||
select_lex->prep_leaf_list_state= SELECT_LEX::READY;
|
||||
select_lex->leaf_tables_exec.empty();
|
||||
}
|
||||
@@ -7956,34 +7877,37 @@ bool setup_tables(THD *thd, Name_resolution_context *context,
|
||||
leaves.push_back(table_list, thd->mem_root);
|
||||
}
|
||||
|
||||
- List_iterator<TABLE_LIST> ti(leaves);
|
||||
while ((table_list= ti++))
|
||||
{
|
||||
- if (setup_table_attributes(thd, table_list, first_select_table, tablenr))
|
||||
- DBUG_RETURN(1);
|
||||
- }
|
||||
-
|
||||
- if (select_insert)
|
||||
- {
|
||||
- /*
|
||||
- The table/view in which the data is inserted must not be included into
|
||||
- the leaf_tables list. But we need this table/view to setup attributes
|
||||
- for it. So build a temporary list of leaves and setup attributes for
|
||||
- the tables included
|
||||
- */
|
||||
- List<TABLE_LIST> leaves;
|
||||
- TABLE_LIST *table= tables;
|
||||
-
|
||||
- make_leaves_for_single_table(thd, leaves, table, full_table_list,
|
||||
- first_select_table);
|
||||
-
|
||||
- List_iterator<TABLE_LIST> ti(leaves);
|
||||
- while ((table_list= ti++))
|
||||
+ TABLE *table= table_list->table;
|
||||
+ if (table)
|
||||
+ table->pos_in_table_list= table_list;
|
||||
+ if (first_select_table &&
|
||||
+ table_list->top_table() == first_select_table)
|
||||
{
|
||||
- if (setup_table_attributes(thd, table_list, first_select_table,
|
||||
- tablenr))
|
||||
+ /* new counting for SELECT of INSERT ... SELECT command */
|
||||
+ first_select_table= 0;
|
||||
+ thd->lex->first_select_lex()->insert_tables= tablenr;
|
||||
+ tablenr= 0;
|
||||
+ }
|
||||
+ if(table_list->jtbm_subselect)
|
||||
+ {
|
||||
+ table_list->jtbm_table_no= tablenr;
|
||||
+ }
|
||||
+ else if (table)
|
||||
+ {
|
||||
+ table->pos_in_table_list= table_list;
|
||||
+ setup_table_map(table, table_list, tablenr);
|
||||
+
|
||||
+ if (table_list->process_index_hints(table))
|
||||
DBUG_RETURN(1);
|
||||
}
|
||||
+ tablenr++;
|
||||
+ }
|
||||
+ if (tablenr > MAX_TABLES)
|
||||
+ {
|
||||
+ my_error(ER_TOO_MANY_TABLES,MYF(0), static_cast<int>(MAX_TABLES));
|
||||
+ DBUG_RETURN(1);
|
||||
}
|
||||
}
|
||||
else
|
||||
diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc
|
||||
index af2c4606..460c552f 100644
|
||||
--- a/sql/sql_insert.cc
|
||||
+++ b/sql/sql_insert.cc
|
||||
@@ -1570,7 +1570,8 @@ static bool mysql_prepare_insert_check_table(THD *thd, TABLE_LIST *table_list,
|
||||
if (insert_into_view && !fields.elements)
|
||||
{
|
||||
thd->lex->empty_field_list_on_rset= 1;
|
||||
- if (!table_list->table || table_list->is_multitable())
|
||||
+ if (!thd->lex->first_select_lex()->leaf_tables.head()->table ||
|
||||
+ table_list->is_multitable())
|
||||
{
|
||||
my_error(ER_VIEW_NO_INSERT_FIELD_LIST, MYF(0),
|
||||
table_list->view_db.str, table_list->view_name.str);
|
||||
@@ -3828,6 +3829,7 @@ int mysql_insert_select_prepare(THD *thd, select_result *sel_res)
|
||||
if (sel_res)
|
||||
sel_res->prepare(lex->returning()->item_list, NULL);
|
||||
|
||||
+ DBUG_ASSERT(select_lex->leaf_tables.elements != 0);
|
||||
List_iterator<TABLE_LIST> ti(select_lex->leaf_tables);
|
||||
TABLE_LIST *table;
|
||||
uint insert_tables;
|
||||
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
|
||||
index 21cc4806..8a7060c3 100644
|
||||
--- a/sql/sql_select.cc
|
||||
+++ b/sql/sql_select.cc
|
||||
@@ -2037,6 +2037,7 @@ JOIN::optimize_inner()
|
||||
/* Merge all mergeable derived tables/views in this SELECT. */
|
||||
if (select_lex->handle_derived(thd->lex, DT_MERGE))
|
||||
DBUG_RETURN(TRUE);
|
||||
+ table_count= select_lex->leaf_tables.elements;
|
||||
}
|
||||
|
||||
if (select_lex->first_cond_optimization &&
|
||||
@@ -2084,6 +2085,8 @@ JOIN::optimize_inner()
|
||||
|
||||
eval_select_list_used_tables();
|
||||
|
||||
+ table_count= select_lex->leaf_tables.elements;
|
||||
+
|
||||
if (select_lex->options & OPTION_SCHEMA_TABLE &&
|
||||
optimize_schema_tables_memory_usage(select_lex->leaf_tables))
|
||||
DBUG_RETURN(1);
|
||||
@@ -14549,6 +14552,7 @@ void JOIN::cleanup(bool full)
|
||||
/* Free the original optimized join created for the group_by_handler */
|
||||
join_tab= original_join_tab;
|
||||
original_join_tab= 0;
|
||||
+ table_count= original_table_count;
|
||||
}
|
||||
|
||||
if (join_tab)
|
||||
diff --git a/sql/sql_select.h b/sql/sql_select.h
|
||||
index 6efdcafd..e1e06e73 100644
|
||||
--- a/sql/sql_select.h
|
||||
+++ b/sql/sql_select.h
|
||||
@@ -1291,6 +1291,7 @@ class JOIN :public Sql_alloc
|
||||
|
||||
Pushdown_query *pushdown_query;
|
||||
JOIN_TAB *original_join_tab;
|
||||
+ uint original_table_count;
|
||||
|
||||
/******* Join optimization state members start *******/
|
||||
/*
|
||||
--
|
||||
2.40.0
|
||||
|
||||
@@ -0,0 +1,168 @@
|
||||
From d98ac8511e39770ef3d8b42937c84e876d1459e7 Mon Sep 17 00:00:00 2001
|
||||
From: Oleg Smirnov <olernov@gmail.com>
|
||||
Date: Sat, 26 Oct 2024 20:29:56 +0700
|
||||
Subject: [PATCH] MDEV-26247 MariaDB Server SEGV on INSERT .. SELECT
|
||||
|
||||
This problem occured for statements like `INSERT INTO t1 SELECT 1`,
|
||||
which do not have tables in the SELECT part. In such scenarios
|
||||
SELECT_LEX::insert_tables was not properly set at `setup_tables()`,
|
||||
and this led to either incorrect execution or a crash
|
||||
|
||||
Reviewer: Oleksandr Byelkin <sanja@mariadb.com>
|
||||
|
||||
CVE: CVE-2023-52969 and CVE-2023-52970
|
||||
Upstream-Status: Backport [https://github.com/MariaDB/server/commit/d98ac8511e39770ef3d8b42937c84e876d1459e7]
|
||||
|
||||
Signed-off-by: Yogita Urade <yogita.urade@windriver.com>
|
||||
---
|
||||
mysql-test/main/insert_select.result | 49 ++++++++++++++++++++++++++++
|
||||
mysql-test/main/insert_select.test | 35 ++++++++++++++++++++
|
||||
sql/sql_base.cc | 16 +++++++--
|
||||
3 files changed, 97 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/mysql-test/main/insert_select.result b/mysql-test/main/insert_select.result
|
||||
index 10c87271..79f8c519 100644
|
||||
--- a/mysql-test/main/insert_select.result
|
||||
+++ b/mysql-test/main/insert_select.result
|
||||
@@ -986,3 +986,52 @@ drop table t1, t2;
|
||||
#
|
||||
# End of 10.3 test
|
||||
#
|
||||
+#
|
||||
+# MDEV-26427 MariaDB Server SEGV on INSERT .. SELECT
|
||||
+#
|
||||
+CREATE TABLE t1 (a int);
|
||||
+INSERT INTO t1 SELECT AVG(1);
|
||||
+SELECT * FROM t1;
|
||||
+a
|
||||
+1
|
||||
+INSERT INTO t1 SELECT MIN(2) OVER ();
|
||||
+SELECT * FROM t1;
|
||||
+a
|
||||
+1
|
||||
+2
|
||||
+CREATE VIEW v1 AS SELECT * FROM t1 ORDER BY a;
|
||||
+INSERT INTO v1 SELECT SUM(3);
|
||||
+SELECT * FROM v1;
|
||||
+a
|
||||
+1
|
||||
+2
|
||||
+3
|
||||
+INSERT INTO v1 SELECT * FROM v1;
|
||||
+SELECT * FROM t1;
|
||||
+a
|
||||
+1
|
||||
+1
|
||||
+2
|
||||
+2
|
||||
+3
|
||||
+3
|
||||
+INSERT INTO t1 SELECT * FROM v1;
|
||||
+SELECT * FROM t1;
|
||||
+a
|
||||
+1
|
||||
+1
|
||||
+1
|
||||
+1
|
||||
+2
|
||||
+2
|
||||
+2
|
||||
+2
|
||||
+3
|
||||
+3
|
||||
+3
|
||||
+3
|
||||
+DROP VIEW v1;
|
||||
+DROP TABLE t1;
|
||||
+#
|
||||
+# End of 10.5 test
|
||||
+#
|
||||
diff --git a/mysql-test/main/insert_select.test b/mysql-test/main/insert_select.test
|
||||
index 7417bab9..0e9bd05a 100644
|
||||
--- a/mysql-test/main/insert_select.test
|
||||
+++ b/mysql-test/main/insert_select.test
|
||||
@@ -559,3 +559,38 @@ drop table t1, t2;
|
||||
--echo #
|
||||
--echo # End of 10.3 test
|
||||
--echo #
|
||||
+
|
||||
+--echo #
|
||||
+--echo # MDEV-26427 MariaDB Server SEGV on INSERT .. SELECT
|
||||
+--echo #
|
||||
+
|
||||
+CREATE TABLE t1 (a int);
|
||||
+
|
||||
+INSERT INTO t1 SELECT AVG(1);
|
||||
+--sorted_result
|
||||
+SELECT * FROM t1;
|
||||
+
|
||||
+INSERT INTO t1 SELECT MIN(2) OVER ();
|
||||
+--sorted_result
|
||||
+SELECT * FROM t1;
|
||||
+
|
||||
+CREATE VIEW v1 AS SELECT * FROM t1 ORDER BY a;
|
||||
+
|
||||
+INSERT INTO v1 SELECT SUM(3);
|
||||
+--sorted_result
|
||||
+SELECT * FROM v1;
|
||||
+
|
||||
+INSERT INTO v1 SELECT * FROM v1;
|
||||
+--sorted_result
|
||||
+SELECT * FROM t1;
|
||||
+
|
||||
+INSERT INTO t1 SELECT * FROM v1;
|
||||
+--sorted_result
|
||||
+SELECT * FROM t1;
|
||||
+
|
||||
+DROP VIEW v1;
|
||||
+DROP TABLE t1;
|
||||
+
|
||||
+--echo #
|
||||
+--echo # End of 10.5 test
|
||||
+--echo #
|
||||
diff --git a/sql/sql_base.cc b/sql/sql_base.cc
|
||||
index 4f04f23d..d50f3407 100644
|
||||
--- a/sql/sql_base.cc
|
||||
+++ b/sql/sql_base.cc
|
||||
@@ -7876,18 +7876,19 @@ bool setup_tables(THD *thd, Name_resolution_context *context,
|
||||
while ((table_list= ti++))
|
||||
leaves.push_back(table_list, thd->mem_root);
|
||||
}
|
||||
-
|
||||
+
|
||||
+ bool is_insert_tables_num_set= false;
|
||||
while ((table_list= ti++))
|
||||
{
|
||||
TABLE *table= table_list->table;
|
||||
if (table)
|
||||
table->pos_in_table_list= table_list;
|
||||
- if (first_select_table &&
|
||||
+ if (select_insert && !is_insert_tables_num_set &&
|
||||
table_list->top_table() == first_select_table)
|
||||
{
|
||||
/* new counting for SELECT of INSERT ... SELECT command */
|
||||
- first_select_table= 0;
|
||||
thd->lex->first_select_lex()->insert_tables= tablenr;
|
||||
+ is_insert_tables_num_set= true;
|
||||
tablenr= 0;
|
||||
}
|
||||
if(table_list->jtbm_subselect)
|
||||
@@ -7909,6 +7910,15 @@ bool setup_tables(THD *thd, Name_resolution_context *context,
|
||||
my_error(ER_TOO_MANY_TABLES,MYF(0), static_cast<int>(MAX_TABLES));
|
||||
DBUG_RETURN(1);
|
||||
}
|
||||
+ if (select_insert && !is_insert_tables_num_set)
|
||||
+ {
|
||||
+ /*
|
||||
+ This happens for statements like `INSERT INTO t1 SELECT 1`,
|
||||
+ when there are no tables in the SELECT part.
|
||||
+ In this case all leaf tables belong to the INSERT part
|
||||
+ */
|
||||
+ thd->lex->first_select_lex()->insert_tables= tablenr;
|
||||
+ }
|
||||
}
|
||||
else
|
||||
{
|
||||
--
|
||||
2.40.0
|
||||
|
||||
@@ -0,0 +1,470 @@
|
||||
From 9b313d2de1df65626abb3b1d6c973f74addb12fb Mon Sep 17 00:00:00 2001
|
||||
From: Oleksandr Byelkin <sanja@mariadb.com>
|
||||
Date: Tue, 1 Apr 2025 20:57:29 +0200
|
||||
Subject: [PATCH] MDEV-32086 Server crash when inserting from derived table
|
||||
containing insert target table
|
||||
|
||||
Use original solution for INSERT ... SELECT - select result buferisation.
|
||||
|
||||
Also fix MDEV-36447 and MDEV-33139
|
||||
|
||||
CVE: CVE-2023-52969 and CVE-2023-52970
|
||||
Upstream-Status: Backport [https://github.com/MariaDB/server/commit/9b313d2de1df65626abb3b1d6c973f74addb12fb]
|
||||
|
||||
Signed-off-by: Yogita Urade <yogita.urade@windriver.com>
|
||||
---
|
||||
mysql-test/main/derived_cond_pushdown.result | 125 ++++++++----------
|
||||
mysql-test/main/derived_view.result | 2 +
|
||||
mysql-test/main/insert_select.result | 129 ++++++++++++++++++-
|
||||
mysql-test/main/insert_select.test | 56 +++++++-
|
||||
sql/sql_base.cc | 15 ++-
|
||||
sql/sql_base.h | 1 +
|
||||
sql/sql_insert.cc | 11 +-
|
||||
7 files changed, 260 insertions(+), 79 deletions(-)
|
||||
|
||||
diff --git a/mysql-test/main/derived_cond_pushdown.result b/mysql-test/main/derived_cond_pushdown.result
|
||||
index f47920c0..9eac511e 100644
|
||||
--- a/mysql-test/main/derived_cond_pushdown.result
|
||||
+++ b/mysql-test/main/derived_cond_pushdown.result
|
||||
@@ -10223,9 +10223,8 @@ SELECT * FROM ( SELECT t1.f FROM v1 JOIN t1 ) AS t WHERE f IS NOT NULL;
|
||||
EXPLAIN INSERT INTO t1
|
||||
SELECT * FROM ( SELECT t1.f FROM v1 JOIN t1 ) AS t WHERE f IS NOT NULL;
|
||||
id select_type table type possible_keys key key_len ref rows Extra
|
||||
-1 PRIMARY <derived2> ALL NULL NULL NULL NULL 144 Using where
|
||||
-2 DERIVED <derived4> ALL NULL NULL NULL NULL 12
|
||||
-2 DERIVED t1 ALL NULL NULL NULL NULL 12 Using where; Using join buffer (flat, BNL join)
|
||||
+1 PRIMARY <derived4> ALL NULL NULL NULL NULL 12 Using temporary
|
||||
+1 PRIMARY t1 ALL NULL NULL NULL NULL 12 Using where; Using join buffer (flat, BNL join)
|
||||
4 DERIVED t1 ALL NULL NULL NULL NULL 12
|
||||
EXPLAIN FORMAT=JSON INSERT INTO t1
|
||||
SELECT * FROM ( SELECT t1.f FROM v1 JOIN t1 ) AS t WHERE f IS NOT NULL;
|
||||
@@ -10233,45 +10232,35 @@ EXPLAIN
|
||||
{
|
||||
"query_block": {
|
||||
"select_id": 1,
|
||||
- "table": {
|
||||
- "table_name": "<derived2>",
|
||||
- "access_type": "ALL",
|
||||
- "rows": 144,
|
||||
- "filtered": 100,
|
||||
- "attached_condition": "t.f is not null",
|
||||
- "materialized": {
|
||||
- "query_block": {
|
||||
- "select_id": 2,
|
||||
- "table": {
|
||||
- "table_name": "<derived4>",
|
||||
- "access_type": "ALL",
|
||||
- "rows": 12,
|
||||
- "filtered": 100,
|
||||
- "materialized": {
|
||||
- "query_block": {
|
||||
- "select_id": 4,
|
||||
- "table": {
|
||||
- "table_name": "t1",
|
||||
- "access_type": "ALL",
|
||||
- "rows": 12,
|
||||
- "filtered": 100
|
||||
- }
|
||||
- }
|
||||
- }
|
||||
- },
|
||||
- "block-nl-join": {
|
||||
+ "temporary_table": {
|
||||
+ "table": {
|
||||
+ "table_name": "<derived4>",
|
||||
+ "access_type": "ALL",
|
||||
+ "rows": 12,
|
||||
+ "filtered": 100,
|
||||
+ "materialized": {
|
||||
+ "query_block": {
|
||||
+ "select_id": 4,
|
||||
"table": {
|
||||
"table_name": "t1",
|
||||
"access_type": "ALL",
|
||||
"rows": 12,
|
||||
- "filtered": 100,
|
||||
- "attached_condition": "t1.f is not null"
|
||||
- },
|
||||
- "buffer_type": "flat",
|
||||
- "buffer_size": "64",
|
||||
- "join_type": "BNL"
|
||||
+ "filtered": 100
|
||||
+ }
|
||||
}
|
||||
}
|
||||
+ },
|
||||
+ "block-nl-join": {
|
||||
+ "table": {
|
||||
+ "table_name": "t1",
|
||||
+ "access_type": "ALL",
|
||||
+ "rows": 12,
|
||||
+ "filtered": 100,
|
||||
+ "attached_condition": "t1.f is not null"
|
||||
+ },
|
||||
+ "buffer_type": "flat",
|
||||
+ "buffer_size": "64",
|
||||
+ "join_type": "BNL"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -10302,43 +10291,33 @@ EXPLAIN
|
||||
{
|
||||
"query_block": {
|
||||
"select_id": 1,
|
||||
- "table": {
|
||||
- "table_name": "<derived2>",
|
||||
- "access_type": "ALL",
|
||||
- "rows": 16,
|
||||
- "filtered": 100,
|
||||
- "attached_condition": "t.f is not null",
|
||||
- "materialized": {
|
||||
- "query_block": {
|
||||
- "select_id": 2,
|
||||
- "table": {
|
||||
- "table_name": "t1",
|
||||
- "access_type": "ALL",
|
||||
- "rows": 8,
|
||||
- "filtered": 100,
|
||||
- "attached_condition": "t1.f is not null"
|
||||
- },
|
||||
- "table": {
|
||||
- "table_name": "<derived4>",
|
||||
- "access_type": "ref",
|
||||
- "possible_keys": ["key0"],
|
||||
- "key": "key0",
|
||||
- "key_length": "4",
|
||||
- "used_key_parts": ["f"],
|
||||
- "ref": ["test.t1.f"],
|
||||
- "rows": 2,
|
||||
- "filtered": 100,
|
||||
- "materialized": {
|
||||
- "query_block": {
|
||||
- "select_id": 4,
|
||||
- "table": {
|
||||
- "table_name": "t1",
|
||||
- "access_type": "ALL",
|
||||
- "rows": 8,
|
||||
- "filtered": 100,
|
||||
- "attached_condition": "t1.f is not null"
|
||||
- }
|
||||
- }
|
||||
+ "temporary_table": {
|
||||
+ "table": {
|
||||
+ "table_name": "t1",
|
||||
+ "access_type": "ALL",
|
||||
+ "rows": 8,
|
||||
+ "filtered": 100,
|
||||
+ "attached_condition": "t1.f is not null"
|
||||
+ },
|
||||
+ "table": {
|
||||
+ "table_name": "<derived4>",
|
||||
+ "access_type": "ref",
|
||||
+ "possible_keys": ["key0"],
|
||||
+ "key": "key0",
|
||||
+ "key_length": "4",
|
||||
+ "used_key_parts": ["f"],
|
||||
+ "ref": ["test.t1.f"],
|
||||
+ "rows": 2,
|
||||
+ "filtered": 100,
|
||||
+ "materialized": {
|
||||
+ "query_block": {
|
||||
+ "select_id": 4,
|
||||
+ "table": {
|
||||
+ "table_name": "t1",
|
||||
+ "access_type": "ALL",
|
||||
+ "rows": 8,
|
||||
+ "filtered": 100,
|
||||
+ "attached_condition": "t1.f is not null"
|
||||
}
|
||||
}
|
||||
}
|
||||
diff --git a/mysql-test/main/derived_view.result b/mysql-test/main/derived_view.result
|
||||
index 15a7784c..3df1acc6 100644
|
||||
--- a/mysql-test/main/derived_view.result
|
||||
+++ b/mysql-test/main/derived_view.result
|
||||
@@ -2383,6 +2383,8 @@ SELECT * FROM t1;
|
||||
a
|
||||
1
|
||||
1
|
||||
+1
|
||||
+1
|
||||
drop table t1,t2;
|
||||
set optimizer_switch=@save968720_optimizer_switch;
|
||||
#
|
||||
diff --git a/mysql-test/main/insert_select.result b/mysql-test/main/insert_select.result
|
||||
index 79f8c519..ceb2fb8f 100644
|
||||
--- a/mysql-test/main/insert_select.result
|
||||
+++ b/mysql-test/main/insert_select.result
|
||||
@@ -1032,6 +1032,133 @@ a
|
||||
3
|
||||
DROP VIEW v1;
|
||||
DROP TABLE t1;
|
||||
+create table t1 (pk int, id int);
|
||||
+insert into t1 values (2,2), (3,3), (4,4);
|
||||
+insert into t1
|
||||
+select 1,10
|
||||
+from
|
||||
+(
|
||||
+select dt2.id from (select id from t1) dt2, t1 t where t.id=dt2.id
|
||||
+) dt
|
||||
+where dt.id=3;
|
||||
+select * from t1;
|
||||
+pk id
|
||||
+2 2
|
||||
+3 3
|
||||
+4 4
|
||||
+1 10
|
||||
+explain insert into t1
|
||||
+select 1,10
|
||||
+from
|
||||
+(
|
||||
+select dt2.id from (select id from t1) dt2, t1 t where t.id=dt2.id
|
||||
+) dt
|
||||
+where dt.id=3;
|
||||
+id select_type table type possible_keys key key_len ref rows Extra
|
||||
+1 SIMPLE t1 ALL NULL NULL NULL NULL 4 Using where; Using temporary
|
||||
+1 SIMPLE t ALL NULL NULL NULL NULL 4 Using where; Using join buffer (flat, BNL join)
|
||||
+explain format=json insert into t1
|
||||
+select 1,10
|
||||
+from
|
||||
+(
|
||||
+select dt2.id from (select id from t1) dt2, t1 t where t.id=dt2.id
|
||||
+) dt
|
||||
+where dt.id=3;
|
||||
+EXPLAIN
|
||||
+{
|
||||
+ "query_block": {
|
||||
+ "select_id": 1,
|
||||
+ "temporary_table": {
|
||||
+ "table": {
|
||||
+ "table_name": "t1",
|
||||
+ "access_type": "ALL",
|
||||
+ "rows": 4,
|
||||
+ "filtered": 100,
|
||||
+ "attached_condition": "t1.`id` = 3"
|
||||
+ },
|
||||
+ "block-nl-join": {
|
||||
+ "table": {
|
||||
+ "table_name": "t",
|
||||
+ "access_type": "ALL",
|
||||
+ "rows": 4,
|
||||
+ "filtered": 100,
|
||||
+ "attached_condition": "t.`id` = 3"
|
||||
+ },
|
||||
+ "buffer_type": "flat",
|
||||
+ "buffer_size": "65",
|
||||
+ "join_type": "BNL"
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
+prepare stmt from "insert into t1
|
||||
+select 1,10
|
||||
+from
|
||||
+(
|
||||
+select dt2.id from (select id from t1) dt2, t1 t where t.id=dt2.id
|
||||
+) dt
|
||||
+where dt.id=3";
|
||||
+execute stmt;
|
||||
+select * from t1;
|
||||
+pk id
|
||||
+2 2
|
||||
+3 3
|
||||
+4 4
|
||||
+1 10
|
||||
+1 10
|
||||
+execute stmt;
|
||||
+select * from t1;
|
||||
+pk id
|
||||
+2 2
|
||||
+3 3
|
||||
+4 4
|
||||
+1 10
|
||||
+1 10
|
||||
+1 10
|
||||
+deallocate prepare stmt;
|
||||
+create procedure p() insert into t1
|
||||
+select 1,10
|
||||
+from
|
||||
+(
|
||||
+select dt2.id from (select id from t1) dt2, t1 t where t.id=dt2.id
|
||||
+) dt
|
||||
+where dt.id=3;
|
||||
+call p();
|
||||
+select * from t1;
|
||||
+pk id
|
||||
+2 2
|
||||
+3 3
|
||||
+4 4
|
||||
+1 10
|
||||
+1 10
|
||||
+1 10
|
||||
+1 10
|
||||
+call p();
|
||||
+select * from t1;
|
||||
+pk id
|
||||
+2 2
|
||||
+3 3
|
||||
+4 4
|
||||
+1 10
|
||||
+1 10
|
||||
+1 10
|
||||
+1 10
|
||||
+1 10
|
||||
+drop procedure p;
|
||||
+drop table t1;
|
||||
#
|
||||
-# End of 10.5 test
|
||||
+# MDEV-33139: Crash of INSERT SELECT when preparing structures for
|
||||
+# split optimization
|
||||
#
|
||||
+CREATE TABLE v0 ( v1 INT UNIQUE ) ;
|
||||
+INSERT INTO v0 ( v1 ) VALUES
|
||||
+( ( SELECT
|
||||
+FROM
|
||||
+( SELECT v1
|
||||
+FROM v0 GROUP BY v1 ) AS v6 NATURAL JOIN
|
||||
+v0 AS v2 NATURAL JOIN
|
||||
+v0 AS v4 NATURAL JOIN
|
||||
+v0 AS v3 NATURAL JOIN
|
||||
+( SELECT v1 FROM v0 ) AS v7 ) ) ;
|
||||
+DROP TABLE v0;
|
||||
+# End of 10.5 tests
|
||||
diff --git a/mysql-test/main/insert_select.test b/mysql-test/main/insert_select.test
|
||||
index 0e9bd05a..5c2691c9 100644
|
||||
--- a/mysql-test/main/insert_select.test
|
||||
+++ b/mysql-test/main/insert_select.test
|
||||
@@ -591,6 +591,60 @@ SELECT * FROM t1;
|
||||
DROP VIEW v1;
|
||||
DROP TABLE t1;
|
||||
|
||||
+#
|
||||
+# MDEV-32086: condition pushdown into two mergeable derived tables,
|
||||
+# one containing the other, when they are forced to be
|
||||
+# materialized in INSERT
|
||||
+#
|
||||
+create table t1 (pk int, id int);
|
||||
+insert into t1 values (2,2), (3,3), (4,4);
|
||||
+
|
||||
+let $q=
|
||||
+insert into t1
|
||||
+ select 1,10
|
||||
+ from
|
||||
+ (
|
||||
+ select dt2.id from (select id from t1) dt2, t1 t where t.id=dt2.id
|
||||
+ ) dt
|
||||
+ where dt.id=3;
|
||||
+
|
||||
+eval $q;
|
||||
+select * from t1;
|
||||
+
|
||||
+eval explain $q;
|
||||
+eval explain format=json $q;
|
||||
+
|
||||
+eval prepare stmt from "$q";
|
||||
+execute stmt;
|
||||
+select * from t1;
|
||||
+execute stmt;
|
||||
+select * from t1;
|
||||
+deallocate prepare stmt;
|
||||
+
|
||||
+eval create procedure p() $q;
|
||||
+call p();
|
||||
+select * from t1;
|
||||
+call p();
|
||||
+select * from t1;
|
||||
+drop procedure p;
|
||||
+
|
||||
+drop table t1;
|
||||
+
|
||||
--echo #
|
||||
---echo # End of 10.5 test
|
||||
+--echo # MDEV-33139: Crash of INSERT SELECT when preparing structures for
|
||||
+--echo # split optimization
|
||||
--echo #
|
||||
+
|
||||
+CREATE TABLE v0 ( v1 INT UNIQUE ) ;
|
||||
+INSERT INTO v0 ( v1 ) VALUES
|
||||
+ ( ( SELECT 1
|
||||
+ FROM
|
||||
+ ( SELECT v1
|
||||
+ FROM v0 GROUP BY v1 ) AS v6 NATURAL JOIN
|
||||
+ v0 AS v2 NATURAL JOIN
|
||||
+ v0 AS v4 NATURAL JOIN
|
||||
+ v0 AS v3 NATURAL JOIN
|
||||
+ ( SELECT v1 FROM v0 ) AS v7 ) ) ;
|
||||
+DROP TABLE v0;
|
||||
+
|
||||
+--echo # End of 10.5 tests
|
||||
diff --git a/sql/sql_base.cc b/sql/sql_base.cc
|
||||
index d50f3407..15a9882b 100644
|
||||
--- a/sql/sql_base.cc
|
||||
+++ b/sql/sql_base.cc
|
||||
@@ -1176,11 +1176,20 @@ TABLE_LIST* find_dup_table(THD *thd, TABLE_LIST *table, TABLE_LIST *table_list,
|
||||
DBUG_PRINT("info",
|
||||
("found same copy of table or table which we should skip"));
|
||||
}
|
||||
- if (res && res->belong_to_derived)
|
||||
+ /*
|
||||
+ If we've found a duplicate in a derived table, try to work around that.
|
||||
+
|
||||
+ For INSERT...SELECT, do not do any workarounds, return the duplicate. The
|
||||
+ caller will enable buffering to handle this.
|
||||
+ */
|
||||
+ if (res && res->belong_to_derived &&
|
||||
+ !(check_flag & CHECK_DUP_FOR_INSERT_SELECT))
|
||||
{
|
||||
/*
|
||||
- We come here for queries of type:
|
||||
- INSERT INTO t1 (SELECT tmp.a FROM (select * FROM t1) as tmp);
|
||||
+ We come here for queries like this:
|
||||
+
|
||||
+ INSERT INTO t1 VALUES ((SELECT tmp.a FROM (select * FROM t1)));
|
||||
+ DELETE FROM t1 WHERE ( ... (SELECT ... FROM t1) ) ;
|
||||
|
||||
Try to fix by materializing the derived table
|
||||
*/
|
||||
diff --git a/sql/sql_base.h b/sql/sql_base.h
|
||||
index 5b449fdd..da9b1575 100644
|
||||
--- a/sql/sql_base.h
|
||||
+++ b/sql/sql_base.h
|
||||
@@ -72,6 +72,7 @@ enum find_item_error_report_type {REPORT_ALL_ERRORS, REPORT_EXCEPT_NOT_FOUND,
|
||||
#define CHECK_DUP_ALLOW_DIFFERENT_ALIAS 1
|
||||
#define CHECK_DUP_FOR_CREATE 2
|
||||
#define CHECK_DUP_SKIP_TEMP_TABLE 4
|
||||
+#define CHECK_DUP_FOR_INSERT_SELECT 8
|
||||
|
||||
uint get_table_def_key(const TABLE_LIST *table_list, const char **key);
|
||||
TABLE *open_ltable(THD *thd, TABLE_LIST *table_list, thr_lock_type update,
|
||||
diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc
|
||||
index 50e3bcd3..d9813660 100644
|
||||
--- a/sql/sql_insert.cc
|
||||
+++ b/sql/sql_insert.cc
|
||||
@@ -1741,6 +1741,14 @@ int mysql_prepare_insert(THD *thd, TABLE_LIST *table_list,
|
||||
DBUG_RETURN(1);
|
||||
}
|
||||
|
||||
+ /*
|
||||
+ Check if we read from the same table we're inserting into.
|
||||
+ Queries like INSERT INTO t1 VALUES ((SELECT ... FROM t1...)) are not
|
||||
+ allowed.
|
||||
+
|
||||
+ INSERT...SELECT is an exception: it will detect this case and use
|
||||
+ buffering to handle it correctly.
|
||||
+ */
|
||||
if (!select_insert)
|
||||
{
|
||||
Item *fake_conds= 0;
|
||||
@@ -4021,7 +4029,8 @@ select_insert::prepare(List<Item> &values, SELECT_LEX_UNIT *u)
|
||||
Is table which we are changing used somewhere in other parts of
|
||||
query
|
||||
*/
|
||||
- if (unique_table(thd, table_list, table_list->next_global, 0))
|
||||
+ if (unique_table(thd, table_list, table_list->next_global,
|
||||
+ CHECK_DUP_FOR_INSERT_SELECT))
|
||||
{
|
||||
/* Using same table for INSERT and SELECT */
|
||||
lex->current_select->options|= OPTION_BUFFER_RESULT;
|
||||
--
|
||||
2.40.0
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user