Merge sanja.is.com.ua:/home/bell/mysql/bk/mysql-4.1

into sanja.is.com.ua:/home/bell/mysql/bk/work-ps2-4.1


sql/table.h:
  Auto merged
This commit is contained in:
unknown 2004-04-05 11:16:44 +03:00
commit 036656e74b
23 changed files with 235 additions and 108 deletions

View file

@ -435,7 +435,7 @@ drop temporary table t1;
create table t1 select a from t1 union select a from t2; create table t1 select a from t1 union select a from t2;
ERROR HY000: You can't specify target table 't1' for update in FROM clause ERROR HY000: You can't specify target table 't1' for update in FROM clause
select a from t1 union select a from t2 order by t2.a; select a from t1 union select a from t2 order by t2.a;
ERROR 42S22: Unknown column 't2.a' in 'ORDER BY' ERROR 42S02: Unknown table 't2' in order clause
drop table t1,t2; drop table t1,t2;
select length(version()) > 1 as `*` UNION select 2; select length(version()) > 1 as `*` UNION select 2;
* *

View file

@ -251,7 +251,7 @@ create temporary table t1 select a from t1 union select a from t2;
drop temporary table t1; drop temporary table t1;
--error 1093 --error 1093
create table t1 select a from t1 union select a from t2; create table t1 select a from t1 union select a from t2;
--error 1054 --error 1109
select a from t1 union select a from t2 order by t2.a; select a from t1 union select a from t2 order by t2.a;
drop table t1,t2; drop table t1,t2;

View file

