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

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

into sanja.is.com.ua:/home/bell/mysql/bk/work-derived2-4.1
parents d13ad082 f9af8578
...@@ -59,7 +59,7 @@ explain select * from t1 as x1, (select * from t1) as x2; ...@@ -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 ...@@ -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 ALL NULL NULL NULL NULL 10000
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 ...@@ -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 eq_ref PRIMARY PRIMARY 3 test.mp.mat_id 1
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 eq_ref PRIMARY PRIMARY 3 test.mp.mat_id 1
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,7 +229,7 @@ explain select count(*) from t1 INNER JOIN (SELECT A.E1, A.E2, A.E3 FROM t1 AS A ...@@ -229,7 +229,7 @@ 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 ALL NULL NULL NULL NULL 2 Using where
3 DEPENDENT SUBQUERY B ALL NULL NULL NULL NULL 2 Using where 3 DEPENDENT SUBQUERY B ALL NULL NULL NULL NULL 2 Using where
drop table t1; drop table t1;
create table t1 (a int); create table t1 (a int);
...@@ -298,3 +298,25 @@ INSERT INTO t3 VALUES (1000,0.00),(1001,0.25),(1002,0.50),(1003,0.75),(1008,1.00 ...@@ -298,3 +298,25 @@ 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
drop table t1;
create table t2 (a int, b int, primary key (a));
insert into t2 values (1,7),(2,7);
explain select a from t2 where a>1;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t2 range PRIMARY PRIMARY 4 NULL 2 Using where; Using index
explain select a from (select a from t2 where a>1) tt;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY <derived2> system NULL NULL NULL NULL 1
2 DERIVED t2 range PRIMARY PRIMARY 4 NULL 2 Using where; Using index
drop table t2;
...@@ -183,3 +183,22 @@ CREATE TABLE t3 ( ...@@ -183,3 +183,22 @@ 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;
drop table t1;
#
# "Using index" in explain
#
create table t2 (a int, b int, primary key (a));
insert into t2 values (1,7),(2,7);
explain select a from t2 where a>1;
explain select a from (select a from t2 where a>1) tt;
drop table t2;
...@@ -247,7 +247,9 @@ extern CHARSET_INFO *national_charset_info, *table_alias_charset; ...@@ -247,7 +247,9 @@ extern CHARSET_INFO *national_charset_info, *table_alias_charset;
// uncachable cause // uncachable cause
#define UNCACHEABLE_DEPENDENT 1 #define UNCACHEABLE_DEPENDENT 1
#define UNCACHEABLE_RAND 2 #define UNCACHEABLE_RAND 2
#define UNCACHEABLE_SIDEEFFECT 4 #define UNCACHEABLE_SIDEEFFECT 4
// forcing to save JOIN for explain
#define UNCACHEABLE_EXPLAIN 8
#ifdef EXTRA_DEBUG #ifdef EXTRA_DEBUG
/* /*
...@@ -481,14 +483,13 @@ int mysql_select(THD *thd, Item ***rref_pointer_array, ...@@ -481,14 +483,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);
...@@ -675,6 +676,7 @@ int setup_ftfuncs(SELECT_LEX* select); ...@@ -675,6 +676,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, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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) ...@@ -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) ...@@ -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, ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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, ...@@ -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, ...@@ -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,58 @@ ...@@ -25,6 +25,58 @@
#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;
}
}
if (lex->describe)
{
/*
Force join->join_tmp creation, because we will use this JOIN
twice for EXPLAIN and we have to have unchanged join for EXPLAINing
*/
sl->uncacheable|= UNCACHEABLE_EXPLAIN;
sl->master_unit()->uncacheable|= UNCACHEABLE_EXPLAIN;
}
}
}
return 0;
}
/* /*
Resolve derived tables in all queries Resolve derived tables in all queries
...@@ -49,9 +101,6 @@ ...@@ -49,9 +101,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 +121,87 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit, ...@@ -72,143 +121,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)))
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;
derived_result->tmp_table_param.init();
derived_result->tmp_table_param.field_count= unit->types.elements;
/* /*
We have to do access checks here as this code is executed before any Temp table is created so that it hounours if UNION without ALL is to be
sql command is started to execute. processed
*/ */
#ifndef NO_EMBEDDED_ACCESS_CHECKS if (!(table= create_tmp_table(thd, &derived_result->tmp_table_param,
if (tables) unit->types, (ORDER*) 0,
res= check_table_access(thd,SELECT_ACL, tables,0); is_union && !unit->union_option, 1,
else (first_select->options | thd->options |
res= check_access(thd, SELECT_ACL, any_db,0,0,0); TMP_TABLE_ALL_COLUMNS),
if (res) HA_POS_ERROR,
DBUG_RETURN(1); org_table_list->alias)))
#endif
if (!(res=open_and_lock_tables(thd,tables)))
{ {
if (is_union || is_subsel) res= -1;
{ goto exit;
/* }
The following code is a re-do of fix_tables_pointers() found derived_result->set_table(table);
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 (is_union)
if ((res= unit->prepare(thd, derived_result, 0))) res= mysql_union(thd, lex, derived_result, unit);
goto exit; 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)
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.field_count= unit->types.elements;
/* /*
Temp table is created so that it hounours if UNION without ALL is to be Here we entirely fix both TABLE_LIST and list of SELECT's as
processed there were no derived tables
*/ */
if (!(table= create_tmp_table(thd, &derived_result->tmp_table_param, if (derived_result->flush())
unit->types, (ORDER*) 0, res= 1;
is_union && !unit->union_option, 1,
(first_select->options | thd->options |
TMP_TABLE_ALL_COLUMNS),
HA_POS_ERROR,
org_table_list->alias)))
{
res= -1;
goto exit;
}
derived_result->set_table(table);
if (is_union)
res= mysql_union(thd, lex, derived_result, unit);
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; table->derived_select_number= first_select->select_number;
table->tmp_table= TMP_TABLE;
#ifndef NO_EMBEDDED_ACCESS_CHECKS #ifndef NO_EMBEDDED_ACCESS_CHECKS
org_table_list->grant.privilege= SELECT_ACL; org_table_list->grant.privilege= SELECT_ACL;
#endif #endif
if (lex->describe) org_table_list->db= (char *)"";
{ // Force read of table stats in the optimizer
// to fix a problem in EXPLAIN table->file->info(HA_STATUS_VARIABLE);
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);
}
} }
if (res) if (res)
...@@ -223,7 +216,6 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit, ...@@ -223,7 +216,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, ...@@ -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";
...@@ -647,7 +646,8 @@ public: ...@@ -647,7 +646,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() ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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: ...@@ -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() ...@@ -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) ...@@ -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) ...@@ -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)
......
...@@ -232,6 +232,7 @@ public: ...@@ -232,6 +232,7 @@ public:
UNCACHEABLE_DEPENDENT UNCACHEABLE_DEPENDENT
UNCACHEABLE_RAND UNCACHEABLE_RAND
UNCACHEABLE_SIDEEFFECT UNCACHEABLE_SIDEEFFECT
UNCACHEABLE_EXPLAIN
*/ */
uint8 uncacheable; uint8 uncacheable;
enum sub_select_type linkage; enum sub_select_type linkage;
...@@ -336,8 +337,7 @@ public: ...@@ -336,8 +337,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 +355,15 @@ public: ...@@ -355,14 +355,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 +498,7 @@ public: ...@@ -497,6 +498,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) ...@@ -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) ...@@ -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) ...@@ -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;
...@@ -1914,7 +1888,6 @@ mysql_execute_command(THD *thd) ...@@ -1914,7 +1888,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;
...@@ -2123,7 +2096,7 @@ mysql_execute_command(THD *thd) ...@@ -2123,7 +2096,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) ?
...@@ -2338,6 +2311,8 @@ mysql_execute_command(THD *thd) ...@@ -2338,6 +2311,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;
...@@ -2669,23 +2644,15 @@ mysql_execute_command(THD *thd) ...@@ -2669,23 +2644,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
} }
...@@ -2699,21 +2666,27 @@ mysql_execute_command(THD *thd) ...@@ -2699,21 +2666,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)))
{ {
...@@ -2958,7 +2931,6 @@ mysql_execute_command(THD *thd) ...@@ -2958,7 +2931,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, ...@@ -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, ...@@ -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);
......
...@@ -173,7 +173,6 @@ int handle_select(THD *thd, LEX *lex, select_result *result) ...@@ -173,7 +173,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
...@@ -1580,8 +1579,8 @@ mysql_select(THD *thd, Item ***rref_pointer_array, ...@@ -1580,8 +1579,8 @@ mysql_select(THD *thd, Item ***rref_pointer_array,
goto err; goto err;
} }
} }
free_join= 0;
} }
free_join= 0;
join->select_options= select_options; join->select_options= select_options;
} }
else else
...@@ -3781,11 +3780,6 @@ JOIN::join_free(bool full) ...@@ -3781,11 +3780,6 @@ JOIN::join_free(bool full)
{ {
if (tab->table) if (tab->table)
{ {
if (tab->table->key_read)
{
tab->table->key_read= 0;
tab->table->file->extra(HA_EXTRA_NO_KEYREAD);
}
/* Don't free index if we are using read_record */ /* Don't free index if we are using read_record */
if (!tab->read_record.table) if (!tab->read_record.table)
tab->table->file->index_end(); tab->table->file->index_end();
...@@ -9133,6 +9127,9 @@ int mysql_explain_union(THD *thd, SELECT_LEX_UNIT *unit, select_result *result) ...@@ -9133,6 +9127,9 @@ int mysql_explain_union(THD *thd, SELECT_LEX_UNIT *unit, select_result *result)
sl; sl;
sl= sl->next_select()) sl= sl->next_select())
{ {
// drop UNCACHEABLE_EXPLAIN, because it is for internal usage only
uint8 uncacheable= (sl->uncacheable & ~UNCACHEABLE_EXPLAIN);
res= mysql_explain_select(thd, sl, res= mysql_explain_select(thd, sl,
(((&thd->lex->select_lex)==sl)? (((&thd->lex->select_lex)==sl)?
((thd->lex->all_selects_list != sl) ? ((thd->lex->all_selects_list != sl) ?
...@@ -9140,13 +9137,13 @@ int mysql_explain_union(THD *thd, SELECT_LEX_UNIT *unit, select_result *result) ...@@ -9140,13 +9137,13 @@ int mysql_explain_union(THD *thd, SELECT_LEX_UNIT *unit, select_result *result)
((sl == first)? ((sl == first)?
((sl->linkage == DERIVED_TABLE_TYPE) ? ((sl->linkage == DERIVED_TABLE_TYPE) ?
"DERIVED": "DERIVED":
((sl->uncacheable & UNCACHEABLE_DEPENDENT) ? ((uncacheable & UNCACHEABLE_DEPENDENT) ?
"DEPENDENT SUBQUERY": "DEPENDENT SUBQUERY":
(sl->uncacheable?"UNCACHEABLE SUBQUERY": (uncacheable?"UNCACHEABLE SUBQUERY":
"SUBQUERY"))): "SUBQUERY"))):
((sl->uncacheable & UNCACHEABLE_DEPENDENT) ? ((uncacheable & UNCACHEABLE_DEPENDENT) ?
"DEPENDENT UNION": "DEPENDENT UNION":
sl->uncacheable?"UNCACHEABLE UNION": uncacheable?"UNCACHEABLE UNION":
"UNION"))), "UNION"))),
result); result);
if (res) if (res)
......
...@@ -428,7 +428,6 @@ public: ...@@ -428,7 +428,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() ...@@ -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, ...@@ -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, ...@@ -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;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment