new SELECT_LEX structure
This commit is contained in:
parent
06ed215c37
commit
494184ff5f
@ -1,4 +1,4 @@
|
||||
drop table if exists t1,t2;
|
||||
drop table if exists t1,t2,t3;
|
||||
CREATE TABLE t1 (a int not null, b char (10) not null);
|
||||
insert into t1 values(1,'a'),(2,'b'),(3,'c'),(3,'c');
|
||||
CREATE TABLE t2 (a int not null, b char (10) not null);
|
||||
@ -7,4 +7,10 @@ select t1.a,t3.y from t1,(select a as y from t2 where b='c') as t3 where t1.a
|
||||
a y
|
||||
3 3
|
||||
3 3
|
||||
drop table if exists t1.t2;
|
||||
CREATE TABLE t3 (a int not null, b char (10) not null);
|
||||
insert into t3 values (3,'f'),(4,'y'),(5,'z'),(6,'c');
|
||||
select t1.a,t4.y from t1,(select t2.a as y from t2,(select t3.b from t3 where t3.a>3) as t5 where t2.b=t5.b) as t4 where t1.a = t4.y;
|
||||
a y
|
||||
3 3
|
||||
3 3
|
||||
drop table if exists t1.t2,t3;
|
||||
|
@ -1,7 +1,10 @@
|
||||
drop table if exists t1,t2;
|
||||
drop table if exists t1,t2,t3;
|
||||
CREATE TABLE t1 (a int not null, b char (10) not null);
|
||||
insert into t1 values(1,'a'),(2,'b'),(3,'c'),(3,'c');
|
||||
CREATE TABLE t2 (a int not null, b char (10) not null);
|
||||
insert into t2 values (3,'c'),(4,'d'),(5,'f'),(6,'e');
|
||||
select t1.a,t3.y from t1,(select a as y from t2 where b='c') as t3 where t1.a = t3.y;
|
||||
drop table if exists t1.t2;
|
||||
CREATE TABLE t3 (a int not null, b char (10) not null);
|
||||
insert into t3 values (3,'f'),(4,'y'),(5,'z'),(6,'c');
|
||||
select t1.a,t4.y from t1,(select t2.a as y from t2,(select t3.b from t3 where t3.a>3) as t5 where t2.b=t5.b) as t4 where t1.a = t4.y;
|
||||
drop table if exists t1.t2,t3;
|
||||
|
@ -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);
|
||||
@ -360,8 +360,8 @@ 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);
|
||||
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);
|
||||
|
@ -706,19 +706,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
|
||||
|
@ -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 *s, 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*)s->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);
|
||||
}
|
||||
}
|
||||
@ -103,9 +107,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;
|
||||
|
115
sql/sql_lex.cc
115
sql/sql_lex.cc
@ -879,3 +879,118 @@ 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= offset_limit= 0;
|
||||
}
|
||||
|
||||
void st_select_lex_unit::init_query()
|
||||
{
|
||||
st_select_lex_node::init_query();
|
||||
global_parameters= this;
|
||||
select_limit_cnt= 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 */
|
||||
|
@ -1240,8 +1240,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)) ||
|
||||
@ -2664,18 +2666,19 @@ 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.select_lex.init_query();
|
||||
thd->lex.unit.slave= &thd->lex.select_lex;
|
||||
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 +2686,52 @@ 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->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 +3161,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 +3206,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)
|
||||
{
|
||||
|
@ -43,8 +43,8 @@ int mysql_union(THD *thd, LEX *lex,select_result *result)
|
||||
/* 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)
|
||||
sl && sl->linkage != GLOBAL_OPTIONS_TYPE;
|
||||
last_sl= sl, sl= (SELECT_LEX *) sl->next)
|
||||
{
|
||||
for (TABLE_LIST *cursor= (TABLE_LIST *)sl->table_list.first;
|
||||
cursor;
|
||||
@ -133,7 +133,7 @@ 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;
|
||||
@ -143,15 +143,19 @@ int mysql_union(THD *thd, LEX *lex,select_result *result)
|
||||
if (thd->select_limit == 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);
|
||||
if (res)
|
||||
goto exit;
|
||||
}
|
||||
|
@ -2155,21 +2155,22 @@ join_table:
|
||||
| '(' SELECT_SYM select_part3 ')' opt_table_alias
|
||||
{
|
||||
LEX *lex=Lex;
|
||||
lex->select=lex->select->prev;
|
||||
if (!($$=add_table_to_list(new Table_ident(Lex->last_select),$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
|
||||
|
||||
@ -3809,7 +3810,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;
|
||||
}
|
||||
@ -3824,10 +3826,10 @@ optional_order_or_limit:
|
||||
|
|
||||
{
|
||||
LEX *lex=Lex;
|
||||
if (!lex->select->braces || mysql_new_select(lex))
|
||||
if (!lex->select->braces || mysql_new_select(lex, 0))
|
||||
YYABORT;
|
||||
mysql_init_select(lex);
|
||||
lex->select->linkage=NOT_A_SELECT;
|
||||
lex->select->linkage= GLOBAL_OPTIONS_TYPE;
|
||||
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