Commit c31f3cf1 authored by bell@sanja.is.com.ua's avatar bell@sanja.is.com.ua

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

into sanja.is.com.ua:/home/bell/mysql/bk/work-on-4.1
parents 18b4e9c9 2f4d2a0e
...@@ -435,7 +435,7 @@ drop temporary table t1; ...@@ -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;
* *
......
...@@ -991,14 +991,11 @@ class Item_cond_xor :public Item_cond ...@@ -991,14 +991,11 @@ class Item_cond_xor :public Item_cond
/* 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);
...@@ -24,8 +24,8 @@ ...@@ -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) ...@@ -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() ...@@ -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 ...@@ -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 ...@@ -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() ...@@ -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() ...@@ -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 ...@@ -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)
......
...@@ -32,40 +32,32 @@ class Item_sum :public Item_result_field ...@@ -32,40 +32,32 @@ class Item_sum :public Item_result_field
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 @@ class Item_sum :public Item_result_field ...@@ -100,6 +92,8 @@ class Item_sum :public Item_result_field
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 ...@@ -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 ...@@ -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),
......
...@@ -287,6 +287,7 @@ void debug_sync_point(const char* lock_name, uint lock_timeout); ...@@ -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 */
......
...@@ -2405,15 +2405,13 @@ int setup_conds(THD *thd,TABLE_LIST *tables,COND **conds) ...@@ -2405,15 +2405,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 +2423,16 @@ int setup_conds(THD *thd,TABLE_LIST *tables,COND **conds) ...@@ -2425,12 +2423,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)
{ {
...@@ -2469,20 +2471,28 @@ int setup_conds(THD *thd,TABLE_LIST *tables,COND **conds) ...@@ -2469,20 +2471,28 @@ int setup_conds(THD *thd,TABLE_LIST *tables,COND **conds)
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);
} }
} }
......
...@@ -4431,11 +4431,10 @@ bool add_to_list(THD *thd, SQL_LIST &list,Item *item,bool asc) ...@@ -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;
......
...@@ -987,6 +987,8 @@ void mysql_stmt_prepare(THD *thd, char *packet, uint packet_length) ...@@ -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) ...@@ -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) ...@@ -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)
{ {
......
...@@ -3536,7 +3536,9 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond) ...@@ -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 &
......
...@@ -208,19 +208,6 @@ int st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result, ...@@ -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())
......
...@@ -26,6 +26,7 @@ class st_select_lex_unit; ...@@ -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 */
......
...@@ -8531,6 +8531,52 @@ static void test_on() ...@@ -8531,6 +8531,52 @@ static void test_on()
} }
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));
mystmt_init(stmt);
for (i= 0; i < 3; i++)
{
rc= mysql_execute(stmt);
mystmt(stmt, rc);
assert(3 == my_process_stmt_result(stmt));
}
mysql_stmt_close(stmt);
rc= mysql_query(mysql, "DROP TABLE t1,t2,t3");
myquery(rc);
}
/* /*
Read and parse arguments and MySQL options from my.cnf Read and parse arguments and MySQL options from my.cnf
*/ */
...@@ -8791,6 +8837,7 @@ int main(int argc, char **argv) ...@@ -8791,6 +8837,7 @@ int main(int argc, char **argv)
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 */ test_on(); /* ... join ... on(), BUG#2794 */
test_selecttmp(); /* temporary table used in select execution */
end_time= time((time_t *)0); end_time= time((time_t *)0);
......
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