While debugging this, I noticed that in 11.0, the function make_default_field is executed exactly 3 times during the execution of this test: 1 time for an earlier UPDATE and 2 times for this last UPDATE. In 11.1, make_default_field would be executed 6 times, and 4 of them during this last UPDATE. So, it seems that there is not only a correctness regression but also a performance regression here.
Here is a call stack from the last make_default_field that is passing the incorrect value 'x' to column c:
Thread 2 hit Breakpoint 2, make_default_field (thd=thd@entry=0x7f3748000d58, field_arg=0x7f37481fbb18) at /mariadb/11.1/sql/item.cc:5133
#5 0x000055c3f23a212d in Sql_cmd_update::prepare_inner (this=0x7f37480152f0, thd=0x7f3748000d58) at /mariadb/11.1/sql/sql_update.cc:3010
#6 0x000055c3f22fa889 in Sql_cmd_dml::prepare (this=0x7f37480152f0, thd=0x7f3748000d58) at /mariadb/11.1/sql/sql_select.cc:33600
#7 0x000055c3f22fbf20 in Sql_cmd_dml::execute (this=0x7f37480152f0, thd=0x7f3748000d58) at /mariadb/11.1/sql/sql_select.cc:33653
#8 0x000055c3f22bf2a1 in mysql_execute_command (thd=thd@entry=0x7f3748000d58, is_called_from_prepared_stmt=is_called_from_prepared_stmt@entry=false) at /mariadb/11.1/sql/sql_parse.cc:4424
#9 0x000055c3f22c3b45 in mysql_parse (thd=thd@entry=0x7f3748000d58, rawbuf=<optimized out>, length=<optimized out>, parser_state=parser_state@entry=0x7f376854c250) at /mariadb/11.1/sql/sql_parse.cc:7871
#10 0x000055c3f22c52ff in dispatch_command (command=command@entry=COM_QUERY, thd=thd@entry=0x7f3748000d58, packet=packet@entry=0x7f3748095059 "update t1 set b=default, c=default(b) where a=1",
packet_length=packet_length@entry=47, blocking=blocking@entry=true) at /mariadb/11.1/sql/sql_parse.cc:1892
#11 0x000055c3f22c66c9 in do_command (thd=0x7f3748000d58, blocking=blocking@entry=true) at /mariadb/11.1/sql/sql_parse.cc:1405
#12 0x000055c3f23f4588 in do_handle_one_connection (connect=<optimized out>, connect@entry=0x55c3f41debd8, put_in_cache=put_in_cache@entry=true) at /mariadb/11.1/sql/sql_connect.cc:1415
#13 0x000055c3f23f47af in handle_one_connection (arg=0x55c3f41debd8) at /mariadb/11.1/sql/sql_connect.cc:1317
#14 0x00007f3768ea645c in start_thread (arg=<optimized out>) at ./nptl/pthread_create.c:444
#15 0x00007f3768f26ae0 in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:100
Attachments
Issue Links
is caused by
MDEV-28883Re-design the upper level of handling UPDATE and DELETE statements
the bug repeatable also in 11.0 and 10.4. It just should be multi-update execute-path (as it in 11.1):
create table t1 (
a int,
b timestamp default '2010-10-10 10:10:10' on update now(),
c varchar(100) default 'x');
create table t2 (a int primary key);
insert t1 (a) values (1),(2);
insert t2 (a) values (1),(2);
select * from t1;
a b c
1 2010-10-10 10:10:10 x
2 2010-10-10 10:10:10 x
set timestamp=unix_timestamp('2011-11-11 11-11-11');
update t1,t2 set b=default, c=default(b) where t1.a=1 and t1.a= t2.a;
select * from t1;
a b c
1 2010-10-10 10:10:10 x
2 2010-10-10 10:10:10 x
drop table t1, t2;
set timestamp=default;
Oleksandr Byelkin
added a comment - - edited the bug repeatable also in 11.0 and 10.4. It just should be multi-update execute-path (as it in 11.1):
create table t1 (
a int,
b timestamp default '2010-10-10 10:10:10' on update now(),
c varchar(100) default 'x');
create table t2 (a int primary key);
insert t1 (a) values (1),(2);
insert t2 (a) values (1),(2);
select * from t1;
a b c
1 2010-10-10 10:10:10 x
2 2010-10-10 10:10:10 x
set timestamp=unix_timestamp('2011-11-11 11-11-11');
update t1,t2 set b=default, c=default(b) where t1.a=1 and t1.a= t2.a;
select * from t1;
a b c
1 2010-10-10 10:10:10 x
2 2010-10-10 10:10:10 x
drop table t1, t2;
set timestamp=default;
Only multi-update path calls associate_with_target_field. Added by
commit e48bd474a2aeb4ecb71fe2d773e11780ea4271fb
Author: Dmitry Shulga <dmitry.shulga@mariadb.com>
Date: Thu Feb 8 12:17:02 2024 +0700
MDEV-15703: Crash in EXECUTE IMMEDIATE 'CREATE OR REPLACE TABLE t1 (a INT DEFAULT ?)' USING DEFAULT
This patch fixes the issue with passing the DEFAULT or IGNORE values to
positional parameters for some kind of SQL statements to be executed
as prepared statements.
The main idea of the patch is to associate an actual value being passed
by the USING clause with the positional parameter represented by
the Item_param class. Such association must be performed on execution of
UPDATE statement in PS/SP mode. Other corner cases that results in
server crash is on handling CREATE TABLE when positional parameter
placed after the DEFAULT clause or CALL statement and passing either
the value DEFAULT or IGNORE as an actual value for the positional parameter.
This case is fixed by checking whether an error is set in diagnostics
area at the function pack_vcols() on return from the function pack_expression()
Oleksandr Byelkin
added a comment - - edited Only multi-update path calls associate_with_target_field. Added by
commit e48bd474a2aeb4ecb71fe2d773e11780ea4271fb
Author: Dmitry Shulga <dmitry.shulga@mariadb.com>
Date: Thu Feb 8 12:17:02 2024 +0700
MDEV-15703: Crash in EXECUTE IMMEDIATE 'CREATE OR REPLACE TABLE t1 (a INT DEFAULT ?)' USING DEFAULT
This patch fixes the issue with passing the DEFAULT or IGNORE values to
positional parameters for some kind of SQL statements to be executed
as prepared statements.
The main idea of the patch is to associate an actual value being passed
by the USING clause with the positional parameter represented by
the Item_param class. Such association must be performed on execution of
UPDATE statement in PS/SP mode. Other corner cases that results in
server crash is on handling CREATE TABLE when positional parameter
placed after the DEFAULT clause or CALL statement and passing either
the value DEFAULT or IGNORE as an actual value for the positional parameter.
This case is fixed by checking whether an error is set in diagnostics
area at the function pack_vcols() on return from the function pack_expression()
MDEV-33790 Incorrect DEFAULT expression evaluated in UPDATE
The problem was that Item_default_value::associate_with_target_field
assigned passed as argument field as an argument which changed argument
in case of default() call with certain field (i.e. deault(field)).
There is no way to get wrong field in constructor so we will not reassign
parameter.
Oleksandr Byelkin
added a comment -
commit ffea313d01c2991d84f71f7b0a143d1327042e2b (HEAD -> bb-10.4-MDEV-33790, origin/bb-10.4-MDEV-33790)
Author: Oleksandr Byelkin <sanja@mariadb.com>
Date: Tue Apr 23 11:37:11 2024 +0200
MDEV-33790 Incorrect DEFAULT expression evaluated in UPDATE
The problem was that Item_default_value::associate_with_target_field
assigned passed as argument field as an argument which changed argument
in case of default() call with certain field (i.e. deault(field)).
There is no way to get wrong field in constructor so we will not reassign
parameter.
the bug repeatable also in 11.0 and 10.4. It just should be multi-update execute-path (as it in 11.1):
create table t1 (
a int,
b timestamp default '2010-10-10 10:10:10' on update now(),
c varchar(100) default 'x');
create table t2 (a int primary key);
insert t1 (a) values (1),(2);
insert t2 (a) values (1),(2);
select * from t1;
a b c
1 2010-10-10 10:10:10 x
2 2010-10-10 10:10:10 x
set timestamp=unix_timestamp('2011-11-11 11-11-11');
update t1,t2 set b=default, c=default(b) where t1.a=1 and t1.a= t2.a;
select * from t1;
a b c
1 2010-10-10 10:10:10 x
2 2010-10-10 10:10:10 x
drop table t1, t2;
set timestamp=default;