[MDEV-7827] Assertion `!table || (!table->read_set || bitmap_is_set(table->read_set, field_index))' failed in Field_long::val_str on EXPLAIN EXTENDED Created: 2015-03-24  Updated: 2021-03-05  Resolved: 2016-02-05

Status: Closed
Project: MariaDB Server
Component/s: Admin statements, Data Manipulation - Subquery
Affects Version/s: 5.3.12, 5.5, 10.0, 10.1
Fix Version/s: 5.5.48, 10.0.24, 10.1.12

Type: Bug Priority: Major
Reporter: Elena Stepanova Assignee: Oleksandr Byelkin
Resolution: Fixed Votes: 0
Labels: verified

Issue Links:
Relates
relates to MDEV-24658 Assertion `marked_for_read()' failed ... Confirmed

 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



 Comments   
Comment by Daniel Black [ 2015-10-01 ]

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

Comment by Oleksandr Byelkin [ 2016-01-24 ]

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?).

Comment by Oleksandr Byelkin [ 2016-01-24 ]

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

Comment by Oleksandr Byelkin [ 2016-01-24 ]

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.

Comment by Oleksandr Byelkin [ 2016-01-24 ]

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`))

Comment by Oleksandr Byelkin [ 2016-01-24 ]

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

Comment by Oleksandr Byelkin [ 2016-01-24 ]

(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.

Comment by Oleksandr Byelkin [ 2016-01-25 ]

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))"

Comment by Oleksandr Byelkin [ 2016-01-25 ]

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

Comment by Oleksandr Byelkin [ 2016-01-25 ]

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)

Comment by Sergei Petrunia [ 2016-01-27 ]

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.

Comment by Sergei Petrunia [ 2016-02-04 ]

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

Generated at Thu Feb 08 07:22:34 UTC 2024 using Jira 8.20.16#820016-sha1:9d11dbea5f4be3d4cc21f03a88dd11d8c8687422.