#At file:///work/bzr_trees/37870-bug-5.1-bugteam/
2694 Evgeny Potemkin 2008-11-05
Bug#37870: Usage of uninitialized value caused failed assertion.
The convert_constant_item function converts a constant to integer using
field for condition like 'field = a_constant'. In some cases the
convert_constant_item is called for a subquery when outer select is already
being executed, so convert_constant_item saves field's value to prevent its
corruption. For EXPLAIN and at the prepare phase field's value isn't
initialized yet, thus when convert_constant_item tries to restore saved
value it fails assertion.
modified:
mysql-test/r/explain.result
mysql-test/t/explain.test
sql/item_cmpfunc.cc
sql/sql_select.cc
sql/sql_select.h
per-file messages:
mysql-test/r/explain.result
Added a test case for the bug#37870.
mysql-test/t/explain.test
Added a test case for the bug#37870.
sql/item_cmpfunc.cc
Bug#37870: Usage of uninitialized value caused failed assertion.
Now the convert_constant_item doesn't save/restore field's value for EXPLAIN
and at the prepare phase since it's not initialized. Outer constants values
are always saved.
sql/sql_select.cc
Bug#37870: Usage of uninitialized value caused failed assertion.
JOIN::exec now sets JOIN::executing flag.
sql/sql_select.h
Bug#37870: Usage of uninitialized value caused failed assertion.
Added flag called executing to the JOIN class. It's used to indicate that the
JOIN is being executed.
=== modified file 'mysql-test/r/explain.result'
--- a/mysql-test/r/explain.result 2008-10-27 12:04:51 +0000
+++ b/mysql-test/r/explain.result 2008-11-05 13:09:48 +0000
@@ -158,15 +158,27 @@ DROP TABLE t1,t2;
#
# Bug#37870: Usage of uninitialized value caused failed assertion.
#
-create table t1 (dt datetime not null);
+create table t1 (dt datetime not null, t time not null);
create table t2 (dt datetime not null);
-insert into t1 values ('2001-01-01 1:1:1'), ('2001-01-01 1:1:1');
+insert into t1 values ('2001-01-01 1:1:1', '1:1:1'),
+('2001-01-01 1:1:1', '1:1:1');
insert into t2 values ('2001-01-01 1:1:1'), ('2001-01-01 1:1:1');
flush tables;
EXPLAIN SELECT OUTR.dt FROM t1 AS OUTR WHERE OUTR.dt IN (SELECT INNR.dt FROM t2 AS INNR WHERE OUTR.dt IS NULL );
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY OUTR ALL NULL NULL NULL NULL 2 Using where
2 DEPENDENT SUBQUERY INNR ALL NULL NULL NULL NULL 2 Using where
+flush tables;
SELECT OUTR.dt FROM t1 AS OUTR WHERE OUTR.dt IN (SELECT INNR.dt FROM t2 AS INNR WHERE OUTR.dt IS NULL );
dt
+flush tables;
+EXPLAIN SELECT OUTR.dt FROM t1 AS OUTR WHERE OUTR.dt IN ( SELECT INNR.dt FROM t2 AS INNR WHERE OUTR.t < '2005-11-13 7:41:31' );
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY OUTR ALL NULL NULL NULL NULL 2 Using where
+2 DEPENDENT SUBQUERY INNR ALL NULL NULL NULL NULL 2 Using where
+flush tables;
+SELECT OUTR.dt FROM t1 AS OUTR WHERE OUTR.dt IN ( SELECT INNR.dt FROM t2 AS INNR WHERE OUTR.t < '2005-11-13 7:41:31' );
+dt
+2001-01-01 01:01:01
+2001-01-01 01:01:01
drop tables t1, t2;
=== modified file 'mysql-test/t/explain.test'
--- a/mysql-test/t/explain.test 2008-10-27 12:04:51 +0000
+++ b/mysql-test/t/explain.test 2008-11-05 13:09:48 +0000
@@ -126,13 +126,19 @@ DROP TABLE t1,t2;
--echo #
--echo # Bug#37870: Usage of uninitialized value caused failed assertion.
--echo #
-create table t1 (dt datetime not null);
+create table t1 (dt datetime not null, t time not null);
create table t2 (dt datetime not null);
-insert into t1 values ('2001-01-01 1:1:1'), ('2001-01-01 1:1:1');
+insert into t1 values ('2001-01-01 1:1:1', '1:1:1'),
+('2001-01-01 1:1:1', '1:1:1');
insert into t2 values ('2001-01-01 1:1:1'), ('2001-01-01 1:1:1');
flush tables;
EXPLAIN SELECT OUTR.dt FROM t1 AS OUTR WHERE OUTR.dt IN (SELECT INNR.dt FROM t2 AS INNR WHERE OUTR.dt IS NULL );
+flush tables;
SELECT OUTR.dt FROM t1 AS OUTR WHERE OUTR.dt IN (SELECT INNR.dt FROM t2 AS INNR WHERE OUTR.dt IS NULL );
+flush tables;
+EXPLAIN SELECT OUTR.dt FROM t1 AS OUTR WHERE OUTR.dt IN ( SELECT INNR.dt FROM t2 AS INNR WHERE OUTR.t < '2005-11-13 7:41:31' );
+flush tables;
+SELECT OUTR.dt FROM t1 AS OUTR WHERE OUTR.dt IN ( SELECT INNR.dt FROM t2 AS INNR WHERE OUTR.t < '2005-11-13 7:41:31' );
drop tables t1, t2;
# End of 5.0 tests.
=== modified file 'sql/item_cmpfunc.cc'
--- a/sql/item_cmpfunc.cc 2008-10-27 16:19:26 +0000
+++ b/sql/item_cmpfunc.cc 2008-11-05 13:09:48 +0000
@@ -415,9 +415,13 @@ static bool convert_constant_item(THD *t
/*
Store the value of the field/constant if it references an outer field because
the call to save_in_field below overrides that value.
- Don't save value of the field for EXPLAIN since it's not initialized.
+ Don't save field value of the field for EXPLAIN and at the prepare phase
+ since it's not initialized. Outer constants values are always saved.
*/
- if (field_item->depended_from && (!thd->lex->describe || field_item->const_item()))
+ if (field_item->depended_from &&
+ ((!thd->lex->describe &&
+ field_item->depended_from->join->executing) ||
+ field_item->const_item()))
orig_field_val= field->val_int();
if (!(*item)->is_null() && !(*item)->save_in_field(field, 1))
{
@@ -428,7 +432,10 @@ static bool convert_constant_item(THD *t
result= 1; // Item was replaced
}
/* Restore the original field value. */
- if (field_item->depended_from && (!thd->lex->describe || field_item->const_item()))
+ if (field_item->depended_from &&
+ ((!thd->lex->describe &&
+ field_item->depended_from->join->executing) ||
+ field_item->const_item()))
{
result= field->store(orig_field_val, TRUE);
/* orig_field_val must be a valid value that can be restored back. */
=== modified file 'sql/sql_select.cc'
--- a/sql/sql_select.cc 2008-11-03 10:40:58 +0000
+++ b/sql/sql_select.cc 2008-11-05 13:09:48 +0000
@@ -1690,6 +1690,7 @@ JOIN::exec()
thd->examined_row_count= 0;
DBUG_VOID_RETURN;
}
+ executing= TRUE;
/*
Don't reset the found rows count if there're no tables as
FOUND_ROWS() may be called. Never reset the examined row count here.
=== modified file 'sql/sql_select.h'
--- a/sql/sql_select.h 2008-10-24 12:50:59 +0000
+++ b/sql/sql_select.h 2008-11-05 13:09:48 +0000
@@ -391,7 +391,7 @@ public:
bool union_part; ///< this subselect is part of union
bool optimized; ///< flag to avoid double optimization in EXPLAIN
-
+ bool executing; ///< JOIN execution is in progress (JOIN::exec is called)
/*
storage for caching buffers allocated during query execution.
These buffers allocations need to be cached as the thread memory pool is
@@ -455,6 +455,7 @@ public:
ref_pointer_array_size= 0;
zero_result_cause= 0;
optimized= 0;
+ executing= 0;
cond_equal= 0;
group_optimized_away= 0;
| Thread |
|---|
| • bzr commit into mysql-5.1 branch (epotemkin:2694) Bug#37870 | Evgeny Potemkin | 5 Nov |