now all tables of query are locked in one place (including derived tables)
fixed BUG#2120 and other problem with EXPLAINing derived tables
This commit is contained in:
parent
95fcfaf63c
commit
2a9cd37cd6
@ -59,7 +59,7 @@ explain select * from t1 as x1, (select * from t1) as x2;
|
|||||||
id select_type table type possible_keys key key_len ref rows Extra
|
id select_type table type possible_keys key key_len ref rows Extra
|
||||||
1 PRIMARY x1 ALL NULL NULL NULL NULL 4
|
1 PRIMARY x1 ALL NULL NULL NULL NULL 4
|
||||||
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 4
|
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 4
|
||||||
2 DERIVED x1 ALL NULL NULL NULL NULL 4
|
2 DERIVED t1 ALL NULL NULL NULL NULL 4
|
||||||
drop table if exists t2,t3;
|
drop table if exists t2,t3;
|
||||||
select * from (select 1) as a;
|
select * from (select 1) as a;
|
||||||
1
|
1
|
||||||
@ -141,7 +141,7 @@ a t
|
|||||||
explain select count(*) from t1 as tt1, (select * from t1) as tt2;
|
explain select count(*) from t1 as tt1, (select * from t1) as tt2;
|
||||||
id select_type table type possible_keys key key_len ref rows Extra
|
id select_type table type possible_keys key key_len ref rows Extra
|
||||||
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Select tables optimized away
|
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Select tables optimized away
|
||||||
2 DERIVED tt1 ALL NULL NULL NULL NULL 10000
|
2 DERIVED t1 index NULL a 4 NULL 10000 Using index
|
||||||
drop table t1;
|
drop table t1;
|
||||||
SELECT * FROM (SELECT (SELECT * FROM (SELECT 1 as a) as a )) as b;
|
SELECT * FROM (SELECT (SELECT * FROM (SELECT 1 as a) as a )) as b;
|
||||||
(SELECT * FROM (SELECT 1 as a) as a )
|
(SELECT * FROM (SELECT 1 as a) as a )
|
||||||
@ -189,13 +189,13 @@ id select_type table type possible_keys key key_len ref rows Extra
|
|||||||
1 PRIMARY m2 ALL NULL NULL NULL NULL 9
|
1 PRIMARY m2 ALL NULL NULL NULL NULL 9
|
||||||
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 6 Using where
|
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 6 Using where
|
||||||
2 DERIVED mp ALL NULL NULL NULL NULL 9 Using temporary; Using filesort
|
2 DERIVED mp ALL NULL NULL NULL NULL 9 Using temporary; Using filesort
|
||||||
2 DERIVED m2 index NULL PRIMARY 3 NULL 9 Using index
|
2 DERIVED m1 index NULL PRIMARY 3 NULL 9 Using index
|
||||||
explain SELECT STRAIGHT_JOIN d.pla_id, m2.test FROM t1 m2 INNER JOIN (SELECT mp.pla_id, MIN(m1.matintnum) AS matintnum FROM t2 mp INNER JOIN t1 m1 ON mp.mat_id=m1.mat_id GROUP BY mp.pla_id) d ON d.matintnum=m2.matintnum;
|
explain SELECT STRAIGHT_JOIN d.pla_id, m2.test FROM t1 m2 INNER JOIN (SELECT mp.pla_id, MIN(m1.matintnum) AS matintnum FROM t2 mp INNER JOIN t1 m1 ON mp.mat_id=m1.mat_id GROUP BY mp.pla_id) d ON d.matintnum=m2.matintnum;
|
||||||
id select_type table type possible_keys key key_len ref rows Extra
|
id select_type table type possible_keys key key_len ref rows Extra
|
||||||
1 PRIMARY m2 ALL NULL NULL NULL NULL 9
|
1 PRIMARY m2 ALL NULL NULL NULL NULL 9
|
||||||
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 6 Using where
|
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 6 Using where
|
||||||
2 DERIVED mp ALL NULL NULL NULL NULL 9 Using temporary; Using filesort
|
2 DERIVED mp ALL NULL NULL NULL NULL 9 Using temporary; Using filesort
|
||||||
2 DERIVED m2 index NULL PRIMARY 3 NULL 9 Using index
|
2 DERIVED m1 index NULL PRIMARY 3 NULL 9 Using index
|
||||||
drop table t1,t2;
|
drop table t1,t2;
|
||||||
SELECT a.x FROM (SELECT 1 AS x) AS a HAVING a.x = 1;
|
SELECT a.x FROM (SELECT 1 AS x) AS a HAVING a.x = 1;
|
||||||
x
|
x
|
||||||
@ -229,8 +229,8 @@ explain select count(*) from t1 INNER JOIN (SELECT A.E1, A.E2, A.E3 FROM t1 AS A
|
|||||||
id select_type table type possible_keys key key_len ref rows Extra
|
id select_type table type possible_keys key key_len ref rows Extra
|
||||||
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 2
|
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 2
|
||||||
1 PRIMARY t1 eq_ref PRIMARY PRIMARY 4 THEMAX.E2 1 Using where
|
1 PRIMARY t1 eq_ref PRIMARY PRIMARY 4 THEMAX.E2 1 Using where
|
||||||
2 DERIVED t1 ALL NULL NULL NULL NULL 2 Using where
|
2 DERIVED A index NULL PRIMARY 4 NULL 2 Using where; Using index
|
||||||
3 DEPENDENT SUBQUERY B ALL NULL NULL NULL NULL 2 Using where
|
3 DEPENDENT SUBQUERY B index NULL PRIMARY 4 NULL 2 Using where; Using index
|
||||||
drop table t1;
|
drop table t1;
|
||||||
create table t1 (a int);
|
create table t1 (a int);
|
||||||
insert into t1 values (1),(2);
|
insert into t1 values (1),(2);
|
||||||
@ -298,3 +298,14 @@ INSERT INTO t3 VALUES (1000,0.00),(1001,0.25),(1002,0.50),(1003,0.75),(1008,1.00
|
|||||||
select 497, TMP.ID, NULL from (select 497 as ID, MAX(t3.DATA) as DATA from t1 join t2 on (t1.ObjectID = t2.ID) join t3 on (t1.ObjectID = t3.ID) group by t2.ParID order by DATA DESC) as TMP;
|
select 497, TMP.ID, NULL from (select 497 as ID, MAX(t3.DATA) as DATA from t1 join t2 on (t1.ObjectID = t2.ID) join t3 on (t1.ObjectID = t3.ID) group by t2.ParID order by DATA DESC) as TMP;
|
||||||
497 ID NULL
|
497 ID NULL
|
||||||
drop table t1, t2, t3;
|
drop table t1, t2, t3;
|
||||||
|
CREATE TABLE t1 (name char(1) default NULL, val int(5) default NULL);
|
||||||
|
INSERT INTO t1 VALUES ('a',1), ('a',2), ('a',2), ('a',2), ('a',3), ('a',6), ('a',7), ('a',11), ('a',11), ('a',12), ('a',13), ('a',13), ('a',20), ('b',2), ('b',3), ('b',4), ('b',5);
|
||||||
|
SELECT s.name, AVG(s.val) AS median FROM (SELECT x.name, x.val FROM t1 x, t1 y WHERE x.name=y.name GROUP BY x.name, x.val HAVING SUM(y.val <= x.val) >= COUNT(*)/2 AND SUM(y.val >= x.val) >= COUNT(*)/2) AS s GROUP BY s.name;
|
||||||
|
name median
|
||||||
|
a 7.0000
|
||||||
|
b 3.5000
|
||||||
|
explain SELECT s.name, AVG(s.val) AS median FROM (SELECT x.name, x.val FROM t1 x, t1 y WHERE x.name=y.name GROUP BY x.name, x.val HAVING SUM(y.val <= x.val) >= COUNT(*)/2 AND SUM(y.val >= x.val) >= COUNT(*)/2) AS s GROUP BY s.name;
|
||||||
|
id select_type table type possible_keys key key_len ref rows Extra
|
||||||
|
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 3 Using temporary; Using filesort
|
||||||
|
2 DERIVED x ALL NULL NULL NULL NULL 17 Using temporary; Using filesort
|
||||||
|
2 DERIVED y ALL NULL NULL NULL NULL 17 Using where
|
||||||
|
@ -183,3 +183,12 @@ CREATE TABLE t3 (
|
|||||||
INSERT INTO t3 VALUES (1000,0.00),(1001,0.25),(1002,0.50),(1003,0.75),(1008,1.00),(1009,1.25),(1010,1.50),(1011,1.75);
|
INSERT INTO t3 VALUES (1000,0.00),(1001,0.25),(1002,0.50),(1003,0.75),(1008,1.00),(1009,1.25),(1010,1.50),(1011,1.75);
|
||||||
select 497, TMP.ID, NULL from (select 497 as ID, MAX(t3.DATA) as DATA from t1 join t2 on (t1.ObjectID = t2.ID) join t3 on (t1.ObjectID = t3.ID) group by t2.ParID order by DATA DESC) as TMP;
|
select 497, TMP.ID, NULL from (select 497 as ID, MAX(t3.DATA) as DATA from t1 join t2 on (t1.ObjectID = t2.ID) join t3 on (t1.ObjectID = t3.ID) group by t2.ParID order by DATA DESC) as TMP;
|
||||||
drop table t1, t2, t3;
|
drop table t1, t2, t3;
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# explain derived
|
||||||
|
#
|
||||||
|
CREATE TABLE t1 (name char(1) default NULL, val int(5) default NULL);
|
||||||
|
INSERT INTO t1 VALUES ('a',1), ('a',2), ('a',2), ('a',2), ('a',3), ('a',6), ('a',7), ('a',11), ('a',11), ('a',12), ('a',13), ('a',13), ('a',20), ('b',2), ('b',3), ('b',4), ('b',5);
|
||||||
|
SELECT s.name, AVG(s.val) AS median FROM (SELECT x.name, x.val FROM t1 x, t1 y WHERE x.name=y.name GROUP BY x.name, x.val HAVING SUM(y.val <= x.val) >= COUNT(*)/2 AND SUM(y.val >= x.val) >= COUNT(*)/2) AS s GROUP BY s.name;
|
||||||
|
explain SELECT s.name, AVG(s.val) AS median FROM (SELECT x.name, x.val FROM t1 x, t1 y WHERE x.name=y.name GROUP BY x.name, x.val HAVING SUM(y.val <= x.val) >= COUNT(*)/2 AND SUM(y.val >= x.val) >= COUNT(*)/2) AS s GROUP BY s.name;
|
||||||
|
@ -481,14 +481,13 @@ int mysql_select(THD *thd, Item ***rref_pointer_array,
|
|||||||
SELECT_LEX *select_lex);
|
SELECT_LEX *select_lex);
|
||||||
void free_underlaid_joins(THD *thd, SELECT_LEX *select);
|
void free_underlaid_joins(THD *thd, SELECT_LEX *select);
|
||||||
void fix_tables_pointers(SELECT_LEX *select_lex);
|
void fix_tables_pointers(SELECT_LEX *select_lex);
|
||||||
void fix_tables_pointers(SELECT_LEX_UNIT *select_lex);
|
|
||||||
int mysql_explain_union(THD *thd, SELECT_LEX_UNIT *unit,
|
int mysql_explain_union(THD *thd, SELECT_LEX_UNIT *unit,
|
||||||
select_result *result);
|
select_result *result);
|
||||||
int mysql_explain_select(THD *thd, SELECT_LEX *sl, char const *type,
|
int mysql_explain_select(THD *thd, SELECT_LEX *sl, char const *type,
|
||||||
select_result *result);
|
select_result *result);
|
||||||
int mysql_union(THD *thd, LEX *lex, select_result *result,
|
int mysql_union(THD *thd, LEX *lex, select_result *result,
|
||||||
SELECT_LEX_UNIT *unit);
|
SELECT_LEX_UNIT *unit);
|
||||||
int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *s, TABLE_LIST *t);
|
int mysql_handle_derived(LEX *lex);
|
||||||
Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type,
|
Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type,
|
||||||
Item ***copy_func, Field **from_field,
|
Item ***copy_func, Field **from_field,
|
||||||
bool group,bool modify_item);
|
bool group,bool modify_item);
|
||||||
@ -676,6 +675,7 @@ int setup_ftfuncs(SELECT_LEX* select);
|
|||||||
int init_ftfuncs(THD *thd, SELECT_LEX* select, bool no_order);
|
int init_ftfuncs(THD *thd, SELECT_LEX* select, bool no_order);
|
||||||
void wait_for_refresh(THD *thd);
|
void wait_for_refresh(THD *thd);
|
||||||
int open_tables(THD *thd,TABLE_LIST *tables);
|
int open_tables(THD *thd,TABLE_LIST *tables);
|
||||||
|
int simple_open_n_lock_tables(THD *thd,TABLE_LIST *tables);
|
||||||
int open_and_lock_tables(THD *thd,TABLE_LIST *tables);
|
int open_and_lock_tables(THD *thd,TABLE_LIST *tables);
|
||||||
int lock_tables(THD *thd,TABLE_LIST *tables);
|
int lock_tables(THD *thd,TABLE_LIST *tables);
|
||||||
TABLE *open_temporary_table(THD *thd, const char *path, const char *db,
|
TABLE *open_temporary_table(THD *thd, const char *path, const char *db,
|
||||||
|
@ -732,7 +732,7 @@ static int fetch_db_tables(THD *thd, MYSQL *mysql, const char *db,
|
|||||||
int error;
|
int error;
|
||||||
if (table_rules_on)
|
if (table_rules_on)
|
||||||
{
|
{
|
||||||
table.next= 0;
|
bzero((char*) &table, sizeof(table)); //just for safe
|
||||||
table.db= (char*) db;
|
table.db= (char*) db;
|
||||||
table.real_name= (char*) table_name;
|
table.real_name= (char*) table_name;
|
||||||
table.updating= 1;
|
table.updating= 1;
|
||||||
|
@ -2247,7 +2247,7 @@ int mysql_table_grant(THD *thd, TABLE_LIST *table_list,
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (open_and_lock_tables(thd,tables))
|
if (simple_open_n_lock_tables(thd,tables))
|
||||||
{ // Should never happen
|
{ // Should never happen
|
||||||
close_thread_tables(thd); /* purecov: deadcode */
|
close_thread_tables(thd); /* purecov: deadcode */
|
||||||
DBUG_RETURN(-1); /* purecov: deadcode */
|
DBUG_RETURN(-1); /* purecov: deadcode */
|
||||||
@ -2395,7 +2395,7 @@ int mysql_grant(THD *thd, const char *db, List <LEX_USER> &list,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* open the mysql.user and mysql.db tables */
|
/* open the mysql.user and mysql.db tables */
|
||||||
|
bzero((char*) &tables,sizeof(tables));
|
||||||
tables[0].alias=tables[0].real_name=(char*) "user";
|
tables[0].alias=tables[0].real_name=(char*) "user";
|
||||||
tables[1].alias=tables[1].real_name=(char*) "db";
|
tables[1].alias=tables[1].real_name=(char*) "db";
|
||||||
tables[0].next=tables+1;
|
tables[0].next=tables+1;
|
||||||
@ -2421,7 +2421,7 @@ int mysql_grant(THD *thd, const char *db, List <LEX_USER> &list,
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (open_and_lock_tables(thd,tables))
|
if (simple_open_n_lock_tables(thd,tables))
|
||||||
{ // This should never happen
|
{ // This should never happen
|
||||||
close_thread_tables(thd); /* purecov: deadcode */
|
close_thread_tables(thd); /* purecov: deadcode */
|
||||||
DBUG_RETURN(-1); /* purecov: deadcode */
|
DBUG_RETURN(-1); /* purecov: deadcode */
|
||||||
@ -2517,7 +2517,7 @@ my_bool grant_init(THD *org_thd)
|
|||||||
thd->store_globals();
|
thd->store_globals();
|
||||||
thd->db= my_strdup("mysql",MYF(0));
|
thd->db= my_strdup("mysql",MYF(0));
|
||||||
thd->db_length=5; // Safety
|
thd->db_length=5; // Safety
|
||||||
bzero((char*) &tables,sizeof(tables));
|
bzero((char*) &tables, sizeof(tables));
|
||||||
tables[0].alias=tables[0].real_name= (char*) "tables_priv";
|
tables[0].alias=tables[0].real_name= (char*) "tables_priv";
|
||||||
tables[1].alias=tables[1].real_name= (char*) "columns_priv";
|
tables[1].alias=tables[1].real_name= (char*) "columns_priv";
|
||||||
tables[0].next=tables+1;
|
tables[0].next=tables+1;
|
||||||
@ -3376,7 +3376,7 @@ int open_grant_tables(THD *thd, TABLE_LIST *tables)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (open_and_lock_tables(thd, tables))
|
if (simple_open_n_lock_tables(thd, tables))
|
||||||
{ // This should never happen
|
{ // This should never happen
|
||||||
close_thread_tables(thd);
|
close_thread_tables(thd);
|
||||||
DBUG_RETURN(-1);
|
DBUG_RETURN(-1);
|
||||||
|
@ -1305,6 +1305,7 @@ static int open_unireg_entry(THD *thd, TABLE *entry, const char *db,
|
|||||||
goto err; // Can't repair the table
|
goto err; // Can't repair the table
|
||||||
|
|
||||||
TABLE_LIST table_list;
|
TABLE_LIST table_list;
|
||||||
|
bzero((char*) &table_list, sizeof(table_list)); // just for safe
|
||||||
table_list.db=(char*) db;
|
table_list.db=(char*) db;
|
||||||
table_list.real_name=(char*) name;
|
table_list.real_name=(char*) name;
|
||||||
table_list.next=0;
|
table_list.next=0;
|
||||||
@ -1372,11 +1373,13 @@ int open_tables(THD *thd,TABLE_LIST *start)
|
|||||||
thd->proc_info="Opening tables";
|
thd->proc_info="Opening tables";
|
||||||
for (tables=start ; tables ; tables=tables->next)
|
for (tables=start ; tables ; tables=tables->next)
|
||||||
{
|
{
|
||||||
|
if (tables->derived)
|
||||||
|
continue;
|
||||||
if (!tables->table &&
|
if (!tables->table &&
|
||||||
!(tables->table=open_table(thd,
|
!(tables->table= open_table(thd,
|
||||||
tables->db,
|
tables->db,
|
||||||
tables->real_name,
|
tables->real_name,
|
||||||
tables->alias, &refresh)))
|
tables->alias, &refresh)))
|
||||||
{
|
{
|
||||||
if (refresh) // Refresh in progress
|
if (refresh) // Refresh in progress
|
||||||
{
|
{
|
||||||
@ -1522,15 +1525,47 @@ TABLE *open_ltable(THD *thd, TABLE_LIST *table_list, thr_lock_type lock_type)
|
|||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Open all tables in list and locks them for read.
|
Open all tables in list and locks them for read without derived
|
||||||
The lock will automaticly be freed by close_thread_tables()
|
tables processing.
|
||||||
|
|
||||||
|
SYNOPSIS
|
||||||
|
simple_open_n_lock_tables()
|
||||||
|
thd - thread handler
|
||||||
|
tables - list of tables for open&locking
|
||||||
|
|
||||||
|
NOTE
|
||||||
|
The lock will automaticly be freed by close_thread_tables()
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int open_and_lock_tables(THD *thd,TABLE_LIST *tables)
|
int simple_open_n_lock_tables(THD *thd, TABLE_LIST *tables)
|
||||||
{
|
{
|
||||||
if (open_tables(thd,tables) || lock_tables(thd,tables))
|
DBUG_ENTER("open_n_lock_tables");
|
||||||
return -1; /* purecov: inspected */
|
if (open_tables(thd, tables) || lock_tables(thd, tables))
|
||||||
return 0;
|
DBUG_RETURN(-1); /* purecov: inspected */
|
||||||
|
DBUG_RETURN(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Open all tables in list, locks them and process derived tables
|
||||||
|
tables processing.
|
||||||
|
|
||||||
|
SYNOPSIS
|
||||||
|
simple_open_n_lock_tables()
|
||||||
|
thd - thread handler
|
||||||
|
tables - list of tables for open&locking
|
||||||
|
|
||||||
|
NOTE
|
||||||
|
The lock will automaticly be freed by close_thread_tables()
|
||||||
|
*/
|
||||||
|
|
||||||
|
int open_and_lock_tables(THD *thd, TABLE_LIST *tables)
|
||||||
|
{
|
||||||
|
DBUG_ENTER("open_and_lock_tables");
|
||||||
|
if (open_tables(thd, tables) || lock_tables(thd, tables))
|
||||||
|
DBUG_RETURN(-1); /* purecov: inspected */
|
||||||
|
fix_tables_pointers(thd->lex->all_selects_list);
|
||||||
|
DBUG_RETURN(mysql_handle_derived(thd->lex));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1563,12 +1598,18 @@ int lock_tables(THD *thd,TABLE_LIST *tables)
|
|||||||
DBUG_ASSERT(thd->lock == 0); // You must lock everything at once
|
DBUG_ASSERT(thd->lock == 0); // You must lock everything at once
|
||||||
uint count=0;
|
uint count=0;
|
||||||
for (table = tables ; table ; table=table->next)
|
for (table = tables ; table ; table=table->next)
|
||||||
count++;
|
{
|
||||||
|
if (!table->derived)
|
||||||
|
count++;
|
||||||
|
}
|
||||||
TABLE **start,**ptr;
|
TABLE **start,**ptr;
|
||||||
if (!(ptr=start=(TABLE**) sql_alloc(sizeof(TABLE*)*count)))
|
if (!(ptr=start=(TABLE**) sql_alloc(sizeof(TABLE*)*count)))
|
||||||
return -1;
|
return -1;
|
||||||
for (table = tables ; table ; table=table->next)
|
for (table = tables ; table ; table=table->next)
|
||||||
*(ptr++)= table->table;
|
{
|
||||||
|
if (!table->derived)
|
||||||
|
*(ptr++)= table->table;
|
||||||
|
}
|
||||||
if (!(thd->lock=mysql_lock_tables(thd,start,count)))
|
if (!(thd->lock=mysql_lock_tables(thd,start,count)))
|
||||||
return -1; /* purecov: inspected */
|
return -1; /* purecov: inspected */
|
||||||
}
|
}
|
||||||
@ -1576,7 +1617,8 @@ int lock_tables(THD *thd,TABLE_LIST *tables)
|
|||||||
{
|
{
|
||||||
for (table = tables ; table ; table=table->next)
|
for (table = tables ; table ; table=table->next)
|
||||||
{
|
{
|
||||||
if (check_lock_and_start_stmt(thd, table->table, table->lock_type))
|
if (!table->derived &&
|
||||||
|
check_lock_and_start_stmt(thd, table->table, table->lock_type))
|
||||||
{
|
{
|
||||||
ha_rollback_stmt(thd);
|
ha_rollback_stmt(thd);
|
||||||
return -1;
|
return -1;
|
||||||
@ -2165,6 +2207,7 @@ insert_fields(THD *thd,TABLE_LIST *tables, const char *db_name,
|
|||||||
#ifndef NO_EMBEDDED_ACCESS_CHECKS
|
#ifndef NO_EMBEDDED_ACCESS_CHECKS
|
||||||
/* Ensure that we have access right to all columns */
|
/* Ensure that we have access right to all columns */
|
||||||
if (!(table->grant.privilege & SELECT_ACL) &&
|
if (!(table->grant.privilege & SELECT_ACL) &&
|
||||||
|
!tables->derived &&
|
||||||
check_grant_all_columns(thd,SELECT_ACL,table))
|
check_grant_all_columns(thd,SELECT_ACL,table))
|
||||||
DBUG_RETURN(-1);
|
DBUG_RETURN(-1);
|
||||||
#endif
|
#endif
|
||||||
|
@ -43,7 +43,6 @@ int mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, SQL_LIST *order,
|
|||||||
|
|
||||||
if ((open_and_lock_tables(thd, table_list)))
|
if ((open_and_lock_tables(thd, table_list)))
|
||||||
DBUG_RETURN(-1);
|
DBUG_RETURN(-1);
|
||||||
fix_tables_pointers(thd->lex->all_selects_list);
|
|
||||||
table= table_list->table;
|
table= table_list->table;
|
||||||
table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK);
|
table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK);
|
||||||
thd->proc_info="init";
|
thd->proc_info="init";
|
||||||
|
@ -25,6 +25,49 @@
|
|||||||
#include "sql_select.h"
|
#include "sql_select.h"
|
||||||
#include "sql_acl.h"
|
#include "sql_acl.h"
|
||||||
|
|
||||||
|
int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *s, TABLE_LIST *t);
|
||||||
|
|
||||||
|
/*
|
||||||
|
Resolve derived tables in all queries
|
||||||
|
|
||||||
|
SYNOPSIS
|
||||||
|
mysql_handle_derived()
|
||||||
|
lex LEX for this thread
|
||||||
|
|
||||||
|
RETURN
|
||||||
|
0 ok
|
||||||
|
-1 Error
|
||||||
|
1 Error and error message given
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
mysql_handle_derived(LEX *lex)
|
||||||
|
{
|
||||||
|
int res= 0;
|
||||||
|
if (lex->derived_tables)
|
||||||
|
{
|
||||||
|
for (SELECT_LEX *sl= lex->all_selects_list;
|
||||||
|
sl;
|
||||||
|
sl= sl->next_select_in_list())
|
||||||
|
{
|
||||||
|
for (TABLE_LIST *cursor= sl->get_table_list();
|
||||||
|
cursor;
|
||||||
|
cursor= cursor->next)
|
||||||
|
{
|
||||||
|
if (cursor->derived && (res=mysql_derived(lex->thd, lex,
|
||||||
|
cursor->derived,
|
||||||
|
cursor)))
|
||||||
|
{
|
||||||
|
if (res < 0 || lex->thd->net.report_error)
|
||||||
|
send_error(lex->thd, lex->thd->killed ? ER_SERVER_SHUTDOWN : 0);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Resolve derived tables in all queries
|
Resolve derived tables in all queries
|
||||||
|
|
||||||
@ -49,9 +92,6 @@
|
|||||||
Derived tables is stored in thd->derived_tables and freed in
|
Derived tables is stored in thd->derived_tables and freed in
|
||||||
close_thread_tables()
|
close_thread_tables()
|
||||||
|
|
||||||
TODO
|
|
||||||
Move creation of derived tables in open_and_lock_tables()
|
|
||||||
|
|
||||||
RETURN
|
RETURN
|
||||||
0 ok
|
0 ok
|
||||||
1 Error
|
1 Error
|
||||||
@ -72,143 +112,87 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit,
|
|||||||
bool is_subsel= first_select->first_inner_unit() ? 1: 0;
|
bool is_subsel= first_select->first_inner_unit() ? 1: 0;
|
||||||
SELECT_LEX *save_current_select= lex->current_select;
|
SELECT_LEX *save_current_select= lex->current_select;
|
||||||
DBUG_ENTER("mysql_derived");
|
DBUG_ENTER("mysql_derived");
|
||||||
|
|
||||||
/*
|
|
||||||
In create_total_list, derived tables have to be treated in case of
|
|
||||||
EXPLAIN, This is because unit/node is not deleted in that
|
|
||||||
case. Current code in this function has to be improved to
|
|
||||||
recognize better when this function is called from derived tables
|
|
||||||
and when from other functions.
|
|
||||||
*/
|
|
||||||
if ((is_union || is_subsel) && unit->create_total_list(thd, lex, &tables, 1))
|
|
||||||
DBUG_RETURN(-1);
|
|
||||||
|
|
||||||
/*
|
if (!(derived_result= new select_union(0)))
|
||||||
We have to do access checks here as this code is executed before any
|
DBUG_RETURN(1); // out of memory
|
||||||
sql command is started to execute.
|
|
||||||
*/
|
|
||||||
#ifndef NO_EMBEDDED_ACCESS_CHECKS
|
|
||||||
if (tables)
|
|
||||||
res= check_table_access(thd,SELECT_ACL, tables,0);
|
|
||||||
else
|
|
||||||
res= check_access(thd, SELECT_ACL, any_db,0,0,0);
|
|
||||||
if (res)
|
|
||||||
DBUG_RETURN(1);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (!(res=open_and_lock_tables(thd,tables)))
|
// st_select_lex_unit::prepare correctly work for single select
|
||||||
{
|
if ((res= unit->prepare(thd, derived_result, 0)))
|
||||||
if (is_union || is_subsel)
|
goto exit;
|
||||||
{
|
|
||||||
/*
|
|
||||||
The following code is a re-do of fix_tables_pointers() found
|
|
||||||
in sql_select.cc for UNION's within derived tables. The only
|
|
||||||
difference is in navigation, as in derived tables we care for
|
|
||||||
this level only.
|
|
||||||
|
|
||||||
*/
|
|
||||||
fix_tables_pointers(unit);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!(derived_result= new select_union(0)))
|
|
||||||
DBUG_RETURN(1); // out of memory
|
|
||||||
|
|
||||||
// st_select_lex_unit::prepare correctly work for single select
|
|
||||||
if ((res= unit->prepare(thd, derived_result, 0)))
|
|
||||||
goto exit;
|
|
||||||
|
|
||||||
/*
|
|
||||||
This is done in order to redo all field optimisations when any of the
|
|
||||||
involved tables is used in the outer query
|
|
||||||
*/
|
|
||||||
if (tables)
|
|
||||||
{
|
|
||||||
for (TABLE_LIST *cursor= tables; cursor; cursor= cursor->next)
|
|
||||||
cursor->table->clear_query_id= 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
derived_result->tmp_table_param.init();
|
derived_result->tmp_table_param.init();
|
||||||
derived_result->tmp_table_param.field_count= unit->types.elements;
|
derived_result->tmp_table_param.field_count= unit->types.elements;
|
||||||
/*
|
/*
|
||||||
Temp table is created so that it hounours if UNION without ALL is to be
|
Temp table is created so that it hounours if UNION without ALL is to be
|
||||||
processed
|
processed
|
||||||
*/
|
*/
|
||||||
if (!(table= create_tmp_table(thd, &derived_result->tmp_table_param,
|
if (!(table= create_tmp_table(thd, &derived_result->tmp_table_param,
|
||||||
unit->types, (ORDER*) 0,
|
unit->types, (ORDER*) 0,
|
||||||
is_union && !unit->union_option, 1,
|
is_union && !unit->union_option, 1,
|
||||||
(first_select->options | thd->options |
|
(first_select->options | thd->options |
|
||||||
TMP_TABLE_ALL_COLUMNS),
|
TMP_TABLE_ALL_COLUMNS),
|
||||||
HA_POS_ERROR,
|
HA_POS_ERROR,
|
||||||
org_table_list->alias)))
|
org_table_list->alias)))
|
||||||
{
|
{
|
||||||
res= -1;
|
res= -1;
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
derived_result->set_table(table);
|
derived_result->set_table(table);
|
||||||
|
|
||||||
if (is_union)
|
|
||||||
res= mysql_union(thd, lex, derived_result, unit);
|
if (is_union)
|
||||||
|
res= mysql_union(thd, lex, derived_result, unit);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
unit->offset_limit_cnt= first_select->offset_limit;
|
||||||
|
unit->select_limit_cnt= first_select->select_limit+
|
||||||
|
first_select->offset_limit;
|
||||||
|
if (unit->select_limit_cnt < first_select->select_limit)
|
||||||
|
unit->select_limit_cnt= HA_POS_ERROR;
|
||||||
|
if (unit->select_limit_cnt == HA_POS_ERROR)
|
||||||
|
first_select->options&= ~OPTION_FOUND_ROWS;
|
||||||
|
|
||||||
|
lex->current_select= first_select;
|
||||||
|
res= mysql_select(thd, &first_select->ref_pointer_array,
|
||||||
|
(TABLE_LIST*) first_select->table_list.first,
|
||||||
|
first_select->with_wild,
|
||||||
|
first_select->item_list, first_select->where,
|
||||||
|
(first_select->order_list.elements+
|
||||||
|
first_select->group_list.elements),
|
||||||
|
(ORDER *) first_select->order_list.first,
|
||||||
|
(ORDER *) first_select->group_list.first,
|
||||||
|
first_select->having, (ORDER*) NULL,
|
||||||
|
(first_select->options | thd->options |
|
||||||
|
SELECT_NO_UNLOCK),
|
||||||
|
derived_result, unit, first_select);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!res)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
Here we entirely fix both TABLE_LIST and list of SELECT's as
|
||||||
|
there were no derived tables
|
||||||
|
*/
|
||||||
|
if (derived_result->flush())
|
||||||
|
res= 1;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
unit->offset_limit_cnt= first_select->offset_limit;
|
org_table_list->real_name= table->real_name;
|
||||||
unit->select_limit_cnt= first_select->select_limit+
|
org_table_list->table= table;
|
||||||
first_select->offset_limit;
|
if (org_table_list->table_list)
|
||||||
if (unit->select_limit_cnt < first_select->select_limit)
|
|
||||||
unit->select_limit_cnt= HA_POS_ERROR;
|
|
||||||
if (unit->select_limit_cnt == HA_POS_ERROR)
|
|
||||||
first_select->options&= ~OPTION_FOUND_ROWS;
|
|
||||||
|
|
||||||
lex->current_select= first_select;
|
|
||||||
res= mysql_select(thd, &first_select->ref_pointer_array,
|
|
||||||
(TABLE_LIST*) first_select->table_list.first,
|
|
||||||
first_select->with_wild,
|
|
||||||
first_select->item_list, first_select->where,
|
|
||||||
(first_select->order_list.elements+
|
|
||||||
first_select->group_list.elements),
|
|
||||||
(ORDER *) first_select->order_list.first,
|
|
||||||
(ORDER *) first_select->group_list.first,
|
|
||||||
first_select->having, (ORDER*) NULL,
|
|
||||||
(first_select->options | thd->options |
|
|
||||||
SELECT_NO_UNLOCK),
|
|
||||||
derived_result, unit, first_select);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!res)
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
Here we entirely fix both TABLE_LIST and list of SELECT's as
|
|
||||||
there were no derived tables
|
|
||||||
*/
|
|
||||||
if (derived_result->flush())
|
|
||||||
res= 1;
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
org_table_list->real_name=table->real_name;
|
org_table_list->table_list->real_name= table->real_name;
|
||||||
org_table_list->table=table;
|
org_table_list->table_list->table= table;
|
||||||
table->derived_select_number= first_select->select_number;
|
|
||||||
table->tmp_table= TMP_TABLE;
|
|
||||||
#ifndef NO_EMBEDDED_ACCESS_CHECKS
|
|
||||||
org_table_list->grant.privilege= SELECT_ACL;
|
|
||||||
#endif
|
|
||||||
if (lex->describe)
|
|
||||||
{
|
|
||||||
// to fix a problem in EXPLAIN
|
|
||||||
if (tables)
|
|
||||||
{
|
|
||||||
for (TABLE_LIST *cursor= tables; cursor; cursor= cursor->next)
|
|
||||||
if (cursor->table_list)
|
|
||||||
cursor->table_list->table=cursor->table;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
unit->exclude_tree();
|
|
||||||
unit->cleanup();
|
|
||||||
}
|
|
||||||
org_table_list->db= (char *)"";
|
|
||||||
// Force read of table stats in the optimizer
|
|
||||||
table->file->info(HA_STATUS_VARIABLE);
|
|
||||||
}
|
}
|
||||||
|
table->derived_select_number= first_select->select_number;
|
||||||
|
table->tmp_table= TMP_TABLE;
|
||||||
|
#ifndef NO_EMBEDDED_ACCESS_CHECKS
|
||||||
|
org_table_list->grant.privilege= SELECT_ACL;
|
||||||
|
#endif
|
||||||
|
org_table_list->db= (char *)"";
|
||||||
|
// Force read of table stats in the optimizer
|
||||||
|
table->file->info(HA_STATUS_VARIABLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (res)
|
if (res)
|
||||||
@ -223,7 +207,6 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit,
|
|||||||
exit:
|
exit:
|
||||||
delete derived_result;
|
delete derived_result;
|
||||||
lex->current_select= save_current_select;
|
lex->current_select= save_current_select;
|
||||||
close_thread_tables(thd, 0, 1);
|
|
||||||
}
|
}
|
||||||
DBUG_RETURN(res);
|
DBUG_RETURN(res);
|
||||||
}
|
}
|
||||||
|
@ -188,7 +188,6 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list,
|
|||||||
res= open_and_lock_tables(thd, table_list);
|
res= open_and_lock_tables(thd, table_list);
|
||||||
if (res)
|
if (res)
|
||||||
DBUG_RETURN(-1);
|
DBUG_RETURN(-1);
|
||||||
fix_tables_pointers(thd->lex->all_selects_list);
|
|
||||||
|
|
||||||
table= table_list->table;
|
table= table_list->table;
|
||||||
thd->proc_info="init";
|
thd->proc_info="init";
|
||||||
@ -646,7 +645,8 @@ public:
|
|||||||
thd.command=COM_DELAYED_INSERT;
|
thd.command=COM_DELAYED_INSERT;
|
||||||
thd.lex->current_select= 0; /* for my_message_sql */
|
thd.lex->current_select= 0; /* for my_message_sql */
|
||||||
|
|
||||||
bzero((char*) &thd.net,sizeof(thd.net)); // Safety
|
bzero((char*) &thd.net, sizeof(thd.net)); // Safety
|
||||||
|
bzero((char*) &table_list, sizeof(table_list)); // Safety
|
||||||
thd.system_thread= SYSTEM_THREAD_DELAYED_INSERT;
|
thd.system_thread= SYSTEM_THREAD_DELAYED_INSERT;
|
||||||
thd.host_or_ip= "";
|
thd.host_or_ip= "";
|
||||||
bzero((char*) &info,sizeof(info));
|
bzero((char*) &info,sizeof(info));
|
||||||
|
@ -1286,12 +1286,10 @@ bool st_select_lex::test_limit()
|
|||||||
!0 - error
|
!0 - error
|
||||||
*/
|
*/
|
||||||
bool st_select_lex_unit::create_total_list(THD *thd_arg, st_lex *lex,
|
bool st_select_lex_unit::create_total_list(THD *thd_arg, st_lex *lex,
|
||||||
TABLE_LIST **result_arg,
|
TABLE_LIST **result_arg)
|
||||||
bool check_derived)
|
|
||||||
{
|
{
|
||||||
*result_arg= 0;
|
*result_arg= 0;
|
||||||
res= create_total_list_n_last_return(thd_arg, lex, &result_arg,
|
res= create_total_list_n_last_return(thd_arg, lex, &result_arg);
|
||||||
check_derived);
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1303,8 +1301,7 @@ bool st_select_lex_unit::create_total_list(THD *thd_arg, st_lex *lex,
|
|||||||
thd THD pointer
|
thd THD pointer
|
||||||
lex pointer on LEX stricture
|
lex pointer on LEX stricture
|
||||||
result pointer on pointer on result list of tables pointer
|
result pointer on pointer on result list of tables pointer
|
||||||
check_derived force derived table chacking (used for creating
|
|
||||||
table list for derived query)
|
|
||||||
DESCRIPTION
|
DESCRIPTION
|
||||||
This is used for UNION & subselect to create a new table list of all used
|
This is used for UNION & subselect to create a new table list of all used
|
||||||
tables.
|
tables.
|
||||||
@ -1318,8 +1315,7 @@ bool st_select_lex_unit::create_total_list(THD *thd_arg, st_lex *lex,
|
|||||||
bool st_select_lex_unit::
|
bool st_select_lex_unit::
|
||||||
create_total_list_n_last_return(THD *thd_arg,
|
create_total_list_n_last_return(THD *thd_arg,
|
||||||
st_lex *lex,
|
st_lex *lex,
|
||||||
TABLE_LIST ***result_arg,
|
TABLE_LIST ***result_arg)
|
||||||
bool check_derived)
|
|
||||||
{
|
{
|
||||||
TABLE_LIST *slave_list_first=0, **slave_list_last= &slave_list_first;
|
TABLE_LIST *slave_list_first=0, **slave_list_last= &slave_list_first;
|
||||||
TABLE_LIST **new_table_list= *result_arg, *aux;
|
TABLE_LIST **new_table_list= *result_arg, *aux;
|
||||||
@ -1345,15 +1341,12 @@ create_total_list_n_last_return(THD *thd_arg,
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sl->linkage == DERIVED_TABLE_TYPE && !check_derived)
|
|
||||||
goto end;
|
|
||||||
|
|
||||||
for (SELECT_LEX_UNIT *inner= sl->first_inner_unit();
|
for (SELECT_LEX_UNIT *inner= sl->first_inner_unit();
|
||||||
inner;
|
inner;
|
||||||
inner= inner->next_unit())
|
inner= inner->next_unit())
|
||||||
{
|
{
|
||||||
if (inner->create_total_list_n_last_return(thd, lex,
|
if (inner->create_total_list_n_last_return(thd, lex,
|
||||||
&slave_list_last, 0))
|
&slave_list_last))
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1400,63 +1393,75 @@ end:
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
st_select_lex_unit* st_select_lex_unit::master_unit()
|
st_select_lex_unit* st_select_lex_unit::master_unit()
|
||||||
{
|
{
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
st_select_lex* st_select_lex_unit::outer_select()
|
st_select_lex* st_select_lex_unit::outer_select()
|
||||||
{
|
{
|
||||||
return (st_select_lex*) master;
|
return (st_select_lex*) master;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool st_select_lex::add_order_to_list(THD *thd, Item *item, bool asc)
|
bool st_select_lex::add_order_to_list(THD *thd, Item *item, bool asc)
|
||||||
{
|
{
|
||||||
return add_to_list(thd, order_list, item, asc);
|
return add_to_list(thd, order_list, item, asc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool st_select_lex::add_item_to_list(THD *thd, Item *item)
|
bool st_select_lex::add_item_to_list(THD *thd, Item *item)
|
||||||
{
|
{
|
||||||
return item_list.push_back(item);
|
return item_list.push_back(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool st_select_lex::add_group_to_list(THD *thd, Item *item, bool asc)
|
bool st_select_lex::add_group_to_list(THD *thd, Item *item, bool asc)
|
||||||
{
|
{
|
||||||
return add_to_list(thd, group_list, item, asc);
|
return add_to_list(thd, group_list, item, asc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool st_select_lex::add_ftfunc_to_list(Item_func_match *func)
|
bool st_select_lex::add_ftfunc_to_list(Item_func_match *func)
|
||||||
{
|
{
|
||||||
return !func || ftfunc_list->push_back(func); // end of memory?
|
return !func || ftfunc_list->push_back(func); // end of memory?
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
st_select_lex_unit* st_select_lex::master_unit()
|
st_select_lex_unit* st_select_lex::master_unit()
|
||||||
{
|
{
|
||||||
return (st_select_lex_unit*) master;
|
return (st_select_lex_unit*) master;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
st_select_lex* st_select_lex::outer_select()
|
st_select_lex* st_select_lex::outer_select()
|
||||||
{
|
{
|
||||||
return (st_select_lex*) master->get_master();
|
return (st_select_lex*) master->get_master();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool st_select_lex::set_braces(bool value)
|
bool st_select_lex::set_braces(bool value)
|
||||||
{
|
{
|
||||||
braces= value;
|
braces= value;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool st_select_lex::inc_in_sum_expr()
|
bool st_select_lex::inc_in_sum_expr()
|
||||||
{
|
{
|
||||||
in_sum_expr++;
|
in_sum_expr++;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
uint st_select_lex::get_in_sum_expr()
|
uint st_select_lex::get_in_sum_expr()
|
||||||
{
|
{
|
||||||
return in_sum_expr;
|
return in_sum_expr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
TABLE_LIST* st_select_lex::get_table_list()
|
TABLE_LIST* st_select_lex::get_table_list()
|
||||||
{
|
{
|
||||||
return (TABLE_LIST*) table_list.first;
|
return (TABLE_LIST*) table_list.first;
|
||||||
@ -1467,21 +1472,25 @@ List<Item>* st_select_lex::get_item_list()
|
|||||||
return &item_list;
|
return &item_list;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
List<String>* st_select_lex::get_use_index()
|
List<String>* st_select_lex::get_use_index()
|
||||||
{
|
{
|
||||||
return use_index_ptr;
|
return use_index_ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
List<String>* st_select_lex::get_ignore_index()
|
List<String>* st_select_lex::get_ignore_index()
|
||||||
{
|
{
|
||||||
return ignore_index_ptr;
|
return ignore_index_ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
ulong st_select_lex::get_table_join_options()
|
ulong st_select_lex::get_table_join_options()
|
||||||
{
|
{
|
||||||
return table_join_options;
|
return table_join_options;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool st_select_lex::setup_ref_array(THD *thd, uint order_group_num)
|
bool st_select_lex::setup_ref_array(THD *thd, uint order_group_num)
|
||||||
{
|
{
|
||||||
if (ref_pointer_array)
|
if (ref_pointer_array)
|
||||||
@ -1493,6 +1502,58 @@ bool st_select_lex::setup_ref_array(THD *thd, uint order_group_num)
|
|||||||
order_group_num)* 5)) == 0;
|
order_group_num)* 5)) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Find db.table which will be updated in this unit
|
||||||
|
|
||||||
|
SYNOPSIS
|
||||||
|
st_select_lex_unit::check_updateable()
|
||||||
|
db - data base name
|
||||||
|
table - real table name
|
||||||
|
|
||||||
|
RETURN
|
||||||
|
1 - found
|
||||||
|
0 - OK (table did not found)
|
||||||
|
*/
|
||||||
|
bool st_select_lex_unit::check_updateable(char *db, char *table)
|
||||||
|
{
|
||||||
|
for(SELECT_LEX *sl= first_select(); sl; sl= sl->next_select())
|
||||||
|
if (sl->check_updateable(db, table))
|
||||||
|
return 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Find db.table which will be updated in this select and
|
||||||
|
underlayed ones (except derived tables)
|
||||||
|
|
||||||
|
SYNOPSIS
|
||||||
|
st_select_lex::check_updateable()
|
||||||
|
db - data base name
|
||||||
|
table - real table name
|
||||||
|
|
||||||
|
RETURN
|
||||||
|
1 - found
|
||||||
|
0 - OK (table did not found)
|
||||||
|
*/
|
||||||
|
bool st_select_lex::check_updateable(char *db, char *table)
|
||||||
|
{
|
||||||
|
if (find_real_table_in_list(get_table_list(), db, table))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
for (SELECT_LEX_UNIT *un= first_inner_unit();
|
||||||
|
un;
|
||||||
|
un= un->next_unit())
|
||||||
|
{
|
||||||
|
if (un->first_select()->linkage != DERIVED_TABLE_TYPE &&
|
||||||
|
un->check_updateable(db, table))
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void st_select_lex_unit::print(String *str)
|
void st_select_lex_unit::print(String *str)
|
||||||
{
|
{
|
||||||
for (SELECT_LEX *sl= first_select(); sl; sl= sl->next_select())
|
for (SELECT_LEX *sl= first_select(); sl; sl= sl->next_select())
|
||||||
@ -1535,6 +1596,7 @@ void st_select_lex::print_order(String *str, ORDER *order)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void st_select_lex::print_limit(THD *thd, String *str)
|
void st_select_lex::print_limit(THD *thd, String *str)
|
||||||
{
|
{
|
||||||
if (!thd)
|
if (!thd)
|
||||||
|
@ -336,8 +336,7 @@ public:
|
|||||||
uint union_option;
|
uint union_option;
|
||||||
|
|
||||||
void init_query();
|
void init_query();
|
||||||
bool create_total_list(THD *thd, st_lex *lex, TABLE_LIST **result,
|
bool create_total_list(THD *thd, st_lex *lex, TABLE_LIST **result);
|
||||||
bool check_current_derived);
|
|
||||||
st_select_lex_unit* master_unit();
|
st_select_lex_unit* master_unit();
|
||||||
st_select_lex* outer_select();
|
st_select_lex* outer_select();
|
||||||
st_select_lex* first_select() { return (st_select_lex*) slave; }
|
st_select_lex* first_select() { return (st_select_lex*) slave; }
|
||||||
@ -355,14 +354,15 @@ public:
|
|||||||
int exec();
|
int exec();
|
||||||
int cleanup();
|
int cleanup();
|
||||||
|
|
||||||
|
bool check_updateable(char *db, char *table);
|
||||||
void print(String *str);
|
void print(String *str);
|
||||||
|
|
||||||
|
|
||||||
friend void mysql_init_query(THD *thd);
|
friend void mysql_init_query(THD *thd);
|
||||||
friend int subselect_union_engine::exec();
|
friend int subselect_union_engine::exec();
|
||||||
private:
|
private:
|
||||||
bool create_total_list_n_last_return(THD *thd, st_lex *lex,
|
bool create_total_list_n_last_return(THD *thd, st_lex *lex,
|
||||||
TABLE_LIST ***result,
|
TABLE_LIST ***result);
|
||||||
bool check_current_derived);
|
|
||||||
};
|
};
|
||||||
typedef class st_select_lex_unit SELECT_LEX_UNIT;
|
typedef class st_select_lex_unit SELECT_LEX_UNIT;
|
||||||
|
|
||||||
@ -497,6 +497,7 @@ public:
|
|||||||
init_select();
|
init_select();
|
||||||
}
|
}
|
||||||
bool setup_ref_array(THD *thd, uint order_group_num);
|
bool setup_ref_array(THD *thd, uint order_group_num);
|
||||||
|
bool check_updateable(char *db, char *table);
|
||||||
void print(THD *thd, String *str);
|
void print(THD *thd, String *str);
|
||||||
static void print_order(String *str, ORDER *order);
|
static void print_order(String *str, ORDER *order);
|
||||||
void print_limit(THD *thd, String *str);
|
void print_limit(THD *thd, String *str);
|
||||||
|
@ -143,18 +143,6 @@ int handle_olaps(LEX *lex, SELECT_LEX *select_lex)
|
|||||||
int count=select_lex->group_list.elements;
|
int count=select_lex->group_list.elements;
|
||||||
int sl_return=0;
|
int sl_return=0;
|
||||||
|
|
||||||
// a fix for UNION's
|
|
||||||
for (TABLE_LIST *cursor= (TABLE_LIST *)select_lex->table_list.first;
|
|
||||||
cursor;
|
|
||||||
cursor=cursor->next)
|
|
||||||
{
|
|
||||||
if (cursor->do_redirect)
|
|
||||||
{
|
|
||||||
//Sinisa TODO: there are function for this purpose: fix_tables_pointers
|
|
||||||
cursor->table= cursor->table_list->table;
|
|
||||||
cursor->do_redirect= 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
lex->last_selects=select_lex;
|
lex->last_selects=select_lex;
|
||||||
|
|
||||||
|
@ -1789,34 +1789,9 @@ mysql_execute_command(THD *thd)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
#endif /* !HAVE_REPLICATION */
|
#endif /* !HAVE_REPLICATION */
|
||||||
/*
|
|
||||||
TODO: make derived tables processing 'inside' SELECT processing.
|
|
||||||
TODO: solve problem with depended derived tables in subselects
|
|
||||||
*/
|
|
||||||
if (lex->derived_tables)
|
|
||||||
{
|
|
||||||
for (SELECT_LEX *sl= lex->all_selects_list;
|
|
||||||
sl;
|
|
||||||
sl= sl->next_select_in_list())
|
|
||||||
{
|
|
||||||
for (TABLE_LIST *cursor= sl->get_table_list();
|
|
||||||
cursor;
|
|
||||||
cursor= cursor->next)
|
|
||||||
{
|
|
||||||
if (cursor->derived && (res=mysql_derived(thd, lex,
|
|
||||||
cursor->derived,
|
|
||||||
cursor)))
|
|
||||||
{
|
|
||||||
if (res < 0 || thd->net.report_error)
|
|
||||||
send_error(thd,thd->killed ? ER_SERVER_SHUTDOWN : 0);
|
|
||||||
DBUG_VOID_RETURN;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (&lex->select_lex != lex->all_selects_list &&
|
if (&lex->select_lex != lex->all_selects_list &&
|
||||||
lex->sql_command != SQLCOM_CREATE_TABLE &&
|
lex->sql_command != SQLCOM_CREATE_TABLE &&
|
||||||
lex->unit.create_total_list(thd, lex, &tables, 0))
|
lex->unit.create_total_list(thd, lex, &tables))
|
||||||
DBUG_VOID_RETURN;
|
DBUG_VOID_RETURN;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -1875,7 +1850,6 @@ mysql_execute_command(THD *thd)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
thd->send_explain_fields(result);
|
thd->send_explain_fields(result);
|
||||||
fix_tables_pointers(lex->all_selects_list);
|
|
||||||
res= mysql_explain_union(thd, &thd->lex->unit, result);
|
res= mysql_explain_union(thd, &thd->lex->unit, result);
|
||||||
MYSQL_LOCK *save_lock= thd->lock;
|
MYSQL_LOCK *save_lock= thd->lock;
|
||||||
thd->lock= (MYSQL_LOCK *)0;
|
thd->lock= (MYSQL_LOCK *)0;
|
||||||
@ -1918,7 +1892,6 @@ mysql_execute_command(THD *thd)
|
|||||||
(res= open_and_lock_tables(thd,tables))))
|
(res= open_and_lock_tables(thd,tables))))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
fix_tables_pointers(lex->all_selects_list);
|
|
||||||
res= mysql_do(thd, *lex->insert_list);
|
res= mysql_do(thd, *lex->insert_list);
|
||||||
if (thd->net.report_error)
|
if (thd->net.report_error)
|
||||||
res= -1;
|
res= -1;
|
||||||
@ -2127,7 +2100,7 @@ mysql_execute_command(THD *thd)
|
|||||||
lex->select_lex.table_list.first= (byte*) (tables);
|
lex->select_lex.table_list.first= (byte*) (tables);
|
||||||
create_table->next= 0;
|
create_table->next= 0;
|
||||||
if (&lex->select_lex != lex->all_selects_list &&
|
if (&lex->select_lex != lex->all_selects_list &&
|
||||||
lex->unit.create_total_list(thd, lex, &tables, 0))
|
lex->unit.create_total_list(thd, lex, &tables))
|
||||||
DBUG_VOID_RETURN;
|
DBUG_VOID_RETURN;
|
||||||
|
|
||||||
ulong want_priv= ((lex->create_info.options & HA_LEX_CREATE_TMP_TABLE) ?
|
ulong want_priv= ((lex->create_info.options & HA_LEX_CREATE_TMP_TABLE) ?
|
||||||
@ -2342,6 +2315,8 @@ mysql_execute_command(THD *thd)
|
|||||||
if (grant_option)
|
if (grant_option)
|
||||||
{
|
{
|
||||||
TABLE_LIST old_list,new_list;
|
TABLE_LIST old_list,new_list;
|
||||||
|
bzero((char*) &old_list, sizeof(old_list));
|
||||||
|
bzero((char*) &new_list, sizeof(new_list)); // Safety
|
||||||
old_list=table[0];
|
old_list=table[0];
|
||||||
new_list=table->next[0];
|
new_list=table->next[0];
|
||||||
old_list.next=new_list.next=0;
|
old_list.next=new_list.next=0;
|
||||||
@ -2673,23 +2648,15 @@ mysql_execute_command(THD *thd)
|
|||||||
}
|
}
|
||||||
if (!walk)
|
if (!walk)
|
||||||
{
|
{
|
||||||
if (lex->derived_tables)
|
|
||||||
{
|
|
||||||
// are we trying to delete derived table?
|
|
||||||
for (walk= (TABLE_LIST*) tables; walk; walk= walk->next)
|
|
||||||
{
|
|
||||||
if (!strcmp(auxi->real_name,walk->alias) &&
|
|
||||||
walk->derived)
|
|
||||||
{
|
|
||||||
net_printf(thd, ER_NON_UPDATABLE_TABLE,
|
|
||||||
auxi->real_name, "DELETE");
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
net_printf(thd, ER_NONUNIQ_TABLE, auxi->real_name);
|
net_printf(thd, ER_NONUNIQ_TABLE, auxi->real_name);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
if (walk->derived)
|
||||||
|
{
|
||||||
|
net_printf(thd, ER_NON_UPDATABLE_TABLE,
|
||||||
|
auxi->real_name, "DELETE");
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
walk->lock_type= auxi->lock_type;
|
walk->lock_type= auxi->lock_type;
|
||||||
auxi->table_list= walk; // Remember corresponding table
|
auxi->table_list= walk; // Remember corresponding table
|
||||||
}
|
}
|
||||||
@ -2703,21 +2670,27 @@ mysql_execute_command(THD *thd)
|
|||||||
break;
|
break;
|
||||||
/* Fix tables-to-be-deleted-from list to point at opened tables */
|
/* Fix tables-to-be-deleted-from list to point at opened tables */
|
||||||
for (auxi=(TABLE_LIST*) aux_tables ; auxi ; auxi=auxi->next)
|
for (auxi=(TABLE_LIST*) aux_tables ; auxi ; auxi=auxi->next)
|
||||||
auxi->table= auxi->table_list->table;
|
|
||||||
if (&lex->select_lex != lex->all_selects_list)
|
|
||||||
{
|
{
|
||||||
for (TABLE_LIST *t= select_lex->get_table_list();
|
auxi->table= auxi->table_list->table;
|
||||||
t; t= t->next)
|
/*
|
||||||
|
Multi-delete can't be constucted over-union => we always have
|
||||||
|
single SELECT on top and have to check underlayed SELECTs of it
|
||||||
|
*/
|
||||||
|
for (SELECT_LEX_UNIT *un= lex->select_lex.first_inner_unit();
|
||||||
|
un;
|
||||||
|
un= un->next_unit())
|
||||||
{
|
{
|
||||||
if (find_real_table_in_list(t->table_list->next, t->db, t->real_name))
|
if (un->first_select()->linkage != DERIVED_TABLE_TYPE &&
|
||||||
|
un->check_updateable(auxi->table_list->db,
|
||||||
|
auxi->table_list->real_name))
|
||||||
{
|
{
|
||||||
my_error(ER_UPDATE_TABLE_USED, MYF(0), t->real_name);
|
my_error(ER_UPDATE_TABLE_USED, MYF(0), auxi->table_list->real_name);
|
||||||
res= -1;
|
res= -1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fix_tables_pointers(lex->all_selects_list);
|
|
||||||
if (!thd->is_fatal_error && (result= new multi_delete(thd,aux_tables,
|
if (!thd->is_fatal_error && (result= new multi_delete(thd,aux_tables,
|
||||||
table_count)))
|
table_count)))
|
||||||
{
|
{
|
||||||
@ -2962,7 +2935,6 @@ mysql_execute_command(THD *thd)
|
|||||||
if (tables && ((res= check_table_access(thd, SELECT_ACL, tables,0)) ||
|
if (tables && ((res= check_table_access(thd, SELECT_ACL, tables,0)) ||
|
||||||
(res= open_and_lock_tables(thd,tables))))
|
(res= open_and_lock_tables(thd,tables))))
|
||||||
break;
|
break;
|
||||||
fix_tables_pointers(lex->all_selects_list);
|
|
||||||
if (!(res= sql_set_variables(thd, &lex->var_list)))
|
if (!(res= sql_set_variables(thd, &lex->var_list)))
|
||||||
send_ok(thd);
|
send_ok(thd);
|
||||||
if (thd->net.report_error)
|
if (thd->net.report_error)
|
||||||
|
@ -733,7 +733,7 @@ static bool mysql_test_select_fields(Prepared_statement *stmt,
|
|||||||
DBUG_RETURN(1);
|
DBUG_RETURN(1);
|
||||||
#endif
|
#endif
|
||||||
if ((&lex->select_lex != lex->all_selects_list &&
|
if ((&lex->select_lex != lex->all_selects_list &&
|
||||||
lex->unit.create_total_list(thd, lex, &tables, 0)))
|
lex->unit.create_total_list(thd, lex, &tables)))
|
||||||
DBUG_RETURN(1);
|
DBUG_RETURN(1);
|
||||||
|
|
||||||
if (open_and_lock_tables(thd, tables))
|
if (open_and_lock_tables(thd, tables))
|
||||||
@ -746,7 +746,6 @@ static bool mysql_test_select_fields(Prepared_statement *stmt,
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
fix_tables_pointers(lex->all_selects_list);
|
|
||||||
if (!result && !(result= new select_send()))
|
if (!result && !(result= new select_send()))
|
||||||
{
|
{
|
||||||
send_error(thd, ER_OUT_OF_RESOURCES);
|
send_error(thd, ER_OUT_OF_RESOURCES);
|
||||||
|
@ -175,7 +175,6 @@ int handle_select(THD *thd, LEX *lex, select_result *result)
|
|||||||
register SELECT_LEX *select_lex = &lex->select_lex;
|
register SELECT_LEX *select_lex = &lex->select_lex;
|
||||||
DBUG_ENTER("handle_select");
|
DBUG_ENTER("handle_select");
|
||||||
|
|
||||||
fix_tables_pointers(lex->all_selects_list);
|
|
||||||
if (select_lex->next_select())
|
if (select_lex->next_select())
|
||||||
res=mysql_union(thd, lex, result, &lex->unit);
|
res=mysql_union(thd, lex, result, &lex->unit);
|
||||||
else
|
else
|
||||||
|
@ -427,7 +427,6 @@ public:
|
|||||||
|
|
||||||
bool cp_buffer_from_ref(TABLE_REF *ref);
|
bool cp_buffer_from_ref(TABLE_REF *ref);
|
||||||
bool error_if_full_join(JOIN *join);
|
bool error_if_full_join(JOIN *join);
|
||||||
void relink_tables(SELECT_LEX *select_lex);
|
|
||||||
int report_error(TABLE *table, int error);
|
int report_error(TABLE *table, int error);
|
||||||
int safe_index_read(JOIN_TAB *tab);
|
int safe_index_read(JOIN_TAB *tab);
|
||||||
COND *eliminate_not_funcs(COND *cond);
|
COND *eliminate_not_funcs(COND *cond);
|
||||||
|
@ -149,7 +149,7 @@ void udf_init()
|
|||||||
tables.lock_type = TL_READ;
|
tables.lock_type = TL_READ;
|
||||||
tables.db=new_thd->db;
|
tables.db=new_thd->db;
|
||||||
|
|
||||||
if (open_and_lock_tables(new_thd, &tables))
|
if (simple_open_n_lock_tables(new_thd, &tables))
|
||||||
{
|
{
|
||||||
DBUG_PRINT("error",("Can't open udf table"));
|
DBUG_PRINT("error",("Can't open udf table"));
|
||||||
sql_print_error("Can't open mysql/func table");
|
sql_print_error("Can't open mysql/func table");
|
||||||
|
@ -79,7 +79,6 @@ int mysql_update(THD *thd,
|
|||||||
if ((open_and_lock_tables(thd, table_list)))
|
if ((open_and_lock_tables(thd, table_list)))
|
||||||
DBUG_RETURN(-1);
|
DBUG_RETURN(-1);
|
||||||
thd->proc_info="init";
|
thd->proc_info="init";
|
||||||
fix_tables_pointers(thd->lex->all_selects_list);
|
|
||||||
table= table_list->table;
|
table= table_list->table;
|
||||||
table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK);
|
table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK);
|
||||||
|
|
||||||
@ -431,7 +430,6 @@ int mysql_multi_update(THD *thd,
|
|||||||
#endif
|
#endif
|
||||||
if ((res=open_and_lock_tables(thd,table_list)))
|
if ((res=open_and_lock_tables(thd,table_list)))
|
||||||
DBUG_RETURN(res);
|
DBUG_RETURN(res);
|
||||||
fix_tables_pointers(thd->lex->all_selects_list);
|
|
||||||
|
|
||||||
select_lex->select_limit= HA_POS_ERROR;
|
select_lex->select_limit= HA_POS_ERROR;
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user