mirror of
https://github.com/MariaDB/server.git
synced 2025-07-30 16:24:05 +03:00
Merge mysql.com:/opt/local/work/mysql-4.1-11458
into mysql.com:/opt/local/work/mysql-5.0-root sql/mysql_priv.h: Auto merged sql/sql_lex.h: Auto merged mysql-test/r/ps.result: Manual merge. mysql-test/t/ps.test: Manual merge. sql/item.cc: Manual merge. sql/item.h: Manual merge. sql/item_subselect.h: Manual merge. sql/sql_parse.cc: Manual merge. sql/sql_prepare.cc: Manual merge.
This commit is contained in:
@ -681,3 +681,60 @@ execute stmt;
|
||||
execute stmt;
|
||||
deallocate prepare stmt;
|
||||
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;
|
||||
execute stmt;
|
||||
deallocate prepare stmt;
|
||||
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;
|
||||
|
28
sql/item.cc
28
sql/item.cc
@ -1701,6 +1701,7 @@ void Item_param::set_null()
|
||||
max_length= 0;
|
||||
decimals= 0;
|
||||
state= NULL_VALUE;
|
||||
item_type= Item::NULL_ITEM;
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
|
||||
@ -2246,33 +2247,6 @@ bool Item_param::convert_str_value(THD *thd)
|
||||
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
|
||||
{
|
||||
|
@ -1039,7 +1039,6 @@ public:
|
||||
bool get_time(TIME *tm);
|
||||
bool get_date(TIME *tm, uint fuzzydate);
|
||||
int save_in_field(Field *field, bool no_conversions);
|
||||
bool fix_fields(THD *, Item **);
|
||||
|
||||
void set_null();
|
||||
void set_int(longlong i, uint32 max_length_arg);
|
||||
|
@ -121,7 +121,6 @@ public:
|
||||
friend class Item_in_optimizer;
|
||||
friend bool Item_field::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*,
|
||||
st_select_lex*, st_select_lex*,
|
||||
Field*, Item*, Item_ident*);
|
||||
|
@ -5212,6 +5212,11 @@ mysql_new_select(LEX *lex, bool move_down)
|
||||
select_lex->init_query();
|
||||
select_lex->init_select();
|
||||
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())
|
||||
select_lex->uncacheable|= UNCACHEABLE_PREPARE;
|
||||
if (move_down)
|
||||
|
@ -1825,7 +1825,10 @@ bool mysql_stmt_prepare(THD *thd, char *packet, uint packet_length,
|
||||
void init_stmt_after_parse(THD *thd, LEX *lex)
|
||||
{
|
||||
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())
|
||||
sl->uncacheable&= ~UNCACHEABLE_PREPARE;
|
||||
}
|
||||
|
Reference in New Issue
Block a user