Commit 51ce56e6 authored by unknown's avatar unknown

Merge bk-internal.mysql.com:/home/bk/mysql-5.0

into  mysql.com:/opt/local/work/mysql-5.0-root

parents 859ccd3b 91c97a76
...@@ -681,3 +681,60 @@ execute stmt; ...@@ -681,3 +681,60 @@ execute stmt;
execute stmt; execute stmt;
deallocate prepare stmt; deallocate prepare stmt;
drop table t1; drop table t1;
create table t1 (
id int(11) unsigned not null primary key auto_increment,
partner_id varchar(35) not null,
t1_status_id int(10) unsigned
);
insert into t1 values ("1", "partner1", "10"), ("2", "partner2", "10"),
("3", "partner3", "10"), ("4", "partner4", "10");
create table t2 (
id int(11) unsigned not null default '0',
t1_line_id int(11) unsigned not null default '0',
article_id varchar(20),
sequence int(11) not null default '0',
primary key (id,t1_line_id)
);
insert into t2 values ("1", "1", "sup", "0"), ("2", "1", "sup", "1"),
("2", "2", "sup", "2"), ("2", "3", "sup", "3"),
("2", "4", "imp", "4"), ("3", "1", "sup", "0"),
("4", "1", "sup", "0");
create table t3 (
id int(11) not null default '0',
preceeding_id int(11) not null default '0',
primary key (id,preceeding_id)
);
create table t4 (
user_id varchar(50) not null,
article_id varchar(20) not null,
primary key (user_id,article_id)
);
insert into t4 values("nicke", "imp");
prepare stmt from
'select distinct t1.partner_id
from t1 left join t3 on t1.id = t3.id
left join t1 pp on pp.id = t3.preceeding_id
where
exists (
select *
from t2 as pl_inner
where pl_inner.id = t1.id
and pl_inner.sequence <= (
select min(sequence) from t2 pl_seqnr
where pl_seqnr.id = t1.id
)
and exists (
select * from t4
where t4.article_id = pl_inner.article_id
and t4.user_id = ?
)
)
and t1.id = ?
group by t1.id
having count(pp.id) = 0';
set @user_id = 'nicke';
set @id = '2';
execute stmt using @user_id, @id;
partner_id
execute stmt using @user_id, @id;
partner_id
...@@ -705,3 +705,71 @@ execute stmt; ...@@ -705,3 +705,71 @@ execute stmt;
execute stmt; execute stmt;
deallocate prepare stmt; deallocate prepare stmt;
drop table t1; drop table t1;
#
# Bug#11458 "Prepared statement with subselects return random data":
# drop PARAM_TABLE_BIT from the list of tables used by a subquery
#
create table t1 (
id int(11) unsigned not null primary key auto_increment,
partner_id varchar(35) not null,
t1_status_id int(10) unsigned
);
insert into t1 values ("1", "partner1", "10"), ("2", "partner2", "10"),
("3", "partner3", "10"), ("4", "partner4", "10");
create table t2 (
id int(11) unsigned not null default '0',
t1_line_id int(11) unsigned not null default '0',
article_id varchar(20),
sequence int(11) not null default '0',
primary key (id,t1_line_id)
);
insert into t2 values ("1", "1", "sup", "0"), ("2", "1", "sup", "1"),
("2", "2", "sup", "2"), ("2", "3", "sup", "3"),
("2", "4", "imp", "4"), ("3", "1", "sup", "0"),
("4", "1", "sup", "0");
create table t3 (
id int(11) not null default '0',
preceeding_id int(11) not null default '0',
primary key (id,preceeding_id)
);
create table t4 (
user_id varchar(50) not null,
article_id varchar(20) not null,
primary key (user_id,article_id)
);
insert into t4 values("nicke", "imp");
prepare stmt from
'select distinct t1.partner_id
from t1 left join t3 on t1.id = t3.id
left join t1 pp on pp.id = t3.preceeding_id
where
exists (
select *
from t2 as pl_inner
where pl_inner.id = t1.id
and pl_inner.sequence <= (
select min(sequence) from t2 pl_seqnr
where pl_seqnr.id = t1.id
)
and exists (
select * from t4
where t4.article_id = pl_inner.article_id
and t4.user_id = ?
)
)
and t1.id = ?
group by t1.id
having count(pp.id) = 0';
set @user_id = 'nicke';
set @id = '2';
execute stmt using @user_id, @id;
execute stmt using @user_id, @id;
deallocate prepare stmt;
drop table t1, t2, t3, t4;
...@@ -1701,6 +1701,7 @@ void Item_param::set_null() ...@@ -1701,6 +1701,7 @@ void Item_param::set_null()
max_length= 0; max_length= 0;
decimals= 0; decimals= 0;
state= NULL_VALUE; state= NULL_VALUE;
item_type= Item::NULL_ITEM;
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
} }
...@@ -2246,33 +2247,6 @@ bool Item_param::convert_str_value(THD *thd) ...@@ -2246,33 +2247,6 @@ bool Item_param::convert_str_value(THD *thd)
return rc; return rc;
} }
bool Item_param::fix_fields(THD *thd, Item **ref)
{
DBUG_ASSERT(fixed == 0);
SELECT_LEX *cursel= (SELECT_LEX *) thd->lex->current_select;
/*
Parameters in a subselect should mark the subselect as not constant
during prepare
*/
if (state == NO_VALUE)
{
/*
SELECT_LEX_UNIT::item set only for subqueries, so test of it presence
can be barrier to stop before derived table SELECT or very outer SELECT
*/
for (; cursel->master_unit()->item;
cursel= cursel->outer_select())
{
Item_subselect *subselect_item= cursel->master_unit()->item;
subselect_item->used_tables_cache|= OUTER_REF_TABLE_BIT;
subselect_item->const_item_cache= 0;
}
}
fixed= 1;
return 0;
}
bool Item_param::basic_const_item() const bool Item_param::basic_const_item() const
{ {
......
...@@ -1039,7 +1039,6 @@ public: ...@@ -1039,7 +1039,6 @@ public:
bool get_time(TIME *tm); bool get_time(TIME *tm);
bool get_date(TIME *tm, uint fuzzydate); bool get_date(TIME *tm, uint fuzzydate);
int save_in_field(Field *field, bool no_conversions); int save_in_field(Field *field, bool no_conversions);
bool fix_fields(THD *, Item **);
void set_null(); void set_null();
void set_int(longlong i, uint32 max_length_arg); void set_int(longlong i, uint32 max_length_arg);
......
...@@ -121,7 +121,6 @@ public: ...@@ -121,7 +121,6 @@ public:
friend class Item_in_optimizer; friend class Item_in_optimizer;
friend bool Item_field::fix_fields(THD *, Item **); friend bool Item_field::fix_fields(THD *, Item **);
friend bool Item_ref::fix_fields(THD *, Item **); friend bool Item_ref::fix_fields(THD *, Item **);
friend bool Item_param::fix_fields(THD *, Item **);
friend void mark_select_range_as_dependent(THD*, friend void mark_select_range_as_dependent(THD*,
st_select_lex*, st_select_lex*, st_select_lex*, st_select_lex*,
Field*, Item*, Item_ident*); Field*, Item*, Item_ident*);
......
...@@ -5212,6 +5212,11 @@ mysql_new_select(LEX *lex, bool move_down) ...@@ -5212,6 +5212,11 @@ mysql_new_select(LEX *lex, bool move_down)
select_lex->init_query(); select_lex->init_query();
select_lex->init_select(); select_lex->init_select();
select_lex->parent_lex= lex; select_lex->parent_lex= lex;
/*
Don't evaluate this subquery during statement prepare even if
it's a constant one. The flag is switched off in the end of
mysql_stmt_prepare.
*/
if (thd->current_arena->is_stmt_prepare()) if (thd->current_arena->is_stmt_prepare())
select_lex->uncacheable|= UNCACHEABLE_PREPARE; select_lex->uncacheable|= UNCACHEABLE_PREPARE;
if (move_down) if (move_down)
......
...@@ -1825,7 +1825,10 @@ bool mysql_stmt_prepare(THD *thd, char *packet, uint packet_length, ...@@ -1825,7 +1825,10 @@ bool mysql_stmt_prepare(THD *thd, char *packet, uint packet_length,
void init_stmt_after_parse(THD *thd, LEX *lex) void init_stmt_after_parse(THD *thd, LEX *lex)
{ {
SELECT_LEX *sl= lex->all_selects_list; SELECT_LEX *sl= lex->all_selects_list;
/*
Switch off a temporary flag that prevents evaluation of
subqueries in statement prepare.
*/
for (; sl; sl= sl->next_select_in_list()) for (; sl; sl= sl->next_select_in_list())
sl->uncacheable&= ~UNCACHEABLE_PREPARE; sl->uncacheable&= ~UNCACHEABLE_PREPARE;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment