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

Assertion `!table || (!table->read_set || bitmap_is_set(table->read_set, field_index))' failed in Field_long::val_str on EXPLAIN EXTENDED

Details

    Description

      CREATE TABLE t1 (f1 INT, f2 INT, KEY(f2)) ENGINE=MyISAM;
      INSERT INTO t1 VALUES (6,9);
       
      CREATE TABLE t2 (f3 INT) ENGINE=MyISAM;
      INSERT INTO t2 VALUES (2),(0);
       
      EXPLAIN EXTENDED 
      SELECT f1 FROM ( SELECT * FROM t1 ) AS sq
      WHERE f1 IN ( 
        SELECT f3 FROM t2 WHERE f2 IN ( 
          SELECT f3 FROM t2 HAVING f3 >= 8 
        ) 
      );

      Stack trace from 5.5 commit 86f46a3da4a6d82cb510dc4c270d46cfd6a8965b

      5.5/sql/field.cc:3669: virtual String* Field_long::val_str(String*, String*): Assertion `!table || (!table->read_set || bitmap_is_set(table->read_set, field_index))' failed.
      150325  0:00:42 [ERROR] mysqld got signal 6 ;
       
      #6  0x00007f8f648e2311 in *__GI___assert_fail (assertion=0xe01f70 "!table || (!table->read_set || bitmap_is_set(table->read_set, field_index))", file=<optimized out>, line=3669, function=0xe053a0 "virtual String* Field_long::val_str(String*, String*)") at assert.c:81
      #7  0x00000000007c5bd2 in Field_long::val_str (this=0x7f8f5f458b48, val_buffer=0x7f8f5ffb4340, val_ptr=0x7f8f5f587e20) at 5.5/sql/field.cc:3669
      #8  0x00000000007fc650 in Item_field::val_str (this=0x7f8f5f587e08, str=0x7f8f5ffb4340) at 5.5/sql/item.cc:2566
      #9  0x00000000007f72af in Item::print_value (this=0x7f8f5f587e08, str=0x7f8f5ffb48a0) at 5.5/sql/item.cc:634
      #10 0x000000000080754a in Item_field::print (this=0x7f8f5f587e08, str=0x7f8f5ffb48a0, query_type=QT_TO_SYSTEM_CHARSET) at 5.5/sql/item.cc:6697
      #11 0x0000000000808a5f in Item_ref::print (this=0x7f8f5f58aa18, str=0x7f8f5ffb48a0, query_type=QT_TO_SYSTEM_CHARSET) at 5.5/sql/item.cc:7204
      #12 0x000000000084351c in Item_func::print_op (this=0x7f8f5f542ab8, str=0x7f8f5ffb48a0, query_type=QT_TO_SYSTEM_CHARSET) at 5.5/sql/item_func.cc:491
      #13 0x000000000082ae63 in Item_bool_func2::print (this=0x7f8f5f542ab8, str=0x7f8f5ffb48a0, query_type=QT_TO_SYSTEM_CHARSET) at 5.5/sql/item_cmpfunc.h:385
      #14 0x0000000000826070 in Item_cond::print (this=0x7f8f5f5437a8, str=0x7f8f5ffb48a0, query_type=QT_TO_SYSTEM_CHARSET) at 5.5/sql/item_cmpfunc.cc:4633
      #15 0x000000000069e315 in st_select_lex::print (this=0x7f8f60553a60, thd=0x7f8f60550060, str=0x7f8f5ffb48a0, query_type=QT_TO_SYSTEM_CHARSET) at 5.5/sql/sql_select.cc:23366
      #16 0x00000000006298f8 in st_select_lex_unit::print (this=0x7f8f60553380, str=0x7f8f5ffb48a0, query_type=QT_TO_SYSTEM_CHARSET) at 5.5/sql/sql_lex.cc:2361
      #17 0x000000000063c0d8 in execute_sqlcom_select (thd=0x7f8f60550060, all_tables=0x7f8f5f5696b0) at 5.5/sql/sql_parse.cc:4674
      #18 0x00000000006353de in mysql_execute_command (thd=0x7f8f60550060) at 5.5/sql/sql_parse.cc:2234
      #19 0x000000000063ece2 in mysql_parse (thd=0x7f8f60550060, rawbuf=0x7f8f5f687078 "EXPLAIN EXTENDED \nSELECT f1 FROM ( SELECT * FROM t1 ) AS sq\nWHERE f1 IN ( \nSELECT f3 FROM t2 WHERE f2 IN ( \nSELECT f3 FROM t2 HAVING f3 >= 8 \n) \n)", length=146, parser_state=0x7f8f5ffb5620) at 5.5/sql/sql_parse.cc:5909
      #20 0x0000000000632925 in dispatch_command (command=COM_QUERY, thd=0x7f8f60550060, packet=0x7f8f60609061 "", packet_length=146) at 5.5/sql/sql_parse.cc:1079
      #21 0x0000000000631ab1 in do_command (thd=0x7f8f60550060) at 5.5/sql/sql_parse.cc:793
      #22 0x0000000000734122 in do_handle_one_connection (thd_arg=0x7f8f60550060) at 5.5/sql/sql_connect.cc:1266
      #23 0x0000000000733be1 in handle_one_connection (arg=0x7f8f60550060) at 5.5/sql/sql_connect.cc:1181
      #24 0x0000000000b6c629 in pfs_spawn_thread (arg=0x7f8f60571fc0) at 5.5/storage/perfschema/pfs.cc:1015
      #25 0x00007f8f666ddb50 in start_thread (arg=<optimized out>) at pthread_create.c:304
      #26 0x00007f8f6499370d in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:112

      Attachments

        Issue Links

          Activity

            danblack Daniel Black added a comment -

            Hitting assertions is quite a bit pain. There's quite a few confirmed assertions that aren't fixed: search 'text ~ "Assertion" and status=CONFIRMED'

            danblack Daniel Black added a comment - Hitting assertions is quite a bit pain. There's quite a few confirmed assertions that aren't fixed: search 'text ~ "Assertion" and status=CONFIRMED'

            Situation is like this: Item_field::print() see that field belongs to constant table and want to print values (why?) but the field it try to print is not marked for read f2.t1.test (why?).

            sanja Oleksandr Byelkin added a comment - Situation is like this: Item_field::print() see that field belongs to constant table and want to print values (why?) but the field it try to print is not marked for read f2.t1.test (why?).
            sanja Oleksandr Byelkin added a comment - - edited

            Here is what is already printed before the crash:

            select 6 AS `f1` from  <materialize> (select `test`.`t2`.`f3` from `test`.`t2` having (`test`.`t2`.`f3` >= 8)) semi join (`test`.`t2`) where ((`test`.`t2`.`f3` = 6) and (

            and probably field is not marked for write because of materialization (not sure yet

            sanja Oleksandr Byelkin added a comment - - edited Here is what is already printed before the crash: select 6 AS `f1` from <materialize> (select `test`.`t2`.`f3` from `test`.`t2` having (`test`.`t2`.`f3` >= 8)) semi join (`test`.`t2`) where ((`test`.`t2`.`f3` = 6) and ( and probably field is not marked for write because of materialization (not sure yet
            sanja Oleksandr Byelkin added a comment - - edited

            It is strange that field has index 1 (i.e. second field) when the field is really first and first field is allowed to read:

            (gdb) p *table->read_set->bitmap
            $5 = 1
            (gdb) p this->field_index
            $6 = 1

            Especially because we see that 6 was already printed in SELECT and it is the same field

            It is really f2 field that is left expression of IN so second field is correct and it is just not marked for read.

            sanja Oleksandr Byelkin added a comment - - edited It is strange that field has index 1 (i.e. second field) when the field is really first and first field is allowed to read: (gdb) p *table->read_set->bitmap $5 = 1 (gdb) p this->field_index $6 = 1 Especially because we see that 6 was already printed in SELECT and it is the same field It is really f2 field that is left expression of IN so second field is correct and it is just not marked for read.

            What it should be if switch off the assertion:
            id select_type table type possible_keys key key_len ref rows filtered Extra
            1 PRIMARY t1 system NULL NULL NULL NULL 1 100.00
            1 PRIMARY <subquery4> eq_ref distinct_key distinct_key 4 test.t1.f2 1 100.00
            1 PRIMARY t2 ALL NULL NULL NULL NULL 2 100.00 Using where; FirstMatch(<subquery4>); Using join buffer (flat, BNL join)
            4 MATERIALIZED t2 ALL NULL NULL NULL NULL 2 100.00
            Warnings:
            Note 1276 Field or reference 'f2' of SELECT #3 was resolved in SELECT #1
            Note 1003 select 6 AS `f1` from <materialize> (select `test`.`t2`.`f3` from `test`.`t2` having (`test`.`t2`.`f3` >= 8)) semi join (`test`.`t2`) where ((`test`.`t2`.`f3` = 6) and (9 = `<subquery4>`.`f3`))

            sanja Oleksandr Byelkin added a comment - What it should be if switch off the assertion: id select_type table type possible_keys key key_len ref rows filtered Extra 1 PRIMARY t1 system NULL NULL NULL NULL 1 100.00 1 PRIMARY <subquery4> eq_ref distinct_key distinct_key 4 test.t1.f2 1 100.00 1 PRIMARY t2 ALL NULL NULL NULL NULL 2 100.00 Using where; FirstMatch(<subquery4>); Using join buffer (flat, BNL join) 4 MATERIALIZED t2 ALL NULL NULL NULL NULL 2 100.00 Warnings: Note 1276 Field or reference 'f2' of SELECT #3 was resolved in SELECT #1 Note 1003 select 6 AS `f1` from <materialize> (select `test`.`t2`.`f3` from `test`.`t2` having (`test`.`t2`.`f3` >= 8)) semi join (`test`.`t2`) where ((`test`.`t2`.`f3` = 6) and (9 = `<subquery4>`.`f3`))

            Without debug output or EXPLAIN value of f2.t1 is really not used.

            sanja Oleksandr Byelkin added a comment - Without debug output or EXPLAIN value of f2.t1 is really not used.

            (gdb) p all_tables->next_global->table_name
            $5 = 0x7fffed72c4d8 "t1"
            (gdb) p all_tables->next_global->table->s->path
            $6 =

            {str = 0x7fffed471360 "./test/t1", length = 9}

            (gdb) p all_tables->next_global->table->read_set
            $7 = (MY_BITMAP *) 0x7fffed4ad980
            (gdb) p all_tables->next_global->table->read_set->bitmap
            $8 = (my_bitmap_map *) 0x7fffef7c7908
            (gdb) p all_tables->next_global->table->read_set->bitmap[0]
            $9 = 0
            (gdb) watch *((my_bitmap_map *) 0x7fffef7c7908)
            Hardware watchpoint 2: *((my_bitmap_map *) 0x7fffef7c7908)
            (gdb)

            First all read_set set all bits by including *
            then all bits reset by SELECT_LEX::update_used_tables()
            then again both set by walking through fields
            then again both reset in SELECT_LEX::update_used_tables() (yet another one optimize)
            but only 0 bit is set back.

            sanja Oleksandr Byelkin added a comment - (gdb) p all_tables->next_global->table_name $5 = 0x7fffed72c4d8 "t1" (gdb) p all_tables->next_global->table->s->path $6 = {str = 0x7fffed471360 "./test/t1", length = 9} (gdb) p all_tables->next_global->table->read_set $7 = (MY_BITMAP *) 0x7fffed4ad980 (gdb) p all_tables->next_global->table->read_set->bitmap $8 = (my_bitmap_map *) 0x7fffef7c7908 (gdb) p all_tables->next_global->table->read_set->bitmap [0] $9 = 0 (gdb) watch *((my_bitmap_map *) 0x7fffef7c7908) Hardware watchpoint 2: *((my_bitmap_map *) 0x7fffef7c7908) (gdb) First all read_set set all bits by including * then all bits reset by SELECT_LEX::update_used_tables() then again both set by walking through fields then again both reset in SELECT_LEX::update_used_tables() (yet another one optimize) but only 0 bit is set back.
            sanja Oleksandr Byelkin added a comment - - edited

            join->conds in first call of used tables update and on second one are different. Second contain no field we are looking for, so it is not updated.

            2 calls of SELECT_LEX::update_used_tables() :

            (gdb) p join
            $2 = (JOIN *) 0x7fffed777088
            (gdb) p this
            $3 = (st_select_lex * const) 0x7fffef4b6168
            (gdb) p this->select_number
            $4 = 1
            (gdb) p dbug_print_item(join->conds)
            $5 = 0x555556d4d4e0 <dbug_item_print_buf> "t1.f1 in (subquery#3)"
            (gdb)

            (gdb) p join
            $6 = (JOIN *) 0x7fffed777088
            (gdb) p this
            $7 = (st_select_lex * const) 0x7fffef4b6168
            (gdb) p this->select_number
            $8 = 1
            (gdb) p dbug_print_item(join->conds)
            $9 = 0x555556d4d4e0 <dbug_item_print_buf> "(1 and 1 and (t1.f1 = t2.f3))"

            sanja Oleksandr Byelkin added a comment - - edited join->conds in first call of used tables update and on second one are different. Second contain no field we are looking for, so it is not updated. 2 calls of SELECT_LEX::update_used_tables() : (gdb) p join $2 = (JOIN *) 0x7fffed777088 (gdb) p this $3 = (st_select_lex * const) 0x7fffef4b6168 (gdb) p this->select_number $4 = 1 (gdb) p dbug_print_item(join->conds) $5 = 0x555556d4d4e0 <dbug_item_print_buf> "t1.f1 in (subquery#3)" (gdb) (gdb) p join $6 = (JOIN *) 0x7fffed777088 (gdb) p this $7 = (st_select_lex * const) 0x7fffef4b6168 (gdb) p this->select_number $8 = 1 (gdb) p dbug_print_item(join->conds) $9 = 0x555556d4d4e0 <dbug_item_print_buf> "(1 and 1 and (t1.f1 = t2.f3))"

            condition transformation above made by
            convert_join_subqueries_to_semijoins -> convert_subq_to_sj
            and first it looks like this:
            (t1.f1 in (subquery#3) and (1 and (t1.f1 = t2.f3)))

            t1.f2 returned by:
            setup_jtbm_semi_joins -> setup_jtbm_semi_joins
            and it converted to
            ((1 and 1 and (t1.f1 = t2.f3)) and ((t1.f2 = `<subquery4>`.f3)))

            but used tables was not updated after this

            sanja Oleksandr Byelkin added a comment - condition transformation above made by convert_join_subqueries_to_semijoins -> convert_subq_to_sj and first it looks like this: (t1.f1 in (subquery#3) and (1 and (t1.f1 = t2.f3))) t1.f2 returned by: setup_jtbm_semi_joins -> setup_jtbm_semi_joins and it converted to ((1 and 1 and (t1.f1 = t2.f3)) and ((t1.f2 = `<subquery4>`.f3))) but used tables was not updated after this

            revision-id: 30a3b97bb321706a0e271268ee30ed62964311a7 (mariadb-10.1.10-24-g30a3b97)
            parent(s): ff8d4009a7743b99c1c13831172b08041a4b272e
            committer: Oleksandr Byelkin
            timestamp: 2016-01-25 21:52:37 +0100
            message:

            MDEV-7827: Assertion `!table || (!table->read_set || bitmap_is_set(table->read_set, field_index))' failed in Field_long::val_str on EXPLAIN EXTENDED

            It looks like printing expression can touch fields which never be calculated normally, so it have no sens to print it by value

            Assert added: a view field should be never print by values (normally view is not optimized and constant tables is not read so we are safe)

            —

            sanja Oleksandr Byelkin added a comment - revision-id: 30a3b97bb321706a0e271268ee30ed62964311a7 (mariadb-10.1.10-24-g30a3b97) parent(s): ff8d4009a7743b99c1c13831172b08041a4b272e committer: Oleksandr Byelkin timestamp: 2016-01-25 21:52:37 +0100 message: MDEV-7827 : Assertion `!table || (!table->read_set || bitmap_is_set(table->read_set, field_index))' failed in Field_long::val_str on EXPLAIN EXTENDED It looks like printing expression can touch fields which never be calculated normally, so it have no sens to print it by value Assert added: a view field should be never print by values (normally view is not optimized and constant tables is not read so we are safe) —

            An alternative fix:

            diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc
            index 898e3ae..c7be909 100644
            --- a/sql/sql_lex.cc
            +++ b/sql/sql_lex.cc
            @@ -3916,6 +3916,19 @@ void SELECT_LEX::update_used_tables()
                   tl->on_expr->update_used_tables();
                   tl->on_expr->walk(&Item::eval_not_null_tables, 0, NULL);
                 }
            +    /* 
            +      - There is no need to check sj_on_expr, because merged semi-joins inject
            +        sj_on_expr into the parent's WHERE clase.
            +      - For non-merged semi-joins (aka JTBMs), we need to check their
            +        left_expr. There is no need to check the rest of the subselect, we know
            +        it is uncorrelated and so cannot refer to any tables in this select.
            +    */
            +    if (tl->jtbm_subselect)
            +    {
            +      Item *left_expr= tl->jtbm_subselect->left_expr;
            +      left_expr->walk(&Item::update_table_bitmaps_processor, FALSE, NULL);
            +    }
            +    
                 embedding= tl->embedding;
                 while (embedding)
                 {

            It makes the crash go away.
            I am not sure about what is exactly the reason I have to call Item::update_table_bitmaps_processor. I first tried update_used_tables() and that didn't work : as soon as Item_ref saw that it refers to upper subselect, it stopped doing anything.

            sanja, we need to discuss this.

            psergei Sergei Petrunia added a comment - An alternative fix: diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 898e3ae..c7be909 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -3916,6 +3916,19 @@ void SELECT_LEX::update_used_tables() tl->on_expr->update_used_tables(); tl->on_expr->walk(&Item::eval_not_null_tables, 0, NULL); } + /* + - There is no need to check sj_on_expr, because merged semi-joins inject + sj_on_expr into the parent's WHERE clase. + - For non-merged semi-joins (aka JTBMs), we need to check their + left_expr. There is no need to check the rest of the subselect, we know + it is uncorrelated and so cannot refer to any tables in this select. + */ + if (tl->jtbm_subselect) + { + Item *left_expr= tl->jtbm_subselect->left_expr; + left_expr->walk(&Item::update_table_bitmaps_processor, FALSE, NULL); + } + embedding= tl->embedding; while (embedding) { It makes the crash go away. I am not sure about what is exactly the reason I have to call Item::update_table_bitmaps_processor. I first tried update_used_tables() and that didn't work : as soon as Item_ref saw that it refers to upper subselect, it stopped doing anything. sanja , we need to discuss this.

            We've agreed that the last version of the fix is correct and should be pushed.

            psergei Sergei Petrunia added a comment - We've agreed that the last version of the fix is correct and should be pushed.

            People

              sanja Oleksandr Byelkin
              elenst Elena Stepanova
              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.