merge
This commit is contained in:
commit
906903b998
@ -88,7 +88,6 @@ explain (select a,b from t1 limit 2) union all (select a,b from t2 order by a l
|
||||
table type possible_keys key key_len ref rows Extra
|
||||
t1 ALL NULL NULL NULL NULL 4
|
||||
t2 ALL NULL NULL NULL NULL 4 Using filesort
|
||||
t1 ALL NULL NULL NULL NULL 4
|
||||
(select sql_calc_found_rows a,b from t1 limit 2) union all (select a,b from t2 order by a) limit 2;
|
||||
a b
|
||||
1 a
|
||||
|
@ -940,6 +940,7 @@ bool Item_sum_count_distinct::fix_fields(THD *thd,TABLE_LIST *tables)
|
||||
bool Item_sum_count_distinct::setup(THD *thd)
|
||||
{
|
||||
List<Item> list;
|
||||
SELECT_LEX *select_lex= current_lex->select;
|
||||
/* Create a table with an unique key over all parameters */
|
||||
for (uint i=0; i < arg_count ; i++)
|
||||
{
|
||||
@ -961,9 +962,10 @@ bool Item_sum_count_distinct::setup(THD *thd)
|
||||
free_tmp_table(thd, table);
|
||||
tmp_table_param->cleanup();
|
||||
}
|
||||
if (!(table=create_tmp_table(thd, tmp_table_param, list, (ORDER*) 0, 1,
|
||||
0, 0,
|
||||
current_lex->select->options | thd->options)))
|
||||
if (!(table= create_tmp_table(thd, tmp_table_param, list, (ORDER*) 0, 1,
|
||||
0, 0,
|
||||
select_lex->options | thd->options,
|
||||
(SELECT_LEX_UNIT*) select_lex->master)))
|
||||
return 1;
|
||||
table->file->extra(HA_EXTRA_NO_ROWS); // Don't update rows
|
||||
table->no_rows=1;
|
||||
|
@ -291,7 +291,7 @@ bool mysql_rename_tables(THD *thd, TABLE_LIST *table_list);
|
||||
bool mysql_change_db(THD *thd,const char *name);
|
||||
void mysql_parse(THD *thd,char *inBuf,uint length);
|
||||
void mysql_init_select(LEX *lex);
|
||||
bool mysql_new_select(LEX *lex);
|
||||
bool mysql_new_select(LEX *lex, bool move_down);
|
||||
void mysql_init_multi_delete(LEX *lex);
|
||||
void init_max_user_conn(void);
|
||||
void free_max_user_conn(void);
|
||||
@ -359,9 +359,10 @@ int setup_order(THD *thd,TABLE_LIST *tables, List<Item> &fields,
|
||||
int handle_select(THD *thd, LEX *lex, select_result *result);
|
||||
int mysql_select(THD *thd,TABLE_LIST *tables,List<Item> &list,COND *conds,
|
||||
ORDER *order, ORDER *group,Item *having,ORDER *proc_param,
|
||||
ulong select_type,select_result *result);
|
||||
int mysql_union(THD *thd,LEX *lex,select_result *result);
|
||||
int mysql_derived(THD *thd,LEX *lex,SELECT_LEX *s, TABLE_LIST *t);
|
||||
ulong select_type,select_result *result,
|
||||
SELECT_LEX_UNIT *unit);
|
||||
int mysql_union(THD *thd, LEX *lex,select_result *result);
|
||||
int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *s, TABLE_LIST *t);
|
||||
Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type,
|
||||
Item_result_field ***copy_func, Field **from_field,
|
||||
bool group,bool modify_item);
|
||||
|
@ -389,9 +389,9 @@ bool select_send::send_data(List<Item> &items)
|
||||
String *packet= &thd->packet;
|
||||
DBUG_ENTER("send_data");
|
||||
|
||||
if (thd->offset_limit)
|
||||
if (unit->offset_limit_cnt)
|
||||
{ // using limit offset,count
|
||||
thd->offset_limit--;
|
||||
unit->offset_limit_cnt--;
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
packet->length(0); // Reset packet
|
||||
@ -439,11 +439,12 @@ select_export::~select_export()
|
||||
}
|
||||
|
||||
int
|
||||
select_export::prepare(List<Item> &list)
|
||||
select_export::prepare(List<Item> &list, SELECT_LEX_UNIT *u)
|
||||
{
|
||||
char path[FN_REFLEN];
|
||||
uint option=4;
|
||||
bool blob_flag=0;
|
||||
unit= u;
|
||||
#ifdef DONT_ALLOW_FULL_LOAD_DATA_PATHS
|
||||
option|=1; // Force use of db directory
|
||||
#endif
|
||||
@ -510,9 +511,9 @@ bool select_export::send_data(List<Item> &items)
|
||||
String tmp(buff,sizeof(buff)),*res;
|
||||
tmp.length(0);
|
||||
|
||||
if (thd->offset_limit)
|
||||
if (unit->offset_limit_cnt)
|
||||
{ // using limit offset,count
|
||||
thd->offset_limit--;
|
||||
unit->offset_limit_cnt--;
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
row_count++;
|
||||
@ -678,9 +679,11 @@ select_dump::~select_dump()
|
||||
}
|
||||
|
||||
int
|
||||
select_dump::prepare(List<Item> &list __attribute__((unused)))
|
||||
select_dump::prepare(List<Item> &list __attribute__((unused)),
|
||||
SELECT_LEX_UNIT *u)
|
||||
{
|
||||
uint option=4;
|
||||
unit= u;
|
||||
#ifdef DONT_ALLOW_FULL_LOAD_DATA_PATHS
|
||||
option|=1; // Force use of db directory
|
||||
#endif
|
||||
@ -719,9 +722,9 @@ bool select_dump::send_data(List<Item> &items)
|
||||
Item *item;
|
||||
DBUG_ENTER("send_data");
|
||||
|
||||
if (thd->offset_limit)
|
||||
if (unit->offset_limit_cnt)
|
||||
{ // using limit offset,count
|
||||
thd->offset_limit--;
|
||||
unit->offset_limit_cnt--;
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
if (row_count++ > 1)
|
||||
|
@ -382,7 +382,7 @@ public:
|
||||
#endif
|
||||
ulonglong next_insert_id,last_insert_id,current_insert_id,
|
||||
limit_found_rows;
|
||||
ha_rows select_limit,offset_limit,default_select_limit,cuted_fields,
|
||||
ha_rows default_select_limit,cuted_fields,
|
||||
max_join_size, sent_row_count, examined_row_count;
|
||||
table_map used_tables;
|
||||
UC *user_connect;
|
||||
@ -551,10 +551,15 @@ void send_error(NET *net,uint sql_errno=0, const char *err=0);
|
||||
class select_result :public Sql_alloc {
|
||||
protected:
|
||||
THD *thd;
|
||||
SELECT_LEX_UNIT *unit;
|
||||
public:
|
||||
select_result();
|
||||
virtual ~select_result() {};
|
||||
virtual int prepare(List<Item> &list) { return 0; }
|
||||
virtual int prepare(List<Item> &list, SELECT_LEX_UNIT *u)
|
||||
{
|
||||
unit= u;
|
||||
return 0;
|
||||
}
|
||||
virtual bool send_fields(List<Item> &list,uint flag)=0;
|
||||
virtual bool send_data(List<Item> &items)=0;
|
||||
virtual void initialize_tables (JOIN *join=0) {}
|
||||
@ -587,7 +592,7 @@ class select_export :public select_result {
|
||||
public:
|
||||
select_export(sql_exchange *ex) :exchange(ex),file(-1),row_count(0L) {}
|
||||
~select_export();
|
||||
int prepare(List<Item> &list);
|
||||
int prepare(List<Item> &list, SELECT_LEX_UNIT *u);
|
||||
bool send_fields(List<Item> &list,
|
||||
uint flag) { return 0; }
|
||||
bool send_data(List<Item> &items);
|
||||
@ -606,7 +611,7 @@ public:
|
||||
select_dump(sql_exchange *ex) :exchange(ex),file(-1),row_count(0L)
|
||||
{ path[0]=0; }
|
||||
~select_dump();
|
||||
int prepare(List<Item> &list);
|
||||
int prepare(List<Item> &list, SELECT_LEX_UNIT *u);
|
||||
bool send_fields(List<Item> &list,
|
||||
uint flag) { return 0; }
|
||||
bool send_data(List<Item> &items);
|
||||
@ -629,7 +634,7 @@ class select_insert :public select_result {
|
||||
info.handle_duplicates=duplic;
|
||||
}
|
||||
~select_insert();
|
||||
int prepare(List<Item> &list);
|
||||
int prepare(List<Item> &list, SELECT_LEX_UNIT *u);
|
||||
bool send_fields(List<Item> &list, uint flag)
|
||||
{ return 0; }
|
||||
bool send_data(List<Item> &items);
|
||||
@ -658,7 +663,7 @@ public:
|
||||
create_info(create_info_par),
|
||||
lock(0)
|
||||
{}
|
||||
int prepare(List<Item> &list);
|
||||
int prepare(List<Item> &list, SELECT_LEX_UNIT *u);
|
||||
bool send_data(List<Item> &values);
|
||||
bool send_eof();
|
||||
void abort();
|
||||
@ -672,7 +677,7 @@ class select_union :public select_result {
|
||||
|
||||
select_union(TABLE *table_par);
|
||||
~select_union();
|
||||
int prepare(List<Item> &list);
|
||||
int prepare(List<Item> &list, SELECT_LEX_UNIT *u);
|
||||
bool send_fields(List<Item> &list, uint flag)
|
||||
{ return 0; }
|
||||
bool send_data(List<Item> &items);
|
||||
@ -706,19 +711,28 @@ class Table_ident :public Sql_alloc {
|
||||
public:
|
||||
LEX_STRING db;
|
||||
LEX_STRING table;
|
||||
SELECT_LEX *sel;
|
||||
inline Table_ident(LEX_STRING db_arg,LEX_STRING table_arg,bool force)
|
||||
:table(table_arg), sel((SELECT_LEX *)0)
|
||||
SELECT_LEX_UNIT *sel;
|
||||
inline Table_ident(LEX_STRING db_arg, LEX_STRING table_arg, bool force)
|
||||
:table(table_arg), sel((SELECT_LEX_UNIT *)0)
|
||||
{
|
||||
if (!force && (current_thd->client_capabilities & CLIENT_NO_SCHEMA))
|
||||
db.str=0;
|
||||
else
|
||||
db= db_arg;
|
||||
}
|
||||
inline Table_ident(LEX_STRING table_arg) :table(table_arg), sel((SELECT_LEX *)0) {db.str=0;}
|
||||
inline Table_ident(SELECT_LEX *s) : sel(s) {db.str=0; table.str=(char *)""; table.length=0;}
|
||||
inline Table_ident(LEX_STRING table_arg)
|
||||
:table(table_arg), sel((SELECT_LEX_UNIT *)0)
|
||||
{
|
||||
db.str=0;
|
||||
}
|
||||
inline Table_ident(SELECT_LEX_UNIT *s) : sel(s)
|
||||
{
|
||||
db.str=0; table.str=(char *)""; table.length=0;
|
||||
}
|
||||
inline void change_db(char *db_name)
|
||||
{ db.str= db_name; db.length=(uint) strlen(db_name); }
|
||||
{
|
||||
db.str= db_name; db.length= (uint) strlen(db_name);
|
||||
}
|
||||
};
|
||||
|
||||
// this is needed for user_vars hash
|
||||
@ -778,7 +792,7 @@ public:
|
||||
multi_delete(THD *thd, TABLE_LIST *dt, thr_lock_type lock_option_arg,
|
||||
uint num_of_tables);
|
||||
~multi_delete();
|
||||
int prepare(List<Item> &list);
|
||||
int prepare(List<Item> &list, SELECT_LEX_UNIT *u);
|
||||
bool send_fields(List<Item> &list,
|
||||
uint flag) { return 0; }
|
||||
bool send_data(List<Item> &items);
|
||||
@ -807,7 +821,7 @@ public:
|
||||
enum enum_duplicates handle_duplicates,
|
||||
thr_lock_type lock_option_arg, uint num);
|
||||
~multi_update();
|
||||
int prepare(List<Item> &list);
|
||||
int prepare(List<Item> &list, SELECT_LEX_UNIT *u);
|
||||
bool send_fields(List<Item> &list,
|
||||
uint flag) { return 0; }
|
||||
bool send_data(List<Item> &items);
|
||||
|
@ -232,9 +232,10 @@ multi_delete::multi_delete(THD *thd_arg, TABLE_LIST *dt,
|
||||
|
||||
|
||||
int
|
||||
multi_delete::prepare(List<Item> &values)
|
||||
multi_delete::prepare(List<Item> &values, SELECT_LEX_UNIT *u)
|
||||
{
|
||||
DBUG_ENTER("multi_delete::prepare");
|
||||
unit= u;
|
||||
do_delete = true;
|
||||
thd->proc_info="deleting from main table";
|
||||
|
||||
|
@ -28,21 +28,25 @@
|
||||
static const char *any_db="*any*"; // Special symbol for check_access
|
||||
|
||||
|
||||
int mysql_derived(THD *thd, LEX *lex,SELECT_LEX *s, TABLE_LIST *t)
|
||||
int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit, TABLE_LIST *t)
|
||||
{
|
||||
SELECT_LEX *sl=s;
|
||||
/*
|
||||
TODO: make derived tables with union inside (now only 1 SELECT may be
|
||||
procesed)
|
||||
*/
|
||||
SELECT_LEX *sl= (SELECT_LEX*)unit->slave;
|
||||
List<Item> item_list;
|
||||
TABLE *table;
|
||||
int res;
|
||||
select_union *derived_result;
|
||||
TABLE_LIST *tables=(TABLE_LIST *)sl->table_list.first;
|
||||
TABLE_LIST *tables= (TABLE_LIST *)sl->table_list.first;
|
||||
TMP_TABLE_PARAM tmp_table_param;
|
||||
DBUG_ENTER("mysql_derived");
|
||||
|
||||
if (tables)
|
||||
res=check_table_access(thd,SELECT_ACL, tables);
|
||||
res= check_table_access(thd,SELECT_ACL, tables);
|
||||
else
|
||||
res=check_access(thd, SELECT_ACL, any_db);
|
||||
res= check_access(thd, SELECT_ACL, any_db);
|
||||
if (res)
|
||||
DBUG_RETURN(-1);
|
||||
|
||||
@ -52,7 +56,7 @@ int mysql_derived(THD *thd, LEX *lex,SELECT_LEX *s, TABLE_LIST *t)
|
||||
{
|
||||
if (cursor->derived)
|
||||
{
|
||||
res=mysql_derived(thd,lex,(SELECT_LEX *)cursor->derived,cursor);
|
||||
res=mysql_derived(thd, lex, (SELECT_LEX_UNIT *)cursor->derived, cursor);
|
||||
if (res) DBUG_RETURN(res);
|
||||
}
|
||||
}
|
||||
@ -71,9 +75,11 @@ int mysql_derived(THD *thd, LEX *lex,SELECT_LEX *s, TABLE_LIST *t)
|
||||
}
|
||||
bzero((char*) &tmp_table_param,sizeof(tmp_table_param));
|
||||
tmp_table_param.field_count=item_list.elements;
|
||||
if (!(table=create_tmp_table(thd, &tmp_table_param, sl->item_list,
|
||||
(ORDER*) 0, 0, 1, 0,
|
||||
(sl->options | thd->options | TMP_TABLE_ALL_COLUMNS))))
|
||||
if (!(table= create_tmp_table(thd, &tmp_table_param, sl->item_list,
|
||||
(ORDER*) 0, 0, 1, 0,
|
||||
(sl->options | thd->options |
|
||||
TMP_TABLE_ALL_COLUMNS),
|
||||
unit)))
|
||||
{
|
||||
res=-1;
|
||||
goto exit;
|
||||
@ -81,11 +87,11 @@ int mysql_derived(THD *thd, LEX *lex,SELECT_LEX *s, TABLE_LIST *t)
|
||||
|
||||
if ((derived_result=new select_union(table)))
|
||||
{
|
||||
thd->offset_limit=sl->offset_limit;
|
||||
thd->select_limit=sl->select_limit+sl->offset_limit;
|
||||
if (thd->select_limit < sl->select_limit)
|
||||
thd->select_limit= HA_POS_ERROR;
|
||||
if (thd->select_limit == HA_POS_ERROR)
|
||||
unit->offset_limit_cnt= sl->offset_limit;
|
||||
unit->select_limit_cnt= sl->select_limit+sl->offset_limit;
|
||||
if (unit->select_limit_cnt < sl->select_limit)
|
||||
unit->select_limit_cnt= HA_POS_ERROR;
|
||||
if (unit->select_limit_cnt == HA_POS_ERROR)
|
||||
sl->options&= ~OPTION_FOUND_ROWS;
|
||||
|
||||
res=mysql_select(thd, tables, sl->item_list,
|
||||
@ -93,7 +99,7 @@ int mysql_derived(THD *thd, LEX *lex,SELECT_LEX *s, TABLE_LIST *t)
|
||||
(ORDER*) sl->group_list.first,
|
||||
sl->having, (ORDER*) NULL,
|
||||
sl->options | thd->options | SELECT_NO_UNLOCK,
|
||||
derived_result);
|
||||
derived_result, unit);
|
||||
if (!res)
|
||||
{
|
||||
// Here we entirely fix both TABLE_LIST and list of SELECT's as there were no derived tables
|
||||
@ -103,9 +109,8 @@ int mysql_derived(THD *thd, LEX *lex,SELECT_LEX *s, TABLE_LIST *t)
|
||||
{
|
||||
t->real_name=table->real_name;
|
||||
t->table=table;
|
||||
sl->prev->next=sl->next;
|
||||
sl->exclude();
|
||||
t->derived=(SELECT_LEX *)0; // just in case ...
|
||||
if (!sl->next) lex->last_select = sl;
|
||||
}
|
||||
}
|
||||
delete derived_result;
|
||||
|
@ -1266,10 +1266,11 @@ bool delayed_insert::handle_inserts(void)
|
||||
***************************************************************************/
|
||||
|
||||
int
|
||||
select_insert::prepare(List<Item> &values)
|
||||
select_insert::prepare(List<Item> &values, SELECT_LEX_UNIT *u)
|
||||
{
|
||||
DBUG_ENTER("select_insert::prepare");
|
||||
|
||||
unit= u;
|
||||
save_time_stamp=table->time_stamp;
|
||||
if (check_insert_fields(thd,table,*fields,values,1))
|
||||
DBUG_RETURN(1);
|
||||
@ -1302,9 +1303,9 @@ select_insert::~select_insert()
|
||||
|
||||
bool select_insert::send_data(List<Item> &values)
|
||||
{
|
||||
if (thd->offset_limit)
|
||||
if (unit->offset_limit_cnt)
|
||||
{ // using limit offset,count
|
||||
thd->offset_limit--;
|
||||
unit->offset_limit_cnt--;
|
||||
return 0;
|
||||
}
|
||||
if (fields->elements)
|
||||
@ -1380,10 +1381,11 @@ bool select_insert::send_eof()
|
||||
***************************************************************************/
|
||||
|
||||
int
|
||||
select_create::prepare(List<Item> &values)
|
||||
select_create::prepare(List<Item> &values, SELECT_LEX_UNIT *u)
|
||||
{
|
||||
DBUG_ENTER("select_create::prepare");
|
||||
|
||||
unit= u;
|
||||
table=create_table_from_items(thd, create_info, db, name,
|
||||
extra_fields, keys, &values, &lock);
|
||||
if (!table)
|
||||
@ -1413,9 +1415,9 @@ select_create::prepare(List<Item> &values)
|
||||
|
||||
bool select_create::send_data(List<Item> &values)
|
||||
{
|
||||
if (thd->offset_limit)
|
||||
if (unit->offset_limit_cnt)
|
||||
{ // using limit offset,count
|
||||
thd->offset_limit--;
|
||||
unit->offset_limit_cnt--;
|
||||
return 0;
|
||||
}
|
||||
fill_record(field,values);
|
||||
|
117
sql/sql_lex.cc
117
sql/sql_lex.cc
@ -879,3 +879,120 @@ int yylex(void *arg)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
st_select_lex structures initialisations
|
||||
*/
|
||||
|
||||
void st_select_lex_node::init_query()
|
||||
{
|
||||
next= master= slave= link_next= 0;
|
||||
prev= link_prev= 0;
|
||||
}
|
||||
|
||||
void st_select_lex_node::init_select()
|
||||
{
|
||||
order_list.elements= 0;
|
||||
order_list.first= 0;
|
||||
order_list.next= (byte**) &order_list.first;
|
||||
select_limit= HA_POS_ERROR;
|
||||
offset_limit= 0;
|
||||
}
|
||||
|
||||
void st_select_lex_unit::init_query()
|
||||
{
|
||||
st_select_lex_node::init_query();
|
||||
global_parameters= this;
|
||||
select_limit_cnt= HA_POS_ERROR;
|
||||
offset_limit_cnt= 0;
|
||||
}
|
||||
|
||||
void st_select_lex::init_query()
|
||||
{
|
||||
st_select_lex_node::init_query();
|
||||
table_list.elements= 0;
|
||||
table_list.first= 0;
|
||||
table_list.next= (byte**) &table_list.first;
|
||||
item_list.empty();
|
||||
}
|
||||
|
||||
void st_select_lex::init_select()
|
||||
{
|
||||
st_select_lex_node::init_select();
|
||||
group_list.elements= 0;
|
||||
group_list.first= 0;
|
||||
group_list.next= (byte**) &group_list.first;
|
||||
options= 0;
|
||||
where= having= 0;
|
||||
when_list.empty();
|
||||
expr_list.empty();
|
||||
interval_list.empty();
|
||||
use_index.empty();
|
||||
ftfunc_list.empty();
|
||||
linkage=UNSPECIFIED_TYPE;
|
||||
}
|
||||
|
||||
/*
|
||||
st_select_lex structures linking
|
||||
*/
|
||||
|
||||
/* include on level down */
|
||||
void st_select_lex_node::include_down(st_select_lex_node *upper)
|
||||
{
|
||||
if ((next= upper->slave))
|
||||
next->prev= &next;
|
||||
prev= &upper->slave;
|
||||
upper->slave= this;
|
||||
master= upper;
|
||||
}
|
||||
|
||||
/* include neighbour (on same level) */
|
||||
void st_select_lex_node::include_neighbour(st_select_lex_node *before)
|
||||
{
|
||||
if ((next= before->next))
|
||||
next->prev= &next;
|
||||
prev= &before->next;
|
||||
before->next= this;
|
||||
master= before->master;
|
||||
}
|
||||
|
||||
/* including in global SELECT_LEX list */
|
||||
void st_select_lex_node::include_global(st_select_lex_node **plink)
|
||||
{
|
||||
if ((link_next= *plink))
|
||||
link_next->link_prev= &link_next;
|
||||
link_prev= plink;
|
||||
*plink= this;
|
||||
}
|
||||
|
||||
//excluding from global list (internal function)
|
||||
void st_select_lex_node::fast_exclude()
|
||||
{
|
||||
if(link_prev)
|
||||
{
|
||||
if ((*link_prev= link_next))
|
||||
link_next->link_prev= link_prev;
|
||||
// Remove slave structure
|
||||
for (; slave; slave= slave->next)
|
||||
slave->fast_exclude();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
excluding select_lex structure (except first (first select can't be
|
||||
deleted, because it is most upper select))
|
||||
*/
|
||||
void st_select_lex_node::exclude()
|
||||
{
|
||||
//exclude from global list
|
||||
fast_exclude();
|
||||
//exclude from other structures
|
||||
if ((*prev= next))
|
||||
next->prev= prev;
|
||||
/*
|
||||
We do not need following statements, because prev pointer of first
|
||||
list element point to master->slave
|
||||
if (master->slave == this)
|
||||
master->slave= next;
|
||||
*/
|
||||
}
|
||||
|
149
sql/sql_lex.h
149
sql/sql_lex.h
@ -103,28 +103,143 @@ typedef struct st_lex_master_info
|
||||
} LEX_MASTER_INFO;
|
||||
|
||||
|
||||
enum sub_select_type {UNSPECIFIED_TYPE,UNION_TYPE, INTERSECT_TYPE, EXCEPT_TYPE, NOT_A_SELECT, DERIVED_TABLE_TYPE};
|
||||
enum sub_select_type {UNSPECIFIED_TYPE,UNION_TYPE, INTERSECT_TYPE,
|
||||
EXCEPT_TYPE, GLOBAL_OPTIONS_TYPE, DERIVED_TABLE_TYPE};
|
||||
|
||||
/* The state of the lex parsing for selects */
|
||||
/*
|
||||
The state of the lex parsing for selects
|
||||
|
||||
All select describing structures linked with following pointers:
|
||||
- list of neighbors (next/prev) (prev of first element point to slave
|
||||
pointer of upper structure)
|
||||
- one level units for unit (union) structure
|
||||
- member of one union(unit) for ordinary select_lex
|
||||
- pointer to master
|
||||
- outer select_lex for unit (union)
|
||||
- unit structure for ordinary select_lex
|
||||
- pointer to slave
|
||||
- first list element of select_lex belonged to this unit for unit
|
||||
- first unit in list of units that belong to this select_lex (as
|
||||
subselects or derived tables) for ordinary select_lex
|
||||
- list of all select_lex (for group operation like correcting list of opened
|
||||
tables)
|
||||
for example for following query:
|
||||
|
||||
typedef struct st_select_lex {
|
||||
select *
|
||||
from table1
|
||||
where table1.field IN (select * from table1_1_1 union
|
||||
select * from table1_1_2)
|
||||
union
|
||||
select *
|
||||
from table2
|
||||
where table2.field=(select (select f1 from table2_1_1_1_1
|
||||
where table2_1_1_1_1.f2=table2_1_1.f3)
|
||||
from table2_1_1
|
||||
where table2_1_1.f1=table2.f2)
|
||||
union
|
||||
select * from table3;
|
||||
|
||||
we will have following structure:
|
||||
|
||||
|
||||
main unit
|
||||
select1 select2 select3
|
||||
|^^ |^
|
||||
s||| ||master
|
||||
l||| |+---------------------------------+
|
||||
a||| +---------------------------------+|
|
||||
v|||master slave ||
|
||||
e||+-------------------------+ ||
|
||||
V| neighbor | V|
|
||||
unit 1.1<==================>unit1.2 unit2.1
|
||||
select1.1.1 select 1.1.2 select1.2.1 select2.1.1 select2.1.2
|
||||
|^
|
||||
||
|
||||
V|
|
||||
unit2.1.1.1
|
||||
select2.1.1.1.1
|
||||
|
||||
|
||||
relation in main unit will be following:
|
||||
|
||||
main unit
|
||||
|^^^
|
||||
||||
|
||||
|||+------------------------------+
|
||||
||+--------------+ |
|
||||
slave||master | |
|
||||
V| neighbor | neighbor |
|
||||
select1<========>select2<========>select3
|
||||
|
||||
list of all select_lex will be following (as it will be constructed by
|
||||
parser):
|
||||
|
||||
select1->select2->select3->select2.1.1->select 2.1.2->select2.1.1.1.1-+
|
||||
|
|
||||
+---------------------------------------------------------------------+
|
||||
|
|
||||
+->select1.1.1->select1.1.2
|
||||
|
||||
*/
|
||||
|
||||
/*
|
||||
Base class for st_select_lex (SELECT_LEX) &
|
||||
st_select_lex_unit (SELECT_LEX_UNIT)
|
||||
*/
|
||||
struct st_select_lex_node {
|
||||
enum sub_select_type linkage;
|
||||
char *db,*db1,*table1,*db2,*table2; /* For outer join using .. */
|
||||
Item *where,*having;
|
||||
ha_rows select_limit,offset_limit;
|
||||
st_select_lex_node *next, **prev, /* neighbor list */
|
||||
*master, *slave, /* vertical links */
|
||||
*link_next, **link_prev; /* list of whole SELECT_LEX */
|
||||
SQL_LIST order_list; /* ORDER clause */
|
||||
ha_rows select_limit, offset_limit; /* LIMIT clause parameters */
|
||||
void init_query();
|
||||
void init_select();
|
||||
void include_down(st_select_lex_node *upper);
|
||||
void include_neighbour(st_select_lex_node *before);
|
||||
void include_global(st_select_lex_node **plink);
|
||||
void exclude();
|
||||
private:
|
||||
void fast_exclude();
|
||||
};
|
||||
|
||||
/*
|
||||
SELECT_LEX_UNIT - unit of selects (UNION, INTERSECT, ...) group
|
||||
SELECT_LEXs
|
||||
*/
|
||||
struct st_select_lex_unit: public st_select_lex_node {
|
||||
/*
|
||||
Pointer to 'last' select or pointer to unit where stored
|
||||
global parameters for union
|
||||
*/
|
||||
st_select_lex_node *global_parameters;
|
||||
/* LIMIT clause runtime counters */
|
||||
ha_rows select_limit_cnt, offset_limit_cnt;
|
||||
void init_query();
|
||||
};
|
||||
typedef struct st_select_lex_unit SELECT_LEX_UNIT;
|
||||
|
||||
/*
|
||||
SELECT_LEX - store information of parsed SELECT_LEX statment
|
||||
*/
|
||||
struct st_select_lex: public st_select_lex_node {
|
||||
char *db, *db1, *table1, *db2, *table2; /* For outer join using .. */
|
||||
Item *where, *having; /* WHERE & HAVING clauses */
|
||||
ulong options;
|
||||
List<List_item> expr_list;
|
||||
List<List_item> when_list;
|
||||
SQL_LIST order_list,table_list,group_list;
|
||||
List<Item> item_list;
|
||||
List<String> interval_list,use_index, *use_index_ptr,
|
||||
List<List_item> when_list; /* WHEN clause */
|
||||
SQL_LIST table_list, group_list; /* FROM & GROUP BY clauses */
|
||||
List<Item> item_list; /* list of fields & expressions */
|
||||
List<String> interval_list, use_index, *use_index_ptr,
|
||||
ignore_index, *ignore_index_ptr;
|
||||
List<Item_func_match> ftfunc_list;
|
||||
uint in_sum_expr, sort_default;
|
||||
bool create_refs, braces;
|
||||
st_select_lex *next, *prev;
|
||||
} SELECT_LEX;
|
||||
|
||||
bool create_refs,
|
||||
braces; /* SELECT ... UNION (SELECT ... ) <- this braces */
|
||||
void init_query();
|
||||
void init_select();
|
||||
};
|
||||
typedef struct st_select_lex SELECT_LEX;
|
||||
|
||||
class Set_option :public Sql_alloc {
|
||||
public:
|
||||
@ -137,13 +252,15 @@ public:
|
||||
:name(par_name), item(par_item), name_length(length), type(par_type) {}
|
||||
};
|
||||
|
||||
|
||||
/* The state of the lex parsing. This is saved in the THD struct */
|
||||
|
||||
typedef struct st_lex {
|
||||
uint yylineno,yytoklen; /* Simulate lex */
|
||||
LEX_YYSTYPE yylval;
|
||||
SELECT_LEX select_lex, *select, *last_select;
|
||||
SELECT_LEX_UNIT unit; /* most upper unit */
|
||||
SELECT_LEX select_lex, /* first SELECT_LEX */
|
||||
/* current SELECT_LEX in parsing */
|
||||
*select;
|
||||
uchar *ptr,*tok_start,*tok_end,*end_of_query;
|
||||
char *length,*dec,*change,*name;
|
||||
char *backup_dir; /* For RESTORE/BACKUP */
|
||||
|
143
sql/sql_parse.cc
143
sql/sql_parse.cc
@ -1203,11 +1203,12 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
|
||||
void
|
||||
mysql_execute_command(void)
|
||||
{
|
||||
int res=0;
|
||||
THD *thd=current_thd;
|
||||
int res= 0;
|
||||
THD *thd= current_thd;
|
||||
LEX *lex= &thd->lex;
|
||||
TABLE_LIST *tables=(TABLE_LIST*) lex->select_lex.table_list.first;
|
||||
SELECT_LEX *select_lex = lex->select;
|
||||
TABLE_LIST *tables= (TABLE_LIST*) lex->select_lex.table_list.first;
|
||||
SELECT_LEX *select_lex= lex->select;
|
||||
SELECT_LEX_UNIT *unit= &lex->unit;
|
||||
DBUG_ENTER("mysql_execute_command");
|
||||
|
||||
if (thd->slave_thread)
|
||||
@ -1240,8 +1241,10 @@ mysql_execute_command(void)
|
||||
{
|
||||
for (TABLE_LIST *cursor= tables;
|
||||
cursor;
|
||||
cursor=cursor->next)
|
||||
if (cursor->derived && mysql_derived(thd,lex,(SELECT_LEX *)cursor->derived,cursor))
|
||||
cursor= cursor->next)
|
||||
if (cursor->derived && mysql_derived(thd, lex,
|
||||
(SELECT_LEX_UNIT *)cursor->derived,
|
||||
cursor))
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
if ((lex->select_lex.next && create_total_list(thd,lex,&tables)) ||
|
||||
@ -1272,11 +1275,11 @@ mysql_execute_command(void)
|
||||
break; // Error message is given
|
||||
}
|
||||
|
||||
thd->offset_limit=select_lex->offset_limit;
|
||||
thd->select_limit=select_lex->select_limit+select_lex->offset_limit;
|
||||
if (thd->select_limit < select_lex->select_limit)
|
||||
thd->select_limit= HA_POS_ERROR; // no limit
|
||||
if (thd->select_limit == HA_POS_ERROR)
|
||||
unit->offset_limit_cnt =select_lex->offset_limit;
|
||||
unit->select_limit_cnt =select_lex->select_limit+select_lex->offset_limit;
|
||||
if (unit->select_limit_cnt < select_lex->select_limit)
|
||||
unit->select_limit_cnt= HA_POS_ERROR; // no limit
|
||||
if (unit->select_limit_cnt == HA_POS_ERROR)
|
||||
select_lex->options&= ~OPTION_FOUND_ROWS;
|
||||
|
||||
if (lex->exchange)
|
||||
@ -1501,10 +1504,11 @@ mysql_execute_command(void)
|
||||
for (table = tables->next ; table ; table=table->next)
|
||||
table->lock_type= lex->lock_option;
|
||||
}
|
||||
thd->offset_limit=select_lex->offset_limit;
|
||||
thd->select_limit=select_lex->select_limit+select_lex->offset_limit;
|
||||
if (thd->select_limit < select_lex->select_limit)
|
||||
thd->select_limit= HA_POS_ERROR; // No limit
|
||||
unit->offset_limit_cnt= select_lex->offset_limit;
|
||||
unit->select_limit_cnt= select_lex->select_limit+
|
||||
select_lex->offset_limit;
|
||||
if (unit->select_limit_cnt < select_lex->select_limit)
|
||||
unit->select_limit_cnt= HA_POS_ERROR; // No limit
|
||||
|
||||
/* Skip first table, which is the table we are creating */
|
||||
lex->select_lex.table_list.first=
|
||||
@ -1786,13 +1790,13 @@ mysql_execute_command(void)
|
||||
while ((item=value_list++))
|
||||
total_list.push_back(item);
|
||||
|
||||
res=mysql_select(thd,tables,total_list,
|
||||
select_lex->where,
|
||||
(ORDER *)NULL,(ORDER *)NULL,(Item *)NULL,
|
||||
(ORDER *)NULL,
|
||||
select_lex->options | thd->options |
|
||||
SELECT_NO_JOIN_CACHE,
|
||||
result);
|
||||
res= mysql_select(thd, tables, total_list,
|
||||
select_lex->where,
|
||||
(ORDER *)NULL, (ORDER *)NULL, (Item *)NULL,
|
||||
(ORDER *)NULL,
|
||||
select_lex->options | thd->options |
|
||||
SELECT_NO_JOIN_CACHE,
|
||||
result, unit);
|
||||
delete result;
|
||||
}
|
||||
else
|
||||
@ -1842,10 +1846,10 @@ mysql_execute_command(void)
|
||||
}
|
||||
|
||||
select_result *result;
|
||||
thd->offset_limit=select_lex->offset_limit;
|
||||
thd->select_limit=select_lex->select_limit+select_lex->offset_limit;
|
||||
if (thd->select_limit < select_lex->select_limit)
|
||||
thd->select_limit= HA_POS_ERROR; // No limit
|
||||
unit->offset_limit_cnt= select_lex->offset_limit;
|
||||
unit->select_limit_cnt= select_lex->select_limit+select_lex->offset_limit;
|
||||
if (unit->select_limit_cnt < select_lex->select_limit)
|
||||
unit->select_limit_cnt= HA_POS_ERROR; // No limit
|
||||
|
||||
if (check_dup(tables->db, tables->real_name, tables->next))
|
||||
{
|
||||
@ -1961,7 +1965,7 @@ mysql_execute_command(void)
|
||||
(ORDER *)NULL,
|
||||
select_lex->options | thd->options |
|
||||
SELECT_NO_JOIN_CACHE,
|
||||
result);
|
||||
result, unit);
|
||||
delete result;
|
||||
}
|
||||
else
|
||||
@ -2664,18 +2668,21 @@ static void
|
||||
mysql_init_query(THD *thd)
|
||||
{
|
||||
DBUG_ENTER("mysql_init_query");
|
||||
thd->lex.select_lex.item_list.empty();
|
||||
thd->lex.unit.init_query();
|
||||
thd->lex.unit.init_select();
|
||||
thd->lex.select_lex.init_query();
|
||||
thd->lex.unit.slave= &thd->lex.select_lex;
|
||||
thd->lex.unit.select_limit= thd->default_select_limit; //Global limit
|
||||
thd->lex.select_lex.master= &thd->lex.unit;
|
||||
thd->lex.select_lex.prev= &thd->lex.unit.slave;
|
||||
thd->lex.value_list.empty();
|
||||
thd->lex.select_lex.table_list.elements=0;
|
||||
thd->free_list=0; thd->lex.union_option=0;
|
||||
thd->lex.select = thd->lex.last_select = &thd->lex.select_lex;
|
||||
thd->lex.select_lex.table_list.first=0;
|
||||
thd->lex.select_lex.table_list.next= (byte**) &thd->lex.select_lex.table_list.first;
|
||||
thd->lex.select_lex.next=0;
|
||||
thd->fatal_error=0; // Safety
|
||||
thd->last_insert_id_used=thd->query_start_used=thd->insert_id_used=0;
|
||||
thd->sent_row_count=thd->examined_row_count=0;
|
||||
thd->safe_to_cache_query=1;
|
||||
thd->free_list= 0;
|
||||
thd->lex.union_option= 0;
|
||||
thd->lex.select= &thd->lex.select_lex;
|
||||
thd->fatal_error= 0; // Safety
|
||||
thd->last_insert_id_used= thd->query_start_used= thd->insert_id_used=0;
|
||||
thd->sent_row_count= thd->examined_row_count= 0;
|
||||
thd->safe_to_cache_query= 1;
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
|
||||
@ -2683,53 +2690,53 @@ void
|
||||
mysql_init_select(LEX *lex)
|
||||
{
|
||||
SELECT_LEX *select_lex = lex->select;
|
||||
select_lex->where=select_lex->having=0;
|
||||
select_lex->init_select();
|
||||
select_lex->select_limit=lex->thd->default_select_limit;
|
||||
select_lex->offset_limit=0;
|
||||
select_lex->options=0;
|
||||
select_lex->linkage=UNSPECIFIED_TYPE;
|
||||
lex->exchange = 0;
|
||||
lex->proc_list.first=0;
|
||||
select_lex->order_list.elements=select_lex->group_list.elements=0;
|
||||
select_lex->order_list.first=0;
|
||||
select_lex->order_list.next= (byte**) &select_lex->order_list.first;
|
||||
select_lex->group_list.first=0;
|
||||
select_lex->group_list.next= (byte**) &select_lex->group_list.first;
|
||||
select_lex->next = select_lex->prev = (SELECT_LEX *)NULL;
|
||||
}
|
||||
|
||||
bool
|
||||
mysql_new_select(LEX *lex)
|
||||
mysql_new_select(LEX *lex, bool move_down)
|
||||
{
|
||||
SELECT_LEX *select_lex = (SELECT_LEX *) lex->thd->calloc(sizeof(SELECT_LEX));
|
||||
if (!select_lex)
|
||||
return 1;
|
||||
lex->select=lex->last_select;
|
||||
lex->select->next=select_lex;
|
||||
lex->select=lex->last_select=select_lex;
|
||||
select_lex->table_list.next= (byte**) &select_lex->table_list.first;
|
||||
select_lex->item_list.empty();
|
||||
select_lex->when_list.empty();
|
||||
select_lex->expr_list.empty();
|
||||
select_lex->interval_list.empty();
|
||||
select_lex->use_index.empty();
|
||||
select_lex->ftfunc_list.empty();
|
||||
select_lex->init_query();
|
||||
select_lex->init_select();
|
||||
if (move_down)
|
||||
{
|
||||
/* first select_lex of subselect or derived table */
|
||||
SELECT_LEX_UNIT *unit=
|
||||
(SELECT_LEX_UNIT *) lex->thd->calloc(sizeof(SELECT_LEX_UNIT));
|
||||
if (!unit)
|
||||
return 1;
|
||||
unit->init_query();
|
||||
unit->init_select();
|
||||
unit->include_down(lex->select);
|
||||
select_lex->include_down(unit);
|
||||
}
|
||||
else
|
||||
select_lex->include_neighbour(lex->select);
|
||||
|
||||
((SELECT_LEX_UNIT*)select_lex->master)->global_parameters= select_lex;
|
||||
select_lex->include_global(&lex->select->link_next);
|
||||
lex->select= select_lex;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void mysql_init_multi_delete(LEX *lex)
|
||||
{
|
||||
lex->sql_command = SQLCOM_DELETE_MULTI;
|
||||
lex->sql_command= SQLCOM_DELETE_MULTI;
|
||||
mysql_init_select(lex);
|
||||
lex->select->select_limit=HA_POS_ERROR;
|
||||
lex->auxilliary_table_list=lex->select_lex.table_list;
|
||||
lex->select->table_list.elements=0;
|
||||
lex->select->table_list.first=0;
|
||||
lex->select->table_list.next= (byte**) &(lex->select->table_list.first);
|
||||
lex->select->select_limit= HA_POS_ERROR;
|
||||
lex->auxilliary_table_list= lex->select_lex.table_list;
|
||||
lex->select->init_query();
|
||||
}
|
||||
|
||||
void
|
||||
mysql_parse(THD *thd,char *inBuf,uint length)
|
||||
mysql_parse(THD *thd, char *inBuf, uint length)
|
||||
{
|
||||
DBUG_ENTER("mysql_parse");
|
||||
|
||||
@ -3159,7 +3166,7 @@ TABLE_LIST *add_table_to_list(Table_ident *table, LEX_STRING *alias,
|
||||
ptr->real_name_length=table->table.length;
|
||||
ptr->lock_type=flags;
|
||||
ptr->updating=updating;
|
||||
ptr->derived=(SELECT_LEX *)table->sel;
|
||||
ptr->derived= (SELECT_LEX_UNIT *) table->sel;
|
||||
if (use_index)
|
||||
ptr->use_index=(List<String> *) thd->memdup((gptr) use_index,
|
||||
sizeof(*use_index));
|
||||
@ -3204,8 +3211,8 @@ static bool create_total_list(THD *thd, LEX *lex, TABLE_LIST **result)
|
||||
SELECT_LEX *sl;
|
||||
TABLE_LIST **new_table_list= result, *aux;
|
||||
|
||||
*new_table_list=0; // end result list
|
||||
for (sl= &lex->select_lex; sl; sl=sl->next)
|
||||
*new_table_list= 0; // end result list
|
||||
for (sl= &lex->select_lex; sl; sl= (SELECT_LEX *) sl->next)
|
||||
{
|
||||
if (sl->order_list.first && sl->next && !sl->braces)
|
||||
{
|
||||
|
@ -65,7 +65,8 @@ static ORDER *remove_const(JOIN *join,ORDER *first_order,COND *cond,
|
||||
static int return_zero_rows(select_result *res,TABLE_LIST *tables,
|
||||
List<Item> &fields, bool send_row,
|
||||
uint select_options, const char *info,
|
||||
Item *having, Procedure *proc);
|
||||
Item *having, Procedure *proc,
|
||||
SELECT_LEX_UNIT *unit);
|
||||
static COND *optimize_cond(COND *conds,Item::cond_result *cond_value);
|
||||
static COND *remove_eq_conds(COND *cond,Item::cond_result *cond_value);
|
||||
static bool const_expression_in_where(COND *conds,Item *item, Item **comp_item);
|
||||
@ -166,7 +167,7 @@ int handle_select(THD *thd, LEX *lex, select_result *result)
|
||||
select_lex->having,
|
||||
(ORDER*) lex->proc_list.first,
|
||||
select_lex->options | thd->options,
|
||||
result);
|
||||
result, &(lex->unit));
|
||||
if (res && result)
|
||||
result->abort();
|
||||
delete result;
|
||||
@ -182,7 +183,8 @@ int handle_select(THD *thd, LEX *lex, select_result *result)
|
||||
int
|
||||
mysql_select(THD *thd,TABLE_LIST *tables,List<Item> &fields,COND *conds,
|
||||
ORDER *order, ORDER *group,Item *having,ORDER *proc_param,
|
||||
ulong select_options,select_result *result)
|
||||
ulong select_options,select_result *result,
|
||||
SELECT_LEX_UNIT *unit)
|
||||
{
|
||||
TABLE *tmp_table;
|
||||
int error, tmp_error;
|
||||
@ -195,8 +197,8 @@ mysql_select(THD *thd,TABLE_LIST *tables,List<Item> &fields,COND *conds,
|
||||
Procedure *procedure;
|
||||
List<Item> all_fields(fields);
|
||||
bool select_distinct;
|
||||
SELECT_LEX *select_lex = &(thd->lex.select_lex);
|
||||
SELECT_LEX *cur_sel = thd->lex.select;
|
||||
SELECT_LEX *select_lex= &(thd->lex.select_lex);
|
||||
SELECT_LEX *cur_sel= thd->lex.select;
|
||||
DBUG_ENTER("mysql_select");
|
||||
|
||||
/* Check that all tables, fields, conds and order are ok */
|
||||
@ -312,7 +314,8 @@ mysql_select(THD *thd,TABLE_LIST *tables,List<Item> &fields,COND *conds,
|
||||
join.do_send_rows = 1;
|
||||
join.group= group != 0;
|
||||
join.row_limit= ((select_distinct || order || group) ? HA_POS_ERROR :
|
||||
thd->select_limit);
|
||||
unit->select_limit_cnt);
|
||||
join.unit= unit;
|
||||
|
||||
#ifdef RESTRICTED_GROUP
|
||||
if (join.sum_func_count && !group && (join.func_count || join.field_count))
|
||||
@ -322,7 +325,7 @@ mysql_select(THD *thd,TABLE_LIST *tables,List<Item> &fields,COND *conds,
|
||||
DBUG_RETURN(-1);
|
||||
}
|
||||
#endif
|
||||
if (!procedure && result->prepare(fields))
|
||||
if (!procedure && result->prepare(fields, unit))
|
||||
{ /* purecov: inspected */
|
||||
DBUG_RETURN(-1); /* purecov: inspected */
|
||||
}
|
||||
@ -351,7 +354,7 @@ mysql_select(THD *thd,TABLE_LIST *tables,List<Item> &fields,COND *conds,
|
||||
delete procedure;
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
if (cond_value == Item::COND_FALSE || !thd->select_limit)
|
||||
if (cond_value == Item::COND_FALSE || !unit->select_limit_cnt)
|
||||
{ /* Impossible cond */
|
||||
if (select_options & SELECT_DESCRIBE && select_lex->next)
|
||||
select_describe(&join,false,false,false,"Impossible WHERE");
|
||||
@ -359,7 +362,7 @@ mysql_select(THD *thd,TABLE_LIST *tables,List<Item> &fields,COND *conds,
|
||||
error=return_zero_rows(result, tables, fields,
|
||||
join.tmp_table_param.sum_func_count != 0 && !group,
|
||||
select_options,"Impossible WHERE",having,
|
||||
procedure);
|
||||
procedure, unit);
|
||||
delete procedure;
|
||||
DBUG_RETURN(error);
|
||||
}
|
||||
@ -376,8 +379,8 @@ mysql_select(THD *thd,TABLE_LIST *tables,List<Item> &fields,COND *conds,
|
||||
select_describe(&join,false,false,false,"No matching min/max row");
|
||||
else
|
||||
error=return_zero_rows(result, tables, fields, !group,
|
||||
select_options,"No matching min/max row",
|
||||
having,procedure);
|
||||
select_options, "No matching min/max row",
|
||||
having, procedure, unit);
|
||||
delete procedure;
|
||||
DBUG_RETURN(error);
|
||||
}
|
||||
@ -435,9 +438,9 @@ mysql_select(THD *thd,TABLE_LIST *tables,List<Item> &fields,COND *conds,
|
||||
if (join.const_table_map != join.found_const_table_map &&
|
||||
!(select_options & SELECT_DESCRIBE))
|
||||
{
|
||||
error=return_zero_rows(result,tables,fields,
|
||||
join.tmp_table_param.sum_func_count != 0 &&
|
||||
!group,0,"",having,procedure);
|
||||
error= return_zero_rows(result, tables, fields,
|
||||
join.tmp_table_param.sum_func_count != 0 &&
|
||||
!group, 0, "", having, procedure, unit);
|
||||
goto err;
|
||||
}
|
||||
if (!(thd->options & OPTION_BIG_SELECTS) &&
|
||||
@ -483,11 +486,12 @@ mysql_select(THD *thd,TABLE_LIST *tables,List<Item> &fields,COND *conds,
|
||||
if (select_options & SELECT_DESCRIBE && select_lex->next)
|
||||
select_describe(&join,false,false,false,"Impossible WHERE noticed after reading const tables");
|
||||
else
|
||||
error=return_zero_rows(result,tables,fields,
|
||||
join.tmp_table_param.sum_func_count != 0 && !group,
|
||||
select_options,
|
||||
"Impossible WHERE noticed after reading const tables",
|
||||
having,procedure);
|
||||
error= return_zero_rows(result,tables,fields,
|
||||
join.tmp_table_param.sum_func_count != 0 &&
|
||||
!group,
|
||||
select_options,
|
||||
"Impossible WHERE noticed after reading const tables",
|
||||
having, procedure, unit);
|
||||
goto err;
|
||||
}
|
||||
|
||||
@ -501,12 +505,12 @@ mysql_select(THD *thd,TABLE_LIST *tables,List<Item> &fields,COND *conds,
|
||||
select_distinct=0;
|
||||
}
|
||||
else if (select_distinct && join.tables - join.const_tables == 1 &&
|
||||
(thd->select_limit == HA_POS_ERROR ||
|
||||
(unit->select_limit_cnt == HA_POS_ERROR ||
|
||||
(join.select_options & OPTION_FOUND_ROWS) ||
|
||||
order &&
|
||||
!(skip_sort_order=
|
||||
test_if_skip_sort_order(&join.join_tab[join.const_tables],
|
||||
order, thd->select_limit,1))))
|
||||
order, unit->select_limit_cnt,1))))
|
||||
{
|
||||
if ((group=create_distinct_group(order,fields)))
|
||||
{
|
||||
@ -593,7 +597,7 @@ mysql_select(THD *thd,TABLE_LIST *tables,List<Item> &fields,COND *conds,
|
||||
((group && join.const_tables != join.tables &&
|
||||
(!simple_group ||
|
||||
!test_if_skip_sort_order(&join.join_tab[join.const_tables], group,
|
||||
thd->select_limit,0))) ||
|
||||
unit->select_limit_cnt, 0))) ||
|
||||
select_distinct) &&
|
||||
join.tmp_table_param.quick_group && !procedure)
|
||||
{
|
||||
@ -610,7 +614,7 @@ mysql_select(THD *thd,TABLE_LIST *tables,List<Item> &fields,COND *conds,
|
||||
test_if_skip_sort_order(&join.join_tab[join.const_tables], order,
|
||||
(join.const_tables != join.tables - 1 ||
|
||||
(join.select_options & OPTION_FOUND_ROWS)) ?
|
||||
HA_POS_ERROR : thd->select_limit,0))))
|
||||
HA_POS_ERROR : unit->select_limit_cnt, 0))))
|
||||
order=0;
|
||||
select_describe(&join,need_tmp,
|
||||
order != 0 && !skip_sort_order,
|
||||
@ -637,7 +641,7 @@ mysql_select(THD *thd,TABLE_LIST *tables,List<Item> &fields,COND *conds,
|
||||
group && simple_group,
|
||||
(order == 0 || skip_sort_order) &&
|
||||
!(join.select_options & OPTION_FOUND_ROWS),
|
||||
join.select_options)))
|
||||
join.select_options, unit)))
|
||||
goto err; /* purecov: inspected */
|
||||
|
||||
if (having && (join.sort_and_group || (tmp_table->distinct && !group)))
|
||||
@ -690,7 +694,7 @@ mysql_select(THD *thd,TABLE_LIST *tables,List<Item> &fields,COND *conds,
|
||||
if (order && skip_sort_order)
|
||||
{
|
||||
(void) test_if_skip_sort_order(&join.join_tab[join.const_tables],
|
||||
order, thd->select_limit,0);
|
||||
order, unit->select_limit_cnt, 0);
|
||||
order=0;
|
||||
}
|
||||
}
|
||||
@ -760,7 +764,7 @@ mysql_select(THD *thd,TABLE_LIST *tables,List<Item> &fields,COND *conds,
|
||||
(ORDER*) 0,
|
||||
select_distinct && !group,
|
||||
1, 0,
|
||||
join.select_options)))
|
||||
join.select_options, unit)))
|
||||
goto err; /* purecov: inspected */
|
||||
if (group)
|
||||
{
|
||||
@ -817,9 +821,9 @@ mysql_select(THD *thd,TABLE_LIST *tables,List<Item> &fields,COND *conds,
|
||||
if (procedure)
|
||||
{
|
||||
if (procedure->change_columns(fields) ||
|
||||
result->prepare(fields))
|
||||
result->prepare(fields, unit))
|
||||
goto err;
|
||||
count_field_types(&join.tmp_table_param,all_fields,0);
|
||||
count_field_types(&join.tmp_table_param, all_fields, 0);
|
||||
}
|
||||
if (join.group || join.tmp_table_param.sum_func_count ||
|
||||
(procedure && (procedure->flags & PROC_GROUP)))
|
||||
@ -864,7 +868,7 @@ mysql_select(THD *thd,TABLE_LIST *tables,List<Item> &fields,COND *conds,
|
||||
(having || group ||
|
||||
join.const_tables != join.tables - 1 ||
|
||||
(join.select_options & OPTION_FOUND_ROWS)) ?
|
||||
HA_POS_ERROR : thd->select_limit))
|
||||
HA_POS_ERROR : unit->select_limit_cnt))
|
||||
goto err; /* purecov: inspected */
|
||||
}
|
||||
join.having=having; // Actually a parameter
|
||||
@ -2480,7 +2484,8 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond)
|
||||
|
||||
if ((tab->keys & ~ tab->const_keys && i > 0) ||
|
||||
(tab->const_keys && i == join->const_tables &&
|
||||
join->thd->select_limit < join->best_positions[i].records_read &&
|
||||
join->unit->select_limit_cnt <
|
||||
join->best_positions[i].records_read &&
|
||||
!(join->select_options & OPTION_FOUND_ROWS)))
|
||||
{
|
||||
/* Join with outer join condition */
|
||||
@ -2491,7 +2496,7 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond)
|
||||
(join->select_options &
|
||||
OPTION_FOUND_ROWS ?
|
||||
HA_POS_ERROR :
|
||||
join->thd->select_limit)) < 0)
|
||||
join->unit->select_limit_cnt)) < 0)
|
||||
DBUG_RETURN(1); // Impossible range
|
||||
sel->cond=orig_cond;
|
||||
}
|
||||
@ -2929,7 +2934,7 @@ remove_const(JOIN *join,ORDER *first_order, COND *cond, bool *simple_order)
|
||||
static int
|
||||
return_zero_rows(select_result *result,TABLE_LIST *tables,List<Item> &fields,
|
||||
bool send_row, uint select_options,const char *info,
|
||||
Item *having, Procedure *procedure)
|
||||
Item *having, Procedure *procedure, SELECT_LEX_UNIT *unit)
|
||||
{
|
||||
DBUG_ENTER("return_zero_rows");
|
||||
|
||||
@ -2940,7 +2945,7 @@ return_zero_rows(select_result *result,TABLE_LIST *tables,List<Item> &fields,
|
||||
}
|
||||
if (procedure)
|
||||
{
|
||||
if (result->prepare(fields)) // This hasn't been done yet
|
||||
if (result->prepare(fields, unit)) // This hasn't been done yet
|
||||
DBUG_RETURN(-1);
|
||||
}
|
||||
if (send_row)
|
||||
@ -3475,7 +3480,8 @@ Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type,
|
||||
TABLE *
|
||||
create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
|
||||
ORDER *group, bool distinct, bool save_sum_fields,
|
||||
bool allow_distinct_limit, ulong select_options)
|
||||
bool allow_distinct_limit, ulong select_options,
|
||||
SELECT_LEX_UNIT *unit)
|
||||
{
|
||||
TABLE *table;
|
||||
uint i,field_count,reclength,null_count,null_pack_length,
|
||||
@ -3846,8 +3852,8 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
|
||||
test(null_pack_length));
|
||||
if (allow_distinct_limit)
|
||||
{
|
||||
set_if_smaller(table->max_rows,thd->select_limit);
|
||||
param->end_write_records=thd->select_limit;
|
||||
set_if_smaller(table->max_rows, unit->select_limit_cnt);
|
||||
param->end_write_records= unit->select_limit_cnt;
|
||||
}
|
||||
else
|
||||
param->end_write_records= HA_POS_ERROR;
|
||||
@ -4892,7 +4898,8 @@ end_send(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)),
|
||||
error=join->result->send_data(*join->fields);
|
||||
if (error)
|
||||
DBUG_RETURN(-1); /* purecov: inspected */
|
||||
if (++join->send_records >= join->thd->select_limit && join->do_send_rows)
|
||||
if (++join->send_records >= join->unit->select_limit_cnt &&
|
||||
join->do_send_rows)
|
||||
{
|
||||
if (join->select_options & OPTION_FOUND_ROWS)
|
||||
{
|
||||
@ -4907,8 +4914,8 @@ end_send(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)),
|
||||
}
|
||||
else
|
||||
{
|
||||
join->do_send_rows=0;
|
||||
join->thd->select_limit = HA_POS_ERROR;
|
||||
join->do_send_rows= 0;
|
||||
join->unit->select_limit= HA_POS_ERROR;
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
}
|
||||
@ -4969,13 +4976,13 @@ end_send_group(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)),
|
||||
DBUG_RETURN(-1); /* purecov: inspected */
|
||||
if (end_of_records)
|
||||
DBUG_RETURN(0);
|
||||
if (!error && ++join->send_records >= join->thd->select_limit &&
|
||||
if (!error && ++join->send_records >= join->unit->select_limit_cnt &&
|
||||
join->do_send_rows)
|
||||
{
|
||||
if (!(join->select_options & OPTION_FOUND_ROWS))
|
||||
DBUG_RETURN(-3); // Abort nicely
|
||||
join->do_send_rows=0;
|
||||
join->thd->select_limit = HA_POS_ERROR;
|
||||
join->unit->select_limit_cnt = HA_POS_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -5056,7 +5063,7 @@ end_write(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)),
|
||||
if (!(join->select_options & OPTION_FOUND_ROWS))
|
||||
DBUG_RETURN(-3);
|
||||
join->do_send_rows=0;
|
||||
join->thd->select_limit = HA_POS_ERROR;
|
||||
join->unit->select_limit_cnt = HA_POS_ERROR;
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
}
|
||||
@ -5755,7 +5762,7 @@ remove_duplicates(JOIN *join, TABLE *entry,List<Item> &fields, Item *having)
|
||||
|
||||
if (!field_count)
|
||||
{ // only const items
|
||||
join->thd->select_limit=1; // Only send first row
|
||||
join->unit->select_limit_cnt= 1; // Only send first row
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
Field **first_field=entry->field+entry->fields - field_count;
|
||||
|
@ -173,6 +173,8 @@ class JOIN {
|
||||
select_result *result;
|
||||
TMP_TABLE_PARAM tmp_table_param;
|
||||
MYSQL_LOCK *lock;
|
||||
// unit structure (with global parameters) for this select
|
||||
SELECT_LEX_UNIT *unit;
|
||||
};
|
||||
|
||||
|
||||
@ -187,7 +189,8 @@ void TEST_join(JOIN *join);
|
||||
bool store_val_in_field(Field *field,Item *val);
|
||||
TABLE *create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
|
||||
ORDER *group, bool distinct, bool save_sum_fields,
|
||||
bool allow_distinct_limit, ulong select_options);
|
||||
bool allow_distinct_limit, ulong select_options,
|
||||
SELECT_LEX_UNIT *unit);
|
||||
void free_tmp_table(THD *thd, TABLE *entry);
|
||||
void count_field_types(TMP_TABLE_PARAM *param, List<Item> &fields,
|
||||
bool reset_with_sum_func);
|
||||
|
124
sql/sql_union.cc
124
sql/sql_union.cc
@ -27,8 +27,8 @@
|
||||
|
||||
int mysql_union(THD *thd, LEX *lex,select_result *result)
|
||||
{
|
||||
SELECT_LEX *sl, *last_sl, *lex_sl;
|
||||
ORDER *order;
|
||||
SELECT_LEX *sl;
|
||||
SELECT_LEX_UNIT *unit= &(lex->unit);
|
||||
List<Item> item_list;
|
||||
TABLE *table;
|
||||
int describe=(lex->select_lex.options & SELECT_DESCRIBE) ? 1 : 0;
|
||||
@ -39,12 +39,12 @@ int mysql_union(THD *thd, LEX *lex,select_result *result)
|
||||
TMP_TABLE_PARAM tmp_table_param;
|
||||
select_union *union_result;
|
||||
DBUG_ENTER("mysql_union");
|
||||
st_select_lex_node * global;
|
||||
|
||||
/* Fix tables 'to-be-unioned-from' list to point at opened tables */
|
||||
last_sl= &lex->select_lex;
|
||||
for (sl= last_sl;
|
||||
sl && sl->linkage != NOT_A_SELECT;
|
||||
last_sl=sl, sl=sl->next)
|
||||
for (sl= &lex->select_lex;
|
||||
sl;
|
||||
sl= (SELECT_LEX *) sl->next)
|
||||
{
|
||||
for (TABLE_LIST *cursor= (TABLE_LIST *)sl->table_list.first;
|
||||
cursor;
|
||||
@ -52,31 +52,13 @@ int mysql_union(THD *thd, LEX *lex,select_result *result)
|
||||
cursor->table= ((TABLE_LIST*) cursor->table)->table;
|
||||
}
|
||||
|
||||
/* last_sel now points at the last select where the ORDER BY is stored */
|
||||
if (sl)
|
||||
/* Global option */
|
||||
if (((void*)(global= unit->global_parameters)) == ((void*)unit))
|
||||
{
|
||||
/*
|
||||
The found SL is an extra SELECT_LEX argument that contains
|
||||
the ORDER BY and LIMIT parameter for the whole UNION
|
||||
*/
|
||||
lex_sl= sl;
|
||||
order= (ORDER *) lex_sl->order_list.first;
|
||||
found_rows_for_union = lex->select_lex.options & OPTION_FOUND_ROWS && !describe && sl->select_limit;
|
||||
found_rows_for_union = lex->select_lex.options & OPTION_FOUND_ROWS &&
|
||||
!describe && global->select_limit;
|
||||
if (found_rows_for_union)
|
||||
lex->select_lex.options ^= OPTION_FOUND_ROWS;
|
||||
// This is done to eliminate unnecessary slowing down of the first query
|
||||
if (!order || !describe)
|
||||
last_sl->next=0; // Remove this extra element
|
||||
}
|
||||
else if (!last_sl->braces)
|
||||
{
|
||||
lex_sl= last_sl; // ORDER BY is here
|
||||
order= (ORDER *) lex_sl->order_list.first;
|
||||
}
|
||||
else
|
||||
{
|
||||
lex_sl=0;
|
||||
order=0;
|
||||
}
|
||||
|
||||
if (describe)
|
||||
@ -113,11 +95,12 @@ int mysql_union(THD *thd, LEX *lex,select_result *result)
|
||||
|
||||
bzero((char*) &tmp_table_param,sizeof(tmp_table_param));
|
||||
tmp_table_param.field_count=item_list.elements;
|
||||
if (!(table=create_tmp_table(thd, &tmp_table_param, item_list,
|
||||
(ORDER*) 0, !describe & !lex->union_option,
|
||||
1, 0,
|
||||
(lex->select_lex.options | thd->options |
|
||||
TMP_TABLE_ALL_COLUMNS))))
|
||||
if (!(table= create_tmp_table(thd, &tmp_table_param, item_list,
|
||||
(ORDER*) 0, !describe & !lex->union_option,
|
||||
1, 0,
|
||||
(lex->select_lex.options | thd->options |
|
||||
TMP_TABLE_ALL_COLUMNS),
|
||||
unit)))
|
||||
DBUG_RETURN(-1);
|
||||
table->file->extra(HA_EXTRA_WRITE_CACHE);
|
||||
table->file->extra(HA_EXTRA_IGNORE_DUP_KEY);
|
||||
@ -133,25 +116,29 @@ int mysql_union(THD *thd, LEX *lex,select_result *result)
|
||||
}
|
||||
union_result->save_time_stamp=!describe;
|
||||
|
||||
for (sl= &lex->select_lex; sl; sl=sl->next)
|
||||
for (sl= &lex->select_lex; sl; sl= (SELECT_LEX*) sl->next)
|
||||
{
|
||||
lex->select=sl;
|
||||
thd->offset_limit=sl->offset_limit;
|
||||
thd->select_limit=sl->select_limit+sl->offset_limit;
|
||||
if (thd->select_limit < sl->select_limit)
|
||||
thd->select_limit= HA_POS_ERROR; // no limit
|
||||
if (thd->select_limit == HA_POS_ERROR)
|
||||
unit->offset_limit_cnt= sl->offset_limit;
|
||||
unit->select_limit_cnt= sl->select_limit+sl->offset_limit;
|
||||
if (unit->select_limit_cnt < sl->select_limit)
|
||||
unit->select_limit_cnt= HA_POS_ERROR; // no limit
|
||||
if (unit->select_limit_cnt == HA_POS_ERROR)
|
||||
sl->options&= ~OPTION_FOUND_ROWS;
|
||||
|
||||
res=mysql_select(thd, (describe && sl->linkage==NOT_A_SELECT) ? first_table : (TABLE_LIST*) sl->table_list.first,
|
||||
sl->item_list,
|
||||
sl->where,
|
||||
(sl->braces) ? (ORDER *)sl->order_list.first : (ORDER *) 0,
|
||||
(ORDER*) sl->group_list.first,
|
||||
sl->having,
|
||||
(ORDER*) NULL,
|
||||
sl->options | thd->options | SELECT_NO_UNLOCK | ((describe) ? SELECT_DESCRIBE : 0),
|
||||
union_result);
|
||||
res= mysql_select(thd,
|
||||
(describe && sl->linkage==GLOBAL_OPTIONS_TYPE) ?
|
||||
first_table : (TABLE_LIST*) sl->table_list.first,
|
||||
sl->item_list,
|
||||
sl->where,
|
||||
(sl->braces) ?
|
||||
(ORDER *)sl->order_list.first : (ORDER *) 0,
|
||||
(ORDER*) sl->group_list.first,
|
||||
sl->having,
|
||||
(ORDER*) NULL,
|
||||
sl->options | thd->options |
|
||||
SELECT_NO_UNLOCK | ((describe) ? SELECT_DESCRIBE : 0),
|
||||
union_result, unit);
|
||||
if (res)
|
||||
goto exit;
|
||||
}
|
||||
@ -183,26 +170,20 @@ int mysql_union(THD *thd, LEX *lex,select_result *result)
|
||||
}
|
||||
if (!thd->fatal_error) // Check if EOM
|
||||
{
|
||||
if (lex_sl)
|
||||
{
|
||||
thd->offset_limit=lex_sl->offset_limit;
|
||||
thd->select_limit=lex_sl->select_limit+lex_sl->offset_limit;
|
||||
if (thd->select_limit < lex_sl->select_limit)
|
||||
thd->select_limit= HA_POS_ERROR; // no limit
|
||||
if (thd->select_limit == HA_POS_ERROR)
|
||||
thd->options&= ~OPTION_FOUND_ROWS;
|
||||
}
|
||||
else
|
||||
{
|
||||
thd->offset_limit= 0;
|
||||
thd->select_limit= thd->default_select_limit;
|
||||
}
|
||||
st_select_lex_node * global= unit->global_parameters;
|
||||
unit->offset_limit_cnt= global->offset_limit;
|
||||
unit->select_limit_cnt= global->select_limit+global->offset_limit;
|
||||
if (unit->select_limit_cnt < global->select_limit)
|
||||
unit->select_limit_cnt= HA_POS_ERROR; // no limit
|
||||
if (unit->select_limit_cnt == HA_POS_ERROR)
|
||||
thd->options&= ~OPTION_FOUND_ROWS;
|
||||
if (describe)
|
||||
thd->select_limit= HA_POS_ERROR; // no limit
|
||||
res=mysql_select(thd,&result_table_list,
|
||||
item_list, NULL, (describe) ? 0 : order,
|
||||
(ORDER*) NULL, NULL, (ORDER*) NULL,
|
||||
thd->options, result);
|
||||
unit->select_limit_cnt= HA_POS_ERROR; // no limit
|
||||
res= mysql_select(thd,&result_table_list,
|
||||
item_list, NULL,
|
||||
(describe) ? 0 : (ORDER*)global->order_list.first,
|
||||
(ORDER*) NULL, NULL, (ORDER*) NULL,
|
||||
thd->options, result, unit);
|
||||
if (found_rows_for_union && !res)
|
||||
thd->limit_found_rows = (ulonglong)table->file->records;
|
||||
}
|
||||
@ -226,7 +207,7 @@ select_union::select_union(TABLE *table_par)
|
||||
We can always use DUP_IGNORE because the temporary table will only
|
||||
contain a unique key if we are using not using UNION ALL
|
||||
*/
|
||||
info.handle_duplicates=DUP_IGNORE;
|
||||
info.handle_duplicates= DUP_IGNORE;
|
||||
}
|
||||
|
||||
select_union::~select_union()
|
||||
@ -234,8 +215,9 @@ select_union::~select_union()
|
||||
}
|
||||
|
||||
|
||||
int select_union::prepare(List<Item> &list)
|
||||
int select_union::prepare(List<Item> &list, SELECT_LEX_UNIT *u)
|
||||
{
|
||||
unit= u;
|
||||
if (save_time_stamp && list.elements != table->fields)
|
||||
{
|
||||
my_message(ER_WRONG_NUMBER_OF_COLUMNS_IN_SELECT,
|
||||
@ -247,9 +229,9 @@ int select_union::prepare(List<Item> &list)
|
||||
|
||||
bool select_union::send_data(List<Item> &values)
|
||||
{
|
||||
if (thd->offset_limit)
|
||||
if (unit->offset_limit_cnt)
|
||||
{ // using limit offset,count
|
||||
thd->offset_limit--;
|
||||
unit->offset_limit_cnt--;
|
||||
return 0;
|
||||
}
|
||||
fill_record(table->field,values);
|
||||
|
@ -379,9 +379,10 @@ multi_update::multi_update(THD *thd_arg, TABLE_LIST *ut, List<Item> &fs,
|
||||
}
|
||||
|
||||
int
|
||||
multi_update::prepare(List<Item> &values)
|
||||
multi_update::prepare(List<Item> &values, SELECT_LEX_UNIT *u)
|
||||
{
|
||||
DBUG_ENTER("multi_update::prepare");
|
||||
unit= u;
|
||||
do_update = true;
|
||||
thd->count_cuted_fields=1;
|
||||
thd->cuted_fields=0L;
|
||||
@ -466,15 +467,19 @@ multi_update::prepare(List<Item> &values)
|
||||
}
|
||||
if (counter)
|
||||
{
|
||||
Field_string offset(table_ref->table->file->ref_length,false,"offset",table_ref->table,true);
|
||||
Field_string offset(table_ref->table->file->ref_length, false,
|
||||
"offset", table_ref->table, true);
|
||||
temp_fields->push_front(new Item_field(((Field *)&offset)));
|
||||
// Here I make tmp tables
|
||||
int cnt=counter-1;
|
||||
TMP_TABLE_PARAM tmp_table_param;
|
||||
bzero((char*) &tmp_table_param,sizeof(tmp_table_param));
|
||||
tmp_table_param.field_count=temp_fields->elements;
|
||||
if (!(tmp_tables[cnt]=create_tmp_table(thd, &tmp_table_param, *temp_fields,
|
||||
(ORDER*) 0, 1, 0, 0, TMP_TABLE_ALL_COLUMNS)))
|
||||
if (!(tmp_tables[cnt]=create_tmp_table(thd, &tmp_table_param,
|
||||
*temp_fields,
|
||||
(ORDER*) 0, 1, 0, 0,
|
||||
TMP_TABLE_ALL_COLUMNS,
|
||||
unit)))
|
||||
{
|
||||
error = 1; // A proper error message is due here
|
||||
DBUG_RETURN(1);
|
||||
|
@ -1449,7 +1449,14 @@ select:
|
||||
select_init:
|
||||
SELECT_SYM select_part2 { Select->braces=false; } union
|
||||
|
|
||||
'(' SELECT_SYM select_part2 ')' { Select->braces=true;} union_opt
|
||||
'(' SELECT_SYM select_part2 ')'
|
||||
{
|
||||
SELECT_LEX * sel=Select;
|
||||
sel->braces=true;
|
||||
/* select in braces, can't contain global parameters */
|
||||
((SELECT_LEX_UNIT*)sel->master)->global_parameters=
|
||||
sel->master;
|
||||
} union_opt
|
||||
|
||||
|
||||
select_part2:
|
||||
@ -2155,23 +2162,22 @@ join_table:
|
||||
| '(' SELECT_SYM select_part3 ')' opt_table_alias
|
||||
{
|
||||
LEX *lex=Lex;
|
||||
SELECT_LEX *select_to_execute= lex->select;
|
||||
lex->select=lex->select->prev;
|
||||
if (!($$=add_table_to_list(new Table_ident(select_to_execute),
|
||||
$5,0,TL_UNLOCK)))
|
||||
SELECT_LEX_UNIT *unit= (SELECT_LEX_UNIT*) lex->select->master;
|
||||
lex->select= (SELECT_LEX*) unit->master;
|
||||
if (!($$= add_table_to_list(new Table_ident(unit),
|
||||
$5,0,TL_UNLOCK)))
|
||||
YYABORT;
|
||||
}
|
||||
|
||||
select_part3:
|
||||
{
|
||||
LEX *lex=Lex;
|
||||
lex->derived_tables=true;
|
||||
SELECT_LEX *tmp=lex->select;
|
||||
if (lex->select->linkage == NOT_A_SELECT || mysql_new_select(lex))
|
||||
LEX *lex= Lex;
|
||||
lex->derived_tables= true;
|
||||
if (lex->select->linkage == GLOBAL_OPTIONS_TYPE ||
|
||||
mysql_new_select(lex, 1))
|
||||
YYABORT;
|
||||
mysql_init_select(lex);
|
||||
lex->select->linkage=DERIVED_TABLE_TYPE;
|
||||
lex->select->prev=tmp;
|
||||
lex->select->linkage= DERIVED_TABLE_TYPE;
|
||||
}
|
||||
select_options select_item_list select_intoto
|
||||
|
||||
@ -3811,7 +3817,8 @@ union_list:
|
||||
net_printf(&lex->thd->net, ER_WRONG_USAGE,"UNION","INTO");
|
||||
YYABORT;
|
||||
}
|
||||
if (lex->select->linkage == NOT_A_SELECT || mysql_new_select(lex))
|
||||
if (lex->select->linkage == GLOBAL_OPTIONS_TYPE ||
|
||||
mysql_new_select(lex, 0))
|
||||
YYABORT;
|
||||
lex->select->linkage=UNION_TYPE;
|
||||
}
|
||||
@ -3826,10 +3833,15 @@ optional_order_or_limit:
|
||||
|
|
||||
{
|
||||
LEX *lex=Lex;
|
||||
if (!lex->select->braces || mysql_new_select(lex))
|
||||
if (!lex->select->braces)
|
||||
YYABORT;
|
||||
mysql_init_select(lex);
|
||||
lex->select->linkage=NOT_A_SELECT;
|
||||
((SELECT_LEX_UNIT*)lex->select->master)->global_parameters=
|
||||
lex->select->master;
|
||||
/*
|
||||
Following type conversion looks like hack, but all that need SELECT_LEX
|
||||
fields always check linkage type.
|
||||
*/
|
||||
lex->select= (SELECT_LEX*)lex->select->master;
|
||||
lex->select->select_limit=lex->thd->default_select_limit;
|
||||
}
|
||||
opt_order_clause limit_clause
|
||||
|
16
sql/table.h
16
sql/table.h
@ -139,18 +139,18 @@ typedef struct st_table_list {
|
||||
struct st_table_list *next;
|
||||
char *db,*name,*real_name;
|
||||
uint32 db_length, real_name_length;
|
||||
Item *on_expr; /* Used with outer join */
|
||||
struct st_table_list *natural_join; /* natural join on this table*/
|
||||
Item *on_expr; /* Used with outer join */
|
||||
struct st_table_list *natural_join; /* natural join on this table*/
|
||||
/* ... join ... USE INDEX ... IGNORE INDEX */
|
||||
List<String> *use_index,*ignore_index;
|
||||
List<String> *use_index, *ignore_index;
|
||||
TABLE *table;
|
||||
GRANT_INFO grant;
|
||||
thr_lock_type lock_type;
|
||||
uint outer_join; /* Which join type */
|
||||
bool straight; /* optimize with prev table */
|
||||
bool updating; /* for replicate-do/ignore table */
|
||||
bool shared; /* Used twice in union */
|
||||
void *derived;
|
||||
uint outer_join; /* Which join type */
|
||||
bool straight; /* optimize with prev table */
|
||||
bool updating; /* for replicate-do/ignore table */
|
||||
bool shared; /* Used twice in union */
|
||||
void *derived; /* SELECT_LEX_UNIT of derived table */
|
||||
} TABLE_LIST;
|
||||
|
||||
typedef struct st_changed_table_list {
|
||||
|
Loading…
x
Reference in New Issue
Block a user