diff --git a/mysql-test/suite/period/r/delete.result b/mysql-test/suite/period/r/delete.result index 2b0a97e03d8e1..563247b78d088 100644 --- a/mysql-test/suite/period/r/delete.result +++ b/mysql-test/suite/period/r/delete.result @@ -421,3 +421,65 @@ id s e drop table t1; drop table log_tbl; drop procedure log; +# +# MDEV-40821 SIGSEGV in Window_funcs_sort::setup +# +# Bound referencing another table must not delete whole rows +create table t1 (x int, s date, e date, period for app(s,e)); +create table t2 (d date); +insert into t1 values (1, '2000-01-01', '2000-01-10'), +(2, '2000-02-01', '2000-02-10'); +insert into t2 values ('2000-01-05'); +delete from t1 for portion of app from (select d from t2) to '2000-01-20'; +ERROR HY000: Expression in FOR PORTION OF must be constant +select * from t1; +x s e +1 2000-01-01 2000-01-10 +2 2000-02-01 2000-02-10 +drop table t1, t2; +# End of 10.11 tests +# +# MDEV-40821 SIGSEGV in Window_funcs_sort::setup +# +# Subquery on the target: row must be split, not deleted +create table t1 (id int, s date, e date, period for app(s,e)); +insert into t1 values (1, '2000-01-01', '2000-01-10'); +delete from t1 for portion of app from '2000-01-05' to '2000-01-20' + where id in (select id from t1); +select * from t1; +id s e +1 2000-01-01 2000-01-05 +drop table t1; +# End of 11.4 tests +# +# MDEV-40821 SIGSEGV in Window_funcs_sort::setup +# +create table t1 (c1 int key); +create sequence cs1 engine myisam; +delete from t1 ignore index (primary) for portion of app from setval(cs1,1) to sum(1) over w1; +ERROR HY000: Period `app` is not found in table +create or replace table t1 (c1 int key, s date, e date, period for app(s,e)); +delete from t1 ignore index (primary) for portion of app from setval(cs1,1) to sum(1) over w1; +ERROR HY000: Window function is allowed only in SELECT list and ORDER BY clause +drop sequence cs1; +drop table t1; +create table t1 (id int, s date, e date, period for app(s,e), key(id)); +# Index hint: row must be split, not deleted +insert into t1 values (1, '2000-01-01', '2000-01-10'); +delete from t1 ignore index (id) +for portion of app from '2000-01-05' to '2000-01-20'; +Warnings: +Warning 4207 Index hints are ignored because they are incompatible with FOR PORTION OF clause +select * from t1; +id s e +1 2000-01-01 2000-01-05 +# Index hint: non-constant bounds must be rejected +delete from t1; +insert into t1 values (1, '2000-01-01', '2000-01-10'); +delete from t1 ignore index (id) for portion of app from s to e; +ERROR HY000: Expression in FOR PORTION OF must be constant +select * from t1; +id s e +1 2000-01-01 2000-01-10 +drop table t1; +# End of 11.8 tests diff --git a/mysql-test/suite/period/t/delete.test b/mysql-test/suite/period/t/delete.test index 676fa256f95ed..0cbb4243cdff2 100644 --- a/mysql-test/suite/period/t/delete.test +++ b/mysql-test/suite/period/t/delete.test @@ -1,6 +1,7 @@ source suite/period/engines.inc; source include/have_log_bin.inc; source include/have_partition.inc; +source include/have_sequence.inc; create table t (id int, s date, e date, period for apptime(s,e)); @@ -268,3 +269,66 @@ select * from t1; drop table t1; drop table log_tbl; drop procedure log; + +--echo # +--echo # MDEV-40821 SIGSEGV in Window_funcs_sort::setup +--echo # +--echo # Bound referencing another table must not delete whole rows +create table t1 (x int, s date, e date, period for app(s,e)); +create table t2 (d date); +insert into t1 values (1, '2000-01-01', '2000-01-10'), + (2, '2000-02-01', '2000-02-10'); +insert into t2 values ('2000-01-05'); +--error ER_NOT_CONSTANT_EXPRESSION +delete from t1 for portion of app from (select d from t2) to '2000-01-20'; +--sorted_result +select * from t1; +drop table t1, t2; + +--echo # End of 10.11 tests + +--echo # +--echo # MDEV-40821 SIGSEGV in Window_funcs_sort::setup +--echo # +--echo # Subquery on the target: row must be split, not deleted +create table t1 (id int, s date, e date, period for app(s,e)); +insert into t1 values (1, '2000-01-01', '2000-01-10'); +delete from t1 for portion of app from '2000-01-05' to '2000-01-20' + where id in (select id from t1); +select * from t1; +drop table t1; + +--echo # End of 11.4 tests + +--echo # +--echo # MDEV-40821 SIGSEGV in Window_funcs_sort::setup +--echo # +create table t1 (c1 int key); +create sequence cs1 engine myisam; +--error ER_PERIOD_NOT_FOUND +delete from t1 ignore index (primary) for portion of app from setval(cs1,1) to sum(1) over w1; +create or replace table t1 (c1 int key, s date, e date, period for app(s,e)); +--error ER_WRONG_PLACEMENT_OF_WINDOW_FUNCTION +delete from t1 ignore index (primary) for portion of app from setval(cs1,1) to sum(1) over w1; +# Cleanup +drop sequence cs1; +drop table t1; + +create table t1 (id int, s date, e date, period for app(s,e), key(id)); + +--echo # Index hint: row must be split, not deleted +insert into t1 values (1, '2000-01-01', '2000-01-10'); +delete from t1 ignore index (id) + for portion of app from '2000-01-05' to '2000-01-20'; +select * from t1; + +--echo # Index hint: non-constant bounds must be rejected +delete from t1; +insert into t1 values (1, '2000-01-01', '2000-01-10'); +--error ER_NOT_CONSTANT_EXPRESSION +delete from t1 ignore index (id) for portion of app from s to e; +select * from t1; + +drop table t1; + +--echo # End of 11.8 tests diff --git a/mysql-test/suite/versioning/r/delete_history.result b/mysql-test/suite/versioning/r/delete_history.result index 61ad71a86d74f..87b53ce440d14 100644 --- a/mysql-test/suite/versioning/r/delete_history.result +++ b/mysql-test/suite/versioning/r/delete_history.result @@ -504,4 +504,114 @@ create table t (a int) with system versioning; insert into t values (1),(2); prepare stmt from 'select * from t for system_time as of timestamp ?'; drop table t; +# +# MDEV-40821 SIGSEGV in Window_funcs_sort::setup +# +# Point referencing another table must purge only history +create table t1 (x int) with system versioning; +create table t2 (d timestamp(6)); +set timestamp= unix_timestamp('2000-01-01 00:00:01'); +insert into t1 values (1), (2); +set timestamp= unix_timestamp('2000-01-01 00:00:02'); +delete from t1 where x = 2; +insert into t2 values ('2000-01-01 00:00:03'); +set timestamp= default; +delete history from t1 before system_time (select d from t2); +select * from t1; +x +1 +select * from t1 for system_time all; +x +1 +# Prepared statement +set timestamp= unix_timestamp('2000-01-01 00:00:02'); +insert into t1 values (3); +delete from t1 where x = 3; +set timestamp= default; +prepare stmt from 'delete history from t1 before system_time (select d from t2)'; +execute stmt; +select * from t1 for system_time all; +x +1 +set timestamp= unix_timestamp('2000-01-01 00:00:02'); +insert into t1 values (4); +delete from t1 where x = 4; +set timestamp= default; +execute stmt; +select * from t1 for system_time all; +x +1 +drop prepare stmt; +# Sequence function in the point +create sequence s start with 3 engine=myisam; +select nextval(s); +nextval(s) +3 +set timestamp= unix_timestamp('2000-01-01 00:00:02'); +insert into t1 values (5); +delete from t1 where x = 5; +set timestamp= default; +delete history from t1 before system_time +timestampadd(second, lastval(s), '2000-01-01 00:00:00'); +select * from t1 for system_time all; +x +1 +drop sequence s; +# Non-versioned table must be rejected +create table t3 (x int); +insert into t3 values (1); +delete history from t3 before system_time (select d from t2); +ERROR HY000: Table `t3` is not system-versioned +select * from t3; +x +1 +drop table t3; +# View over partitioned table +create table t3 (x int) with system versioning +partition by system_time limit 1; +create view v as select * from t3; +delete history from v; +ERROR 42S02: 'v' is a view +drop view v; +drop table t3; +# Locking subquery on partitioned table +create table t3 (d timestamp(6)) with system versioning +partition by system_time limit 1; +set timestamp= unix_timestamp('2000-01-01 00:00:02'); +insert into t1 values (6); +delete from t1 where x = 6; +insert into t3 values ('2000-01-01 00:00:03'); +set timestamp= default; +delete history from t1 before system_time (select d from t3 for update); +select * from t1 for system_time all; +x +1 +# Subquery with its own FOR SYSTEM_TIME +create table t4 (d timestamp(6)) with system versioning; +set timestamp= unix_timestamp('2000-01-01 00:00:02'); +insert into t1 values (7); +delete from t1 where x = 7; +insert into t4 values ('2000-01-01 00:00:03'); +set timestamp= unix_timestamp('2000-01-01 00:00:03'); +update t4 set d= '2000-01-01 00:00:00'; +set timestamp= default; +delete history from t1 before system_time +(select max(d) from t4 for system_time all); +select * from t1 for system_time all; +x +1 +drop table t1, t2, t3, t4; # End of 10.11 tests +# +# MDEV-40821 SIGSEGV in Window_funcs_sort::setup +# +create table t1 (c1 int key); +create sequence cs1 engine myisam; +delete history from t1 ignore index (primary) before system_time timestamp(setval(cs1,1),sum(1) over w1); +ERROR HY000: Table `t1` is not system-versioned +create or replace table t1 (c1 int key) with system versioning; +delete history from t1 ignore index (primary) before system_time timestamp(setval(cs1,1),sum(1) over w1); +ERROR HY000: Window function is allowed only in SELECT list and ORDER BY clause +drop sequence cs1; +drop table t1; +# End of 11.8 tests diff --git a/mysql-test/suite/versioning/r/not_embedded.result b/mysql-test/suite/versioning/r/not_embedded.result index 5d8380e096962..eb03338fb115c 100644 --- a/mysql-test/suite/versioning/r/not_embedded.result +++ b/mysql-test/suite/versioning/r/not_embedded.result @@ -93,3 +93,21 @@ connection default; commit; drop table t; set timestamp= default; +# +# MDEV-40821 SIGSEGV in Window_funcs_sort::setup +# +# DELETE privilege is not enough for DELETE HISTORY with a subquery +create database mysqltest; +create table mysqltest.t (a int) with system versioning; +create table mysqltest.t2 (d timestamp(6)); +insert into mysqltest.t2 values (now(6)); +create user mysqltest_1@localhost; +grant select, delete on mysqltest.* to mysqltest_1@localhost; +connect user1,localhost,mysqltest_1,,mysqltest; +delete history from t before system_time (select d from t2); +ERROR 42000: DELETE HISTORY command denied to user 'mysqltest_1'@'localhost' for table `mysqltest`.`t` +disconnect user1; +connection default; +drop user mysqltest_1@localhost; +drop database mysqltest; +# End of 10.11 tests diff --git a/mysql-test/suite/versioning/t/delete_history.test b/mysql-test/suite/versioning/t/delete_history.test index cdf4c0432e03d..011f03af1ae38 100644 --- a/mysql-test/suite/versioning/t/delete_history.test +++ b/mysql-test/suite/versioning/t/delete_history.test @@ -2,6 +2,7 @@ --source include/have_partition.inc --source suite/versioning/engines.inc --source include/word_size.inc +--source include/have_sequence.inc call mtr.add_suppression("need more HISTORY partitions"); @@ -372,6 +373,104 @@ insert into t values (1),(2); prepare stmt from 'select * from t for system_time as of timestamp ?'; drop table t; +--echo # +--echo # MDEV-40821 SIGSEGV in Window_funcs_sort::setup +--echo # +--echo # Point referencing another table must purge only history +create table t1 (x int) with system versioning; +create table t2 (d timestamp(6)); +set timestamp= unix_timestamp('2000-01-01 00:00:01'); +insert into t1 values (1), (2); +set timestamp= unix_timestamp('2000-01-01 00:00:02'); +delete from t1 where x = 2; +insert into t2 values ('2000-01-01 00:00:03'); +set timestamp= default; +delete history from t1 before system_time (select d from t2); +select * from t1; +select * from t1 for system_time all; +--echo # Prepared statement +set timestamp= unix_timestamp('2000-01-01 00:00:02'); +insert into t1 values (3); +delete from t1 where x = 3; +set timestamp= default; +prepare stmt from 'delete history from t1 before system_time (select d from t2)'; +execute stmt; +select * from t1 for system_time all; +set timestamp= unix_timestamp('2000-01-01 00:00:02'); +insert into t1 values (4); +delete from t1 where x = 4; +set timestamp= default; +execute stmt; +select * from t1 for system_time all; +drop prepare stmt; +--echo # Sequence function in the point +create sequence s start with 3 engine=myisam; +--disable_ps2_protocol +select nextval(s); +--enable_ps2_protocol +set timestamp= unix_timestamp('2000-01-01 00:00:02'); +insert into t1 values (5); +delete from t1 where x = 5; +set timestamp= default; +delete history from t1 before system_time + timestampadd(second, lastval(s), '2000-01-01 00:00:00'); +select * from t1 for system_time all; +drop sequence s; +--echo # Non-versioned table must be rejected +create table t3 (x int); +insert into t3 values (1); +--error ER_VERS_NOT_VERSIONED +delete history from t3 before system_time (select d from t2); +select * from t3; +drop table t3; +--echo # View over partitioned table +create table t3 (x int) with system versioning + partition by system_time limit 1; +create view v as select * from t3; +--error ER_IT_IS_A_VIEW +delete history from v; +drop view v; +drop table t3; +--echo # Locking subquery on partitioned table +create table t3 (d timestamp(6)) with system versioning + partition by system_time limit 1; +set timestamp= unix_timestamp('2000-01-01 00:00:02'); +insert into t1 values (6); +delete from t1 where x = 6; +insert into t3 values ('2000-01-01 00:00:03'); +set timestamp= default; +delete history from t1 before system_time (select d from t3 for update); +select * from t1 for system_time all; +--echo # Subquery with its own FOR SYSTEM_TIME +create table t4 (d timestamp(6)) with system versioning; +set timestamp= unix_timestamp('2000-01-01 00:00:02'); +insert into t1 values (7); +delete from t1 where x = 7; +insert into t4 values ('2000-01-01 00:00:03'); +set timestamp= unix_timestamp('2000-01-01 00:00:03'); +update t4 set d= '2000-01-01 00:00:00'; +set timestamp= default; +delete history from t1 before system_time + (select max(d) from t4 for system_time all); +select * from t1 for system_time all; +drop table t1, t2, t3, t4; + --echo # End of 10.11 tests +--echo # +--echo # MDEV-40821 SIGSEGV in Window_funcs_sort::setup +--echo # +create table t1 (c1 int key); +create sequence cs1 engine myisam; +--error ER_VERS_NOT_VERSIONED +delete history from t1 ignore index (primary) before system_time timestamp(setval(cs1,1),sum(1) over w1); +create or replace table t1 (c1 int key) with system versioning; +--error ER_WRONG_PLACEMENT_OF_WINDOW_FUNCTION +delete history from t1 ignore index (primary) before system_time timestamp(setval(cs1,1),sum(1) over w1); +# Cleanup +drop sequence cs1; +drop table t1; + +--echo # End of 11.8 tests + --source suite/versioning/common_finish.inc diff --git a/mysql-test/suite/versioning/t/not_embedded.test b/mysql-test/suite/versioning/t/not_embedded.test index 38f42a44587c1..73953045146f4 100644 --- a/mysql-test/suite/versioning/t/not_embedded.test +++ b/mysql-test/suite/versioning/t/not_embedded.test @@ -105,3 +105,23 @@ reap; commit; drop table t; set timestamp= default; + +--echo # +--echo # MDEV-40821 SIGSEGV in Window_funcs_sort::setup +--echo # +--echo # DELETE privilege is not enough for DELETE HISTORY with a subquery +create database mysqltest; +create table mysqltest.t (a int) with system versioning; +create table mysqltest.t2 (d timestamp(6)); +insert into mysqltest.t2 values (now(6)); +create user mysqltest_1@localhost; +grant select, delete on mysqltest.* to mysqltest_1@localhost; +connect (user1,localhost,mysqltest_1,,mysqltest); +--error ER_TABLEACCESS_DENIED_ERROR +delete history from t before system_time (select d from t2); +disconnect user1; +connection default; +drop user mysqltest_1@localhost; +drop database mysqltest; + +--echo # End of 10.11 tests diff --git a/sql/share/errmsg-utf8.txt b/sql/share/errmsg-utf8.txt index e8ed15a7bf146..f4ad832a9e70c 100644 --- a/sql/share/errmsg-utf8.txt +++ b/sql/share/errmsg-utf8.txt @@ -12293,7 +12293,7 @@ ER_PSEUDO_THREAD_ID_OVERWRITE ER_VEC_DISTANCE_TYPE eng "Cannot determine distance type for VEC_DISTANCE, index is not found" WARN_INDEX_HINTS_IGNORED - eng "Index hints are ignored because they are incompatible with RETURNING clause" - ukr "Підказки по використанню индексів ігноруются тому що вони несумісні з RETURNING" + eng "Index hints are ignored because they are incompatible with %s clause" + ukr "Підказки по використанню индексів ігноруются тому що вони несумісні з %s" ER_SIGNAL_SKIP_ROW_FROM_TRIGGER eng "The row is skipped by a trigger implementation" diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 101314fe1c6b3..76c85661478fc 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -1873,8 +1873,6 @@ bool TABLE::vers_switch_partition(THD *thd, TABLE_LIST *table_list, } break; } - DBUG_ASSERT(!thd->lex->last_table() || - !thd->lex->last_table()->vers_conditions.delete_history); } if (table_list->partition_names) diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc index b7ee620961631..ee8ff1319fa51 100644 --- a/sql/sql_delete.cc +++ b/sql/sql_delete.cc @@ -1839,7 +1839,8 @@ void Sql_cmd_delete::remove_order_by_without_limit(THD *thd) bool Sql_cmd_delete::processing_as_multitable_delete_prohibited(THD *thd) { return - (thd->lex->has_returning()); + (thd->lex->has_returning() || + thd->lex->period_conditions.is_set()); } @@ -1966,7 +1967,9 @@ bool Sql_cmd_delete::prepare_inner(THD *thd) { push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN, WARN_INDEX_HINTS_IGNORED, - "%s", ER_THD(thd, WARN_INDEX_HINTS_IGNORED)); + ER_THD(thd, WARN_INDEX_HINTS_IGNORED), + thd->lex->has_returning() ? + "RETURNING" : "FOR PORTION OF"); } } if (table_list->vers_conditions.is_set() && table_list->is_view_or_derived()) diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 8b02697d2430f..f0caebd0a87f4 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -1693,6 +1693,7 @@ rule: derived_table_list table_reference_list_parens nested_table_reference_list join_table_parens update_table_list table_function + delete_single_table %type date_time_type; %type interval @@ -14010,7 +14011,7 @@ delete_part2: | HISTORY_SYM delete_single_table opt_delete_system_time { LEX *lex= Lex; - lex->last_table()->vers_conditions= lex->vers_conditions; + $2->vers_conditions= lex->vers_conditions; lex->sql_command= SQLCOM_DELETE; if (!(lex->m_sql_cmd= new (thd->mem_root) Sql_cmd_delete(false))) @@ -14038,12 +14039,12 @@ delete_single_table: Lex->query_tables= 0; Lex->query_tables_last= &Lex->query_tables; - if (unlikely(!Select-> - add_table_to_list(thd, $2, $3, TL_OPTION_UPDATING, - YYPS->m_lock_type, - YYPS->m_mdl_type, - Select->pop_index_hints(), - $5))) + if (!($$= Select-> + add_table_to_list(thd, $2, $3, TL_OPTION_UPDATING, + YYPS->m_lock_type, + YYPS->m_mdl_type, + Select->pop_index_hints(), + $5))) MYSQL_YYABORT; Lex->auxiliary_table_list.first->correspondent_table= Lex->query_tables; @@ -14056,7 +14057,7 @@ delete_single_table_for_period: delete_single_table opt_for_portion_of_time_clause { if ($2) - Lex->last_table()->period_conditions= Lex->period_conditions; + $1->period_conditions= Lex->period_conditions; } ;