@ -713,7 +713,7 @@ bool Item_param::get_time(TIME *res)
double Item_param::val() double Item_param::val()
{ {
DBUG_ASSERT(fixed == 1); DBUG_ASSERT(value_is_set == 1);
int err; int err;
switch (item_result_type) { switch (item_result_type) {
case STRING_RESULT: case STRING_RESULT:
@ -729,7 +729,7 @@ double Item_param::val()
longlong Item_param::val_int() longlong Item_param::val_int()
{ {
DBUG_ASSERT(fixed == 1); DBUG_ASSERT(value_is_set == 1);
int err; int err;
switch (item_result_type) { switch (item_result_type) {
case STRING_RESULT: case STRING_RESULT:
@ -746,7 +746,7 @@ longlong Item_param::val_int()
String *Item_param::val_str(String* str) String *Item_param::val_str(String* str)
{ {
DBUG_ASSERT(fixed == 1); DBUG_ASSERT(value_is_set == 1);
switch (item_result_type) { switch (item_result_type) {
case INT_RESULT: case INT_RESULT:
str->set(int_value, &my_charset_bin); str->set(int_value, &my_charset_bin);
@ -766,7 +766,7 @@ String *Item_param::val_str(String* str)
String *Item_param::query_val_str(String* str) String *Item_param::query_val_str(String* str)
{ {
DBUG_ASSERT(fixed == 1); DBUG_ASSERT(value_is_set == 1);
switch (item_result_type) { switch (item_result_type) {
case INT_RESULT: case INT_RESULT:
case REAL_RESULT: case REAL_RESULT:

View file

@ -991,14 +991,11 @@ public:
/* Some usefull inline functions */ /* Some usefull inline functions */
inline Item *and_conds(THD *thd, Item *a, Item *b, TABLE_LIST *tables) inline Item *and_conds(Item *a, Item *b)
{ {
if (!b) return a; if (!b) return a;
if (!a) return b; if (!a) return b;
Item *cond= new Item_cond_and(a,b); return new Item_cond_and(a, b);
if (cond)
cond->fix_fields(thd, tables, &cond);
return cond;
} }
Item *and_expressions(Item *a, Item *b, Item **org_item); Item *and_expressions(Item *a, Item *b, Item **org_item);

View file

@ -24,8 +24,8 @@
#include "mysql_priv.h" #include "mysql_priv.h"
Item_sum::Item_sum(List<Item> &list) Item_sum::Item_sum(List<Item> &list)
:args_copy(0), arg_count(list.elements)
{ {
arg_count=list.elements;
if ((args=(Item**) sql_alloc(sizeof(Item*)*arg_count))) if ((args=(Item**) sql_alloc(sizeof(Item*)*arg_count)))
{ {
uint i=0; uint i=0;
@ -43,18 +43,51 @@ Item_sum::Item_sum(List<Item> &list)
// Constructor used in processing select with temporary tebles // Constructor used in processing select with temporary tebles
Item_sum::Item_sum(THD *thd, Item_sum *item): Item_sum::Item_sum(THD *thd, Item_sum *item):
Item_result_field(thd, item), quick_group(item->quick_group) Item_result_field(thd, item), arg_count(item->arg_count),
quick_group(item->quick_group)
{ {
arg_count= item->arg_count;
if (arg_count <= 2) if (arg_count <= 2)
args=tmp_args; args=tmp_args;
else else
if (!(args=(Item**) sql_alloc(sizeof(Item*)*arg_count))) if (!(args= (Item**) thd->alloc(sizeof(Item*)*arg_count)))
return; return;
for (uint i= 0; i < arg_count; i++) memcpy(args, item->args, sizeof(Item*)*arg_count);
args[i]= item->args[i]; if (item->args_copy != 0)
save_args(thd);
else
args_copy= 0;
} }
/*
Save copy of arguments if we are prepare prepared statement
(arguments can be rewritten in get_tmp_table_item())
SYNOPSIS
Item_sum::save_args_for_prepared_statements()
thd - thread handler
RETURN
0 - OK
1 - Error
*/
bool Item_sum::save_args_for_prepared_statements(THD *thd)
{
if (thd->current_statement)
return save_args(thd->current_statement);
return 0;
}
bool Item_sum::save_args(Statement* stmt)
{
if (!(args_copy= (Item**) stmt->alloc(sizeof(Item*)*arg_count)))
return 1;
memcpy(args_copy, args, sizeof(Item*)*arg_count);
return 0;
}
void Item_sum::mark_as_sum_func() void Item_sum::mark_as_sum_func()
{ {
current_thd->lex->current_select->with_sum_func= 1; current_thd->lex->current_select->with_sum_func= 1;
@ -62,6 +95,17 @@ void Item_sum::mark_as_sum_func()
} }
void Item_sum::cleanup()
{
DBUG_ENTER("Item_sum::cleanup");
Item_result_field::cleanup();
if (args_copy != 0)
memcpy(args, args_copy, sizeof(Item*)*arg_count);
result_field=0;
DBUG_VOID_RETURN;
}
void Item_sum::make_field(Send_field *tmp_field) void Item_sum::make_field(Send_field *tmp_field)
{ {
if (args[0]->type() == Item::FIELD_ITEM && keep_field_type()) if (args[0]->type() == Item::FIELD_ITEM && keep_field_type())
@ -165,6 +209,10 @@ bool
Item_sum_num::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) Item_sum_num::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
{ {
DBUG_ASSERT(fixed == 0); DBUG_ASSERT(fixed == 0);
if (save_args_for_prepared_statements(thd))
return 1;
if (!thd->allow_sum_func) if (!thd->allow_sum_func)
{ {
my_error(ER_INVALID_GROUP_FUNC_USE,MYF(0)); my_error(ER_INVALID_GROUP_FUNC_USE,MYF(0));
@ -195,6 +243,10 @@ bool
Item_sum_hybrid::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) Item_sum_hybrid::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
{ {
DBUG_ASSERT(fixed == 0); DBUG_ASSERT(fixed == 0);
if (save_args_for_prepared_statements(thd))
return 1;
Item *item= args[0]; Item *item= args[0];
if (!thd->allow_sum_func) if (!thd->allow_sum_func)
{ {
@ -1131,15 +1183,6 @@ void Item_sum_count_distinct::cleanup()
} }
bool Item_sum_count_distinct::fix_fields(THD *thd, TABLE_LIST *tables,
Item **ref)
{
DBUG_ASSERT(fixed == 0);
if (Item_sum_num::fix_fields(thd, tables, ref))
return 1;
return 0;
}
/* This is used by rollup to create a separate usable copy of the function */ /* This is used by rollup to create a separate usable copy of the function */
void Item_sum_count_distinct::make_unique() void Item_sum_count_distinct::make_unique()
@ -1705,6 +1748,11 @@ void Item_func_group_concat::cleanup()
{ {
DBUG_ENTER("Item_func_group_concat::cleanup"); DBUG_ENTER("Item_func_group_concat::cleanup");
Item_sum::cleanup(); Item_sum::cleanup();
/* fix order list */
for (uint i= 0; i < arg_count_order ; i++)
order[i]->item= &order[i]->item_ptr;
/* /*
Free table and tree if they belong to this item (if item have not pointer Free table and tree if they belong to this item (if item have not pointer
to original item from which was made copy => it own its objects ) to original item from which was made copy => it own its objects )
@ -1821,6 +1869,10 @@ bool
Item_func_group_concat::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) Item_func_group_concat::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
{ {
DBUG_ASSERT(fixed == 0); DBUG_ASSERT(fixed == 0);
if (save_args_for_prepared_statements(thd))
return 1;
uint i; /* for loop variable */ uint i; /* for loop variable */
if (!thd->allow_sum_func) if (!thd->allow_sum_func)

View file

@ -32,40 +32,32 @@ public:
UDF_SUM_FUNC, GROUP_CONCAT_FUNC UDF_SUM_FUNC, GROUP_CONCAT_FUNC
}; };
Item **args,*tmp_args[2]; Item **args, *tmp_args[2];
Item **args_copy; /* copy of arguments for PS */
uint arg_count; uint arg_count;
bool quick_group; /* If incremental update of fields */ bool quick_group; /* If incremental update of fields */
void mark_as_sum_func(); void mark_as_sum_func();
Item_sum() : arg_count(0),quick_group(1) Item_sum() :args_copy(0), arg_count(0), quick_group(1)
{ {
mark_as_sum_func(); mark_as_sum_func();
} }
Item_sum(Item *a) :quick_group(1) Item_sum(Item *a)
:args(tmp_args), args_copy(0), arg_count(1), quick_group(1)
{ {
arg_count=1;
args=tmp_args;
args[0]=a; args[0]=a;
mark_as_sum_func(); mark_as_sum_func();
} }
Item_sum( Item *a, Item *b ) :quick_group(1) Item_sum( Item *a, Item *b )
:args(tmp_args), args_copy(0), arg_count(2), quick_group(1)
{ {
arg_count=2;
args=tmp_args;
args[0]=a; args[1]=b; args[0]=a; args[1]=b;
mark_as_sum_func(); mark_as_sum_func();
} }
Item_sum(List<Item> &list); Item_sum(List<Item> &list);
//Copy constructor, need to perform subselects with temporary tables //Copy constructor, need to perform subselects with temporary tables
Item_sum(THD *thd, Item_sum *item); Item_sum(THD *thd, Item_sum *item);
void cleanup() void cleanup();
{
DBUG_ENTER("Item_sum::cleanup");
Item_result_field::cleanup();
result_field=0;
DBUG_VOID_RETURN;
}
enum Type type() const { return SUM_FUNC_ITEM; } enum Type type() const { return SUM_FUNC_ITEM; }
virtual enum Sumfunctype sum_func () const=0; virtual enum Sumfunctype sum_func () const=0;
inline bool reset() { clear(); return add(); }; inline bool reset() { clear(); return add(); };
@ -100,6 +92,8 @@ public:
virtual bool setup(THD *thd) {return 0;} virtual bool setup(THD *thd) {return 0;}
virtual void make_unique() {} virtual void make_unique() {}
Item *get_tmp_table_item(THD *thd); Item *get_tmp_table_item(THD *thd);
bool save_args_for_prepared_statements(THD *);
bool save_args(Statement* stmt);
bool walk (Item_processor processor, byte *argument); bool walk (Item_processor processor, byte *argument);
}; };
@ -190,7 +184,6 @@ class Item_sum_count_distinct :public Item_sum_int
{ {
TABLE *table; TABLE *table;
table_map used_table_cache; table_map used_table_cache;
bool fix_fields(THD *thd, TABLE_LIST *tables, Item **ref);
uint32 *field_lengths; uint32 *field_lengths;
TMP_TABLE_PARAM *tmp_table_param; TMP_TABLE_PARAM *tmp_table_param;
TREE tree_base; TREE tree_base;
@ -236,7 +229,8 @@ class Item_sum_count_distinct :public Item_sum_int
Item_sum_count_distinct(THD *thd, Item_sum_count_distinct *item) Item_sum_count_distinct(THD *thd, Item_sum_count_distinct *item)
:Item_sum_int(thd, item), table(item->table), :Item_sum_int(thd, item), table(item->table),
used_table_cache(item->used_table_cache), used_table_cache(item->used_table_cache),
field_lengths(item->field_lengths), tmp_table_param(item->tmp_table_param), field_lengths(item->field_lengths),
tmp_table_param(item->tmp_table_param),
tree(item->tree), original(item), key_length(item->key_length), tree(item->tree), original(item), key_length(item->key_length),
max_elements_in_tree(item->max_elements_in_tree), max_elements_in_tree(item->max_elements_in_tree),
rec_offset(item->rec_offset), use_tree(item->use_tree), rec_offset(item->rec_offset), use_tree(item->use_tree),

View file

@ -1698,6 +1698,7 @@ int Load_log_event::exec_event(NET* net, struct st_relay_log_info* rli,
tables.alias = tables.real_name = (char*)table_name; tables.alias = tables.real_name = (char*)table_name;
tables.lock_type = TL_WRITE; tables.lock_type = TL_WRITE;
tables.updating= 1; tables.updating= 1;
tables.non_cachable_table= 1; // just safety for table on stack
// the table will be opened in mysql_load // the table will be opened in mysql_load
if (table_rules_on && !tables_ok(thd, &tables)) if (table_rules_on && !tables_ok(thd, &tables))
{ {

View file

@ -287,6 +287,7 @@ void debug_sync_point(const char* lock_name, uint lock_timeout);
struct st_table; struct st_table;
class THD; class THD;
class Statement;
/* Struct to handle simple linked lists */ /* Struct to handle simple linked lists */

View file

@ -736,6 +736,7 @@ static int fetch_db_tables(THD *thd, MYSQL *mysql, const char *db,
table.db= (char*) db; table.db= (char*) db;
table.real_name= (char*) table_name; table.real_name= (char*) table_name;
table.updating= 1; table.updating= 1;
table.non_cachable_table= 1; // just safety for table on stack
if (!tables_ok(thd, &table)) if (!tables_ok(thd, &table))
continue; continue;
} }

View file

@ -1216,6 +1216,7 @@ static int create_table_from_dump(THD* thd, MYSQL *mysql, const char* db,
bzero((char*) &tables,sizeof(tables)); bzero((char*) &tables,sizeof(tables));
tables.db = (char*)db; tables.db = (char*)db;
tables.alias= tables.real_name= (char*)table_name; tables.alias= tables.real_name= (char*)table_name;
tables.non_cachable_table= 1; // just safety for table on stack
/* Drop the table if 'overwrite' is true */ /* Drop the table if 'overwrite' is true */
if (overwrite && mysql_rm_table(thd,&tables,1,0)) /* drop if exists */ if (overwrite && mysql_rm_table(thd,&tables,1,0)) /* drop if exists */
{ {

View file

@ -172,6 +172,9 @@ my_bool acl_init(THD *org_thd, bool dont_read_acl_tables)
tables[1].next=tables+2; tables[1].next=tables+2;
tables[0].lock_type=tables[1].lock_type=tables[2].lock_type=TL_READ; tables[0].lock_type=tables[1].lock_type=tables[2].lock_type=TL_READ;
tables[0].db=tables[1].db=tables[2].db=thd->db; tables[0].db=tables[1].db=tables[2].db=thd->db;
// just safety for table on stack
tables[0].non_cachable_table= tables[1].non_cachable_table=
tables[2].non_cachable_table= 1;
uint counter; uint counter;
if (open_tables(thd, tables, &counter)) if (open_tables(thd, tables, &counter))
@ -1325,6 +1328,7 @@ static bool update_user_table(THD *thd, const char *host, const char *user,
bzero((char*) &tables,sizeof(tables)); bzero((char*) &tables,sizeof(tables));
tables.alias=tables.real_name=(char*) "user"; tables.alias=tables.real_name=(char*) "user";
tables.db=(char*) "mysql"; tables.db=(char*) "mysql";
tables.non_cachable_table= 1; // just safety for table on stack
#ifdef HAVE_REPLICATION #ifdef HAVE_REPLICATION
/* /*
GRANT and REVOKE are applied the slave in/exclusion rules as they are GRANT and REVOKE are applied the slave in/exclusion rules as they are
@ -1382,6 +1386,7 @@ static bool test_if_create_new_users(THD *thd)
bzero((char*) &tl,sizeof(tl)); bzero((char*) &tl,sizeof(tl));
tl.db= (char*) "mysql"; tl.db= (char*) "mysql";
tl.real_name= (char*) "user"; tl.real_name= (char*) "user";
tl.non_cachable_table= 1; // just safety for table on stack
db_access=acl_get(thd->host, thd->ip, db_access=acl_get(thd->host, thd->ip,
thd->priv_user, tl.db, 0); thd->priv_user, tl.db, 0);
if (!(db_access & INSERT_ACL)) if (!(db_access & INSERT_ACL))
@ -2233,6 +2238,9 @@ int mysql_table_grant(THD *thd, TABLE_LIST *table_list,
? tables+2 : 0); ? tables+2 : 0);
tables[0].lock_type=tables[1].lock_type=tables[2].lock_type=TL_WRITE; tables[0].lock_type=tables[1].lock_type=tables[2].lock_type=TL_WRITE;
tables[0].db=tables[1].db=tables[2].db=(char*) "mysql"; tables[0].db=tables[1].db=tables[2].db=(char*) "mysql";
// just safety for table on stack
tables[0].non_cachable_table= tables[1].non_cachable_table=
tables[2].non_cachable_table= 1;
#ifdef HAVE_REPLICATION #ifdef HAVE_REPLICATION
/* /*
@ -2407,6 +2415,8 @@ int mysql_grant(THD *thd, const char *db, List <LEX_USER> &list,
tables[0].lock_type=tables[1].lock_type=TL_WRITE; tables[0].lock_type=tables[1].lock_type=TL_WRITE;
tables[0].db=tables[1].db=(char*) "mysql"; tables[0].db=tables[1].db=(char*) "mysql";
tables[0].table=tables[1].table=0; tables[0].table=tables[1].table=0;
// just safety for table on stack
tables[0].non_cachable_table= tables[1].non_cachable_table= 1;
#ifdef HAVE_REPLICATION #ifdef HAVE_REPLICATION
/* /*
@ -2526,6 +2536,8 @@ my_bool grant_init(THD *org_thd)
tables[0].next=tables+1; tables[0].next=tables+1;
tables[0].lock_type=tables[1].lock_type=TL_READ; tables[0].lock_type=tables[1].lock_type=TL_READ;
tables[0].db=tables[1].db=thd->db; tables[0].db=tables[1].db=thd->db;
// just safety for table on stack
tables[0].non_cachable_table= tables[1].non_cachable_table= 1;
uint counter; uint counter;
if (open_tables(thd, tables, &counter)) if (open_tables(thd, tables, &counter))
@ -3363,6 +3375,9 @@ int open_grant_tables(THD *thd, TABLE_LIST *tables)
tables->lock_type= (tables+1)->lock_type= tables->lock_type= (tables+1)->lock_type=
(tables+2)->lock_type= (tables+3)->lock_type= TL_WRITE; (tables+2)->lock_type= (tables+3)->lock_type= TL_WRITE;
tables->db= (tables+1)->db= (tables+2)->db= (tables+3)->db=(char*) "mysql"; tables->db= (tables+1)->db= (tables+2)->db= (tables+3)->db=(char*) "mysql";
// just safety for table on stack
tables[0].non_cachable_table= tables[1].non_cachable_table=
tables[2].non_cachable_table= tables[3].non_cachable_table=1;
#ifdef HAVE_REPLICATION #ifdef HAVE_REPLICATION
/* /*

View file

@ -156,6 +156,7 @@ OPEN_TABLE_LIST *list_open_tables(THD *thd, const char *wild)
table_list.db= (char*) entry->table_cache_key; table_list.db= (char*) entry->table_cache_key;
table_list.real_name= entry->real_name; table_list.real_name= entry->real_name;
table_list.grant.privilege=0; table_list.grant.privilege=0;
table_list.non_cachable_table= 1; // just safety for table on stack
if (check_table_access(thd,SELECT_ACL | EXTRA_ACL,&table_list,1)) if (check_table_access(thd,SELECT_ACL | EXTRA_ACL,&table_list,1))
continue; continue;
/* need to check if we haven't already listed it */ /* need to check if we haven't already listed it */
@ -1332,6 +1333,7 @@ static int open_unireg_entry(THD *thd, TABLE *entry, const char *db,
bzero((char*) &table_list, sizeof(table_list)); // just for safe bzero((char*) &table_list, sizeof(table_list)); // just for safe
table_list.db=(char*) db; table_list.db=(char*) db;
table_list.real_name=(char*) name; table_list.real_name=(char*) name;
table_list.non_cachable_table= 1; // just safety for table on stack
safe_mutex_assert_owner(&LOCK_open); safe_mutex_assert_owner(&LOCK_open);
if ((error=lock_table_name(thd,&table_list))) if ((error=lock_table_name(thd,&table_list)))
@ -1886,7 +1888,7 @@ find_field_in_tables(THD *thd, Item_ident *item, TABLE_LIST *tables,
char name_buff[NAME_LEN+1]; char name_buff[NAME_LEN+1];
if (!thd->no_table_fix_fields_cache && item->cached_table) if (item->cached_table)
{ {
/* /*
This shortcut is used by prepared statements. We assuming that This shortcut is used by prepared statements. We assuming that
@ -1939,6 +1941,8 @@ find_field_in_tables(THD *thd, Item_ident *item, TABLE_LIST *tables,
if (find) if (find)
{ {
(*where)= item->cached_table= tables; (*where)= item->cached_table= tables;
if (tables->non_cachable_table)
item->cached_table= 0;
if (find == WRONG_GRANT) if (find == WRONG_GRANT)
return (Field*) 0; return (Field*) 0;
if (db || !thd->where) if (db || !thd->where)
@ -1998,6 +2002,8 @@ find_field_in_tables(THD *thd, Item_ident *item, TABLE_LIST *tables,
if (field == WRONG_GRANT) if (field == WRONG_GRANT)
return (Field*) 0; return (Field*) 0;
(*where)= item->cached_table= tables; (*where)= item->cached_table= tables;
if (tables->non_cachable_table)
item->cached_table= 0;
if (found) if (found)
{ {
if (!thd->where) // Returns first found if (!thd->where) // Returns first found
@ -2405,15 +2411,13 @@ int setup_conds(THD *thd,TABLE_LIST *tables,COND **conds)
{ {
if (table->on_expr) if (table->on_expr)
{ {
if (stmt)
thd->set_n_backup_item_arena(stmt, &backup);
/* Make a join an a expression */ /* Make a join an a expression */
thd->where="on clause"; thd->where="on clause";
if (!table->on_expr->fixed && if (!table->on_expr->fixed &&
table->on_expr->fix_fields(thd, tables, &table->on_expr) || table->on_expr->fix_fields(thd, tables, &table->on_expr) ||
table->on_expr->check_cols(1)) table->on_expr->check_cols(1))
goto err; DBUG_RETURN(1);
thd->lex->current_select->cond_count++; thd->lex->current_select->cond_count++;
/* /*
@ -2425,12 +2429,16 @@ int setup_conds(THD *thd,TABLE_LIST *tables,COND **conds)
!(specialflag & SPECIAL_NO_NEW_FUNC))) !(specialflag & SPECIAL_NO_NEW_FUNC)))
{ {
table->outer_join= 0; table->outer_join= 0;
if (!(*conds= and_conds(thd, *conds, table->on_expr, tables))) if (stmt)
goto err; thd->set_n_backup_item_arena(stmt, &backup);
*conds= and_conds(*conds, table->on_expr);
table->on_expr=0; table->on_expr=0;
if (stmt)
thd->restore_backup_item_arena(stmt, &backup);
if ((*conds) && !(*conds)->fixed &&
(*conds)->fix_fields(thd, tables, conds))
DBUG_RETURN(1);
} }
if (stmt)
thd->restore_backup_item_arena(stmt, &backup);
} }
if (table->natural_join) if (table->natural_join)
{ {
@ -2467,22 +2475,33 @@ int setup_conds(THD *thd,TABLE_LIST *tables,COND **conds)
} }
thd->lex->current_select->cond_count+= cond_and->list.elements; thd->lex->current_select->cond_count+= cond_and->list.elements;
// to prevent natural join processing during PS re-execution
table->natural_join= 0;
if (!table->outer_join) // Not left join if (!table->outer_join) // Not left join
{ {
if (!(*conds= and_conds(thd, *conds, cond_and, tables)) || *conds= and_conds(*conds, cond_and);
(*conds && !(*conds)->fixed && // fix_fields() should be made with temporary memory pool
(*conds)->fix_fields(thd, tables, conds))) if (stmt)
goto err; thd->restore_backup_item_arena(stmt, &backup);
if (*conds && !(*conds)->fixed)
{
if ((*conds)->fix_fields(thd, tables, conds))
DBUG_RETURN(1);
}
} }
else else
{ {
table->on_expr= and_conds(thd, table->on_expr, cond_and, tables); table->on_expr= and_conds(table->on_expr, cond_and);
if (table->on_expr && !table->on_expr->fixed && // fix_fields() should be made with temporary memory pool
table->on_expr->fix_fields(thd, tables, &table->on_expr)) if (stmt)
goto err; thd->restore_backup_item_arena(stmt, &backup);
if (table->on_expr && !table->on_expr->fixed)
{
if (table->on_expr->fix_fields(thd, tables, &table->on_expr))
DBUG_RETURN(1);
}
} }
if (stmt)
thd->restore_backup_item_arena(stmt, &backup);
} }
} }

View file

@ -1022,6 +1022,7 @@ Query_cache::send_result_to_client(THD *thd, char *sql, uint query_length)
Query_cache_table *table = block_table->parent; Query_cache_table *table = block_table->parent;
table_list.db = table->db(); table_list.db = table->db();
table_list.alias= table_list.real_name= table->table(); table_list.alias= table_list.real_name= table->table();
table_list.non_cachable_table= 1; // just safety for table on stack
#ifndef NO_EMBEDDED_ACCESS_CHECKS #ifndef NO_EMBEDDED_ACCESS_CHECKS
if (check_table_access(thd,SELECT_ACL,&table_list,1)) if (check_table_access(thd,SELECT_ACL,&table_list,1))
{ {

View file

@ -84,7 +84,6 @@ extern "C" void free_user_var(user_var_entry *entry)
****************************************************************************/ ****************************************************************************/
THD::THD():user_time(0), current_statement(0), is_fatal_error(0), THD::THD():user_time(0), current_statement(0), is_fatal_error(0),
no_table_fix_fields_cache(0),
last_insert_id_used(0), last_insert_id_used(0),
insert_id_used(0), rand_used(0), in_lock_tables(0), insert_id_used(0), rand_used(0), in_lock_tables(0),
global_read_lock(0), bootstrap(0) global_read_lock(0), bootstrap(0)

View file

@ -787,12 +787,6 @@ public:
bool charset_is_system_charset, charset_is_collation_connection; bool charset_is_system_charset, charset_is_collation_connection;
bool slow_command; bool slow_command;
/*
Used in prepared statement to prevent using table/field cache in
Item_idend, bacuse it can point on removed table.
*/
bool no_table_fix_fields_cache;
/* /*
If we do a purge of binary logs, log index info of the threads If we do a purge of binary logs, log index info of the threads
that are currently reading it needs to be adjusted. To do that that are currently reading it needs to be adjusted. To do that

View file

@ -659,20 +659,20 @@ int mysqld_help(THD *thd, const char *mask)
bzero((gptr)tables,sizeof(tables)); bzero((gptr)tables,sizeof(tables));
tables[0].alias= tables[0].real_name= (char*) "help_topic"; tables[0].alias= tables[0].real_name= (char*) "help_topic";
tables[0].lock_type= TL_READ; tables[0].lock_type= TL_READ;
tables[0].db= (char*) "mysql";
tables[0].next= &tables[1]; tables[0].next= &tables[1];
tables[1].alias= tables[1].real_name= (char*) "help_category"; tables[1].alias= tables[1].real_name= (char*) "help_category";
tables[1].lock_type= TL_READ; tables[1].lock_type= TL_READ;
tables[1].db= (char*) "mysql";
tables[1].next= &tables[2]; tables[1].next= &tables[2];
tables[2].alias= tables[2].real_name= (char*) "help_relation"; tables[2].alias= tables[2].real_name= (char*) "help_relation";
tables[2].lock_type= TL_READ; tables[2].lock_type= TL_READ;
tables[2].db= (char*) "mysql";
tables[2].next= &tables[3]; tables[2].next= &tables[3];
tables[3].alias= tables[3].real_name= (char*) "help_keyword"; tables[3].alias= tables[3].real_name= (char*) "help_keyword";
tables[3].lock_type= TL_READ; tables[3].lock_type= TL_READ;
tables[3].db= (char*) "mysql";
tables[3].next= 0; tables[3].next= 0;
tables[0].db= tables[1].db= tables[2].db= tables[3].db= (char*) "mysql";
// just safety for table on stack
tables[0].non_cachable_table= tables[1].non_cachable_table=
tables[2].non_cachable_table= tables[3].non_cachable_table= 1;
List<String> topics_list, categories_list, subcategories_list; List<String> topics_list, categories_list, subcategories_list;
String name, description, example; String name, description, example;

View file

@ -82,16 +82,13 @@ check_insert_fields(THD *thd,TABLE *table,List<Item> &fields,
table_list.real_name= table_list.alias= table->table_name; table_list.real_name= table_list.alias= table->table_name;
table_list.table=table; table_list.table=table;
table_list.grant=table->grant; table_list.grant=table->grant;
table_list.non_cachable_table= 1;
thd->dupp_field=0; thd->dupp_field=0;
thd->no_table_fix_fields_cache= 1;
if (setup_tables(&table_list) || if (setup_tables(&table_list) ||
setup_fields(thd, 0, &table_list,fields,1,0,0)) setup_fields(thd, 0, &table_list,fields,1,0,0))
{
thd->no_table_fix_fields_cache= 0;
return -1; return -1;
}
thd->no_table_fix_fields_cache= 0;
if (thd->dupp_field) if (thd->dupp_field)
{ {
my_error(ER_FIELD_SPECIFIED_TWICE,MYF(0), thd->dupp_field->field_name); my_error(ER_FIELD_SPECIFIED_TWICE,MYF(0), thd->dupp_field->field_name);

View file

@ -4431,11 +4431,10 @@ bool add_to_list(THD *thd, SQL_LIST &list,Item *item,bool asc)
ORDER *order; ORDER *order;
Item **item_ptr; Item **item_ptr;
DBUG_ENTER("add_to_list"); DBUG_ENTER("add_to_list");
if (!(order = (ORDER *) thd->alloc(sizeof(ORDER)+sizeof(Item*)))) if (!(order = (ORDER *) thd->alloc(sizeof(ORDER))))
DBUG_RETURN(1); DBUG_RETURN(1);
item_ptr = (Item**) (order+1); order->item_ptr= item;
*item_ptr=item; order->item= &order->item_ptr;
order->item= item_ptr;
order->asc = asc; order->asc = asc;
order->free_me=0; order->free_me=0;
order->used=0; order->used=0;

View file

@ -987,6 +987,8 @@ void mysql_stmt_prepare(THD *thd, char *packet, uint packet_length)
int error; int error;
DBUG_ENTER("mysql_stmt_prepare"); DBUG_ENTER("mysql_stmt_prepare");
DBUG_PRINT("pquery", ("%s", packet));
if (stmt == 0) if (stmt == 0)
{ {
send_error(thd, ER_OUT_OF_RESOURCES); send_error(thd, ER_OUT_OF_RESOURCES);
@ -1076,11 +1078,11 @@ static void reset_stmt_for_execute(Prepared_statement *stmt)
DBUG_ASSERT(sl->join == 0); DBUG_ASSERT(sl->join == 0);
ORDER *order; ORDER *order;
/* Fix GROUP list */ /* Fix GROUP list */
for (order=(ORDER *)sl->group_list.first ; order ; order=order->next) for (order= (ORDER *)sl->group_list.first; order; order= order->next)
order->item= (Item **)(order+1); order->item= &order->item_ptr;
/* Fix ORDER list */ /* Fix ORDER list */
for (order=(ORDER *)sl->order_list.first ; order ; order=order->next) for (order= (ORDER *)sl->order_list.first; order; order= order->next)
order->item= (Item **)(order+1); order->item= &order->item_ptr;
/* /*
TODO: When the new table structure is ready, then have a status bit TODO: When the new table structure is ready, then have a status bit
@ -1131,6 +1133,8 @@ void mysql_stmt_execute(THD *thd, char *packet, uint packet_length)
if (!(stmt= find_prepared_statement(thd, stmt_id, "execute", SEND_ERROR))) if (!(stmt= find_prepared_statement(thd, stmt_id, "execute", SEND_ERROR)))
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
DBUG_PRINT("equery:", ("%s", stmt->query));
/* Check if we got an error when sending long data */ /* Check if we got an error when sending long data */
if (stmt->get_longdata_error) if (stmt->get_longdata_error)
{ {

View file

@ -3536,7 +3536,9 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond)
{ {
/* Join with outer join condition */ /* Join with outer join condition */
COND *orig_cond=sel->cond; COND *orig_cond=sel->cond;
sel->cond=and_conds(join->thd, sel->cond, tab->on_expr, 0); sel->cond= and_conds(sel->cond, tab->on_expr);
if (sel->cond && !sel->cond->fixed)
sel->cond->fix_fields(join->thd, 0, &sel->cond);
if (sel->test_quick_select(join->thd, tab->keys, if (sel->test_quick_select(join->thd, tab->keys,
used_tables & ~ current_map, used_tables & ~ current_map,
(join->select_options & (join->select_options &

View file

@ -208,19 +208,6 @@ int st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result,
} }
} }
for (tmp_order= (ORDER*) global_parameters->order_list.first;
tmp_order ;
tmp_order= tmp_order->next)
{
Item *item= *tmp_order->item;
if (((item->type() == Item::FIELD_ITEM) &&
((class Item_field*) item)->table_name))
{
my_error(ER_BAD_FIELD_ERROR,MYF(0),item->full_name(),"ORDER BY");
DBUG_RETURN(-1);
}
}
item_list.empty(); item_list.empty();
// it is not single select // it is not single select
if (first_select->next_select()) if (first_select->next_select())

View file

@ -26,6 +26,7 @@ class st_select_lex_unit;
typedef struct st_order { typedef struct st_order {
struct st_order *next; struct st_order *next;
Item **item; /* Point at item in select fields */ Item **item; /* Point at item in select fields */
Item *item_ptr; /* Storage for initial item */
bool asc; /* true if ascending */ bool asc; /* true if ascending */
bool free_me; /* true if item isn't shared */ bool free_me; /* true if item isn't shared */
bool in_field_list; /* true if in select field list */ bool in_field_list; /* true if in select field list */
@ -192,6 +193,7 @@ typedef struct st_table_list
bool updating; /* for replicate-do/ignore table */ bool updating; /* for replicate-do/ignore table */
bool force_index; /* Prefer index over table scan */ bool force_index; /* Prefer index over table scan */
bool ignore_leaves; /* Preload only non-leaf nodes */ bool ignore_leaves; /* Preload only non-leaf nodes */
bool non_cachable_table; /* stop PS caching */
} TABLE_LIST; } TABLE_LIST;
typedef struct st_changed_table_list typedef struct st_changed_table_list

View file

@ -8495,13 +8495,21 @@ static void test_bug3117()
} }
static void test_on() static void jest_join()
{ {
MYSQL_STMT *stmt; MYSQL_STMT *stmt;
int rc, i; int rc, i, j;
const char *query= "SELECT * FROM t2 join t1 on (t1.a=t2.a)"; const char *query[]={"SELECT * FROM t2 join t1 on (t1.a=t2.a)",
"SELECT * FROM t2 natural join t1",
"SELECT * FROM t2 join t1 using(a)",
"SELECT * FROM t2 left join t1 on(t1.a=t2.a)",
"SELECT * FROM t2 natural left join t1",
"SELECT * FROM t2 left join t1 using(a)",
"SELECT * FROM t2 right join t1 on(t1.a=t2.a)",
"SELECT * FROM t2 natural right join t1",
"SELECT * FROM t2 right join t1 using(a)"};
myheader("test_on"); myheader("jest_join");
rc = mysql_query(mysql, "DROP TABLE IF EXISTS t1,t2"); rc = mysql_query(mysql, "DROP TABLE IF EXISTS t1,t2");
myquery(rc); myquery(rc);
@ -8513,7 +8521,59 @@ static void test_on()
"insert into t1 values (1,1), (2, 2), (3,3), (4,4), (5,5);"); "insert into t1 values (1,1), (2, 2), (3,3), (4,4), (5,5);");
myquery(rc); myquery(rc);
rc= mysql_query(mysql,"create table t2 select * from t1;"); rc= mysql_query(mysql,"CREATE TABLE t2 (a int , c int);");
myquery(rc);
rc= mysql_query(mysql,
"insert into t2 values (1,1), (2, 2), (3,3), (4,4), (5,5);");
for (j= 0; j < 9; j++)
{
stmt= mysql_prepare(mysql, query[j], strlen(query[j]));
mystmt_init(stmt);
for (i= 0; i < 3; i++)
{
rc= mysql_execute(stmt);
mystmt(stmt, rc);
assert(5 == my_process_stmt_result(stmt));
}
mysql_stmt_close(stmt);
}
rc= mysql_query(mysql, "DROP TABLE t1,t2");
myquery(rc);
}
static void test_selecttmp()
{
MYSQL_STMT *stmt;
int rc, i;
const char *query= "select a,(select count(distinct t1.b) as sum from t1,t2 where t1.a=t2.a and t2.b > 0 and t1.a <= t3.b group by t1.a order by sum limit 1) from t3";
myheader("test_select_tmp");
rc = mysql_query(mysql, "DROP TABLE IF EXISTS t1,t2,t3");
myquery(rc);
rc= mysql_query(mysql,"CREATE TABLE t1 (a int , b int);");
myquery(rc);
rc= mysql_query(mysql,"create table t2 (a int, b int);");
myquery(rc);
rc= mysql_query(mysql,"create table t3 (a int, b int);");
myquery(rc);
rc= mysql_query(mysql,
"insert into t1 values (0,100),(1,2), (1,3), (2,2), (2,7), \
(2,-1), (3,10);");
myquery(rc);
rc= mysql_query(mysql,
"insert into t2 values (0,0), (1,1), (2,1), (3,1), (4,1);");
myquery(rc);
rc= mysql_query(mysql,
"insert into t3 values (3,3), (2,2), (1,1);");
myquery(rc); myquery(rc);
stmt= mysql_prepare(mysql, query, strlen(query)); stmt= mysql_prepare(mysql, query, strlen(query));
@ -8522,11 +8582,11 @@ static void test_on()
{ {
rc= mysql_execute(stmt); rc= mysql_execute(stmt);
mystmt(stmt, rc); mystmt(stmt, rc);
assert(5 == my_process_stmt_result(stmt)); assert(3 == my_process_stmt_result(stmt));
} }
mysql_stmt_close(stmt); mysql_stmt_close(stmt);
rc= mysql_query(mysql, "DROP TABLE t1,t2"); rc= mysql_query(mysql, "DROP TABLE t1,t2,t3");
myquery(rc); myquery(rc);
} }
@ -8790,7 +8850,8 @@ int main(int argc, char **argv)
Item_field -> Item_ref */ Item_field -> Item_ref */
test_union(); /* test union with prepared statements */ test_union(); /* test union with prepared statements */
test_bug3117(); /* BUG#3117: LAST_INSERT_ID() */ test_bug3117(); /* BUG#3117: LAST_INSERT_ID() */
test_on(); /* ... join ... on(), BUG#2794 */ jest_join(); /* different kinds of join, BUG#2794 */
test_selecttmp(); /* temporary table used in select execution */
end_time= time((time_t *)0); end_time= time((time_t *)0);