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;
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;
ERROR 42S22: Unknown column 't2.a' in 'ORDER BY'
ERROR 42S02: Unknown table 't2' in order clause
drop table t1,t2;
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;
--error 1093
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;
drop table t1,t2;

View file

@ -713,7 +713,7 @@ bool Item_param::get_time(TIME *res)
double Item_param::val()
{
DBUG_ASSERT(fixed == 1);
DBUG_ASSERT(value_is_set == 1);
int err;
switch (item_result_type) {
case STRING_RESULT:
@ -729,7 +729,7 @@ double Item_param::val()
longlong Item_param::val_int()
{
DBUG_ASSERT(fixed == 1);
DBUG_ASSERT(value_is_set == 1);
int err;
switch (item_result_type) {
case STRING_RESULT:
@ -746,7 +746,7 @@ longlong Item_param::val_int()
String *Item_param::val_str(String* str)
{
DBUG_ASSERT(fixed == 1);
DBUG_ASSERT(value_is_set == 1);
switch (item_result_type) {
case INT_RESULT:
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)
{
DBUG_ASSERT(fixed == 1);
DBUG_ASSERT(value_is_set == 1);
switch (item_result_type) {
case INT_RESULT:
case REAL_RESULT:

View file

@ -991,14 +991,11 @@ public:
/* 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 (!a) return b;
Item *cond= new Item_cond_and(a,b);
if (cond)
cond->fix_fields(thd, tables, &cond);
return cond;
return new Item_cond_and(a, b);
}
Item *and_expressions(Item *a, Item *b, Item **org_item);

View file

@ -24,8 +24,8 @@
#include "mysql_priv.h"
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)))
{
uint i=0;
@ -43,18 +43,51 @@ Item_sum::Item_sum(List<Item> &list)
// Constructor used in processing select with temporary tebles
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)
args=tmp_args;
else
if (!(args=(Item**) sql_alloc(sizeof(Item*)*arg_count)))
if (!(args= (Item**) thd->alloc(sizeof(Item*)*arg_count)))
return;
for (uint i= 0; i < arg_count; i++)
args[i]= item->args[i];
memcpy(args, item->args, sizeof(Item*)*arg_count);
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()
{
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)
{
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)
{
DBUG_ASSERT(fixed == 0);
if (save_args_for_prepared_statements(thd))
return 1;
if (!thd->allow_sum_func)
{
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)
{
DBUG_ASSERT(fixed == 0);
if (save_args_for_prepared_statements(thd))
return 1;
Item *item= args[0];
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 */
void Item_sum_count_distinct::make_unique()
@ -1705,6 +1748,11 @@ void Item_func_group_concat::cleanup()
{
DBUG_ENTER("Item_func_group_concat::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
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)
{
DBUG_ASSERT(fixed == 0);
if (save_args_for_prepared_statements(thd))
return 1;
uint i; /* for loop variable */
if (!thd->allow_sum_func)

View file

@ -32,40 +32,32 @@ public:
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;
bool quick_group; /* If incremental update of fields */
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();
}
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;
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;
mark_as_sum_func();
}
Item_sum(List<Item> &list);
//Copy constructor, need to perform subselects with temporary tables
Item_sum(THD *thd, Item_sum *item);
void cleanup()
{
DBUG_ENTER("Item_sum::cleanup");
Item_result_field::cleanup();
result_field=0;
DBUG_VOID_RETURN;
}
void cleanup();
enum Type type() const { return SUM_FUNC_ITEM; }
virtual enum Sumfunctype sum_func () const=0;
inline bool reset() { clear(); return add(); };
@ -100,6 +92,8 @@ public:
virtual bool setup(THD *thd) {return 0;}
virtual void make_unique() {}
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);
};
@ -190,7 +184,6 @@ class Item_sum_count_distinct :public Item_sum_int
{
TABLE *table;
table_map used_table_cache;
bool fix_fields(THD *thd, TABLE_LIST *tables, Item **ref);
uint32 *field_lengths;
TMP_TABLE_PARAM *tmp_table_param;
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_int(thd, item), table(item->table),
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),
max_elements_in_tree(item->max_elements_in_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.lock_type = TL_WRITE;
tables.updating= 1;
tables.non_cachable_table= 1; // just safety for table on stack
// the table will be opened in mysql_load
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;
class THD;
class Statement;
/* 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.real_name= (char*) table_name;
table.updating= 1;
table.non_cachable_table= 1; // just safety for table on stack
if (!tables_ok(thd, &table))
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));
tables.db = (char*)db;
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 */
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[0].lock_type=tables[1].lock_type=tables[2].lock_type=TL_READ;
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;
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));
tables.alias=tables.real_name=(char*) "user";
tables.db=(char*) "mysql";
tables.non_cachable_table= 1; // just safety for table on stack
#ifdef HAVE_REPLICATION
/*
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));
tl.db= (char*) "mysql";
tl.real_name= (char*) "user";
tl.non_cachable_table= 1; // just safety for table on stack
db_access=acl_get(thd->host, thd->ip,
thd->priv_user, tl.db, 0);
if (!(db_access & INSERT_ACL))
@ -2233,6 +2238,9 @@ int mysql_table_grant(THD *thd, TABLE_LIST *table_list,
? tables+2 : 0);
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";
// 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
/*
@ -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].db=tables[1].db=(char*) "mysql";
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
/*
@ -2526,6 +2536,8 @@ my_bool grant_init(THD *org_thd)
tables[0].next=tables+1;
tables[0].lock_type=tables[1].lock_type=TL_READ;
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;
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+2)->lock_type= (tables+3)->lock_type= TL_WRITE;
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
/*

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.real_name= entry->real_name;
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))
continue;
/* 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
table_list.db=(char*) db;
table_list.real_name=(char*) name;
table_list.non_cachable_table= 1; // just safety for table on stack
safe_mutex_assert_owner(&LOCK_open);
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];
if (!thd->no_table_fix_fields_cache && item->cached_table)
if (item->cached_table)
{
/*
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)
{
(*where)= item->cached_table= tables;
if (tables->non_cachable_table)
item->cached_table= 0;
if (find == WRONG_GRANT)
return (Field*) 0;
if (db || !thd->where)
@ -1998,6 +2002,8 @@ find_field_in_tables(THD *thd, Item_ident *item, TABLE_LIST *tables,
if (field == WRONG_GRANT)
return (Field*) 0;
(*where)= item->cached_table= tables;
if (tables->non_cachable_table)
item->cached_table= 0;
if (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 (stmt)
thd->set_n_backup_item_arena(stmt, &backup);
/* Make a join an a expression */
thd->where="on clause";
if (!table->on_expr->fixed &&
table->on_expr->fix_fields(thd, tables, &table->on_expr) ||
table->on_expr->check_cols(1))
goto err;
DBUG_RETURN(1);
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)))
{
table->outer_join= 0;
if (!(*conds= and_conds(thd, *conds, table->on_expr, tables)))
goto err;
if (stmt)
thd->set_n_backup_item_arena(stmt, &backup);
*conds= and_conds(*conds, table->on_expr);
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)
{
@ -2467,22 +2475,33 @@ int setup_conds(THD *thd,TABLE_LIST *tables,COND **conds)
}
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 (!(*conds= and_conds(thd, *conds, cond_and, tables)) ||
(*conds && !(*conds)->fixed &&
(*conds)->fix_fields(thd, tables, conds)))
goto err;
*conds= and_conds(*conds, cond_and);
// fix_fields() should be made with temporary memory pool
if (stmt)
thd->restore_backup_item_arena(stmt, &backup);
if (*conds && !(*conds)->fixed)
{
if ((*conds)->fix_fields(thd, tables, conds))
DBUG_RETURN(1);
}
}
else
{
table->on_expr= and_conds(thd, table->on_expr, cond_and, tables);
if (table->on_expr && !table->on_expr->fixed &&
table->on_expr->fix_fields(thd, tables, &table->on_expr))
goto err;
table->on_expr= and_conds(table->on_expr, cond_and);
// fix_fields() should be made with temporary memory pool
if (stmt)
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;
table_list.db = table->db();
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
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),
no_table_fix_fields_cache(0),
last_insert_id_used(0),
insert_id_used(0), rand_used(0), in_lock_tables(0),
global_read_lock(0), bootstrap(0)

View file

@ -787,12 +787,6 @@ public:
bool charset_is_system_charset, charset_is_collation_connection;
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
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));
tables[0].alias= tables[0].real_name= (char*) "help_topic";
tables[0].lock_type= TL_READ;
tables[0].db= (char*) "mysql";
tables[0].next= &tables[1];
tables[1].alias= tables[1].real_name= (char*) "help_category";
tables[1].lock_type= TL_READ;
tables[1].db= (char*) "mysql";
tables[1].next= &tables[2];
tables[2].alias= tables[2].real_name= (char*) "help_relation";
tables[2].lock_type= TL_READ;
tables[2].db= (char*) "mysql";
tables[2].next= &tables[3];
tables[3].alias= tables[3].real_name= (char*) "help_keyword";
tables[3].lock_type= TL_READ;
tables[3].db= (char*) "mysql";
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;
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.table=table;
table_list.grant=table->grant;
table_list.non_cachable_table= 1;
thd->dupp_field=0;
thd->no_table_fix_fields_cache= 1;
if (setup_tables(&table_list) ||
setup_fields(thd, 0, &table_list,fields,1,0,0))
{
thd->no_table_fix_fields_cache= 0;
return -1;
}
thd->no_table_fix_fields_cache= 0;
if (thd->dupp_field)
{
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;
Item **item_ptr;
DBUG_ENTER("add_to_list");
if (!(order = (ORDER *) thd->alloc(sizeof(ORDER)+sizeof(Item*))))
if (!(order = (ORDER *) thd->alloc(sizeof(ORDER))))
DBUG_RETURN(1);
item_ptr = (Item**) (order+1);
*item_ptr=item;
order->item= item_ptr;
order->item_ptr= item;
order->item= &order->item_ptr;
order->asc = asc;
order->free_me=0;
order->used=0;

View file

@ -987,6 +987,8 @@ void mysql_stmt_prepare(THD *thd, char *packet, uint packet_length)
int error;
DBUG_ENTER("mysql_stmt_prepare");
DBUG_PRINT("pquery", ("%s", packet));
if (stmt == 0)
{
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);
ORDER *order;
/* Fix GROUP list */
for (order=(ORDER *)sl->group_list.first ; order ; order=order->next)
order->item= (Item **)(order+1);
for (order= (ORDER *)sl->group_list.first; order; order= order->next)
order->item= &order->item_ptr;
/* Fix ORDER list */
for (order=(ORDER *)sl->order_list.first ; order ; order=order->next)
order->item= (Item **)(order+1);
for (order= (ORDER *)sl->order_list.first; order; order= order->next)
order->item= &order->item_ptr;
/*
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)))
DBUG_VOID_RETURN;
DBUG_PRINT("equery:", ("%s", stmt->query));
/* Check if we got an error when sending long data */
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 */
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,
used_tables & ~ current_map,
(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();
// it is not single select
if (first_select->next_select())

View file

@ -26,6 +26,7 @@ class st_select_lex_unit;
typedef struct st_order {
struct st_order *next;
Item **item; /* Point at item in select fields */
Item *item_ptr; /* Storage for initial item */
bool asc; /* true if ascending */
bool free_me; /* true if item isn't shared */
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 force_index; /* Prefer index over table scan */
bool ignore_leaves; /* Preload only non-leaf nodes */
bool non_cachable_table; /* stop PS caching */
} 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;
int rc, i;
const char *query= "SELECT * FROM t2 join t1 on (t1.a=t2.a)";
int rc, i, j;
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");
myquery(rc);
@ -8513,7 +8521,59 @@ static void test_on()
"insert into t1 values (1,1), (2, 2), (3,3), (4,4), (5,5);");
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);
stmt= mysql_prepare(mysql, query, strlen(query));
@ -8522,11 +8582,11 @@ static void test_on()
{
rc= mysql_execute(stmt);
mystmt(stmt, rc);
assert(5 == my_process_stmt_result(stmt));
assert(3 == my_process_stmt_result(stmt));
}
mysql_stmt_close(stmt);
rc= mysql_query(mysql, "DROP TABLE t1,t2");
rc= mysql_query(mysql, "DROP TABLE t1,t2,t3");
myquery(rc);
}
@ -8790,7 +8850,8 @@ int main(int argc, char **argv)
Item_field -> Item_ref */
test_union(); /* test union with prepared statements */
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);