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
This commit is contained in:
commit
ff0a6e9686
@ -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
|
||||
1 PRIMARY x1 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;
|
||||
select * from (select 1) as a;
|
||||
1
|
||||
@ -141,7 +141,7 @@ a t
|
||||
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
|
||||
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;
|
||||
SELECT * FROM (SELECT (SELECT * FROM (SELECT 1 as a) as a )) as b;
|
||||
(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 <derived2> ALL NULL NULL NULL NULL 6 Using where
|
||||
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;
|
||||
id select_type table type possible_keys key key_len ref rows Extra
|
||||
1 PRIMARY m2 ALL NULL NULL NULL NULL 9
|
||||
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 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;
|
||||
SELECT a.x FROM (SELECT 1 AS x) AS a HAVING a.x = 1;
|
||||
x
|
||||
@ -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
|
||||
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 2
|
||||
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
|
||||
drop table t1;
|
||||
create table t1 (a int);
|
||||
@ -265,12 +265,16 @@ N M
|
||||
3 0
|
||||
UPDATE `t1` AS P1 INNER JOIN (SELECT N FROM `t1` GROUP BY N HAVING Count(M) > 1) AS P2 ON P1.N = P2.N SET P1.M = 2, P2.N = 2;
|
||||
ERROR HY000: The target table P2 of the UPDATE is not updatable.
|
||||
UPDATE `t1` AS P1 INNER JOIN (SELECT aaaa FROM `t1` GROUP BY N HAVING Count(M) > 1) AS P2 ON P1.N = P2.N SET P1.M = 2;
|
||||
ERROR 42S22: Unknown column 'aaaa' in 'field list'
|
||||
delete P1.* from `t1` AS P1 INNER JOIN (SELECT N FROM `t1` GROUP BY N HAVING Count(M) > 1) AS P2 ON P1.N = P2.N;
|
||||
select * from t1;
|
||||
N M
|
||||
3 0
|
||||
delete P1.*,P2.* from `t1` AS P1 INNER JOIN (SELECT N FROM `t1` GROUP BY N HAVING Count(M) > 1) AS P2 ON P1.N = P2.N;
|
||||
ERROR HY000: The target table P2 of the DELETE is not updatable.
|
||||
delete P1.* from `t1` AS P1 INNER JOIN (SELECT aaa FROM `t1` GROUP BY N HAVING Count(M) > 1) AS P2 ON P1.N = P2.N;
|
||||
ERROR 42S22: Unknown column 'aaa' in 'field list'
|
||||
drop table t1;
|
||||
CREATE TABLE t1 (
|
||||
OBJECTID int(11) NOT NULL default '0',
|
||||
@ -294,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;
|
||||
497 ID NULL
|
||||
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;
|
||||
|
@ -153,10 +153,14 @@ UPDATE `t1` AS P1 INNER JOIN (SELECT N FROM `t1` GROUP BY N HAVING Count(M) > 1)
|
||||
select * from t1;
|
||||
-- error 1287
|
||||
UPDATE `t1` AS P1 INNER JOIN (SELECT N FROM `t1` GROUP BY N HAVING Count(M) > 1) AS P2 ON P1.N = P2.N SET P1.M = 2, P2.N = 2;
|
||||
-- error 1054
|
||||
UPDATE `t1` AS P1 INNER JOIN (SELECT aaaa FROM `t1` GROUP BY N HAVING Count(M) > 1) AS P2 ON P1.N = P2.N SET P1.M = 2;
|
||||
delete P1.* from `t1` AS P1 INNER JOIN (SELECT N FROM `t1` GROUP BY N HAVING Count(M) > 1) AS P2 ON P1.N = P2.N;
|
||||
select * from t1;
|
||||
-- error 1287
|
||||
delete P1.*,P2.* from `t1` AS P1 INNER JOIN (SELECT N FROM `t1` GROUP BY N HAVING Count(M) > 1) AS P2 ON P1.N = P2.N;
|
||||
-- error 1054
|
||||
delete P1.* from `t1` AS P1 INNER JOIN (SELECT aaa FROM `t1` GROUP BY N HAVING Count(M) > 1) AS P2 ON P1.N = P2.N;
|
||||
drop table t1;
|
||||
|
||||
#
|
||||
@ -183,3 +187,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);
|
||||
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;
|
||||
|
||||
|
||||
#
|
||||
# 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;
|
||||
// uncachable cause
|
||||
#define UNCACHEABLE_DEPENDENT 1
|
||||
#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
|
||||
/*
|
||||
@ -481,14 +483,13 @@ int mysql_select(THD *thd, Item ***rref_pointer_array,
|
||||
SELECT_LEX *select_lex);
|
||||
void free_underlaid_joins(THD *thd, SELECT_LEX *select);
|
||||
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,
|
||||
select_result *result);
|
||||
int mysql_explain_select(THD *thd, SELECT_LEX *sl, char const *type,
|
||||
select_result *result);
|
||||
int mysql_union(THD *thd, LEX *lex, select_result *result,
|
||||
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,
|
||||
Item ***copy_func, Field **from_field,
|
||||
bool group,bool modify_item);
|
||||
@ -674,9 +675,10 @@ int setup_conds(THD *thd,TABLE_LIST *tables,COND **conds);
|
||||
int setup_ftfuncs(SELECT_LEX* select);
|
||||
int init_ftfuncs(THD *thd, SELECT_LEX* select, bool no_order);
|
||||
void wait_for_refresh(THD *thd);
|
||||
int open_tables(THD *thd,TABLE_LIST *tables);
|
||||
int open_tables(THD *thd, TABLE_LIST *tables, uint *counter);
|
||||
int simple_open_n_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, uint counter);
|
||||
TABLE *open_temporary_table(THD *thd, const char *path, const char *db,
|
||||
const char *table_name, bool link_in_list);
|
||||
bool rm_temporary_table(enum db_type base, char *path);
|
||||
|
@ -732,7 +732,7 @@ static int fetch_db_tables(THD *thd, MYSQL *mysql, const char *db,
|
||||
int error;
|
||||
if (table_rules_on)
|
||||
{
|
||||
table.next= 0;
|
||||
bzero((char*) &table, sizeof(table)); //just for safe
|
||||
table.db= (char*) db;
|
||||
table.real_name= (char*) table_name;
|
||||
table.updating= 1;
|
||||
|
@ -173,7 +173,8 @@ my_bool acl_init(THD *org_thd, bool dont_read_acl_tables)
|
||||
tables[0].lock_type=tables[1].lock_type=tables[2].lock_type=TL_READ;
|
||||
tables[0].db=tables[1].db=tables[2].db=thd->db;
|
||||
|
||||
if (open_tables(thd,tables))
|
||||
uint counter;
|
||||
if (open_tables(thd, tables, &counter))
|
||||
{
|
||||
sql_print_error("Fatal error: Can't open privilege tables: %s",
|
||||
thd->net.last_error);
|
||||
@ -2247,7 +2248,7 @@ int mysql_table_grant(THD *thd, TABLE_LIST *table_list,
|
||||
}
|
||||
#endif
|
||||
|
||||
if (open_and_lock_tables(thd,tables))
|
||||
if (simple_open_n_lock_tables(thd,tables))
|
||||
{ // Should never happen
|
||||
close_thread_tables(thd); /* purecov: deadcode */
|
||||
DBUG_RETURN(-1); /* purecov: deadcode */
|
||||
@ -2395,7 +2396,7 @@ int mysql_grant(THD *thd, const char *db, List <LEX_USER> &list,
|
||||
}
|
||||
|
||||
/* open the mysql.user and mysql.db tables */
|
||||
|
||||
bzero((char*) &tables,sizeof(tables));
|
||||
tables[0].alias=tables[0].real_name=(char*) "user";
|
||||
tables[1].alias=tables[1].real_name=(char*) "db";
|
||||
tables[0].next=tables+1;
|
||||
@ -2421,7 +2422,7 @@ int mysql_grant(THD *thd, const char *db, List <LEX_USER> &list,
|
||||
}
|
||||
#endif
|
||||
|
||||
if (open_and_lock_tables(thd,tables))
|
||||
if (simple_open_n_lock_tables(thd,tables))
|
||||
{ // This should never happen
|
||||
close_thread_tables(thd); /* purecov: deadcode */
|
||||
DBUG_RETURN(-1); /* purecov: deadcode */
|
||||
@ -2517,14 +2518,15 @@ my_bool grant_init(THD *org_thd)
|
||||
thd->store_globals();
|
||||
thd->db= my_strdup("mysql",MYF(0));
|
||||
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[1].alias=tables[1].real_name= (char*) "columns_priv";
|
||||
tables[0].next=tables+1;
|
||||
tables[0].lock_type=tables[1].lock_type=TL_READ;
|
||||
tables[0].db=tables[1].db=thd->db;
|
||||
|
||||
if (open_tables(thd,tables))
|
||||
uint counter;
|
||||
if (open_tables(thd, tables, &counter))
|
||||
goto end;
|
||||
|
||||
TABLE *ptr[2]; // Lock tables for quick update
|
||||
@ -3376,7 +3378,7 @@ int open_grant_tables(THD *thd, TABLE_LIST *tables)
|
||||
}
|
||||
#endif
|
||||
|
||||
if (open_and_lock_tables(thd, tables))
|
||||
if (simple_open_n_lock_tables(thd, tables))
|
||||
{ // This should never happen
|
||||
close_thread_tables(thd);
|
||||
DBUG_RETURN(-1);
|
||||
|
104
sql/sql_base.cc
104
sql/sql_base.cc
@ -1305,9 +1305,9 @@ static int open_unireg_entry(THD *thd, TABLE *entry, const char *db,
|
||||
goto err; // Can't repair the table
|
||||
|
||||
TABLE_LIST table_list;
|
||||
bzero((char*) &table_list, sizeof(table_list)); // just for safe
|
||||
table_list.db=(char*) db;
|
||||
table_list.real_name=(char*) name;
|
||||
table_list.next=0;
|
||||
safe_mutex_assert_owner(&LOCK_open);
|
||||
|
||||
if ((error=lock_table_name(thd,&table_list)))
|
||||
@ -1356,27 +1356,45 @@ err:
|
||||
DBUG_RETURN(1);
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
** open all tables in list
|
||||
*****************************************************************************/
|
||||
/*
|
||||
Open all tables in list
|
||||
|
||||
int open_tables(THD *thd,TABLE_LIST *start)
|
||||
SYNOPSIS
|
||||
open_tables()
|
||||
thd - thread handler
|
||||
start - list of tables
|
||||
counter - number of opened tables will be return using this parameter
|
||||
|
||||
RETURN
|
||||
0 - OK
|
||||
-1 - error
|
||||
*/
|
||||
|
||||
int open_tables(THD *thd, TABLE_LIST *start, uint *counter)
|
||||
{
|
||||
TABLE_LIST *tables;
|
||||
bool refresh;
|
||||
int result=0;
|
||||
DBUG_ENTER("open_tables");
|
||||
*counter= 0;
|
||||
|
||||
thd->current_tablenr= 0;
|
||||
restart:
|
||||
thd->proc_info="Opening tables";
|
||||
for (tables=start ; tables ; tables=tables->next)
|
||||
{
|
||||
/*
|
||||
Ignore placeholders for derived tables. After derived tables
|
||||
processing, link to created temporary table will be put here.
|
||||
*/
|
||||
if (tables->derived)
|
||||
continue;
|
||||
(*counter)++;
|
||||
if (!tables->table &&
|
||||
!(tables->table=open_table(thd,
|
||||
tables->db,
|
||||
tables->real_name,
|
||||
tables->alias, &refresh)))
|
||||
!(tables->table= open_table(thd,
|
||||
tables->db,
|
||||
tables->real_name,
|
||||
tables->alias, &refresh)))
|
||||
{
|
||||
if (refresh) // Refresh in progress
|
||||
{
|
||||
@ -1522,15 +1540,57 @@ TABLE *open_ltable(THD *thd, TABLE_LIST *table_list, thr_lock_type lock_type)
|
||||
|
||||
|
||||
/*
|
||||
Open all tables in list and locks them for read.
|
||||
The lock will automaticly be freed by close_thread_tables()
|
||||
Open all tables in list and locks them for read without derived
|
||||
tables processing.
|
||||
|
||||
SYNOPSIS
|
||||
simple_open_n_lock_tables()
|
||||
thd - thread handler
|
||||
tables - list of tables for open&locking
|
||||
|
||||
RETURN
|
||||
0 - ok
|
||||
-1 - error
|
||||
|
||||
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))
|
||||
return -1; /* purecov: inspected */
|
||||
return 0;
|
||||
DBUG_ENTER("simple_open_n_lock_tables");
|
||||
uint counter;
|
||||
if (open_tables(thd, tables, &counter) || lock_tables(thd, tables, counter))
|
||||
DBUG_RETURN(-1); /* purecov: inspected */
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Open all tables in list, locks them and process derived tables
|
||||
tables processing.
|
||||
|
||||
SYNOPSIS
|
||||
open_and_lock_tables()
|
||||
thd - thread handler
|
||||
tables - list of tables for open&locking
|
||||
|
||||
RETURN
|
||||
0 - ok
|
||||
-1 - error
|
||||
|
||||
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");
|
||||
uint counter;
|
||||
if (open_tables(thd, tables, &counter) || lock_tables(thd, tables, counter))
|
||||
DBUG_RETURN(-1); /* purecov: inspected */
|
||||
fix_tables_pointers(thd->lex->all_selects_list);
|
||||
DBUG_RETURN(mysql_handle_derived(thd->lex));
|
||||
}
|
||||
|
||||
|
||||
@ -1541,6 +1601,7 @@ int open_and_lock_tables(THD *thd,TABLE_LIST *tables)
|
||||
lock_tables()
|
||||
thd Thread handler
|
||||
tables Tables to lock
|
||||
count umber of opened tables
|
||||
|
||||
NOTES
|
||||
You can't call lock_tables twice, as this would break the dead-lock-free
|
||||
@ -1552,7 +1613,7 @@ int open_and_lock_tables(THD *thd,TABLE_LIST *tables)
|
||||
-1 Error
|
||||
*/
|
||||
|
||||
int lock_tables(THD *thd,TABLE_LIST *tables)
|
||||
int lock_tables(THD *thd, TABLE_LIST *tables, uint count)
|
||||
{
|
||||
TABLE_LIST *table;
|
||||
if (!tables)
|
||||
@ -1561,14 +1622,14 @@ int lock_tables(THD *thd,TABLE_LIST *tables)
|
||||
if (!thd->locked_tables)
|
||||
{
|
||||
DBUG_ASSERT(thd->lock == 0); // You must lock everything at once
|
||||
uint count=0;
|
||||
for (table = tables ; table ; table=table->next)
|
||||
count++;
|
||||
TABLE **start,**ptr;
|
||||
if (!(ptr=start=(TABLE**) sql_alloc(sizeof(TABLE*)*count)))
|
||||
return -1;
|
||||
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)))
|
||||
return -1; /* purecov: inspected */
|
||||
}
|
||||
@ -1576,7 +1637,8 @@ int lock_tables(THD *thd,TABLE_LIST *tables)
|
||||
{
|
||||
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);
|
||||
return -1;
|
||||
|
@ -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)))
|
||||
DBUG_RETURN(-1);
|
||||
fix_tables_pointers(thd->lex->all_selects_list);
|
||||
table= table_list->table;
|
||||
table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK);
|
||||
thd->proc_info="init";
|
||||
|
@ -25,6 +25,58 @@
|
||||
#include "sql_select.h"
|
||||
#include "sql_acl.h"
|
||||
|
||||
static 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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
int res;
|
||||
if (cursor->derived && (res=mysql_derived(lex->thd, lex,
|
||||
cursor->derived,
|
||||
cursor)))
|
||||
{
|
||||
return res;
|
||||
}
|
||||
}
|
||||
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
|
||||
|
||||
@ -49,9 +101,6 @@
|
||||
Derived tables is stored in thd->derived_tables and freed in
|
||||
close_thread_tables()
|
||||
|
||||
TODO
|
||||
Move creation of derived tables in open_and_lock_tables()
|
||||
|
||||
RETURN
|
||||
0 ok
|
||||
1 Error
|
||||
@ -59,8 +108,8 @@
|
||||
*/
|
||||
|
||||
|
||||
int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit,
|
||||
TABLE_LIST *org_table_list)
|
||||
static int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit,
|
||||
TABLE_LIST *org_table_list)
|
||||
{
|
||||
SELECT_LEX *first_select= unit->first_select();
|
||||
TABLE *table;
|
||||
@ -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;
|
||||
SELECT_LEX *save_current_select= lex->current_select;
|
||||
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);
|
||||
|
||||
/*
|
||||
We have to do access checks here as this code is executed before any
|
||||
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 (!(derived_result= new select_union(0)))
|
||||
DBUG_RETURN(1); // out of memory
|
||||
|
||||
if (!(res=open_and_lock_tables(thd,tables)))
|
||||
{
|
||||
if (is_union || is_subsel)
|
||||
{
|
||||
/*
|
||||
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.
|
||||
// st_select_lex_unit::prepare correctly work for single select
|
||||
if ((res= unit->prepare(thd, derived_result, 0)))
|
||||
goto exit;
|
||||
|
||||
*/
|
||||
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.field_count= unit->types.elements;
|
||||
/*
|
||||
Temp table is created so that it hounours if UNION without ALL is to be
|
||||
processed
|
||||
*/
|
||||
if (!(table= create_tmp_table(thd, &derived_result->tmp_table_param,
|
||||
unit->types, (ORDER*) 0,
|
||||
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);
|
||||
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
|
||||
processed
|
||||
*/
|
||||
if (!(table= create_tmp_table(thd, &derived_result->tmp_table_param,
|
||||
unit->types, (ORDER*) 0,
|
||||
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);
|
||||
|
||||
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
|
||||
{
|
||||
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
|
||||
org_table_list->real_name= table->real_name;
|
||||
org_table_list->table= table;
|
||||
if (org_table_list->table_list)
|
||||
{
|
||||
org_table_list->real_name=table->real_name;
|
||||
org_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);
|
||||
org_table_list->table_list->real_name= table->real_name;
|
||||
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
|
||||
table->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)
|
||||
@ -223,7 +216,6 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit,
|
||||
exit:
|
||||
delete derived_result;
|
||||
lex->current_select= save_current_select;
|
||||
close_thread_tables(thd, 0, 1);
|
||||
}
|
||||
DBUG_RETURN(res);
|
||||
}
|
||||
|
@ -48,7 +48,8 @@ static TABLE **find_table_ptr_by_name(THD *thd,const char *db,
|
||||
int mysql_ha_open(THD *thd, TABLE_LIST *tables)
|
||||
{
|
||||
HANDLER_TABLES_HACK(thd);
|
||||
int err=open_tables(thd,tables);
|
||||
uint counter;
|
||||
int err=open_tables(thd, tables, &counter);
|
||||
HANDLER_TABLES_HACK(thd);
|
||||
if (err)
|
||||
return -1;
|
||||
|
@ -188,7 +188,6 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list,
|
||||
res= open_and_lock_tables(thd, table_list);
|
||||
if (res)
|
||||
DBUG_RETURN(-1);
|
||||
fix_tables_pointers(thd->lex->all_selects_list);
|
||||
|
||||
table= table_list->table;
|
||||
thd->proc_info="init";
|
||||
@ -647,7 +646,8 @@ public:
|
||||
thd.command=COM_DELAYED_INSERT;
|
||||
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.host_or_ip= "";
|
||||
bzero((char*) &info,sizeof(info));
|
||||
|
@ -1286,12 +1286,10 @@ bool st_select_lex::test_limit()
|
||||
!0 - error
|
||||
*/
|
||||
bool st_select_lex_unit::create_total_list(THD *thd_arg, st_lex *lex,
|
||||
TABLE_LIST **result_arg,
|
||||
bool check_derived)
|
||||
TABLE_LIST **result_arg)
|
||||
{
|
||||
*result_arg= 0;
|
||||
res= create_total_list_n_last_return(thd_arg, lex, &result_arg,
|
||||
check_derived);
|
||||
res= create_total_list_n_last_return(thd_arg, lex, &result_arg);
|
||||
return res;
|
||||
}
|
||||
|
||||
@ -1303,8 +1301,7 @@ bool st_select_lex_unit::create_total_list(THD *thd_arg, st_lex *lex,
|
||||
thd THD pointer
|
||||
lex pointer on LEX stricture
|
||||
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
|
||||
This is used for UNION & subselect to create a new table list of all used
|
||||
tables.
|
||||
@ -1318,8 +1315,7 @@ bool st_select_lex_unit::create_total_list(THD *thd_arg, st_lex *lex,
|
||||
bool st_select_lex_unit::
|
||||
create_total_list_n_last_return(THD *thd_arg,
|
||||
st_lex *lex,
|
||||
TABLE_LIST ***result_arg,
|
||||
bool check_derived)
|
||||
TABLE_LIST ***result_arg)
|
||||
{
|
||||
TABLE_LIST *slave_list_first=0, **slave_list_last= &slave_list_first;
|
||||
TABLE_LIST **new_table_list= *result_arg, *aux;
|
||||
@ -1345,15 +1341,12 @@ create_total_list_n_last_return(THD *thd_arg,
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (sl->linkage == DERIVED_TABLE_TYPE && !check_derived)
|
||||
goto end;
|
||||
|
||||
for (SELECT_LEX_UNIT *inner= sl->first_inner_unit();
|
||||
inner;
|
||||
inner= inner->next_unit())
|
||||
{
|
||||
if (inner->create_total_list_n_last_return(thd, lex,
|
||||
&slave_list_last, 0))
|
||||
&slave_list_last))
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -1400,63 +1393,75 @@ end:
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
st_select_lex_unit* st_select_lex_unit::master_unit()
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
st_select_lex* st_select_lex_unit::outer_select()
|
||||
{
|
||||
return (st_select_lex*) master;
|
||||
}
|
||||
|
||||
|
||||
bool st_select_lex::add_order_to_list(THD *thd, Item *item, bool asc)
|
||||
{
|
||||
return add_to_list(thd, order_list, item, asc);
|
||||
}
|
||||
|
||||
|
||||
bool st_select_lex::add_item_to_list(THD *thd, Item *item)
|
||||
{
|
||||
return item_list.push_back(item);
|
||||
}
|
||||
|
||||
|
||||
bool st_select_lex::add_group_to_list(THD *thd, Item *item, bool asc)
|
||||
{
|
||||
return add_to_list(thd, group_list, item, asc);
|
||||
}
|
||||
|
||||
|
||||
bool st_select_lex::add_ftfunc_to_list(Item_func_match *func)
|
||||
{
|
||||
return !func || ftfunc_list->push_back(func); // end of memory?
|
||||
}
|
||||
|
||||
|
||||
st_select_lex_unit* st_select_lex::master_unit()
|
||||
{
|
||||
return (st_select_lex_unit*) master;
|
||||
}
|
||||
|
||||
|
||||
st_select_lex* st_select_lex::outer_select()
|
||||
{
|
||||
return (st_select_lex*) master->get_master();
|
||||
}
|
||||
|
||||
|
||||
bool st_select_lex::set_braces(bool value)
|
||||
{
|
||||
braces= value;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
bool st_select_lex::inc_in_sum_expr()
|
||||
{
|
||||
in_sum_expr++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
uint st_select_lex::get_in_sum_expr()
|
||||
{
|
||||
return in_sum_expr;
|
||||
}
|
||||
|
||||
|
||||
TABLE_LIST* st_select_lex::get_table_list()
|
||||
{
|
||||
return (TABLE_LIST*) table_list.first;
|
||||
@ -1467,21 +1472,25 @@ List<Item>* st_select_lex::get_item_list()
|
||||
return &item_list;
|
||||
}
|
||||
|
||||
|
||||
List<String>* st_select_lex::get_use_index()
|
||||
{
|
||||
return use_index_ptr;
|
||||
}
|
||||
|
||||
|
||||
List<String>* st_select_lex::get_ignore_index()
|
||||
{
|
||||
return ignore_index_ptr;
|
||||
}
|
||||
|
||||
|
||||
ulong st_select_lex::get_table_join_options()
|
||||
{
|
||||
return table_join_options;
|
||||
}
|
||||
|
||||
|
||||
bool st_select_lex::setup_ref_array(THD *thd, uint order_group_num)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
if (!thd)
|
||||
|
@ -232,6 +232,7 @@ public:
|
||||
UNCACHEABLE_DEPENDENT
|
||||
UNCACHEABLE_RAND
|
||||
UNCACHEABLE_SIDEEFFECT
|
||||
UNCACHEABLE_EXPLAIN
|
||||
*/
|
||||
uint8 uncacheable;
|
||||
enum sub_select_type linkage;
|
||||
@ -336,8 +337,7 @@ public:
|
||||
uint union_option;
|
||||
|
||||
void init_query();
|
||||
bool create_total_list(THD *thd, st_lex *lex, TABLE_LIST **result,
|
||||
bool check_current_derived);
|
||||
bool create_total_list(THD *thd, st_lex *lex, TABLE_LIST **result);
|
||||
st_select_lex_unit* master_unit();
|
||||
st_select_lex* outer_select();
|
||||
st_select_lex* first_select() { return (st_select_lex*) slave; }
|
||||
@ -355,14 +355,15 @@ public:
|
||||
int exec();
|
||||
int cleanup();
|
||||
|
||||
bool check_updateable(char *db, char *table);
|
||||
void print(String *str);
|
||||
|
||||
|
||||
friend void mysql_init_query(THD *thd);
|
||||
friend int subselect_union_engine::exec();
|
||||
private:
|
||||
bool create_total_list_n_last_return(THD *thd, st_lex *lex,
|
||||
TABLE_LIST ***result,
|
||||
bool check_current_derived);
|
||||
TABLE_LIST ***result);
|
||||
};
|
||||
typedef class st_select_lex_unit SELECT_LEX_UNIT;
|
||||
|
||||
@ -497,6 +498,7 @@ public:
|
||||
init_select();
|
||||
}
|
||||
bool setup_ref_array(THD *thd, uint order_group_num);
|
||||
bool check_updateable(char *db, char *table);
|
||||
void print(THD *thd, String *str);
|
||||
static void print_order(String *str, ORDER *order);
|
||||
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 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;
|
||||
|
||||
|
@ -1789,34 +1789,9 @@ mysql_execute_command(THD *thd)
|
||||
#endif
|
||||
}
|
||||
#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 &&
|
||||
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;
|
||||
|
||||
/*
|
||||
@ -1875,7 +1850,6 @@ mysql_execute_command(THD *thd)
|
||||
}
|
||||
else
|
||||
thd->send_explain_fields(result);
|
||||
fix_tables_pointers(lex->all_selects_list);
|
||||
res= mysql_explain_union(thd, &thd->lex->unit, result);
|
||||
MYSQL_LOCK *save_lock= thd->lock;
|
||||
thd->lock= (MYSQL_LOCK *)0;
|
||||
@ -1914,7 +1888,6 @@ mysql_execute_command(THD *thd)
|
||||
(res= open_and_lock_tables(thd,tables))))
|
||||
break;
|
||||
|
||||
fix_tables_pointers(lex->all_selects_list);
|
||||
res= mysql_do(thd, *lex->insert_list);
|
||||
if (thd->net.report_error)
|
||||
res= -1;
|
||||
@ -2123,7 +2096,7 @@ mysql_execute_command(THD *thd)
|
||||
lex->select_lex.table_list.first= (byte*) (tables);
|
||||
create_table->next= 0;
|
||||
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;
|
||||
|
||||
ulong want_priv= ((lex->create_info.options & HA_LEX_CREATE_TMP_TABLE) ?
|
||||
@ -2338,6 +2311,8 @@ mysql_execute_command(THD *thd)
|
||||
if (grant_option)
|
||||
{
|
||||
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];
|
||||
new_list=table->next[0];
|
||||
old_list.next=new_list.next=0;
|
||||
@ -2669,23 +2644,15 @@ mysql_execute_command(THD *thd)
|
||||
}
|
||||
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);
|
||||
goto error;
|
||||
}
|
||||
if (walk->derived)
|
||||
{
|
||||
net_printf(thd, ER_NON_UPDATABLE_TABLE,
|
||||
auxi->real_name, "DELETE");
|
||||
goto error;
|
||||
}
|
||||
walk->lock_type= auxi->lock_type;
|
||||
auxi->table_list= walk; // Remember corresponding table
|
||||
}
|
||||
@ -2699,21 +2666,27 @@ mysql_execute_command(THD *thd)
|
||||
break;
|
||||
/* Fix tables-to-be-deleted-from list to point at opened tables */
|
||||
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();
|
||||
t; t= t->next)
|
||||
auxi->table= auxi->table_list->table;
|
||||
/*
|
||||
Multi-delete can't be constructed over-union => we always have
|
||||
single SELECT on top and have to check underlaying 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;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
fix_tables_pointers(lex->all_selects_list);
|
||||
|
||||
if (!thd->is_fatal_error && (result= new multi_delete(thd,aux_tables,
|
||||
table_count)))
|
||||
{
|
||||
@ -2958,7 +2931,6 @@ mysql_execute_command(THD *thd)
|
||||
if (tables && ((res= check_table_access(thd, SELECT_ACL, tables,0)) ||
|
||||
(res= open_and_lock_tables(thd,tables))))
|
||||
break;
|
||||
fix_tables_pointers(lex->all_selects_list);
|
||||
if (!(res= sql_set_variables(thd, &lex->var_list)))
|
||||
send_ok(thd);
|
||||
if (thd->net.report_error)
|
||||
|
@ -733,7 +733,7 @@ static bool mysql_test_select_fields(Prepared_statement *stmt,
|
||||
DBUG_RETURN(1);
|
||||
#endif
|
||||
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);
|
||||
|
||||
if (open_and_lock_tables(thd, tables))
|
||||
@ -746,7 +746,6 @@ static bool mysql_test_select_fields(Prepared_statement *stmt,
|
||||
}
|
||||
else
|
||||
{
|
||||
fix_tables_pointers(lex->all_selects_list);
|
||||
if (!result && !(result= new select_send()))
|
||||
{
|
||||
send_error(thd, ER_OUT_OF_RESOURCES);
|
||||
|
@ -173,7 +173,6 @@ int handle_select(THD *thd, LEX *lex, select_result *result)
|
||||
register SELECT_LEX *select_lex = &lex->select_lex;
|
||||
DBUG_ENTER("handle_select");
|
||||
|
||||
fix_tables_pointers(lex->all_selects_list);
|
||||
if (select_lex->next_select())
|
||||
res=mysql_union(thd, lex, result, &lex->unit);
|
||||
else
|
||||
@ -1580,8 +1579,8 @@ mysql_select(THD *thd, Item ***rref_pointer_array,
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
free_join= 0;
|
||||
}
|
||||
free_join= 0;
|
||||
join->select_options= select_options;
|
||||
}
|
||||
else
|
||||
@ -3794,11 +3793,6 @@ JOIN::join_free(bool full)
|
||||
{
|
||||
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 */
|
||||
if (!tab->read_record.table)
|
||||
tab->table->file->index_end();
|
||||
@ -9149,6 +9143,9 @@ int mysql_explain_union(THD *thd, SELECT_LEX_UNIT *unit, select_result *result)
|
||||
sl;
|
||||
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,
|
||||
(((&thd->lex->select_lex)==sl)?
|
||||
((thd->lex->all_selects_list != sl) ?
|
||||
@ -9156,13 +9153,13 @@ int mysql_explain_union(THD *thd, SELECT_LEX_UNIT *unit, select_result *result)
|
||||
((sl == first)?
|
||||
((sl->linkage == DERIVED_TABLE_TYPE) ?
|
||||
"DERIVED":
|
||||
((sl->uncacheable & UNCACHEABLE_DEPENDENT) ?
|
||||
((uncacheable & UNCACHEABLE_DEPENDENT) ?
|
||||
"DEPENDENT SUBQUERY":
|
||||
(sl->uncacheable?"UNCACHEABLE SUBQUERY":
|
||||
(uncacheable?"UNCACHEABLE SUBQUERY":
|
||||
"SUBQUERY"))):
|
||||
((sl->uncacheable & UNCACHEABLE_DEPENDENT) ?
|
||||
((uncacheable & UNCACHEABLE_DEPENDENT) ?
|
||||
"DEPENDENT UNION":
|
||||
sl->uncacheable?"UNCACHEABLE UNION":
|
||||
uncacheable?"UNCACHEABLE UNION":
|
||||
"UNION"))),
|
||||
result);
|
||||
if (res)
|
||||
|
@ -428,7 +428,6 @@ public:
|
||||
|
||||
bool cp_buffer_from_ref(TABLE_REF *ref);
|
||||
bool error_if_full_join(JOIN *join);
|
||||
void relink_tables(SELECT_LEX *select_lex);
|
||||
int report_error(TABLE *table, int error);
|
||||
int safe_index_read(JOIN_TAB *tab);
|
||||
COND *eliminate_not_funcs(COND *cond);
|
||||
|
@ -149,7 +149,7 @@ void udf_init()
|
||||
tables.lock_type = TL_READ;
|
||||
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"));
|
||||
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)))
|
||||
DBUG_RETURN(-1);
|
||||
thd->proc_info="init";
|
||||
fix_tables_pointers(thd->lex->all_selects_list);
|
||||
table= table_list->table;
|
||||
table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK);
|
||||
|
||||
@ -431,7 +430,6 @@ int mysql_multi_update(THD *thd,
|
||||
#endif
|
||||
if ((res=open_and_lock_tables(thd,table_list)))
|
||||
DBUG_RETURN(res);
|
||||
fix_tables_pointers(thd->lex->all_selects_list);
|
||||
|
||||
select_lex->select_limit= HA_POS_ERROR;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user