Uploaded image for project: 'MariaDB Server'
  1. MariaDB Server
  2. MDEV-33790

Incorrect DEFAULT expression evaluated in UPDATE

Details

    Description

      The last UPDATE in the test main.function_defaults would produce an incorrect result after a merge to 11.1:

      CURRENT_TEST: main.function_defaults
      --- /mariadb/11.1/mysql-test/main/function_defaults.result	2024-01-10 12:45:29.965451779 +0200
      +++ /mariadb/11.1/mysql-test/main/function_defaults.reject	2024-03-28 11:56:47.820191010 +0200
      @@ -3141,7 +3141,7 @@
       update t1 set b=default, c=default(b) where a=1;
       select * from t1;
       a	b	c
      -1	2010-10-10 10:10:10	2010-10-10 10:10:10
      +1	2010-10-10 10:10:10	x
       2	2010-10-10 10:10:10	x
       drop table t1;
       set timestamp=default;
      

      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
      5133	{
      2: *field_arg = {<Value_source> = {<No data fields>}, _vptr.Field = 0x55c3f296d730 <vtable for Field_varstring+16>, ptr = 0x7f37481fb871 "\001x", null_ptr = 0x7f37481fb868 <incomplete sequence \371>, 
        table = 0x7f37481fb428, orig_table = 0x7f37481fb428, table_name = 0x7f37481fb538, field_name = {str = 0x7f374820880d "c", length = 1}, comment = {str = 0x55c3f1823d83 "", length = 0}, option_list = 0x0, 
        option_struct = 0x0, key_start = {buffer = {0}}, part_of_key = {buffer = {0}}, part_of_key_not_clustered = {buffer = {0}}, part_of_sortkey = {buffer = {0}}, unireg_check = Field::NONE, invisible = VISIBLE, 
        field_length = 100, flags = 0, field_index = 2, null_bit = 4 '\004', is_created_from_null_item = false, cond_selectivity = 1, next_equal_field = 0x0, read_stats = 0x7f37481b2aa0, collected_stats = 0x0, 
        vcol_info = 0x0, check_constraint = 0x0, default_value = 0x0}
      (rr) bt
      #0  make_default_field (thd=thd@entry=0x7f3748000d58, field_arg=0x7f37481fbb18) at /mariadb/11.1/sql/item.cc:5133
      #1  0x000055c3f207ea76 in Item_default_value::tie_field (this=0x7f37480151a0, thd=0x7f3748000d58) at /mariadb/11.1/sql/item.cc:9986
      #2  0x000055c3f207ebb7 in Item_default_value::associate_with_target_field (this=<optimized out>, thd=<optimized out>, field=<optimized out>) at /mariadb/11.1/sql/item.cc:9935
      #3  0x000055c3f239f041 in multi_update::prepare (this=0x7f3748015730, not_used_values=<optimized out>, lex_unit=<optimized out>) at /mariadb/11.1/sql/sql_update.cc:1874
      #4  0x000055c3f23192a4 in JOIN::prepare (this=this@entry=0x7f3748015840, tables_init=tables_init@entry=0x7f37480145b0, conds_init=<optimized out>, og_num=<optimized out>, order_init=<optimized out>, 
          skip_order_by=skip_order_by@entry=false, group_init=<optimized out>, having_init=<optimized out>, proc_param_init=<optimized out>, select_lex_arg=<optimized out>, unit_arg=<optimized out>)
          at /mariadb/11.1/sql/sql_select.cc:1832
      #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

          Activity

            sanja 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;
            

            sanja 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;
            sanja 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()
            

            sanja 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()

            the above patch change case FIELD=DEFAULT() but broke case FIELD=DEFAULT(OTHER_FIELD);

            sanja Oleksandr Byelkin added a comment - the above patch change case FIELD=DEFAULT() but broke case FIELD=DEFAULT(OTHER_FIELD);

            There is no way to incorrectly set Item_default_value, so we should not change it in associate_with_target_field.

            sanja Oleksandr Byelkin added a comment - There is no way to incorrectly set Item_default_value, so we should not change it in associate_with_target_field.

            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.
            

            sanja 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.
            shulga Dmitry Shulga added a comment -

            OK to push

            shulga Dmitry Shulga added a comment - OK to push

            People

              sanja Oleksandr Byelkin
              marko Marko Mäkelä
              Votes:
              0 Vote for this issue
              Watchers:
              4 Start watching this issue

              Dates

                Created:
                Updated:
                Resolved:

                Git Integration

                  Error rendering 'com.xiplink.jira.git.jira_git_plugin:git-issue-webpanel'. Please contact your Jira administrators.