mirror of
https://github.com/MariaDB/server.git
synced 2025-06-15 00:02:46 +03:00
merge
This commit is contained in:
@ -386,4 +386,7 @@
|
|||||||
#define ER_ILLEGAL_VALUE_FOR_TYPE 1367
|
#define ER_ILLEGAL_VALUE_FOR_TYPE 1367
|
||||||
#define ER_VIEW_NONUPD_CHECK 1368
|
#define ER_VIEW_NONUPD_CHECK 1368
|
||||||
#define ER_VIEW_CHECK_FAILED 1369
|
#define ER_VIEW_CHECK_FAILED 1369
|
||||||
#define ER_ERROR_MESSAGES 370
|
#define ER_VIEW_MULTIUPDATE 1370
|
||||||
|
#define ER_VIEW_NO_INSERT_FIELD_LIST 1371
|
||||||
|
#define ER_VIEW_DELETE_MERGE_VIEW 1372
|
||||||
|
#define ER_ERROR_MESSAGES 373
|
||||||
|
@ -877,7 +877,7 @@ insert into t1 values (1), (2), (3), (200);
|
|||||||
create view v1 (x) as select a from t1 where a > 1;
|
create view v1 (x) as select a from t1 where a > 1;
|
||||||
create view v2 (y) as select x from v1 where x < 100;
|
create view v2 (y) as select x from v1 where x < 100;
|
||||||
select * from v2;
|
select * from v2;
|
||||||
x
|
y
|
||||||
2
|
2
|
||||||
3
|
3
|
||||||
drop table t1;
|
drop table t1;
|
||||||
@ -1424,3 +1424,201 @@ a
|
|||||||
1
|
1
|
||||||
drop view v1;
|
drop view v1;
|
||||||
drop table t1;
|
drop table t1;
|
||||||
|
drop table t1,t2;
|
||||||
|
create table t1 (a int);
|
||||||
|
create table t2 (a int);
|
||||||
|
create table t3 (a int);
|
||||||
|
insert into t1 values (1), (2), (3);
|
||||||
|
insert into t2 values (1), (3);
|
||||||
|
insert into t3 values (1), (2), (4);
|
||||||
|
create view v3 (a,b) as select t1.a as a, t2.a as b from t1 left join t2 on (t1.a=t2.a);
|
||||||
|
select * from t3 left join v3 on (t3.a = v3.a);
|
||||||
|
a a b
|
||||||
|
1 1 1
|
||||||
|
2 2 NULL
|
||||||
|
4 NULL NULL
|
||||||
|
explain extended select * from t3 left join v3 on (t3.a = v3.a);
|
||||||
|
id select_type table type possible_keys key key_len ref rows Extra
|
||||||
|
1 PRIMARY t3 ALL NULL NULL NULL NULL 3
|
||||||
|
1 PRIMARY t1 ALL NULL NULL NULL NULL 3
|
||||||
|
1 PRIMARY t2 ALL NULL NULL NULL NULL 2
|
||||||
|
Warnings:
|
||||||
|
Note 1003 select `test`.`t3`.`a` AS `a`,`test`.`t1`.`a` AS `a`,`test`.`t2`.`a` AS `b` from `test`.`t3` left join (`test`.`t1` left join `test`.`t2` on((`test`.`t1`.`a` = `test`.`t2`.`a`))) on((`test`.`t3`.`a` = `test`.`t1`.`a`)) where 1
|
||||||
|
create view v1 (a) as select a from t1;
|
||||||
|
create view v2 (a) as select a from t2;
|
||||||
|
create view v4 (a,b) as select v1.a as a, v2.a as b from v1 left join v2 on (v1.a=v2.a);
|
||||||
|
select * from t3 left join v4 on (t3.a = v4.a);
|
||||||
|
a a b
|
||||||
|
1 1 1
|
||||||
|
2 2 NULL
|
||||||
|
4 NULL NULL
|
||||||
|
explain extended select * from t3 left join v4 on (t3.a = v4.a);
|
||||||
|
id select_type table type possible_keys key key_len ref rows Extra
|
||||||
|
1 PRIMARY t3 ALL NULL NULL NULL NULL 3
|
||||||
|
1 PRIMARY t1 ALL NULL NULL NULL NULL 3
|
||||||
|
1 PRIMARY t2 ALL NULL NULL NULL NULL 2
|
||||||
|
Warnings:
|
||||||
|
Note 1003 select `test`.`t3`.`a` AS `a`,`test`.`t1`.`a` AS `a`,`test`.`t2`.`a` AS `b` from `test`.`t3` left join (`test`.`v1` left join `test`.`v2` on((`test`.`t1`.`a` = `test`.`t2`.`a`))) on((`test`.`t3`.`a` = `test`.`t1`.`a`)) where 1
|
||||||
|
prepare stmt1 from "select * from t3 left join v4 on (t3.a = v4.a);";
|
||||||
|
execute stmt1;
|
||||||
|
a a b
|
||||||
|
1 1 1
|
||||||
|
2 2 NULL
|
||||||
|
4 NULL NULL
|
||||||
|
execute stmt1;
|
||||||
|
a a b
|
||||||
|
1 1 1
|
||||||
|
2 2 NULL
|
||||||
|
4 NULL NULL
|
||||||
|
deallocate prepare stmt1;
|
||||||
|
drop view v4,v3,v2,v1;
|
||||||
|
drop tables t1,t2,t3;
|
||||||
|
create table t1 (a int, primary key (a), b int);
|
||||||
|
create table t2 (a int, primary key (a));
|
||||||
|
insert into t1 values (1,100), (2,200);
|
||||||
|
insert into t2 values (1), (3);
|
||||||
|
create view v3 (a,b) as select t1.a as a, t2.a as b from t1, t2;
|
||||||
|
update v3 set a= 10 where a=1;
|
||||||
|
select * from t1;
|
||||||
|
a b
|
||||||
|
10 100
|
||||||
|
2 200
|
||||||
|
select * from t2;
|
||||||
|
a
|
||||||
|
1
|
||||||
|
3
|
||||||
|
create view v2 (a,b) as select t1.b as a, t2.a as b from t1, t2;
|
||||||
|
update v2 set a= 10 where a=200;
|
||||||
|
ERROR HY000: The target table v2 of the UPDATE is not updatable
|
||||||
|
select * from v3;
|
||||||
|
a b
|
||||||
|
2 1
|
||||||
|
10 1
|
||||||
|
2 3
|
||||||
|
10 3
|
||||||
|
select * from v2;
|
||||||
|
a b
|
||||||
|
100 1
|
||||||
|
200 1
|
||||||
|
100 3
|
||||||
|
200 3
|
||||||
|
set @a= 10;
|
||||||
|
set @b= 100;
|
||||||
|
prepare stmt1 from "update v3 set a= ? where a=?";
|
||||||
|
execute stmt1 using @a,@b;
|
||||||
|
select * from v3;
|
||||||
|
a b
|
||||||
|
2 1
|
||||||
|
10 1
|
||||||
|
2 3
|
||||||
|
10 3
|
||||||
|
set @a= 300;
|
||||||
|
set @b= 10;
|
||||||
|
execute stmt1 using @a,@b;
|
||||||
|
select * from v3;
|
||||||
|
a b
|
||||||
|
2 1
|
||||||
|
300 1
|
||||||
|
2 3
|
||||||
|
300 3
|
||||||
|
deallocate prepare stmt1;
|
||||||
|
drop view v3,v2;
|
||||||
|
drop tables t1,t2;
|
||||||
|
create table t1 (a int, primary key (a), b int);
|
||||||
|
create table t2 (a int, primary key (a), b int);
|
||||||
|
insert into t2 values (1000, 2000);
|
||||||
|
create view v3 (a,b) as select t1.a as a, t2.a as b from t1, t2;
|
||||||
|
insert into v3 values (1,2);
|
||||||
|
ERROR HY000: Can not insert into join view 'test.v3' without fields list
|
||||||
|
insert into v3 select * from t2;
|
||||||
|
ERROR HY000: Can not insert into join view 'test.v3' without fields list
|
||||||
|
insert into v3(a,b) values (1,2);
|
||||||
|
ERROR HY000: Can not modify more than one base table through a join view 'test.v3'
|
||||||
|
insert into v3(a,b) select * from t2;
|
||||||
|
ERROR HY000: Can not modify more than one base table through a join view 'test.v3'
|
||||||
|
insert into v3(a) values (1);
|
||||||
|
insert into v3(b) values (10);
|
||||||
|
insert into v3(a) select a from t2;
|
||||||
|
insert into v3(b) select b from t2;
|
||||||
|
Warnings:
|
||||||
|
Warning 1263 Data truncated; NULL supplied to NOT NULL column 'a' at row 2
|
||||||
|
insert into v3(a) values (1) on duplicate key update a=a+10000+VALUES(a);
|
||||||
|
select * from t1;
|
||||||
|
a b
|
||||||
|
10002 NULL
|
||||||
|
10 NULL
|
||||||
|
1000 NULL
|
||||||
|
select * from t2;
|
||||||
|
a b
|
||||||
|
1000 2000
|
||||||
|
10 NULL
|
||||||
|
2000 NULL
|
||||||
|
0 NULL
|
||||||
|
create view v2 (a,b) as select t1.b as a, t2.a as b from t1, t2;
|
||||||
|
insert into v2(a) values (10);
|
||||||
|
ERROR HY000: The target table v2 of the INSERT is not updatable
|
||||||
|
select * from v3;
|
||||||
|
a b
|
||||||
|
10 1000
|
||||||
|
1000 1000
|
||||||
|
10002 1000
|
||||||
|
10 10
|
||||||
|
1000 10
|
||||||
|
10002 10
|
||||||
|
10 2000
|
||||||
|
1000 2000
|
||||||
|
10002 2000
|
||||||
|
10 0
|
||||||
|
1000 0
|
||||||
|
10002 0
|
||||||
|
select * from v2;
|
||||||
|
a b
|
||||||
|
NULL 1000
|
||||||
|
NULL 1000
|
||||||
|
NULL 1000
|
||||||
|
NULL 10
|
||||||
|
NULL 10
|
||||||
|
NULL 10
|
||||||
|
NULL 2000
|
||||||
|
NULL 2000
|
||||||
|
NULL 2000
|
||||||
|
NULL 0
|
||||||
|
NULL 0
|
||||||
|
NULL 0
|
||||||
|
delete from v3;
|
||||||
|
ERROR HY000: Can not delete from join view 'test.v3'
|
||||||
|
delete v3,t1 from v3,t1;
|
||||||
|
ERROR HY000: Can not delete from join view 'test.v3'
|
||||||
|
delete from t1;
|
||||||
|
prepare stmt1 from "insert into v3(a) values (?);";
|
||||||
|
set @a= 100;
|
||||||
|
execute stmt1 using @a;
|
||||||
|
set @a= 300;
|
||||||
|
execute stmt1 using @a;
|
||||||
|
deallocate prepare stmt1;
|
||||||
|
prepare stmt1 from "insert into v3(a) select ?;";
|
||||||
|
set @a= 101;
|
||||||
|
execute stmt1 using @a;
|
||||||
|
set @a= 301;
|
||||||
|
execute stmt1 using @a;
|
||||||
|
deallocate prepare stmt1;
|
||||||
|
select * from v3;
|
||||||
|
a b
|
||||||
|
100 1000
|
||||||
|
101 1000
|
||||||
|
300 1000
|
||||||
|
301 1000
|
||||||
|
100 10
|
||||||
|
101 10
|
||||||
|
300 10
|
||||||
|
301 10
|
||||||
|
100 2000
|
||||||
|
101 2000
|
||||||
|
300 2000
|
||||||
|
301 2000
|
||||||
|
100 0
|
||||||
|
101 0
|
||||||
|
300 0
|
||||||
|
301 0
|
||||||
|
drop view v3,v2;
|
||||||
|
drop tables t1,t2;
|
||||||
|
@ -1387,3 +1387,121 @@ insert ignore into v1 values (1) on duplicate key update a=2;
|
|||||||
select * from t1;
|
select * from t1;
|
||||||
drop view v1;
|
drop view v1;
|
||||||
drop table t1;
|
drop table t1;
|
||||||
|
drop table t1,t2;
|
||||||
|
|
||||||
|
#
|
||||||
|
# merge of VIEW with several tables
|
||||||
|
#
|
||||||
|
create table t1 (a int);
|
||||||
|
create table t2 (a int);
|
||||||
|
create table t3 (a int);
|
||||||
|
insert into t1 values (1), (2), (3);
|
||||||
|
insert into t2 values (1), (3);
|
||||||
|
insert into t3 values (1), (2), (4);
|
||||||
|
# view over tables
|
||||||
|
create view v3 (a,b) as select t1.a as a, t2.a as b from t1 left join t2 on (t1.a=t2.a);
|
||||||
|
select * from t3 left join v3 on (t3.a = v3.a);
|
||||||
|
explain extended select * from t3 left join v3 on (t3.a = v3.a);
|
||||||
|
# view over views
|
||||||
|
create view v1 (a) as select a from t1;
|
||||||
|
create view v2 (a) as select a from t2;
|
||||||
|
create view v4 (a,b) as select v1.a as a, v2.a as b from v1 left join v2 on (v1.a=v2.a);
|
||||||
|
select * from t3 left join v4 on (t3.a = v4.a);
|
||||||
|
explain extended select * from t3 left join v4 on (t3.a = v4.a);
|
||||||
|
# PS with view over views
|
||||||
|
prepare stmt1 from "select * from t3 left join v4 on (t3.a = v4.a);";
|
||||||
|
execute stmt1;
|
||||||
|
execute stmt1;
|
||||||
|
deallocate prepare stmt1;
|
||||||
|
drop view v4,v3,v2,v1;
|
||||||
|
drop tables t1,t2,t3;
|
||||||
|
|
||||||
|
#
|
||||||
|
# updating of join view
|
||||||
|
#
|
||||||
|
create table t1 (a int, primary key (a), b int);
|
||||||
|
create table t2 (a int, primary key (a));
|
||||||
|
insert into t1 values (1,100), (2,200);
|
||||||
|
insert into t2 values (1), (3);
|
||||||
|
# legal view for update
|
||||||
|
create view v3 (a,b) as select t1.a as a, t2.a as b from t1, t2;
|
||||||
|
update v3 set a= 10 where a=1;
|
||||||
|
select * from t1;
|
||||||
|
select * from t2;
|
||||||
|
# view without primary key
|
||||||
|
create view v2 (a,b) as select t1.b as a, t2.a as b from t1, t2;
|
||||||
|
-- error 1288
|
||||||
|
update v2 set a= 10 where a=200;
|
||||||
|
# just view selects
|
||||||
|
select * from v3;
|
||||||
|
select * from v2;
|
||||||
|
# prepare statement with updating join view
|
||||||
|
set @a= 10;
|
||||||
|
set @b= 100;
|
||||||
|
prepare stmt1 from "update v3 set a= ? where a=?";
|
||||||
|
execute stmt1 using @a,@b;
|
||||||
|
select * from v3;
|
||||||
|
set @a= 300;
|
||||||
|
set @b= 10;
|
||||||
|
execute stmt1 using @a,@b;
|
||||||
|
select * from v3;
|
||||||
|
deallocate prepare stmt1;
|
||||||
|
drop view v3,v2;
|
||||||
|
drop tables t1,t2;
|
||||||
|
|
||||||
|
#
|
||||||
|
# inserting/deleting join view
|
||||||
|
#
|
||||||
|
create table t1 (a int, primary key (a), b int);
|
||||||
|
create table t2 (a int, primary key (a), b int);
|
||||||
|
insert into t2 values (1000, 2000);
|
||||||
|
create view v3 (a,b) as select t1.a as a, t2.a as b from t1, t2;
|
||||||
|
# inserting into join view without field list
|
||||||
|
-- error 1365
|
||||||
|
insert into v3 values (1,2);
|
||||||
|
-- error 1365
|
||||||
|
insert into v3 select * from t2;
|
||||||
|
# inserting in several tables of join view
|
||||||
|
-- error 1364
|
||||||
|
insert into v3(a,b) values (1,2);
|
||||||
|
-- error 1364
|
||||||
|
insert into v3(a,b) select * from t2;
|
||||||
|
# correct inserts into join view
|
||||||
|
insert into v3(a) values (1);
|
||||||
|
insert into v3(b) values (10);
|
||||||
|
insert into v3(a) select a from t2;
|
||||||
|
insert into v3(b) select b from t2;
|
||||||
|
insert into v3(a) values (1) on duplicate key update a=a+10000+VALUES(a);
|
||||||
|
select * from t1;
|
||||||
|
select * from t2;
|
||||||
|
# view without primary key
|
||||||
|
create view v2 (a,b) as select t1.b as a, t2.a as b from t1, t2;
|
||||||
|
-- error 1288
|
||||||
|
insert into v2(a) values (10);
|
||||||
|
# just view selects
|
||||||
|
select * from v3;
|
||||||
|
select * from v2;
|
||||||
|
# try delete from join view
|
||||||
|
-- error 1366
|
||||||
|
delete from v3;
|
||||||
|
-- error 1366
|
||||||
|
delete v3,t1 from v3,t1;
|
||||||
|
# delete from t1 just to reduce result set size
|
||||||
|
delete from t1;
|
||||||
|
# prepare statement with insert join view
|
||||||
|
prepare stmt1 from "insert into v3(a) values (?);";
|
||||||
|
set @a= 100;
|
||||||
|
execute stmt1 using @a;
|
||||||
|
set @a= 300;
|
||||||
|
execute stmt1 using @a;
|
||||||
|
deallocate prepare stmt1;
|
||||||
|
prepare stmt1 from "insert into v3(a) select ?;";
|
||||||
|
set @a= 101;
|
||||||
|
execute stmt1 using @a;
|
||||||
|
set @a= 301;
|
||||||
|
execute stmt1 using @a;
|
||||||
|
deallocate prepare stmt1;
|
||||||
|
select * from v3;
|
||||||
|
|
||||||
|
drop view v3,v2;
|
||||||
|
drop tables t1,t2;
|
||||||
|
34
sql/item.cc
34
sql/item.cc
@ -45,12 +45,11 @@ void item_init(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
Item::Item():
|
Item::Item():
|
||||||
name_length(0), fixed(0)
|
name(0), orig_name(0), name_length(0), fixed(0)
|
||||||
{
|
{
|
||||||
marker= 0;
|
marker= 0;
|
||||||
maybe_null=null_value=with_sum_func=unsigned_flag=0;
|
maybe_null=null_value=with_sum_func=unsigned_flag=0;
|
||||||
collation.set(default_charset(), DERIVATION_COERCIBLE);
|
collation.set(default_charset(), DERIVATION_COERCIBLE);
|
||||||
name= 0;
|
|
||||||
decimals= 0; max_length= 0;
|
decimals= 0; max_length= 0;
|
||||||
|
|
||||||
/* Put item in free list so that we can free all items at end */
|
/* Put item in free list so that we can free all items at end */
|
||||||
@ -80,6 +79,7 @@ Item::Item():
|
|||||||
Item::Item(THD *thd, Item *item):
|
Item::Item(THD *thd, Item *item):
|
||||||
str_value(item->str_value),
|
str_value(item->str_value),
|
||||||
name(item->name),
|
name(item->name),
|
||||||
|
orig_name(item->orig_name),
|
||||||
max_length(item->max_length),
|
max_length(item->max_length),
|
||||||
marker(item->marker),
|
marker(item->marker),
|
||||||
decimals(item->decimals),
|
decimals(item->decimals),
|
||||||
@ -110,12 +110,35 @@ void Item::print_item_w_name(String *str)
|
|||||||
void Item::cleanup()
|
void Item::cleanup()
|
||||||
{
|
{
|
||||||
DBUG_ENTER("Item::cleanup");
|
DBUG_ENTER("Item::cleanup");
|
||||||
DBUG_PRINT("info", ("Item: 0x%lx", this));
|
DBUG_PRINT("info", ("Item: 0x%lx, Type: %d, name %s, original name %s",
|
||||||
DBUG_PRINT("info", ("Type: %d", (int)type()));
|
this, (int)type(), name, orig_name));
|
||||||
fixed=0;
|
fixed=0;
|
||||||
|
if (orig_name)
|
||||||
|
name= orig_name;
|
||||||
DBUG_VOID_RETURN;
|
DBUG_VOID_RETURN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
rename item (used for views, cleanup() return original name)
|
||||||
|
|
||||||
|
SYNOPSIS
|
||||||
|
Item::rename()
|
||||||
|
new_name new name of item;
|
||||||
|
*/
|
||||||
|
|
||||||
|
void Item::rename(char *new_name)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
we can compare pointers to names here, bacause if name was not changed,
|
||||||
|
pointer will be same
|
||||||
|
*/
|
||||||
|
if (!orig_name && new_name != name)
|
||||||
|
orig_name= name;
|
||||||
|
name= new_name;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
Item_ident::Item_ident(const char *db_name_par,const char *table_name_par,
|
Item_ident::Item_ident(const char *db_name_par,const char *table_name_par,
|
||||||
const char *field_name_par)
|
const char *field_name_par)
|
||||||
:orig_db_name(db_name_par), orig_table_name(table_name_par),
|
:orig_db_name(db_name_par), orig_table_name(table_name_par),
|
||||||
@ -2319,6 +2342,9 @@ void Item_ref::cleanup()
|
|||||||
DBUG_ENTER("Item_ref::cleanup");
|
DBUG_ENTER("Item_ref::cleanup");
|
||||||
Item_ident::cleanup();
|
Item_ident::cleanup();
|
||||||
result_field= 0;
|
result_field= 0;
|
||||||
|
DBUG_PRINT("info", ("hook: 0x%lx(0x%lx) original item: 0x%lx",
|
||||||
|
(ulong)hook_ptr, (ulong)(hook_ptr?*hook_ptr:0),
|
||||||
|
(ulong)orig_item));
|
||||||
if (hook_ptr)
|
if (hook_ptr)
|
||||||
*hook_ptr= orig_item;
|
*hook_ptr= orig_item;
|
||||||
DBUG_VOID_RETURN;
|
DBUG_VOID_RETURN;
|
||||||
|
27
sql/item.h
27
sql/item.h
@ -116,6 +116,8 @@ public:
|
|||||||
*/
|
*/
|
||||||
String str_value;
|
String str_value;
|
||||||
my_string name; /* Name from select */
|
my_string name; /* Name from select */
|
||||||
|
/* Original item name (if it was renamed)*/
|
||||||
|
my_string orig_name;
|
||||||
Item *next;
|
Item *next;
|
||||||
uint32 max_length;
|
uint32 max_length;
|
||||||
uint name_length; /* Length of name */
|
uint name_length; /* Length of name */
|
||||||
@ -143,6 +145,7 @@ public:
|
|||||||
name=0;
|
name=0;
|
||||||
} /*lint -e1509 */
|
} /*lint -e1509 */
|
||||||
void set_name(const char *str,uint length, CHARSET_INFO *cs);
|
void set_name(const char *str,uint length, CHARSET_INFO *cs);
|
||||||
|
void rename(char *new_name);
|
||||||
void init_make_field(Send_field *tmp_field,enum enum_field_types type);
|
void init_make_field(Send_field *tmp_field,enum enum_field_types type);
|
||||||
virtual void cleanup();
|
virtual void cleanup();
|
||||||
virtual void make_field(Send_field *field);
|
virtual void make_field(Send_field *field);
|
||||||
@ -926,15 +929,33 @@ public:
|
|||||||
Item_ref(Item **hook, Item *original,const char *db_par,
|
Item_ref(Item **hook, Item *original,const char *db_par,
|
||||||
const char *table_name_par, const char *field_name_par)
|
const char *table_name_par, const char *field_name_par)
|
||||||
:Item_ident(db_par, table_name_par, field_name_par), result_field(0),
|
:Item_ident(db_par, table_name_par, field_name_par), result_field(0),
|
||||||
ref(0), hook_ptr(hook), orig_item(original) {}
|
ref(0), hook_ptr(hook), orig_item(original)
|
||||||
|
{
|
||||||
|
DBUG_ENTER("Item_ref::Item_ref (Item **, Item * ...) ");
|
||||||
|
DBUG_PRINT("info", ("hook 0x%lx, original item: 0x%lx",
|
||||||
|
hook_ptr, orig_item));
|
||||||
|
DBUG_VOID_RETURN;
|
||||||
|
}
|
||||||
Item_ref(Item **item, Item **hook,
|
Item_ref(Item **item, Item **hook,
|
||||||
const char *table_name_par, const char *field_name_par)
|
const char *table_name_par, const char *field_name_par)
|
||||||
:Item_ident(NullS, table_name_par, field_name_par), result_field(0),
|
:Item_ident(NullS, table_name_par, field_name_par), result_field(0),
|
||||||
ref(item), hook_ptr(hook), orig_item(hook ? *hook:0) {}
|
ref(item), hook_ptr(hook), orig_item(hook ? *hook:0)
|
||||||
|
{
|
||||||
|
DBUG_ENTER("Item_ref::Item_ref (Item **, Item ** ...) ");
|
||||||
|
DBUG_PRINT("info", ("hook 0x%lx, original item: 0x%lx",
|
||||||
|
hook_ptr, orig_item));
|
||||||
|
DBUG_VOID_RETURN;
|
||||||
|
}
|
||||||
// Constructor need to process subselect with temporary tables (see Item)
|
// Constructor need to process subselect with temporary tables (see Item)
|
||||||
Item_ref(THD *thd, Item_ref *item, Item **hook)
|
Item_ref(THD *thd, Item_ref *item, Item **hook)
|
||||||
:Item_ident(thd, item), result_field(item->result_field), ref(item->ref),
|
:Item_ident(thd, item), result_field(item->result_field), ref(item->ref),
|
||||||
hook_ptr(hook), orig_item(hook ? *hook : 0) {}
|
hook_ptr(hook), orig_item(hook ? *hook : 0)
|
||||||
|
{
|
||||||
|
DBUG_ENTER("Item_ref::Item_ref (THD*, Item_ref, ...)");
|
||||||
|
DBUG_PRINT("info", ("hook 0x%lx, original item: 0x%lx",
|
||||||
|
hook_ptr, orig_item));
|
||||||
|
DBUG_VOID_RETURN;
|
||||||
|
}
|
||||||
enum Type type() const { return REF_ITEM; }
|
enum Type type() const { return REF_ITEM; }
|
||||||
bool eq(const Item *item, bool binary_cmp) const
|
bool eq(const Item *item, bool binary_cmp) const
|
||||||
{ return ref && (*ref)->eq(item, binary_cmp); }
|
{ return ref && (*ref)->eq(item, binary_cmp); }
|
||||||
|
@ -965,7 +965,8 @@ public:
|
|||||||
void update_used_tables();
|
void update_used_tables();
|
||||||
void print(String *str);
|
void print(String *str);
|
||||||
void split_sum_func(Item **ref_pointer_array, List<Item> &fields);
|
void split_sum_func(Item **ref_pointer_array, List<Item> &fields);
|
||||||
friend int setup_conds(THD *thd,TABLE_LIST *tables,COND **conds);
|
friend int setup_conds(THD *thd, TABLE_LIST *tables, TABLE_LIST *leaves,
|
||||||
|
COND **conds);
|
||||||
void top_level_item() { abort_on_null=1; }
|
void top_level_item() { abort_on_null=1; }
|
||||||
void copy_andor_arguments(THD *thd, Item_cond *item);
|
void copy_andor_arguments(THD *thd, Item_cond *item);
|
||||||
bool walk(Item_processor processor, byte *arg);
|
bool walk(Item_processor processor, byte *arg);
|
||||||
|
@ -1411,7 +1411,7 @@ void subselect_uniquesubquery_engine::exclude()
|
|||||||
table_map subselect_engine::calc_const_tables(TABLE_LIST *table)
|
table_map subselect_engine::calc_const_tables(TABLE_LIST *table)
|
||||||
{
|
{
|
||||||
table_map map= 0;
|
table_map map= 0;
|
||||||
for(; table; table= table->next_local)
|
for(; table; table= table->next_leaf)
|
||||||
{
|
{
|
||||||
TABLE *tbl= table->table;
|
TABLE *tbl= table->table;
|
||||||
if (tbl && tbl->const_table)
|
if (tbl && tbl->const_table)
|
||||||
@ -1424,14 +1424,13 @@ table_map subselect_engine::calc_const_tables(TABLE_LIST *table)
|
|||||||
table_map subselect_single_select_engine::upper_select_const_tables()
|
table_map subselect_single_select_engine::upper_select_const_tables()
|
||||||
{
|
{
|
||||||
return calc_const_tables((TABLE_LIST *) select_lex->outer_select()->
|
return calc_const_tables((TABLE_LIST *) select_lex->outer_select()->
|
||||||
table_list.first);
|
leaf_tables);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
table_map subselect_union_engine::upper_select_const_tables()
|
table_map subselect_union_engine::upper_select_const_tables()
|
||||||
{
|
{
|
||||||
return calc_const_tables((TABLE_LIST *) unit->outer_select()->
|
return calc_const_tables((TABLE_LIST *) unit->outer_select()->leaf_tables);
|
||||||
table_list.first);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -618,7 +618,8 @@ int mysql_multi_update(THD *thd, TABLE_LIST *table_list,
|
|||||||
List<Item> *fields, List<Item> *values,
|
List<Item> *fields, List<Item> *values,
|
||||||
COND *conds, ulong options,
|
COND *conds, ulong options,
|
||||||
enum enum_duplicates handle_duplicates,
|
enum enum_duplicates handle_duplicates,
|
||||||
SELECT_LEX_UNIT *unit, SELECT_LEX *select_lex);
|
SELECT_LEX_UNIT *unit, SELECT_LEX *select_lex,
|
||||||
|
bool converted);
|
||||||
int mysql_prepare_insert(THD *thd, TABLE_LIST *table_list, TABLE *table,
|
int mysql_prepare_insert(THD *thd, TABLE_LIST *table_list, TABLE *table,
|
||||||
List<Item> &fields, List_item *values,
|
List<Item> &fields, List_item *values,
|
||||||
List<Item> &update_fields,
|
List<Item> &update_fields,
|
||||||
@ -774,13 +775,15 @@ bool insert_fields(THD *thd,TABLE_LIST *tables,
|
|||||||
const char *db_name, const char *table_name,
|
const char *db_name, const char *table_name,
|
||||||
List_iterator<Item> *it, bool any_privileges,
|
List_iterator<Item> *it, bool any_privileges,
|
||||||
bool allocate_view_names);
|
bool allocate_view_names);
|
||||||
bool setup_tables(THD *thd, TABLE_LIST *tables, Item **conds);
|
bool setup_tables(THD *thd, TABLE_LIST *tables, Item **conds,
|
||||||
|
TABLE_LIST **leaves, bool refresh_only);
|
||||||
int setup_wild(THD *thd, TABLE_LIST *tables, List<Item> &fields,
|
int setup_wild(THD *thd, TABLE_LIST *tables, List<Item> &fields,
|
||||||
List<Item> *sum_func_list, uint wild_num);
|
List<Item> *sum_func_list, uint wild_num);
|
||||||
int setup_fields(THD *thd, Item** ref_pointer_array, TABLE_LIST *tables,
|
int setup_fields(THD *thd, Item** ref_pointer_array, TABLE_LIST *tables,
|
||||||
List<Item> &item, bool set_query_id,
|
List<Item> &item, bool set_query_id,
|
||||||
List<Item> *sum_func_list, bool allow_sum_func);
|
List<Item> *sum_func_list, bool allow_sum_func);
|
||||||
int setup_conds(THD *thd,TABLE_LIST *tables,COND **conds);
|
int setup_conds(THD *thd, TABLE_LIST *tables, TABLE_LIST *leaves,
|
||||||
|
COND **conds);
|
||||||
int setup_ftfuncs(SELECT_LEX* select);
|
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);
|
||||||
|
@ -59,7 +59,7 @@ static int maxmin_in_range(bool max_fl, Field* field, COND *cond);
|
|||||||
|
|
||||||
SYNOPSIS
|
SYNOPSIS
|
||||||
opt_sum_query()
|
opt_sum_query()
|
||||||
tables Tables in query
|
tables list of leaves of join table tree
|
||||||
all_fields All fields to be returned
|
all_fields All fields to be returned
|
||||||
conds WHERE clause
|
conds WHERE clause
|
||||||
|
|
||||||
@ -89,7 +89,7 @@ int opt_sum_query(TABLE_LIST *tables, List<Item> &all_fields,COND *conds)
|
|||||||
where_tables= conds->used_tables();
|
where_tables= conds->used_tables();
|
||||||
|
|
||||||
/* Don't replace expression on a table that is part of an outer join */
|
/* Don't replace expression on a table that is part of an outer join */
|
||||||
for (TABLE_LIST *tl= tables; tl; tl= tl->next_local)
|
for (TABLE_LIST *tl= tables; tl; tl= tl->next_leaf)
|
||||||
{
|
{
|
||||||
if (tl->on_expr)
|
if (tl->on_expr)
|
||||||
{
|
{
|
||||||
@ -128,7 +128,7 @@ int opt_sum_query(TABLE_LIST *tables, List<Item> &all_fields,COND *conds)
|
|||||||
{
|
{
|
||||||
longlong count= 1;
|
longlong count= 1;
|
||||||
TABLE_LIST *table;
|
TABLE_LIST *table;
|
||||||
for (table= tables; table; table= table->next_local)
|
for (table= tables; table; table= table->next_leaf)
|
||||||
{
|
{
|
||||||
if (outer_tables || (table->table->file->table_flags() &
|
if (outer_tables || (table->table->file->table_flags() &
|
||||||
HA_NOT_EXACT_COUNT))
|
HA_NOT_EXACT_COUNT))
|
||||||
|
@ -398,3 +398,6 @@ character-set=latin2
|
|||||||
"Illegal %s '%-.64s' value found during parsing",
|
"Illegal %s '%-.64s' value found during parsing",
|
||||||
"CHECK OPTION on non-updatable view '%-.64s.%-.64s'"
|
"CHECK OPTION on non-updatable view '%-.64s.%-.64s'"
|
||||||
"CHECK OPTION failed '%-.64s.%-.64s'"
|
"CHECK OPTION failed '%-.64s.%-.64s'"
|
||||||
|
"Can not modify more than one base table through a join view '%-.64s.%-.64s'"
|
||||||
|
"Can not insert into join view '%-.64s.%-.64s' without fields list"
|
||||||
|
"Can not delete from join view '%-.64s.%-.64s'"
|
||||||
|
@ -389,3 +389,6 @@ character-set=latin1
|
|||||||
"Illegal %s '%-.64s' value found during parsing",
|
"Illegal %s '%-.64s' value found during parsing",
|
||||||
"CHECK OPTION on non-updatable view '%-.64s.%-.64s'"
|
"CHECK OPTION on non-updatable view '%-.64s.%-.64s'"
|
||||||
"CHECK OPTION failed '%-.64s.%-.64s'"
|
"CHECK OPTION failed '%-.64s.%-.64s'"
|
||||||
|
"Can not modify more than one base table through a join view '%-.64s.%-.64s'"
|
||||||
|
"Can not insert into join view '%-.64s.%-.64s' without fields list"
|
||||||
|
"Can not delete from join view '%-.64s.%-.64s'"
|
||||||
|
@ -398,3 +398,6 @@ character-set=latin1
|
|||||||
"Illegal %s '%-.64s' value found during parsing",
|
"Illegal %s '%-.64s' value found during parsing",
|
||||||
"CHECK OPTION on non-updatable view '%-.64s.%-.64s'"
|
"CHECK OPTION on non-updatable view '%-.64s.%-.64s'"
|
||||||
"CHECK OPTION failed '%-.64s.%-.64s'"
|
"CHECK OPTION failed '%-.64s.%-.64s'"
|
||||||
|
"Can not modify more than one base table through a join view '%-.64s.%-.64s'"
|
||||||
|
"Can not insert into join view '%-.64s.%-.64s' without fields list"
|
||||||
|
"Can not delete from join view '%-.64s.%-.64s'"
|
||||||
|
@ -386,3 +386,6 @@ character-set=latin1
|
|||||||
"Illegal %s '%-.64s' value found during parsing",
|
"Illegal %s '%-.64s' value found during parsing",
|
||||||
"CHECK OPTION on non-updatable view '%-.64s.%-.64s'"
|
"CHECK OPTION on non-updatable view '%-.64s.%-.64s'"
|
||||||
"CHECK OPTION failed '%-.64s.%-.64s'"
|
"CHECK OPTION failed '%-.64s.%-.64s'"
|
||||||
|
"Can not modify more than one base table through a join view '%-.64s.%-.64s'"
|
||||||
|
"Can not insert into join view '%-.64s.%-.64s' without fields list"
|
||||||
|
"Can not delete from join view '%-.64s.%-.64s'"
|
||||||
|
@ -391,3 +391,6 @@ character-set=latin7
|
|||||||
"Illegal %s '%-.64s' value found during parsing",
|
"Illegal %s '%-.64s' value found during parsing",
|
||||||
"CHECK OPTION on non-updatable view '%-.64s.%-.64s'"
|
"CHECK OPTION on non-updatable view '%-.64s.%-.64s'"
|
||||||
"CHECK OPTION failed '%-.64s.%-.64s'"
|
"CHECK OPTION failed '%-.64s.%-.64s'"
|
||||||
|
"Can not modify more than one base table through a join view '%-.64s.%-.64s'"
|
||||||
|
"Can not insert into join view '%-.64s.%-.64s' without fields list"
|
||||||
|
"Can not delete from join view '%-.64s.%-.64s'"
|
||||||
|
@ -386,3 +386,6 @@ character-set=latin1
|
|||||||
"Illegal %s '%-.64s' value found during parsing",
|
"Illegal %s '%-.64s' value found during parsing",
|
||||||
"CHECK OPTION on non-updatable view '%-.64s.%-.64s'"
|
"CHECK OPTION on non-updatable view '%-.64s.%-.64s'"
|
||||||
"CHECK OPTION failed '%-.64s.%-.64s'"
|
"CHECK OPTION failed '%-.64s.%-.64s'"
|
||||||
|
"Can not modify more than one base table through a join view '%-.64s.%-.64s'"
|
||||||
|
"Can not insert into join view '%-.64s.%-.64s' without fields list"
|
||||||
|
"Can not delete from join view '%-.64s.%-.64s'"
|
||||||
|
@ -399,3 +399,6 @@ character-set=latin1
|
|||||||
"Illegal %s '%-.64s' value found during parsing",
|
"Illegal %s '%-.64s' value found during parsing",
|
||||||
"CHECK OPTION on non-updatable view '%-.64s.%-.64s'"
|
"CHECK OPTION on non-updatable view '%-.64s.%-.64s'"
|
||||||
"CHECK OPTION failed '%-.64s.%-.64s'"
|
"CHECK OPTION failed '%-.64s.%-.64s'"
|
||||||
|
"Can not modify more than one base table through a join view '%-.64s.%-.64s'"
|
||||||
|
"Can not insert into join view '%-.64s.%-.64s' without fields list"
|
||||||
|
"Can not delete from join view '%-.64s.%-.64s'"
|
||||||
|
@ -386,3 +386,6 @@ character-set=greek
|
|||||||
"Illegal %s '%-.64s' value found during parsing",
|
"Illegal %s '%-.64s' value found during parsing",
|
||||||
"CHECK OPTION on non-updatable view '%-.64s.%-.64s'"
|
"CHECK OPTION on non-updatable view '%-.64s.%-.64s'"
|
||||||
"CHECK OPTION failed '%-.64s.%-.64s'"
|
"CHECK OPTION failed '%-.64s.%-.64s'"
|
||||||
|
"Can not modify more than one base table through a join view '%-.64s.%-.64s'"
|
||||||
|
"Can not insert into join view '%-.64s.%-.64s' without fields list"
|
||||||
|
"Can not delete from join view '%-.64s.%-.64s'"
|
||||||
|
@ -391,3 +391,6 @@ character-set=latin2
|
|||||||
"Illegal %s '%-.64s' value found during parsing",
|
"Illegal %s '%-.64s' value found during parsing",
|
||||||
"CHECK OPTION on non-updatable view '%-.64s.%-.64s'"
|
"CHECK OPTION on non-updatable view '%-.64s.%-.64s'"
|
||||||
"CHECK OPTION failed '%-.64s.%-.64s'"
|
"CHECK OPTION failed '%-.64s.%-.64s'"
|
||||||
|
"Can not modify more than one base table through a join view '%-.64s.%-.64s'"
|
||||||
|
"Can not insert into join view '%-.64s.%-.64s' without fields list"
|
||||||
|
"Can not delete from join view '%-.64s.%-.64s'"
|
||||||
|
@ -386,3 +386,6 @@ character-set=latin1
|
|||||||
"Illegal %s '%-.64s' value found during parsing",
|
"Illegal %s '%-.64s' value found during parsing",
|
||||||
"CHECK OPTION on non-updatable view '%-.64s.%-.64s'"
|
"CHECK OPTION on non-updatable view '%-.64s.%-.64s'"
|
||||||
"CHECK OPTION failed '%-.64s.%-.64s'"
|
"CHECK OPTION failed '%-.64s.%-.64s'"
|
||||||
|
"Can not modify more than one base table through a join view '%-.64s.%-.64s'"
|
||||||
|
"Can not insert into join view '%-.64s.%-.64s' without fields list"
|
||||||
|
"Can not delete from join view '%-.64s.%-.64s'"
|
||||||
|
@ -390,3 +390,6 @@ character-set=ujis
|
|||||||
"Illegal %s '%-.64s' value found during parsing",
|
"Illegal %s '%-.64s' value found during parsing",
|
||||||
"CHECK OPTION on non-updatable view '%-.64s.%-.64s'"
|
"CHECK OPTION on non-updatable view '%-.64s.%-.64s'"
|
||||||
"CHECK OPTION failed '%-.64s.%-.64s'"
|
"CHECK OPTION failed '%-.64s.%-.64s'"
|
||||||
|
"Can not modify more than one base table through a join view '%-.64s.%-.64s'"
|
||||||
|
"Can not insert into join view '%-.64s.%-.64s' without fields list"
|
||||||
|
"Can not delete from join view '%-.64s.%-.64s'"
|
||||||
|
@ -386,3 +386,6 @@ character-set=euckr
|
|||||||
"Illegal %s '%-.64s' value found during parsing",
|
"Illegal %s '%-.64s' value found during parsing",
|
||||||
"CHECK OPTION on non-updatable view '%-.64s.%-.64s'"
|
"CHECK OPTION on non-updatable view '%-.64s.%-.64s'"
|
||||||
"CHECK OPTION failed '%-.64s.%-.64s'"
|
"CHECK OPTION failed '%-.64s.%-.64s'"
|
||||||
|
"Can not modify more than one base table through a join view '%-.64s.%-.64s'"
|
||||||
|
"Can not insert into join view '%-.64s.%-.64s' without fields list"
|
||||||
|
"Can not delete from join view '%-.64s.%-.64s'"
|
||||||
|
@ -388,3 +388,6 @@ character-set=latin1
|
|||||||
"Illegal %s '%-.64s' value found during parsing",
|
"Illegal %s '%-.64s' value found during parsing",
|
||||||
"CHECK OPTION on non-updatable view '%-.64s.%-.64s'"
|
"CHECK OPTION on non-updatable view '%-.64s.%-.64s'"
|
||||||
"CHECK OPTION failed '%-.64s.%-.64s'"
|
"CHECK OPTION failed '%-.64s.%-.64s'"
|
||||||
|
"Can not modify more than one base table through a join view '%-.64s.%-.64s'"
|
||||||
|
"Can not insert into join view '%-.64s.%-.64s' without fields list"
|
||||||
|
"Can not delete from join view '%-.64s.%-.64s'"
|
||||||
|
@ -388,3 +388,6 @@ character-set=latin1
|
|||||||
"Illegal %s '%-.64s' value found during parsing",
|
"Illegal %s '%-.64s' value found during parsing",
|
||||||
"CHECK OPTION on non-updatable view '%-.64s.%-.64s'"
|
"CHECK OPTION on non-updatable view '%-.64s.%-.64s'"
|
||||||
"CHECK OPTION failed '%-.64s.%-.64s'"
|
"CHECK OPTION failed '%-.64s.%-.64s'"
|
||||||
|
"Can not modify more than one base table through a join view '%-.64s.%-.64s'"
|
||||||
|
"Can not insert into join view '%-.64s.%-.64s' without fields list"
|
||||||
|
"Can not delete from join view '%-.64s.%-.64s'"
|
||||||
|
@ -391,3 +391,6 @@ character-set=latin2
|
|||||||
"Illegal %s '%-.64s' value found during parsing",
|
"Illegal %s '%-.64s' value found during parsing",
|
||||||
"CHECK OPTION on non-updatable view '%-.64s.%-.64s'"
|
"CHECK OPTION on non-updatable view '%-.64s.%-.64s'"
|
||||||
"CHECK OPTION failed '%-.64s.%-.64s'"
|
"CHECK OPTION failed '%-.64s.%-.64s'"
|
||||||
|
"Can not modify more than one base table through a join view '%-.64s.%-.64s'"
|
||||||
|
"Can not insert into join view '%-.64s.%-.64s' without fields list"
|
||||||
|
"Can not delete from join view '%-.64s.%-.64s'"
|
||||||
|
@ -388,3 +388,6 @@ character-set=latin1
|
|||||||
"Illegal %s '%-.64s' value found during parsing",
|
"Illegal %s '%-.64s' value found during parsing",
|
||||||
"CHECK OPTION on non-updatable view '%-.64s.%-.64s'"
|
"CHECK OPTION on non-updatable view '%-.64s.%-.64s'"
|
||||||
"CHECK OPTION failed '%-.64s.%-.64s'"
|
"CHECK OPTION failed '%-.64s.%-.64s'"
|
||||||
|
"Can not modify more than one base table through a join view '%-.64s.%-.64s'"
|
||||||
|
"Can not insert into join view '%-.64s.%-.64s' without fields list"
|
||||||
|
"Can not delete from join view '%-.64s.%-.64s'"
|
||||||
|
@ -391,3 +391,6 @@ character-set=latin2
|
|||||||
"Illegal %s '%-.64s' value found during parsing",
|
"Illegal %s '%-.64s' value found during parsing",
|
||||||
"CHECK OPTION on non-updatable view '%-.64s.%-.64s'"
|
"CHECK OPTION on non-updatable view '%-.64s.%-.64s'"
|
||||||
"CHECK OPTION failed '%-.64s.%-.64s'"
|
"CHECK OPTION failed '%-.64s.%-.64s'"
|
||||||
|
"Can not modify more than one base table through a join view '%-.64s.%-.64s'"
|
||||||
|
"Can not insert into join view '%-.64s.%-.64s' without fields list"
|
||||||
|
"Can not delete from join view '%-.64s.%-.64s'"
|
||||||
|
@ -376,7 +376,7 @@ character-set=koi8r
|
|||||||
"View SELECT <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> '%-.64s'"
|
"View SELECT <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> '%-.64s'"
|
||||||
"View SELECT <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> view <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>"
|
"View SELECT <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> view <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>"
|
||||||
"<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> view <20><> <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> (<28><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>)"
|
"<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> view <20><> <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> (<28><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>)"
|
||||||
"<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> view <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>(<28>)"
|
"<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> view <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>(<28><>) <20> <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>(<28>)"
|
||||||
"View '%-.64s.%-.64s' <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>"
|
"View '%-.64s.%-.64s' <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>"
|
||||||
"Can't drop a %s from within another stored routine"
|
"Can't drop a %s from within another stored routine"
|
||||||
"GOTO is not allowed in a stored procedure handler"
|
"GOTO is not allowed in a stored procedure handler"
|
||||||
@ -391,3 +391,6 @@ character-set=koi8r
|
|||||||
"Illegal %s '%-.64s' value found during parsing",
|
"Illegal %s '%-.64s' value found during parsing",
|
||||||
"CHECK OPTION <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> VIEW '%-.64s.%-.64s'"
|
"CHECK OPTION <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> VIEW '%-.64s.%-.64s'"
|
||||||
"<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> CHECK OPTION <20><><EFBFBD> VIEW '%-.64s.%-.64s' <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>"
|
"<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> CHECK OPTION <20><><EFBFBD> VIEW '%-.64s.%-.64s' <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>"
|
||||||
|
"<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> VIEW '%-.64s.%-.64s'"
|
||||||
|
"<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> VIEW '%-.64s.%-.64s' <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>"
|
||||||
|
"<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> VIEW '%-.64s.%-.64s'"
|
||||||
|
@ -379,3 +379,6 @@ character-set=cp1250
|
|||||||
"Illegal %s '%-.64s' value found during parsing",
|
"Illegal %s '%-.64s' value found during parsing",
|
||||||
"CHECK OPTION on non-updatable view '%-.64s.%-.64s'"
|
"CHECK OPTION on non-updatable view '%-.64s.%-.64s'"
|
||||||
"CHECK OPTION failed '%-.64s.%-.64s'"
|
"CHECK OPTION failed '%-.64s.%-.64s'"
|
||||||
|
"Can not modify more than one base table through a join view '%-.64s.%-.64s'"
|
||||||
|
"Can not insert into join view '%-.64s.%-.64s' without fields list"
|
||||||
|
"Can not delete from join view '%-.64s.%-.64s'"
|
||||||
|
@ -394,3 +394,6 @@ character-set=latin2
|
|||||||
"Illegal %s '%-.64s' value found during parsing",
|
"Illegal %s '%-.64s' value found during parsing",
|
||||||
"CHECK OPTION on non-updatable view '%-.64s.%-.64s'"
|
"CHECK OPTION on non-updatable view '%-.64s.%-.64s'"
|
||||||
"CHECK OPTION failed '%-.64s.%-.64s'"
|
"CHECK OPTION failed '%-.64s.%-.64s'"
|
||||||
|
"Can not modify more than one base table through a join view '%-.64s.%-.64s'"
|
||||||
|
"Can not insert into join view '%-.64s.%-.64s' without fields list"
|
||||||
|
"Can not delete from join view '%-.64s.%-.64s'"
|
||||||
|
@ -390,3 +390,6 @@ character-set=latin1
|
|||||||
"Illegal %s '%-.64s' value found during parsing",
|
"Illegal %s '%-.64s' value found during parsing",
|
||||||
"CHECK OPTION on non-updatable view '%-.64s.%-.64s'"
|
"CHECK OPTION on non-updatable view '%-.64s.%-.64s'"
|
||||||
"CHECK OPTION failed '%-.64s.%-.64s'"
|
"CHECK OPTION failed '%-.64s.%-.64s'"
|
||||||
|
"Can not modify more than one base table through a join view '%-.64s.%-.64s'"
|
||||||
|
"Can not insert into join view '%-.64s.%-.64s' without fields list"
|
||||||
|
"Can not delete from join view '%-.64s.%-.64s'"
|
||||||
|
@ -386,3 +386,6 @@ character-set=latin1
|
|||||||
"Illegal %s '%-.64s' value found during parsing",
|
"Illegal %s '%-.64s' value found during parsing",
|
||||||
"CHECK OPTION on non-updatable view '%-.64s.%-.64s'"
|
"CHECK OPTION on non-updatable view '%-.64s.%-.64s'"
|
||||||
"CHECK OPTION failed '%-.64s.%-.64s'"
|
"CHECK OPTION failed '%-.64s.%-.64s'"
|
||||||
|
"Can not modify more than one base table through a join view '%-.64s.%-.64s'"
|
||||||
|
"Can not insert into join view '%-.64s.%-.64s' without fields list"
|
||||||
|
"Can not delete from join view '%-.64s.%-.64s'"
|
||||||
|
@ -392,3 +392,6 @@ character-set=koi8u
|
|||||||
"Illegal %s '%-.64s' value found during parsing",
|
"Illegal %s '%-.64s' value found during parsing",
|
||||||
"CHECK OPTION <20><><EFBFBD> VIEW '%-.64s.%-.64s' <20><> <20><> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>"
|
"CHECK OPTION <20><><EFBFBD> VIEW '%-.64s.%-.64s' <20><> <20><> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>"
|
||||||
"<22><><EFBFBD><EFBFBD>צ<EFBFBD><D7A6><EFBFBD> CHECK OPTION <20><><EFBFBD> VIEW '%-.64s.%-.64s' <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>"
|
"<22><><EFBFBD><EFBFBD>צ<EFBFBD><D7A6><EFBFBD> CHECK OPTION <20><><EFBFBD> VIEW '%-.64s.%-.64s' <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>"
|
||||||
|
"<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> ¦<><C2A6><EFBFBD> <20><><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> VIEW '%-.64s.%-.64s', <20><> ͦ<>Ԧ<EFBFBD><D4A6> <20><>˦<EFBFBD><CBA6><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>"
|
||||||
|
"<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> <20> VIEW '%-.64s.%-.64s', <20><> ͦ<><CDA6><EFBFBD><EFBFBD><EFBFBD> <20><>˦<EFBFBD><CBA6><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>æ<EFBFBD>"
|
||||||
|
"<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> <20> VIEW '%-.64s.%-.64s', <20><> ͦ<><CDA6><EFBFBD><EFBFBD><EFBFBD> <20><>˦<EFBFBD><CBA6><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>"
|
||||||
|
@ -551,6 +551,7 @@ db_show_routine_status(THD *thd, int type, const char *wild)
|
|||||||
Item *item;
|
Item *item;
|
||||||
List<Item> field_list;
|
List<Item> field_list;
|
||||||
struct st_used_field *used_field;
|
struct st_used_field *used_field;
|
||||||
|
TABLE_LIST *leaves= 0;
|
||||||
st_used_field used_fields[array_elements(init_fields)];
|
st_used_field used_fields[array_elements(init_fields)];
|
||||||
|
|
||||||
memcpy((char*) used_fields, (char*) init_fields, sizeof(used_fields));
|
memcpy((char*) used_fields, (char*) init_fields, sizeof(used_fields));
|
||||||
@ -583,7 +584,7 @@ db_show_routine_status(THD *thd, int type, const char *wild)
|
|||||||
|
|
||||||
tables is not VIEW for sure => we can pass 0 as condition
|
tables is not VIEW for sure => we can pass 0 as condition
|
||||||
*/
|
*/
|
||||||
setup_tables(thd, &tables, 0);
|
setup_tables(thd, &tables, 0, &leaves, 0);
|
||||||
for (used_field= &used_fields[0];
|
for (used_field= &used_fields[0];
|
||||||
used_field->field_name;
|
used_field->field_name;
|
||||||
used_field++)
|
used_field++)
|
||||||
|
168
sql/sql_base.cc
168
sql/sql_base.cc
@ -577,13 +577,14 @@ TABLE_LIST *find_table_in_list(TABLE_LIST *table,
|
|||||||
{
|
{
|
||||||
for (; table; table= *(TABLE_LIST **) ((char*) table + offset))
|
for (; table; table= *(TABLE_LIST **) ((char*) table + offset))
|
||||||
{
|
{
|
||||||
if ((!strcmp(table->db, db_name) &&
|
if (table->table->tmp_table == NO_TMP_TABLE &&
|
||||||
|
((!strcmp(table->db, db_name) &&
|
||||||
!strcmp(table->real_name, table_name)) ||
|
!strcmp(table->real_name, table_name)) ||
|
||||||
(table->view &&
|
(table->view &&
|
||||||
!my_strcasecmp(table_alias_charset,
|
!my_strcasecmp(table_alias_charset,
|
||||||
table->table->table_cache_key, db_name) &&
|
table->table->table_cache_key, db_name) &&
|
||||||
!my_strcasecmp(table_alias_charset,
|
!my_strcasecmp(table_alias_charset,
|
||||||
table->table->table_name, table_name)))
|
table->table->table_name, table_name))))
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -591,11 +592,12 @@ TABLE_LIST *find_table_in_list(TABLE_LIST *table,
|
|||||||
{
|
{
|
||||||
for (; table; table= *(TABLE_LIST **) ((char*) table + offset))
|
for (; table; table= *(TABLE_LIST **) ((char*) table + offset))
|
||||||
{
|
{
|
||||||
if ((!strcmp(table->db, db_name) &&
|
if (table->table->tmp_table == NO_TMP_TABLE &&
|
||||||
|
((!strcmp(table->db, db_name) &&
|
||||||
!strcmp(table->real_name, table_name)) ||
|
!strcmp(table->real_name, table_name)) ||
|
||||||
(table->view &&
|
(table->view &&
|
||||||
!strcmp(table->table->table_cache_key, db_name) &&
|
!strcmp(table->table->table_cache_key, db_name) &&
|
||||||
!strcmp(table->table->table_name, table_name)))
|
!strcmp(table->table->table_name, table_name))))
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2036,15 +2038,18 @@ find_field_in_table(THD *thd, TABLE_LIST *table_list,
|
|||||||
bool allow_rowid,
|
bool allow_rowid,
|
||||||
uint *cached_field_index_ptr)
|
uint *cached_field_index_ptr)
|
||||||
{
|
{
|
||||||
|
DBUG_ENTER("find_field_in_table");
|
||||||
|
DBUG_PRINT("enter", ("table:%s name: %s item name %s, ref 0x%lx",
|
||||||
|
table_list->alias, name, item_name, (ulong)ref));
|
||||||
Field *fld;
|
Field *fld;
|
||||||
if (table_list->field_translation)
|
if (table_list->field_translation)
|
||||||
{
|
{
|
||||||
DBUG_ASSERT(ref != 0 && table_list->view != 0);
|
DBUG_ASSERT(ref != 0 && table_list->view != 0);
|
||||||
uint num= table_list->view->select_lex.item_list.elements;
|
uint num= table_list->view->select_lex.item_list.elements;
|
||||||
Item **trans= table_list->field_translation;
|
Field_translator *trans= table_list->field_translation;
|
||||||
for (uint i= 0; i < num; i ++)
|
for (uint i= 0; i < num; i ++)
|
||||||
{
|
{
|
||||||
if (strcmp(trans[i]->name, name) == 0)
|
if (strcmp(trans[i].name, name) == 0)
|
||||||
{
|
{
|
||||||
#ifndef NO_EMBEDDED_ACCESS_CHECKS
|
#ifndef NO_EMBEDDED_ACCESS_CHECKS
|
||||||
if (check_grants_view &&
|
if (check_grants_view &&
|
||||||
@ -2052,22 +2057,22 @@ find_field_in_table(THD *thd, TABLE_LIST *table_list,
|
|||||||
table_list->view_db.str,
|
table_list->view_db.str,
|
||||||
table_list->view_name.str,
|
table_list->view_name.str,
|
||||||
name, length))
|
name, length))
|
||||||
return WRONG_GRANT;
|
DBUG_RETURN(WRONG_GRANT);
|
||||||
#endif
|
#endif
|
||||||
if (thd->lex->current_select->no_wrap_view_item)
|
if (thd->lex->current_select->no_wrap_view_item)
|
||||||
*ref= trans[i];
|
*ref= trans[i].item;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
*ref= new Item_ref(trans + i, ref, table_list->view_name.str,
|
*ref= new Item_ref(&trans[i].item, ref, table_list->view_name.str,
|
||||||
item_name);
|
item_name);
|
||||||
/* as far as Item_ref have defined refernce it do not need tables */
|
/* as far as Item_ref have defined refernce it do not need tables */
|
||||||
if (*ref)
|
if (*ref)
|
||||||
(*ref)->fix_fields(thd, 0, ref);
|
(*ref)->fix_fields(thd, 0, ref);
|
||||||
}
|
}
|
||||||
return (Field*) view_ref_found;
|
DBUG_RETURN((Field*) view_ref_found);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
DBUG_RETURN(0);
|
||||||
}
|
}
|
||||||
fld= find_field_in_real_table(thd, table_list->table, name, length,
|
fld= find_field_in_real_table(thd, table_list->table, name, length,
|
||||||
check_grants_table, allow_rowid,
|
check_grants_table, allow_rowid,
|
||||||
@ -2081,10 +2086,10 @@ find_field_in_table(THD *thd, TABLE_LIST *table_list,
|
|||||||
table_list->view_name.str,
|
table_list->view_name.str,
|
||||||
name, length))
|
name, length))
|
||||||
{
|
{
|
||||||
return WRONG_GRANT;
|
DBUG_RETURN(WRONG_GRANT);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
return fld;
|
DBUG_RETURN(fld);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -2213,6 +2218,8 @@ find_field_in_tables(THD *thd, Item_ident *item, TABLE_LIST *tables,
|
|||||||
field makes some prepared query ambiguous and so erronous, but we
|
field makes some prepared query ambiguous and so erronous, but we
|
||||||
accept this trade off.
|
accept this trade off.
|
||||||
*/
|
*/
|
||||||
|
if (item->cached_table->table)
|
||||||
|
{
|
||||||
found= find_field_in_real_table(thd, item->cached_table->table,
|
found= find_field_in_real_table(thd, item->cached_table->table,
|
||||||
name, length,
|
name, length,
|
||||||
test(item->cached_table->
|
test(item->cached_table->
|
||||||
@ -2220,6 +2227,20 @@ find_field_in_tables(THD *thd, Item_ident *item, TABLE_LIST *tables,
|
|||||||
check_privileges,
|
check_privileges,
|
||||||
1, &(item->cached_field_index));
|
1, &(item->cached_field_index));
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
TABLE_LIST *table= item->cached_table;
|
||||||
|
Field *find= find_field_in_table(thd, table, name, item->name, length,
|
||||||
|
ref,
|
||||||
|
(table->table &&
|
||||||
|
test(table->table->grant.
|
||||||
|
want_privilege) &&
|
||||||
|
check_privileges),
|
||||||
|
(test(table->grant.want_privilege) &&
|
||||||
|
check_privileges),
|
||||||
|
1, &(item->cached_field_index));
|
||||||
|
}
|
||||||
if (found)
|
if (found)
|
||||||
{
|
{
|
||||||
if (found == WRONG_GRANT)
|
if (found == WRONG_GRANT)
|
||||||
@ -2251,7 +2272,8 @@ find_field_in_tables(THD *thd, Item_ident *item, TABLE_LIST *tables,
|
|||||||
found_table=1;
|
found_table=1;
|
||||||
Field *find= find_field_in_table(thd, tables, name, item->name,
|
Field *find= find_field_in_table(thd, tables, name, item->name,
|
||||||
length, ref,
|
length, ref,
|
||||||
(test(tables->table->grant.
|
(tables->table &&
|
||||||
|
test(tables->table->grant.
|
||||||
want_privilege) &&
|
want_privilege) &&
|
||||||
check_privileges),
|
check_privileges),
|
||||||
(test(tables->grant.want_privilege) &&
|
(test(tables->grant.want_privilege) &&
|
||||||
@ -2305,7 +2327,7 @@ find_field_in_tables(THD *thd, Item_ident *item, TABLE_LIST *tables,
|
|||||||
bool allow_rowid= tables && !tables->next_local; // Only one table
|
bool allow_rowid= tables && !tables->next_local; // Only one table
|
||||||
for (; tables ; tables= tables->next_local)
|
for (; tables ; tables= tables->next_local)
|
||||||
{
|
{
|
||||||
if (!tables->table)
|
if (!tables->table && !tables->ancestor)
|
||||||
{
|
{
|
||||||
if (report_error)
|
if (report_error)
|
||||||
my_printf_error(ER_BAD_FIELD_ERROR,ER(ER_BAD_FIELD_ERROR),MYF(0),
|
my_printf_error(ER_BAD_FIELD_ERROR,ER(ER_BAD_FIELD_ERROR),MYF(0),
|
||||||
@ -2315,7 +2337,8 @@ find_field_in_tables(THD *thd, Item_ident *item, TABLE_LIST *tables,
|
|||||||
|
|
||||||
Field *field= find_field_in_table(thd, tables, name, item->name,
|
Field *field= find_field_in_table(thd, tables, name, item->name,
|
||||||
length, ref,
|
length, ref,
|
||||||
(test(tables->table->grant.
|
(tables->table &&
|
||||||
|
test(tables->table->grant.
|
||||||
want_privilege) &&
|
want_privilege) &&
|
||||||
check_privileges),
|
check_privileges),
|
||||||
(test(tables->grant.want_privilege) &&
|
(test(tables->grant.want_privilege) &&
|
||||||
@ -2628,7 +2651,6 @@ int setup_fields(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables,
|
|||||||
if (!item->fixed && item->fix_fields(thd, tables, it.ref()) ||
|
if (!item->fixed && item->fix_fields(thd, tables, it.ref()) ||
|
||||||
(item= *(it.ref()))->check_cols(1))
|
(item= *(it.ref()))->check_cols(1))
|
||||||
{
|
{
|
||||||
select_lex->no_wrap_view_item= 0;
|
|
||||||
DBUG_RETURN(-1); /* purecov: inspected */
|
DBUG_RETURN(-1); /* purecov: inspected */
|
||||||
}
|
}
|
||||||
if (ref)
|
if (ref)
|
||||||
@ -2642,6 +2664,36 @@ int setup_fields(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
make list of leaves of join table tree
|
||||||
|
|
||||||
|
SYNOPSIS
|
||||||
|
make_leaves_list()
|
||||||
|
list pointer to pointer on list first element
|
||||||
|
tables table list
|
||||||
|
|
||||||
|
RETURN pointer on pointer to next_leaf of last element
|
||||||
|
*/
|
||||||
|
|
||||||
|
TABLE_LIST **make_leaves_list(TABLE_LIST **list, TABLE_LIST *tables)
|
||||||
|
{
|
||||||
|
for (TABLE_LIST *table= tables; table; table= table->next_local)
|
||||||
|
{
|
||||||
|
if (table->view && !table->table)
|
||||||
|
{
|
||||||
|
/* it is for multi table views only, check it */
|
||||||
|
DBUG_ASSERT(table->ancestor->next_local);
|
||||||
|
list= make_leaves_list(list, table->ancestor);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
*list= table;
|
||||||
|
list= &table->next_leaf;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
prepare tables
|
prepare tables
|
||||||
|
|
||||||
@ -2650,6 +2702,8 @@ int setup_fields(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables,
|
|||||||
thd - thread handler
|
thd - thread handler
|
||||||
tables - tables list
|
tables - tables list
|
||||||
conds - condition of current SELECT (can be changed by VIEW)
|
conds - condition of current SELECT (can be changed by VIEW)
|
||||||
|
leaves - list of join table leaves list
|
||||||
|
refresh - it is onle refresh for subquery
|
||||||
|
|
||||||
RETURN
|
RETURN
|
||||||
0 ok; In this case *map will includes the choosed index
|
0 ok; In this case *map will includes the choosed index
|
||||||
@ -2666,16 +2720,23 @@ int setup_fields(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables,
|
|||||||
if tables do not contain VIEWs it is OK to pass 0 as conds
|
if tables do not contain VIEWs it is OK to pass 0 as conds
|
||||||
*/
|
*/
|
||||||
|
|
||||||
bool setup_tables(THD *thd, TABLE_LIST *tables, Item **conds)
|
bool setup_tables(THD *thd, TABLE_LIST *tables, Item **conds,
|
||||||
|
TABLE_LIST **leaves, bool refresh)
|
||||||
{
|
{
|
||||||
DBUG_ENTER("setup_tables");
|
DBUG_ENTER("setup_tables");
|
||||||
if (!tables || tables->setup_is_done)
|
if (!tables || tables->setup_is_done)
|
||||||
DBUG_RETURN(0);
|
DBUG_RETURN(0);
|
||||||
tables->setup_is_done= 1;
|
tables->setup_is_done= 1;
|
||||||
|
|
||||||
|
if (!(*leaves))
|
||||||
|
{
|
||||||
|
make_leaves_list(leaves, tables);
|
||||||
|
}
|
||||||
|
|
||||||
uint tablenr=0;
|
uint tablenr=0;
|
||||||
for (TABLE_LIST *table_list= tables;
|
for (TABLE_LIST *table_list= *leaves;
|
||||||
table_list;
|
table_list;
|
||||||
table_list= table_list->next_local, tablenr++)
|
table_list= table_list->next_leaf, tablenr++)
|
||||||
{
|
{
|
||||||
TABLE *table= table_list->table;
|
TABLE *table= table_list->table;
|
||||||
setup_table_map(table, table_list, tablenr);
|
setup_table_map(table, table_list, tablenr);
|
||||||
@ -2697,14 +2758,22 @@ bool setup_tables(THD *thd, TABLE_LIST *tables, Item **conds)
|
|||||||
table->keys_in_use_for_query.subtract(map);
|
table->keys_in_use_for_query.subtract(map);
|
||||||
}
|
}
|
||||||
table->used_keys.intersect(table->keys_in_use_for_query);
|
table->used_keys.intersect(table->keys_in_use_for_query);
|
||||||
if (table_list->ancestor && table_list->setup_ancestor(thd, conds))
|
|
||||||
DBUG_RETURN(1);
|
|
||||||
}
|
}
|
||||||
if (tablenr > MAX_TABLES)
|
if (tablenr > MAX_TABLES)
|
||||||
{
|
{
|
||||||
my_error(ER_TOO_MANY_TABLES,MYF(0),MAX_TABLES);
|
my_error(ER_TOO_MANY_TABLES,MYF(0),MAX_TABLES);
|
||||||
DBUG_RETURN(1);
|
DBUG_RETURN(1);
|
||||||
}
|
}
|
||||||
|
if (!refresh)
|
||||||
|
{
|
||||||
|
for (TABLE_LIST *table_list= tables;
|
||||||
|
table_list;
|
||||||
|
table_list= table_list->next_local)
|
||||||
|
{
|
||||||
|
if (table_list->ancestor && table_list->setup_ancestor(thd, conds))
|
||||||
|
DBUG_RETURN(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
DBUG_RETURN(0);
|
DBUG_RETURN(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2807,9 +2876,12 @@ insert_fields(THD *thd, TABLE_LIST *tables, const char *db_name,
|
|||||||
tables->alias) &&
|
tables->alias) &&
|
||||||
(!db_name || !strcmp(tables->db,db_name))))
|
(!db_name || !strcmp(tables->db,db_name))))
|
||||||
{
|
{
|
||||||
|
bool view;
|
||||||
#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) && !any_privileges)
|
if (!((table && (table->grant.privilege & SELECT_ACL) ||
|
||||||
|
tables->view && (tables->grant.privilege & SELECT_ACL))) &&
|
||||||
|
!any_privileges)
|
||||||
{
|
{
|
||||||
if (tables->view)
|
if (tables->view)
|
||||||
{
|
{
|
||||||
@ -2822,6 +2894,7 @@ insert_fields(THD *thd, TABLE_LIST *tables, const char *db_name,
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
DBUG_ASSERT(table != 0);
|
||||||
table_iter.set(tables);
|
table_iter.set(tables);
|
||||||
if (check_grant_all_columns(thd, SELECT_ACL, &table->grant,
|
if (check_grant_all_columns(thd, SELECT_ACL, &table->grant,
|
||||||
table->table_cache_key, table->real_name,
|
table->table_cache_key, table->real_name,
|
||||||
@ -2830,8 +2903,17 @@ insert_fields(THD *thd, TABLE_LIST *tables, const char *db_name,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
natural_join_table= 0;
|
if (table)
|
||||||
thd->used_tables|= table->map;
|
thd->used_tables|= table->map;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
view_iter.set(tables);
|
||||||
|
for (; !view_iter.end_of_fields(); view_iter.next())
|
||||||
|
{
|
||||||
|
thd->used_tables|= view_iter.item(thd)->used_tables();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
natural_join_table= 0;
|
||||||
last= embedded= tables;
|
last= embedded= tables;
|
||||||
|
|
||||||
while ((embedding= embedded->embedding) &&
|
while ((embedding= embedded->embedding) &&
|
||||||
@ -2858,9 +2940,15 @@ insert_fields(THD *thd, TABLE_LIST *tables, const char *db_name,
|
|||||||
natural_join_table= embedding;
|
natural_join_table= embedding;
|
||||||
}
|
}
|
||||||
if (tables->field_translation)
|
if (tables->field_translation)
|
||||||
|
{
|
||||||
iterator= &view_iter;
|
iterator= &view_iter;
|
||||||
|
view= 1;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
iterator= &table_iter;
|
iterator= &table_iter;
|
||||||
|
view= 0;
|
||||||
|
}
|
||||||
iterator->set(tables);
|
iterator->set(tables);
|
||||||
|
|
||||||
for (; !iterator->end_of_fields(); iterator->next())
|
for (; !iterator->end_of_fields(); iterator->next())
|
||||||
@ -2880,6 +2968,11 @@ insert_fields(THD *thd, TABLE_LIST *tables, const char *db_name,
|
|||||||
(void) it->replace(item); // Replace '*'
|
(void) it->replace(item); // Replace '*'
|
||||||
else
|
else
|
||||||
it->after(item);
|
it->after(item);
|
||||||
|
if (view && !thd->lex->current_select->no_wrap_view_item)
|
||||||
|
{
|
||||||
|
item= new Item_ref(it->ref(), NULL, tables->view_name.str,
|
||||||
|
field_name);
|
||||||
|
}
|
||||||
#ifndef NO_EMBEDDED_ACCESS_CHECKS
|
#ifndef NO_EMBEDDED_ACCESS_CHECKS
|
||||||
if (any_privileges)
|
if (any_privileges)
|
||||||
{
|
{
|
||||||
@ -2945,7 +3038,11 @@ insert_fields(THD *thd, TABLE_LIST *tables, const char *db_name,
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
/* All fields are used */
|
/*
|
||||||
|
All fields are used in case if usual tables (in case of view used
|
||||||
|
fields merked in setu_tables during fix_fields of view columns
|
||||||
|
*/
|
||||||
|
if (table)
|
||||||
table->used_fields=table->fields;
|
table->used_fields=table->fields;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2964,10 +3061,16 @@ err:
|
|||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Fix all conditions and outer join expressions
|
Fix all conditions and outer join expressions
|
||||||
|
|
||||||
|
SYNOPSIS
|
||||||
|
setup_conds()
|
||||||
|
thd thread handler
|
||||||
|
tables list of tables for name resolving
|
||||||
|
leaves list of leaves of join table tree
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int setup_conds(THD *thd,TABLE_LIST *tables,COND **conds)
|
int setup_conds(THD *thd, TABLE_LIST *tables, TABLE_LIST *leaves, COND **conds)
|
||||||
{
|
{
|
||||||
table_map not_null_tables= 0;
|
table_map not_null_tables= 0;
|
||||||
SELECT_LEX *select_lex= thd->lex->current_select;
|
SELECT_LEX *select_lex= thd->lex->current_select;
|
||||||
@ -2991,7 +3094,7 @@ int setup_conds(THD *thd,TABLE_LIST *tables,COND **conds)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Check if we are using outer joins */
|
/* Check if we are using outer joins */
|
||||||
for (TABLE_LIST *table= tables; table; table= table->next_local)
|
for (TABLE_LIST *table= leaves; table; table= table->next_leaf)
|
||||||
{
|
{
|
||||||
TABLE_LIST *embedded;
|
TABLE_LIST *embedded;
|
||||||
TABLE_LIST *embedding= table;
|
TABLE_LIST *embedding= table;
|
||||||
@ -3055,7 +3158,7 @@ int setup_conds(THD *thd,TABLE_LIST *tables,COND **conds)
|
|||||||
Field_iterator_view view_iter;
|
Field_iterator_view view_iter;
|
||||||
Field_iterator *iterator;
|
Field_iterator *iterator;
|
||||||
Field *t1_field, *t2_field;
|
Field *t1_field, *t2_field;
|
||||||
Item *item_t2;
|
Item *item_t2= 0;
|
||||||
Item_cond_and *cond_and= new Item_cond_and();
|
Item_cond_and *cond_and= new Item_cond_and();
|
||||||
|
|
||||||
if (!cond_and) // If not out of memory
|
if (!cond_and) // If not out of memory
|
||||||
@ -3092,6 +3195,13 @@ int setup_conds(THD *thd,TABLE_LIST *tables,COND **conds)
|
|||||||
t2_field->query_id= thd->query_id;
|
t2_field->query_id= thd->query_id;
|
||||||
t2->used_keys.intersect(t2_field->part_of_key);
|
t2->used_keys.intersect(t2_field->part_of_key);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DBUG_ASSERT(t2_field == view_ref_found &&
|
||||||
|
item_t2->type() == Item::REF_ITEM);
|
||||||
|
/* remove hooking to stack variable */
|
||||||
|
((Item_ref*) item_t2)->hook_ptr= 0;
|
||||||
|
}
|
||||||
if ((t1_field= iterator->field()))
|
if ((t1_field= iterator->field()))
|
||||||
{
|
{
|
||||||
/* Mark field used for table cache */
|
/* Mark field used for table cache */
|
||||||
|
@ -1568,7 +1568,9 @@ public:
|
|||||||
|
|
||||||
class multi_update :public select_result
|
class multi_update :public select_result
|
||||||
{
|
{
|
||||||
TABLE_LIST *all_tables, *update_tables, *table_being_updated;
|
TABLE_LIST *all_tables; /* query/update command tables */
|
||||||
|
TABLE_LIST *leaves; /* list of leves of join table tree */
|
||||||
|
TABLE_LIST *update_tables, *table_being_updated;
|
||||||
THD *thd;
|
THD *thd;
|
||||||
TABLE **tmp_tables, *main_table, *table_to_update;
|
TABLE **tmp_tables, *main_table, *table_to_update;
|
||||||
TMP_TABLE_PARAM *tmp_table_param;
|
TMP_TABLE_PARAM *tmp_table_param;
|
||||||
@ -1581,8 +1583,9 @@ class multi_update :public select_result
|
|||||||
bool do_update, trans_safe, transactional_tables, log_delayed;
|
bool do_update, trans_safe, transactional_tables, log_delayed;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
multi_update(THD *thd_arg, TABLE_LIST *ut, List<Item> *fields,
|
multi_update(THD *thd_arg, TABLE_LIST *ut, TABLE_LIST *leaves_list,
|
||||||
List<Item> *values, enum_duplicates handle_duplicates);
|
List<Item> *fields, List<Item> *values,
|
||||||
|
enum_duplicates handle_duplicates);
|
||||||
~multi_update();
|
~multi_update();
|
||||||
int prepare(List<Item> &list, SELECT_LEX_UNIT *u);
|
int prepare(List<Item> &list, SELECT_LEX_UNIT *u);
|
||||||
bool send_fields(List<Item> &list, uint flags) { return 0; }
|
bool send_fields(List<Item> &list, uint flags) { return 0; }
|
||||||
|
@ -43,7 +43,14 @@ int mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, SQL_LIST *order,
|
|||||||
|
|
||||||
if ((error= open_and_lock_tables(thd, table_list)))
|
if ((error= open_and_lock_tables(thd, table_list)))
|
||||||
DBUG_RETURN(error);
|
DBUG_RETURN(error);
|
||||||
table= table_list->table;
|
if (!(table= table_list->table))
|
||||||
|
{
|
||||||
|
DBUG_ASSERT(table_list->view &&
|
||||||
|
table_list->ancestor && table_list->ancestor->next_local);
|
||||||
|
my_error(ER_VIEW_DELETE_MERGE_VIEW, MYF(0),
|
||||||
|
table_list->view_db.str, table_list->view_name.str);
|
||||||
|
DBUG_RETURN(-1);
|
||||||
|
}
|
||||||
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";
|
||||||
table->map=1;
|
table->map=1;
|
||||||
@ -284,8 +291,8 @@ int mysql_prepare_delete(THD *thd, TABLE_LIST *table_list, Item **conds)
|
|||||||
SELECT_LEX *select_lex= &thd->lex->select_lex;
|
SELECT_LEX *select_lex= &thd->lex->select_lex;
|
||||||
DBUG_ENTER("mysql_prepare_delete");
|
DBUG_ENTER("mysql_prepare_delete");
|
||||||
|
|
||||||
if (setup_tables(thd, table_list, conds) ||
|
if (setup_tables(thd, table_list, conds, &select_lex->leaf_tables, 0) ||
|
||||||
setup_conds(thd, table_list, conds) ||
|
setup_conds(thd, table_list, select_lex->leaf_tables, conds) ||
|
||||||
setup_ftfuncs(select_lex))
|
setup_ftfuncs(select_lex))
|
||||||
DBUG_RETURN(-1);
|
DBUG_RETURN(-1);
|
||||||
if (!table_list->updatable || check_key_in_view(thd, table_list))
|
if (!table_list->updatable || check_key_in_view(thd, table_list))
|
||||||
@ -341,7 +348,8 @@ int mysql_multi_delete_prepare(THD *thd)
|
|||||||
|
|
||||||
lex->query_tables also point on local list of DELETE SELECT_LEX
|
lex->query_tables also point on local list of DELETE SELECT_LEX
|
||||||
*/
|
*/
|
||||||
if (setup_tables(thd, lex->query_tables, &lex->select_lex.where))
|
if (setup_tables(thd, lex->query_tables, &lex->select_lex.where,
|
||||||
|
&lex->select_lex.leaf_tables, 0))
|
||||||
DBUG_RETURN(-1);
|
DBUG_RETURN(-1);
|
||||||
|
|
||||||
/* Fix tables-to-be-deleted-from list to point at opened tables */
|
/* Fix tables-to-be-deleted-from list to point at opened tables */
|
||||||
|
@ -619,6 +619,7 @@ int mysqld_help(THD *thd, const char *mask)
|
|||||||
st_find_field used_fields[array_elements(init_used_fields)];
|
st_find_field used_fields[array_elements(init_used_fields)];
|
||||||
DBUG_ENTER("mysqld_help");
|
DBUG_ENTER("mysqld_help");
|
||||||
|
|
||||||
|
TABLE_LIST *leaves= 0;
|
||||||
TABLE_LIST tables[4];
|
TABLE_LIST tables[4];
|
||||||
bzero((gptr)tables,sizeof(tables));
|
bzero((gptr)tables,sizeof(tables));
|
||||||
tables[0].alias= tables[0].real_name= (char*) "help_topic";
|
tables[0].alias= tables[0].real_name= (char*) "help_topic";
|
||||||
@ -647,7 +648,7 @@ int mysqld_help(THD *thd, const char *mask)
|
|||||||
|
|
||||||
tables do not contain VIEWs => we can pass 0 as conds
|
tables do not contain VIEWs => we can pass 0 as conds
|
||||||
*/
|
*/
|
||||||
setup_tables(thd, tables, 0);
|
setup_tables(thd, tables, 0, &leaves, 0);
|
||||||
memcpy((char*) used_fields, (char*) init_used_fields, sizeof(used_fields));
|
memcpy((char*) used_fields, (char*) init_used_fields, sizeof(used_fields));
|
||||||
if (init_fields(thd, tables, used_fields, array_elements(used_fields)))
|
if (init_fields(thd, tables, used_fields, array_elements(used_fields)))
|
||||||
{
|
{
|
||||||
|
@ -21,6 +21,7 @@
|
|||||||
#include "sql_acl.h"
|
#include "sql_acl.h"
|
||||||
#include "sp_head.h"
|
#include "sp_head.h"
|
||||||
#include "sql_trigger.h"
|
#include "sql_trigger.h"
|
||||||
|
#include "sql_select.h"
|
||||||
|
|
||||||
static int check_null_fields(THD *thd,TABLE *entry);
|
static int check_null_fields(THD *thd,TABLE *entry);
|
||||||
#ifndef EMBEDDED_LIBRARY
|
#ifndef EMBEDDED_LIBRARY
|
||||||
@ -31,6 +32,7 @@ static void end_delayed_insert(THD *thd);
|
|||||||
extern "C" pthread_handler_decl(handle_delayed_insert,arg);
|
extern "C" pthread_handler_decl(handle_delayed_insert,arg);
|
||||||
static void unlink_blobs(register TABLE *table);
|
static void unlink_blobs(register TABLE *table);
|
||||||
#endif
|
#endif
|
||||||
|
static bool check_view_insertability(TABLE_LIST *view, ulong query_id);
|
||||||
|
|
||||||
/* Define to force use of my_malloc() if the allocated memory block is big */
|
/* Define to force use of my_malloc() if the allocated memory block is big */
|
||||||
|
|
||||||
@ -54,8 +56,22 @@ check_insert_fields(THD *thd, TABLE_LIST *table_list, List<Item> &fields,
|
|||||||
{
|
{
|
||||||
TABLE *table= table_list->table;
|
TABLE *table= table_list->table;
|
||||||
|
|
||||||
|
if (!table_list->updatable)
|
||||||
|
{
|
||||||
|
my_error(ER_NON_UPDATABLE_TABLE, MYF(0), table_list->alias, "INSERT");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
if (fields.elements == 0 && values.elements != 0)
|
if (fields.elements == 0 && values.elements != 0)
|
||||||
{
|
{
|
||||||
|
if (!table)
|
||||||
|
{
|
||||||
|
DBUG_ASSERT(table_list->view &&
|
||||||
|
table_list->ancestor && table_list->ancestor->next_local);
|
||||||
|
my_error(ER_VIEW_NO_INSERT_FIELD_LIST, MYF(0),
|
||||||
|
table_list->view_db.str, table_list->view_name.str);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
if (values.elements != table->fields)
|
if (values.elements != table->fields)
|
||||||
{
|
{
|
||||||
my_printf_error(ER_WRONG_VALUE_COUNT_ON_ROW,
|
my_printf_error(ER_WRONG_VALUE_COUNT_ON_ROW,
|
||||||
@ -97,6 +113,23 @@ check_insert_fields(THD *thd, TABLE_LIST *table_list, List<Item> &fields,
|
|||||||
thd->lex->select_lex.no_wrap_view_item= 0;
|
thd->lex->select_lex.no_wrap_view_item= 0;
|
||||||
if (res)
|
if (res)
|
||||||
return -1;
|
return -1;
|
||||||
|
if (table == 0)
|
||||||
|
{
|
||||||
|
/* it is join view => we need to find table for update */
|
||||||
|
List_iterator_fast<Item> it(fields);
|
||||||
|
Item *item;
|
||||||
|
TABLE_LIST *tbl= 0;
|
||||||
|
table_map map= 0;
|
||||||
|
while (item= it++)
|
||||||
|
map|= item->used_tables();
|
||||||
|
if (table_list->check_single_table(&tbl, map) || tbl == 0)
|
||||||
|
{
|
||||||
|
my_error(ER_VIEW_MULTIUPDATE, MYF(0),
|
||||||
|
table_list->view_db.str, table_list->view_name.str);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
table_list->table= table= tbl->table;
|
||||||
|
}
|
||||||
|
|
||||||
if (check_unique && thd->dupp_field)
|
if (check_unique && thd->dupp_field)
|
||||||
{
|
{
|
||||||
@ -111,6 +144,15 @@ check_insert_fields(THD *thd, TABLE_LIST *table_list, List<Item> &fields,
|
|||||||
#ifndef NO_EMBEDDED_ACCESS_CHECKS
|
#ifndef NO_EMBEDDED_ACCESS_CHECKS
|
||||||
table->grant.want_privilege=(SELECT_ACL & ~table->grant.privilege);
|
table->grant.want_privilege=(SELECT_ACL & ~table->grant.privilege);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
if (check_key_in_view(thd, table_list) ||
|
||||||
|
(table_list->view &&
|
||||||
|
check_view_insertability(table_list, thd->query_id)))
|
||||||
|
{
|
||||||
|
my_error(ER_NON_UPDATABLE_TABLE, MYF(0), table_list->alias, "INSERT");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -135,7 +177,7 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list,
|
|||||||
ulong counter = 1;
|
ulong counter = 1;
|
||||||
ulonglong id;
|
ulonglong id;
|
||||||
COPY_INFO info;
|
COPY_INFO info;
|
||||||
TABLE *table;
|
TABLE *table= 0;
|
||||||
List_iterator_fast<List_item> its(values_list);
|
List_iterator_fast<List_item> its(values_list);
|
||||||
List_item *values;
|
List_item *values;
|
||||||
#ifndef EMBEDDED_LIBRARY
|
#ifndef EMBEDDED_LIBRARY
|
||||||
@ -202,17 +244,14 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list,
|
|||||||
if (res || thd->is_fatal_error)
|
if (res || thd->is_fatal_error)
|
||||||
DBUG_RETURN(-1);
|
DBUG_RETURN(-1);
|
||||||
|
|
||||||
table= table_list->table;
|
|
||||||
thd->proc_info="init";
|
thd->proc_info="init";
|
||||||
thd->used_tables=0;
|
thd->used_tables=0;
|
||||||
values= its++;
|
values= its++;
|
||||||
|
|
||||||
if (duplic == DUP_UPDATE && !table->insert_values)
|
if (duplic == DUP_UPDATE)
|
||||||
{
|
{
|
||||||
/* it should be allocated before Item::fix_fields() */
|
/* it should be allocated before Item::fix_fields() */
|
||||||
table->insert_values=
|
if (table_list->set_insert_values(&thd->mem_root))
|
||||||
(byte *)alloc_root(&thd->mem_root, table->rec_buff_length);
|
|
||||||
if (!table->insert_values)
|
|
||||||
goto abort;
|
goto abort;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -220,6 +259,9 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list,
|
|||||||
update_fields, update_values, duplic))
|
update_fields, update_values, duplic))
|
||||||
goto abort;
|
goto abort;
|
||||||
|
|
||||||
|
/* mysql_prepare_insert set table_list->table if it was not set */
|
||||||
|
table= table_list->table;
|
||||||
|
|
||||||
// is table which we are changing used somewhere in other parts of query
|
// is table which we are changing used somewhere in other parts of query
|
||||||
value_count= values->elements;
|
value_count= values->elements;
|
||||||
while ((values= its++))
|
while ((values= its++))
|
||||||
@ -463,7 +505,7 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list,
|
|||||||
::send_ok(thd, (ulong) thd->row_count_func, id, buff);
|
::send_ok(thd, (ulong) thd->row_count_func, id, buff);
|
||||||
}
|
}
|
||||||
free_underlaid_joins(thd, &thd->lex->select_lex);
|
free_underlaid_joins(thd, &thd->lex->select_lex);
|
||||||
table->insert_values=0;
|
table_list->clear_insert_values();
|
||||||
thd->abort_on_warning= 0;
|
thd->abort_on_warning= 0;
|
||||||
DBUG_RETURN(0);
|
DBUG_RETURN(0);
|
||||||
|
|
||||||
@ -473,7 +515,7 @@ abort:
|
|||||||
end_delayed_insert(thd);
|
end_delayed_insert(thd);
|
||||||
#endif
|
#endif
|
||||||
free_underlaid_joins(thd, &thd->lex->select_lex);
|
free_underlaid_joins(thd, &thd->lex->select_lex);
|
||||||
table->insert_values=0;
|
table_list->clear_insert_values();
|
||||||
thd->abort_on_warning= 0;
|
thd->abort_on_warning= 0;
|
||||||
DBUG_RETURN(-1);
|
DBUG_RETURN(-1);
|
||||||
}
|
}
|
||||||
@ -504,8 +546,9 @@ static bool check_view_insertability(TABLE_LIST *view, ulong query_id)
|
|||||||
{
|
{
|
||||||
uint num= view->view->select_lex.item_list.elements;
|
uint num= view->view->select_lex.item_list.elements;
|
||||||
TABLE *table= view->table;
|
TABLE *table= view->table;
|
||||||
Item **trans_start= view->field_translation, **trans_end=trans_start+num;
|
Field_translator *trans_start= view->field_translation,
|
||||||
Item **trans;
|
*trans_end= trans_start + num;
|
||||||
|
Field_translator *trans;
|
||||||
Field **field_ptr= table->field;
|
Field **field_ptr= table->field;
|
||||||
ulong other_query_id= query_id - 1;
|
ulong other_query_id= query_id - 1;
|
||||||
DBUG_ENTER("check_key_in_view");
|
DBUG_ENTER("check_key_in_view");
|
||||||
@ -518,7 +561,7 @@ static bool check_view_insertability(TABLE_LIST *view, ulong query_id)
|
|||||||
{
|
{
|
||||||
Item_field *field;
|
Item_field *field;
|
||||||
/* simple SELECT list entry (field without expression) */
|
/* simple SELECT list entry (field without expression) */
|
||||||
if (!(field= (*trans)->filed_for_view_update()))
|
if (!(field= trans->item->filed_for_view_update()))
|
||||||
DBUG_RETURN(TRUE);
|
DBUG_RETURN(TRUE);
|
||||||
if (field->field->unireg_check == Field::NEXT_NUMBER)
|
if (field->field->unireg_check == Field::NEXT_NUMBER)
|
||||||
view->contain_auto_increment= 1;
|
view->contain_auto_increment= 1;
|
||||||
@ -530,7 +573,7 @@ static bool check_view_insertability(TABLE_LIST *view, ulong query_id)
|
|||||||
for (trans= trans_start; trans != trans_end; trans++)
|
for (trans= trans_start; trans != trans_end; trans++)
|
||||||
{
|
{
|
||||||
/* Thanks to test above, we know that all columns are of type Item_field */
|
/* Thanks to test above, we know that all columns are of type Item_field */
|
||||||
Item_field *field= (Item_field *)(*trans);
|
Item_field *field= (Item_field *)trans->item;
|
||||||
if (field->field->query_id == query_id)
|
if (field->field->query_id == query_id)
|
||||||
DBUG_RETURN(TRUE);
|
DBUG_RETURN(TRUE);
|
||||||
field->field->query_id= query_id;
|
field->field->query_id= query_id;
|
||||||
@ -549,7 +592,7 @@ static bool check_view_insertability(TABLE_LIST *view, ulong query_id)
|
|||||||
{
|
{
|
||||||
if (trans == trans_end)
|
if (trans == trans_end)
|
||||||
DBUG_RETURN(TRUE); // Field was not part of view
|
DBUG_RETURN(TRUE); // Field was not part of view
|
||||||
if (((Item_field *)(*trans))->field == *field_ptr)
|
if (((Item_field *)trans->item)->field == *field_ptr)
|
||||||
break; // ok
|
break; // ok
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -570,32 +613,34 @@ static bool check_view_insertability(TABLE_LIST *view, ulong query_id)
|
|||||||
|
|
||||||
RETURN
|
RETURN
|
||||||
0 ok
|
0 ok
|
||||||
1 ERROR
|
1 ERROR and message sent to client
|
||||||
|
-1 ERROR but message is not sent to client
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static bool mysql_prepare_insert_check_table(THD *thd, TABLE_LIST *table_list,
|
static int mysql_prepare_insert_check_table(THD *thd, TABLE_LIST *table_list,
|
||||||
List<Item> &fields, COND **where)
|
List<Item> &fields, COND **where)
|
||||||
{
|
{
|
||||||
bool insert_into_view= (table_list->view != 0);
|
bool insert_into_view= (table_list->view != 0);
|
||||||
DBUG_ENTER("mysql_prepare_insert_check_table");
|
DBUG_ENTER("mysql_prepare_insert_check_table");
|
||||||
|
|
||||||
if (setup_tables(thd, table_list, where))
|
if (setup_tables(thd, table_list, where, &thd->lex->select_lex.leaf_tables,
|
||||||
DBUG_RETURN(1);
|
0))
|
||||||
|
DBUG_RETURN(thd->net.report_error ? -1 : 1);
|
||||||
|
|
||||||
if (insert_into_view && !fields.elements)
|
if (insert_into_view && !fields.elements)
|
||||||
{
|
{
|
||||||
thd->lex->empty_field_list_on_rset= 1;
|
thd->lex->empty_field_list_on_rset= 1;
|
||||||
insert_view_fields(&fields, table_list);
|
if (!table_list->table)
|
||||||
|
{
|
||||||
|
DBUG_ASSERT(table_list->view &&
|
||||||
|
table_list->ancestor && table_list->ancestor->next_local);
|
||||||
|
my_error(ER_VIEW_NO_INSERT_FIELD_LIST, MYF(0),
|
||||||
|
table_list->view_db.str, table_list->view_name.str);
|
||||||
|
DBUG_RETURN(-1);
|
||||||
|
}
|
||||||
|
DBUG_RETURN(insert_view_fields(&fields, table_list));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!table_list->updatable ||
|
|
||||||
check_key_in_view(thd, table_list) ||
|
|
||||||
(insert_into_view &&
|
|
||||||
check_view_insertability(table_list, thd->query_id)))
|
|
||||||
{
|
|
||||||
my_error(ER_NON_UPDATABLE_TABLE, MYF(0), table_list->alias, "INSERT");
|
|
||||||
DBUG_RETURN(1);
|
|
||||||
}
|
|
||||||
DBUG_RETURN(0);
|
DBUG_RETURN(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -624,8 +669,9 @@ int mysql_prepare_insert(THD *thd, TABLE_LIST *table_list, TABLE *table,
|
|||||||
int res;
|
int res;
|
||||||
DBUG_ENTER("mysql_prepare_insert");
|
DBUG_ENTER("mysql_prepare_insert");
|
||||||
|
|
||||||
if (mysql_prepare_insert_check_table(thd, table_list, fields, &unused_conds))
|
if ((res= mysql_prepare_insert_check_table(thd, table_list,
|
||||||
DBUG_RETURN(-1);
|
fields, &unused_conds)))
|
||||||
|
DBUG_RETURN(res);
|
||||||
|
|
||||||
if (check_insert_fields(thd, table_list, fields, *values, 1,
|
if (check_insert_fields(thd, table_list, fields, *values, 1,
|
||||||
!insert_into_view) ||
|
!insert_into_view) ||
|
||||||
@ -1649,22 +1695,48 @@ bool delayed_insert::handle_inserts(void)
|
|||||||
|
|
||||||
RETURN
|
RETURN
|
||||||
0 OK
|
0 OK
|
||||||
-1 Error
|
1 Error sent to client
|
||||||
|
-1 Error is not sent to client
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int mysql_insert_select_prepare(THD *thd)
|
int mysql_insert_select_prepare(THD *thd)
|
||||||
{
|
{
|
||||||
LEX *lex= thd->lex;
|
LEX *lex= thd->lex;
|
||||||
|
TABLE_LIST* first_select_table=
|
||||||
|
(TABLE_LIST*)lex->select_lex.table_list.first;
|
||||||
|
TABLE_LIST* first_select_leaf_table;
|
||||||
|
int res;
|
||||||
DBUG_ENTER("mysql_insert_select_prepare");
|
DBUG_ENTER("mysql_insert_select_prepare");
|
||||||
/*
|
/*
|
||||||
SELECT_LEX do not belong to INSERT statement, so we can't add WHERE
|
SELECT_LEX do not belong to INSERT statement, so we can't add WHERE
|
||||||
clasue if table is VIEW
|
clasue if table is VIEW
|
||||||
*/
|
*/
|
||||||
lex->query_tables->no_where_clause= 1;
|
lex->query_tables->no_where_clause= 1;
|
||||||
if (mysql_prepare_insert_check_table(thd, lex->query_tables,
|
if ((res= mysql_prepare_insert_check_table(thd, lex->query_tables,
|
||||||
lex->field_list,
|
lex->field_list,
|
||||||
&lex->select_lex.where))
|
&lex->select_lex.where)))
|
||||||
DBUG_RETURN(-1);
|
DBUG_RETURN(res);
|
||||||
|
/*
|
||||||
|
setup was done in mysql_insert_select_prepare, but we have to mark
|
||||||
|
first local table
|
||||||
|
*/
|
||||||
|
if (first_select_table)
|
||||||
|
first_select_table->setup_is_done= 1;
|
||||||
|
/*
|
||||||
|
exclude first table from leaf tables list, because it belong to
|
||||||
|
INSERT
|
||||||
|
*/
|
||||||
|
DBUG_ASSERT(lex->select_lex.leaf_tables);
|
||||||
|
lex->leaf_tables_insert= lex->select_lex.leaf_tables;
|
||||||
|
/* skip all leaf tables belonged to view where we are insert */
|
||||||
|
for (first_select_leaf_table= lex->select_lex.leaf_tables->next_leaf;
|
||||||
|
first_select_leaf_table &&
|
||||||
|
first_select_leaf_table->belong_to_view &&
|
||||||
|
first_select_leaf_table->belong_to_view ==
|
||||||
|
lex->leaf_tables_insert->belong_to_view;
|
||||||
|
first_select_leaf_table= first_select_leaf_table->next_leaf)
|
||||||
|
{}
|
||||||
|
lex->select_lex.leaf_tables= first_select_leaf_table;
|
||||||
DBUG_RETURN(0);
|
DBUG_RETURN(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1693,6 +1765,23 @@ select_insert::prepare(List<Item> &values, SELECT_LEX_UNIT *u)
|
|||||||
if (check_insert_fields(thd, table_list, *fields, values, 1,
|
if (check_insert_fields(thd, table_list, *fields, values, 1,
|
||||||
!insert_into_view))
|
!insert_into_view))
|
||||||
DBUG_RETURN(1);
|
DBUG_RETURN(1);
|
||||||
|
/*
|
||||||
|
if it is INSERT into join view then check_insert_fields already found
|
||||||
|
real table for insert
|
||||||
|
*/
|
||||||
|
table= table_list->table;
|
||||||
|
|
||||||
|
/*
|
||||||
|
Is table which we are changing used somewhere in other parts of
|
||||||
|
query
|
||||||
|
*/
|
||||||
|
if (!(thd->lex->current_select->options & OPTION_BUFFER_RESULT) &&
|
||||||
|
unique_table(table_list, table_list->next_independent()))
|
||||||
|
{
|
||||||
|
/* Using same table for INSERT and SELECT */
|
||||||
|
thd->lex->current_select->options|= OPTION_BUFFER_RESULT;
|
||||||
|
thd->lex->current_select->join->select_options|= OPTION_BUFFER_RESULT;
|
||||||
|
}
|
||||||
|
|
||||||
restore_record(table,default_values); // Get empty record
|
restore_record(table,default_values); // Get empty record
|
||||||
table->next_number_field=table->found_next_number_field;
|
table->next_number_field=table->found_next_number_field;
|
||||||
|
@ -1006,7 +1006,7 @@ void st_select_lex::init_query()
|
|||||||
table_list.empty();
|
table_list.empty();
|
||||||
top_join_list.empty();
|
top_join_list.empty();
|
||||||
join_list= &top_join_list;
|
join_list= &top_join_list;
|
||||||
embedding= 0;
|
embedding= leaf_tables= 0;
|
||||||
item_list.empty();
|
item_list.empty();
|
||||||
join= 0;
|
join= 0;
|
||||||
where= prep_where= 0;
|
where= prep_where= 0;
|
||||||
@ -1564,7 +1564,7 @@ bool st_lex::can_be_merged()
|
|||||||
select_lex.group_list.elements == 0 &&
|
select_lex.group_list.elements == 0 &&
|
||||||
select_lex.having == 0 &&
|
select_lex.having == 0 &&
|
||||||
select_lex.with_sum_func == 0 &&
|
select_lex.with_sum_func == 0 &&
|
||||||
select_lex.table_list.elements == 1 &&
|
select_lex.table_list.elements >= 1 &&
|
||||||
!(select_lex.options & SELECT_DISTINCT) &&
|
!(select_lex.options & SELECT_DISTINCT) &&
|
||||||
select_lex.select_limit == HA_POS_ERROR);
|
select_lex.select_limit == HA_POS_ERROR);
|
||||||
}
|
}
|
||||||
|
@ -432,6 +432,7 @@ public:
|
|||||||
List<TABLE_LIST> top_join_list; /* join list of the top level */
|
List<TABLE_LIST> top_join_list; /* join list of the top level */
|
||||||
List<TABLE_LIST> *join_list; /* list for the currently parsed join */
|
List<TABLE_LIST> *join_list; /* list for the currently parsed join */
|
||||||
TABLE_LIST *embedding; /* table embedding to the above list */
|
TABLE_LIST *embedding; /* table embedding to the above list */
|
||||||
|
TABLE_LIST *leaf_tables; /* list of leaves in join table tree */
|
||||||
const char *type; /* type of select for EXPLAIN */
|
const char *type; /* type of select for EXPLAIN */
|
||||||
|
|
||||||
SQL_LIST order_list; /* ORDER clause */
|
SQL_LIST order_list; /* ORDER clause */
|
||||||
@ -650,6 +651,8 @@ typedef struct st_lex
|
|||||||
*/
|
*/
|
||||||
TABLE_LIST **query_tables_last;
|
TABLE_LIST **query_tables_last;
|
||||||
TABLE_LIST *proc_table; /* refer to mysql.proc if it was opened by VIEW */
|
TABLE_LIST *proc_table; /* refer to mysql.proc if it was opened by VIEW */
|
||||||
|
/* store original leaf_tables for INSERT SELECT and PS/SP */
|
||||||
|
TABLE_LIST *leaf_tables_insert;
|
||||||
|
|
||||||
List<key_part_spec> col_list;
|
List<key_part_spec> col_list;
|
||||||
List<key_part_spec> ref_list;
|
List<key_part_spec> ref_list;
|
||||||
|
@ -138,7 +138,8 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
|
|||||||
thd->dupp_field=0;
|
thd->dupp_field=0;
|
||||||
/* TODO: use this conds for 'WITH CHECK OPTIONS' */
|
/* TODO: use this conds for 'WITH CHECK OPTIONS' */
|
||||||
Item *unused_conds= 0;
|
Item *unused_conds= 0;
|
||||||
if (setup_tables(thd, table_list, &unused_conds) ||
|
TABLE_LIST *leaves= 0;
|
||||||
|
if (setup_tables(thd, table_list, &unused_conds, &leaves, 0) ||
|
||||||
setup_fields(thd, 0, table_list, fields, 1, 0, 0))
|
setup_fields(thd, 0, table_list, fields, 1, 0, 0))
|
||||||
DBUG_RETURN(-1);
|
DBUG_RETURN(-1);
|
||||||
if (thd->dupp_field)
|
if (thd->dupp_field)
|
||||||
|
@ -153,7 +153,7 @@ int handle_olaps(LEX *lex, SELECT_LEX *select_lex)
|
|||||||
|
|
||||||
|
|
||||||
if (setup_tables(lex->thd, (TABLE_LIST *)select_lex->table_list.first
|
if (setup_tables(lex->thd, (TABLE_LIST *)select_lex->table_list.first
|
||||||
&select_lex->where) ||
|
&select_lex->where, &select_lex->leaf_tables, 0) ||
|
||||||
setup_fields(lex->thd, 0, (TABLE_LIST *)select_lex->table_list.first,
|
setup_fields(lex->thd, 0, (TABLE_LIST *)select_lex->table_list.first,
|
||||||
select_lex->item_list, 1, &all_fields,1) ||
|
select_lex->item_list, 1, &all_fields,1) ||
|
||||||
setup_fields(lex->thd, 0, (TABLE_LIST *)select_lex->table_list.first,
|
setup_fields(lex->thd, 0, (TABLE_LIST *)select_lex->table_list.first,
|
||||||
|
@ -2756,18 +2756,29 @@ unsent_create_error:
|
|||||||
lex->duplicates);
|
lex->duplicates);
|
||||||
if (thd->net.report_error)
|
if (thd->net.report_error)
|
||||||
res= -1;
|
res= -1;
|
||||||
|
if (res != 2)
|
||||||
break;
|
break;
|
||||||
case SQLCOM_UPDATE_MULTI:
|
case SQLCOM_UPDATE_MULTI:
|
||||||
{
|
{
|
||||||
|
bool converted= 0;
|
||||||
DBUG_ASSERT(first_table == all_tables && first_table != 0);
|
DBUG_ASSERT(first_table == all_tables && first_table != 0);
|
||||||
|
if (res != 2)
|
||||||
|
{
|
||||||
if ((res= multi_update_precheck(thd, all_tables)))
|
if ((res= multi_update_precheck(thd, all_tables)))
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
res= 0;
|
||||||
|
converted= 1;
|
||||||
|
}
|
||||||
res= mysql_multi_update(thd, all_tables,
|
res= mysql_multi_update(thd, all_tables,
|
||||||
&select_lex->item_list,
|
&select_lex->item_list,
|
||||||
&lex->value_list,
|
&lex->value_list,
|
||||||
select_lex->where,
|
select_lex->where,
|
||||||
select_lex->options,
|
select_lex->options,
|
||||||
lex->duplicates, unit, select_lex);
|
lex->duplicates, unit, select_lex,
|
||||||
|
converted);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SQLCOM_REPLACE:
|
case SQLCOM_REPLACE:
|
||||||
@ -2804,36 +2815,29 @@ unsent_create_error:
|
|||||||
unit->set_limit(select_lex, select_lex);
|
unit->set_limit(select_lex, select_lex);
|
||||||
|
|
||||||
if (!(res= open_and_lock_tables(thd, all_tables)))
|
if (!(res= open_and_lock_tables(thd, all_tables)))
|
||||||
{
|
|
||||||
/*
|
|
||||||
Is table which we are changing used somewhere in other parts of
|
|
||||||
query
|
|
||||||
*/
|
|
||||||
if (unique_table(first_table, all_tables->next_independent()))
|
|
||||||
{
|
|
||||||
/* Using same table for INSERT and SELECT */
|
|
||||||
select_lex->options |= OPTION_BUFFER_RESULT;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((res= mysql_insert_select_prepare(thd)))
|
|
||||||
break;
|
|
||||||
if ((result= new select_insert(first_table, first_table->table,
|
|
||||||
&lex->field_list, lex->duplicates,
|
|
||||||
lex->duplicates == DUP_IGNORE)))
|
|
||||||
{
|
{
|
||||||
/* Skip first table, which is the table we are inserting in */
|
/* Skip first table, which is the table we are inserting in */
|
||||||
lex->select_lex.table_list.first= (byte*)first_table->next_local;
|
lex->select_lex.table_list.first= (byte*)first_table->next_local;
|
||||||
|
|
||||||
|
res= mysql_insert_select_prepare(thd);
|
||||||
|
if (!res && (result= new select_insert(first_table, first_table->table,
|
||||||
|
&lex->field_list,
|
||||||
|
lex->duplicates,
|
||||||
|
lex->duplicates == DUP_IGNORE)))
|
||||||
|
{
|
||||||
|
TABLE_LIST *first_select_table;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
insert/replace from SELECT give its SELECT_LEX for SELECT,
|
insert/replace from SELECT give its SELECT_LEX for SELECT,
|
||||||
and item_list belong to SELECT
|
and item_list belong to SELECT
|
||||||
*/
|
*/
|
||||||
lex->select_lex.resolve_mode= SELECT_LEX::SELECT_MODE;
|
lex->select_lex.resolve_mode= SELECT_LEX::SELECT_MODE;
|
||||||
res= handle_select(thd, lex, result);
|
res= handle_select(thd, lex, result);
|
||||||
/* revert changes for SP */
|
|
||||||
lex->select_lex.table_list.first= (byte*) first_table;
|
|
||||||
lex->select_lex.resolve_mode= SELECT_LEX::INSERT_MODE;
|
lex->select_lex.resolve_mode= SELECT_LEX::INSERT_MODE;
|
||||||
delete result;
|
delete result;
|
||||||
}
|
}
|
||||||
|
/* revert changes for SP */
|
||||||
|
lex->select_lex.table_list.first= (byte*) first_table;
|
||||||
if (thd->net.report_error)
|
if (thd->net.report_error)
|
||||||
res= -1;
|
res= -1;
|
||||||
}
|
}
|
||||||
@ -2897,6 +2901,16 @@ unsent_create_error:
|
|||||||
if ((res= open_and_lock_tables(thd, all_tables)))
|
if ((res= open_and_lock_tables(thd, all_tables)))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
if (!first_table->table)
|
||||||
|
{
|
||||||
|
DBUG_ASSERT(first_table->view &&
|
||||||
|
first_table->ancestor && first_table->ancestor->next_local);
|
||||||
|
my_error(ER_VIEW_DELETE_MERGE_VIEW, MYF(0),
|
||||||
|
first_table->view_db.str, first_table->view_name.str);
|
||||||
|
res= -1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
if ((res= mysql_multi_delete_prepare(thd)))
|
if ((res= mysql_multi_delete_prepare(thd)))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -4366,7 +4380,7 @@ mysql_init_query(THD *thd, uchar *buf, uint length, bool lexonly)
|
|||||||
lex->found_colon= 0;
|
lex->found_colon= 0;
|
||||||
lex->safe_to_cache_query= 1;
|
lex->safe_to_cache_query= 1;
|
||||||
lex->time_zone_tables_used= 0;
|
lex->time_zone_tables_used= 0;
|
||||||
lex->proc_table= lex->query_tables= 0;
|
lex->leaf_tables_insert= lex->proc_table= lex->query_tables= 0;
|
||||||
lex->query_tables_last= &lex->query_tables;
|
lex->query_tables_last= &lex->query_tables;
|
||||||
lex->variables_used= 0;
|
lex->variables_used= 0;
|
||||||
lex->select_lex.parent_lex= lex;
|
lex->select_lex.parent_lex= lex;
|
||||||
|
@ -959,6 +959,7 @@ error:
|
|||||||
|
|
||||||
RETURN VALUE
|
RETURN VALUE
|
||||||
0 success
|
0 success
|
||||||
|
2 convert to multi_update
|
||||||
1 error, sent to client
|
1 error, sent to client
|
||||||
-1 error, not sent to client
|
-1 error, not sent to client
|
||||||
*/
|
*/
|
||||||
@ -975,6 +976,15 @@ static int mysql_test_update(Prepared_statement *stmt,
|
|||||||
|
|
||||||
if (!(res=open_and_lock_tables(thd, table_list)))
|
if (!(res=open_and_lock_tables(thd, table_list)))
|
||||||
{
|
{
|
||||||
|
if (table_list->table == 0)
|
||||||
|
{
|
||||||
|
DBUG_ASSERT(table_list->view &&
|
||||||
|
table_list->ancestor && table_list->ancestor->next_local);
|
||||||
|
stmt->lex->sql_command= SQLCOM_UPDATE_MULTI;
|
||||||
|
DBUG_PRINT("info", ("Switch to multi-update (command replaced)"));
|
||||||
|
/* convert to multiupdate */
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
if (!(res= mysql_prepare_update(thd, table_list,
|
if (!(res= mysql_prepare_update(thd, table_list,
|
||||||
&select->where,
|
&select->where,
|
||||||
select->order_list.elements,
|
select->order_list.elements,
|
||||||
@ -1027,6 +1037,15 @@ static int mysql_test_delete(Prepared_statement *stmt,
|
|||||||
|
|
||||||
if (!(res=open_and_lock_tables(thd, table_list)))
|
if (!(res=open_and_lock_tables(thd, table_list)))
|
||||||
{
|
{
|
||||||
|
if (!table_list->table)
|
||||||
|
{
|
||||||
|
DBUG_ASSERT(table_list->view &&
|
||||||
|
table_list->ancestor && table_list->ancestor->next_local);
|
||||||
|
my_error(ER_VIEW_DELETE_MERGE_VIEW, MYF(0),
|
||||||
|
table_list->view_db.str, table_list->view_name.str);
|
||||||
|
DBUG_RETURN(-1);
|
||||||
|
}
|
||||||
|
|
||||||
res= mysql_prepare_delete(thd, table_list, &lex->select_lex.where);
|
res= mysql_prepare_delete(thd, table_list, &lex->select_lex.where);
|
||||||
lex->unit.cleanup();
|
lex->unit.cleanup();
|
||||||
}
|
}
|
||||||
@ -1219,7 +1238,10 @@ static int select_like_statement_test(Prepared_statement *stmt,
|
|||||||
LEX *lex= stmt->lex;
|
LEX *lex= stmt->lex;
|
||||||
int res= 0;
|
int res= 0;
|
||||||
|
|
||||||
if (tables && (res= open_and_lock_tables(thd, tables)))
|
/* check that tables was not opened during conversion from usual update */
|
||||||
|
if (tables &&
|
||||||
|
(!tables->table && !tables->view) &&
|
||||||
|
(res= open_and_lock_tables(thd, tables)))
|
||||||
goto end;
|
goto end;
|
||||||
|
|
||||||
if (specific_prepare && (res= (*specific_prepare)(thd)))
|
if (specific_prepare && (res= (*specific_prepare)(thd)))
|
||||||
@ -1285,6 +1307,7 @@ static int mysql_test_create_table(Prepared_statement *stmt)
|
|||||||
mysql_test_multiupdate()
|
mysql_test_multiupdate()
|
||||||
stmt prepared statemen handler
|
stmt prepared statemen handler
|
||||||
tables list of tables queries
|
tables list of tables queries
|
||||||
|
converted converted to multi-update from usual update
|
||||||
|
|
||||||
RETURN VALUE
|
RETURN VALUE
|
||||||
0 success
|
0 success
|
||||||
@ -1292,10 +1315,11 @@ static int mysql_test_create_table(Prepared_statement *stmt)
|
|||||||
-1 error, not sent to client
|
-1 error, not sent to client
|
||||||
*/
|
*/
|
||||||
static int mysql_test_multiupdate(Prepared_statement *stmt,
|
static int mysql_test_multiupdate(Prepared_statement *stmt,
|
||||||
TABLE_LIST *tables)
|
TABLE_LIST *tables,
|
||||||
|
bool converted)
|
||||||
{
|
{
|
||||||
int res;
|
int res;
|
||||||
if ((res= multi_update_precheck(stmt->thd, tables)))
|
if (!converted && (res= multi_update_precheck(stmt->thd, tables)))
|
||||||
return res;
|
return res;
|
||||||
return select_like_statement_test(stmt, tables, &mysql_multi_update_prepare);
|
return select_like_statement_test(stmt, tables, &mysql_multi_update_prepare);
|
||||||
}
|
}
|
||||||
@ -1325,7 +1349,19 @@ static int mysql_test_multidelete(Prepared_statement *stmt,
|
|||||||
uint fake_counter;
|
uint fake_counter;
|
||||||
if ((res= multi_delete_precheck(stmt->thd, tables, &fake_counter)))
|
if ((res= multi_delete_precheck(stmt->thd, tables, &fake_counter)))
|
||||||
return res;
|
return res;
|
||||||
return select_like_statement_test(stmt, tables, &mysql_multi_delete_prepare);
|
if ((res= select_like_statement_test(stmt, tables,
|
||||||
|
&mysql_multi_delete_prepare)))
|
||||||
|
return res;
|
||||||
|
if (!tables->table)
|
||||||
|
{
|
||||||
|
DBUG_ASSERT(tables->view &&
|
||||||
|
tables->ancestor && tables->ancestor->next_local);
|
||||||
|
my_error(ER_VIEW_DELETE_MERGE_VIEW, MYF(0),
|
||||||
|
tables->view_db.str, tables->view_name.str);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1404,6 +1440,11 @@ static int send_prepare_results(Prepared_statement *stmt, bool text_protocol)
|
|||||||
|
|
||||||
case SQLCOM_UPDATE:
|
case SQLCOM_UPDATE:
|
||||||
res= mysql_test_update(stmt, tables);
|
res= mysql_test_update(stmt, tables);
|
||||||
|
if (res != 2)
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SQLCOM_UPDATE_MULTI:
|
||||||
|
res= mysql_test_multiupdate(stmt, tables, res == 2);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SQLCOM_DELETE:
|
case SQLCOM_DELETE:
|
||||||
@ -1432,10 +1473,6 @@ static int send_prepare_results(Prepared_statement *stmt, bool text_protocol)
|
|||||||
res= mysql_test_multidelete(stmt, tables);
|
res= mysql_test_multidelete(stmt, tables);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SQLCOM_UPDATE_MULTI:
|
|
||||||
res= mysql_test_multiupdate(stmt, tables);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case SQLCOM_INSERT_SELECT:
|
case SQLCOM_INSERT_SELECT:
|
||||||
res= mysql_test_insert_select(stmt, tables);
|
res= mysql_test_insert_select(stmt, tables);
|
||||||
break;
|
break;
|
||||||
@ -1716,8 +1753,15 @@ void reset_stmt_for_execute(THD *thd, LEX *lex)
|
|||||||
were closed in the end of previous prepare or execute call.
|
were closed in the end of previous prepare or execute call.
|
||||||
*/
|
*/
|
||||||
tables->table= 0;
|
tables->table= 0;
|
||||||
|
if (tables->nested_join)
|
||||||
|
tables->nested_join->counter= 0;
|
||||||
}
|
}
|
||||||
lex->current_select= &lex->select_lex;
|
lex->current_select= &lex->select_lex;
|
||||||
|
|
||||||
|
/* restore original list used in INSERT ... SELECT */
|
||||||
|
if (lex->leaf_tables_insert)
|
||||||
|
lex->select_lex.leaf_tables= lex->leaf_tables_insert;
|
||||||
|
|
||||||
if (lex->result)
|
if (lex->result)
|
||||||
lex->result->cleanup();
|
lex->result->cleanup();
|
||||||
}
|
}
|
||||||
|
@ -38,7 +38,7 @@ const key_map key_map_empty(0);
|
|||||||
const key_map key_map_full(~0);
|
const key_map key_map_full(~0);
|
||||||
|
|
||||||
static void optimize_keyuse(JOIN *join, DYNAMIC_ARRAY *keyuse_array);
|
static void optimize_keyuse(JOIN *join, DYNAMIC_ARRAY *keyuse_array);
|
||||||
static bool make_join_statistics(JOIN *join,TABLE_LIST *tables,COND *conds,
|
static bool make_join_statistics(JOIN *join, TABLE_LIST *leaves, COND *conds,
|
||||||
DYNAMIC_ARRAY *keyuse);
|
DYNAMIC_ARRAY *keyuse);
|
||||||
static bool update_ref_and_keys(THD *thd, DYNAMIC_ARRAY *keyuse,
|
static bool update_ref_and_keys(THD *thd, DYNAMIC_ARRAY *keyuse,
|
||||||
JOIN_TAB *join_tab,
|
JOIN_TAB *join_tab,
|
||||||
@ -241,6 +241,7 @@ int handle_select(THD *thd, LEX *lex, select_result *result)
|
|||||||
*/
|
*/
|
||||||
inline int setup_without_group(THD *thd, Item **ref_pointer_array,
|
inline int setup_without_group(THD *thd, Item **ref_pointer_array,
|
||||||
TABLE_LIST *tables,
|
TABLE_LIST *tables,
|
||||||
|
TABLE_LIST *leaves,
|
||||||
List<Item> &fields,
|
List<Item> &fields,
|
||||||
List<Item> &all_fields,
|
List<Item> &all_fields,
|
||||||
COND **conds,
|
COND **conds,
|
||||||
@ -253,7 +254,7 @@ inline int setup_without_group(THD *thd, Item **ref_pointer_array,
|
|||||||
|
|
||||||
save_allow_sum_func= thd->allow_sum_func;
|
save_allow_sum_func= thd->allow_sum_func;
|
||||||
thd->allow_sum_func= 0;
|
thd->allow_sum_func= 0;
|
||||||
res= (setup_conds(thd, tables, conds) ||
|
res= (setup_conds(thd, tables, leaves, conds) ||
|
||||||
setup_order(thd, ref_pointer_array, tables, fields, all_fields,
|
setup_order(thd, ref_pointer_array, tables, fields, all_fields,
|
||||||
order) ||
|
order) ||
|
||||||
setup_group(thd, ref_pointer_array, tables, fields, all_fields,
|
setup_group(thd, ref_pointer_array, tables, fields, all_fields,
|
||||||
@ -300,12 +301,13 @@ JOIN::prepare(Item ***rref_pointer_array,
|
|||||||
|
|
||||||
/* Check that all tables, fields, conds and order are ok */
|
/* Check that all tables, fields, conds and order are ok */
|
||||||
|
|
||||||
if (setup_tables(thd, tables_list, &conds) ||
|
if (setup_tables(thd, tables_list, &conds, &select_lex->leaf_tables, 0) ||
|
||||||
setup_wild(thd, tables_list, fields_list, &all_fields, wild_num) ||
|
setup_wild(thd, tables_list, fields_list, &all_fields, wild_num) ||
|
||||||
select_lex->setup_ref_array(thd, og_num) ||
|
select_lex->setup_ref_array(thd, og_num) ||
|
||||||
setup_fields(thd, (*rref_pointer_array), tables_list, fields_list, 1,
|
setup_fields(thd, (*rref_pointer_array), tables_list, fields_list, 1,
|
||||||
&all_fields, 1) ||
|
&all_fields, 1) ||
|
||||||
setup_without_group(thd, (*rref_pointer_array), tables_list, fields_list,
|
setup_without_group(thd, (*rref_pointer_array), tables_list,
|
||||||
|
select_lex->leaf_tables, fields_list,
|
||||||
all_fields, &conds, order, group_list,
|
all_fields, &conds, order, group_list,
|
||||||
&hidden_group_fields))
|
&hidden_group_fields))
|
||||||
DBUG_RETURN(-1); /* purecov: inspected */
|
DBUG_RETURN(-1); /* purecov: inspected */
|
||||||
@ -373,7 +375,9 @@ JOIN::prepare(Item ***rref_pointer_array,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
TABLE_LIST *table_ptr;
|
TABLE_LIST *table_ptr;
|
||||||
for (table_ptr= tables_list; table_ptr; table_ptr= table_ptr->next_local)
|
for (table_ptr= select_lex->leaf_tables;
|
||||||
|
table_ptr;
|
||||||
|
table_ptr= table_ptr->next_leaf)
|
||||||
tables++;
|
tables++;
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
@ -550,7 +554,7 @@ JOIN::optimize()
|
|||||||
opt_sum_query() returns -1 if no rows match to the WHERE conditions,
|
opt_sum_query() returns -1 if no rows match to the WHERE conditions,
|
||||||
or 1 if all items were resolved, or 0, or an error number HA_ERR_...
|
or 1 if all items were resolved, or 0, or an error number HA_ERR_...
|
||||||
*/
|
*/
|
||||||
if ((res=opt_sum_query(tables_list, all_fields, conds)))
|
if ((res=opt_sum_query(select_lex->leaf_tables, all_fields, conds)))
|
||||||
{
|
{
|
||||||
if (res > 1)
|
if (res > 1)
|
||||||
{
|
{
|
||||||
@ -576,11 +580,11 @@ JOIN::optimize()
|
|||||||
DBUG_RETURN(0);
|
DBUG_RETURN(0);
|
||||||
}
|
}
|
||||||
error= -1; // Error is sent to client
|
error= -1; // Error is sent to client
|
||||||
sort_by_table= get_sort_by_table(order, group_list, tables_list);
|
sort_by_table= get_sort_by_table(order, group_list, select_lex->leaf_tables);
|
||||||
|
|
||||||
/* Calculate how to do the join */
|
/* Calculate how to do the join */
|
||||||
thd->proc_info= "statistics";
|
thd->proc_info= "statistics";
|
||||||
if (make_join_statistics(this, tables_list, conds, &keyuse) ||
|
if (make_join_statistics(this, select_lex->leaf_tables, conds, &keyuse) ||
|
||||||
thd->is_fatal_error)
|
thd->is_fatal_error)
|
||||||
{
|
{
|
||||||
DBUG_PRINT("error",("Error: make_join_statistics() failed"));
|
DBUG_PRINT("error",("Error: make_join_statistics() failed"));
|
||||||
@ -1014,7 +1018,7 @@ JOIN::reinit()
|
|||||||
if (tables_list)
|
if (tables_list)
|
||||||
{
|
{
|
||||||
tables_list->setup_is_done= 0;
|
tables_list->setup_is_done= 0;
|
||||||
if (setup_tables(thd, tables_list, &conds))
|
if (setup_tables(thd, tables_list, &conds, &select_lex->leaf_tables, 1))
|
||||||
DBUG_RETURN(1);
|
DBUG_RETURN(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1119,7 +1123,7 @@ JOIN::exec()
|
|||||||
|
|
||||||
if (zero_result_cause)
|
if (zero_result_cause)
|
||||||
{
|
{
|
||||||
(void) return_zero_rows(this, result, tables_list, fields_list,
|
(void) return_zero_rows(this, result, select_lex->leaf_tables, fields_list,
|
||||||
send_row_on_empty_set(),
|
send_row_on_empty_set(),
|
||||||
select_options,
|
select_options,
|
||||||
zero_result_cause,
|
zero_result_cause,
|
||||||
@ -2058,7 +2062,7 @@ make_join_statistics(JOIN *join,TABLE_LIST *tables,COND *conds,
|
|||||||
|
|
||||||
for (s= stat, i= 0;
|
for (s= stat, i= 0;
|
||||||
tables;
|
tables;
|
||||||
s++, tables= tables->next_local, i++)
|
s++, tables= tables->next_leaf, i++)
|
||||||
{
|
{
|
||||||
TABLE_LIST *embedding= tables->embedding;
|
TABLE_LIST *embedding= tables->embedding;
|
||||||
stat_vector[i]=s;
|
stat_vector[i]=s;
|
||||||
@ -4834,6 +4838,7 @@ add_found_match_trig_cond(JOIN_TAB *tab, COND *cond, JOIN_TAB *root_tab)
|
|||||||
static void
|
static void
|
||||||
make_outerjoin_info(JOIN *join)
|
make_outerjoin_info(JOIN *join)
|
||||||
{
|
{
|
||||||
|
DBUG_ENTER("make_outerjoin_info");
|
||||||
for (uint i=join->const_tables ; i < join->tables ; i++)
|
for (uint i=join->const_tables ; i < join->tables ; i++)
|
||||||
{
|
{
|
||||||
JOIN_TAB *tab=join->join_tab+i;
|
JOIN_TAB *tab=join->join_tab+i;
|
||||||
@ -4875,6 +4880,7 @@ make_outerjoin_info(JOIN *join)
|
|||||||
nested_join->first_nested->last_inner= tab;
|
nested_join->first_nested->last_inner= tab;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
DBUG_VOID_RETURN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -4972,7 +4978,9 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond)
|
|||||||
in the ON part of an OUTER JOIN. In this case we want the code
|
in the ON part of an OUTER JOIN. In this case we want the code
|
||||||
below to check if we should use 'quick' instead.
|
below to check if we should use 'quick' instead.
|
||||||
*/
|
*/
|
||||||
|
DBUG_PRINT("info", ("Item_int"));
|
||||||
tmp= new Item_int((longlong) 1,1); // Always true
|
tmp= new Item_int((longlong) 1,1); // Always true
|
||||||
|
DBUG_PRINT("info", ("Item_int 0x%lx", (ulong)tmp));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -5142,13 +5150,18 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond)
|
|||||||
Now add the guard turning the predicate off for
|
Now add the guard turning the predicate off for
|
||||||
the null complemented row.
|
the null complemented row.
|
||||||
*/
|
*/
|
||||||
|
DBUG_PRINT("info", ("Item_func_trig_cond"));
|
||||||
tmp= new Item_func_trig_cond(tmp,
|
tmp= new Item_func_trig_cond(tmp,
|
||||||
&first_inner_tab->not_null_compl);
|
&first_inner_tab->not_null_compl);
|
||||||
|
DBUG_PRINT("info", ("Item_func_trig_cond 0x%lx", (ulong) tmp));
|
||||||
if (tmp)
|
if (tmp)
|
||||||
tmp->quick_fix_field();
|
tmp->quick_fix_field();
|
||||||
/* Add the predicate to other pushed down predicates */
|
/* Add the predicate to other pushed down predicates */
|
||||||
|
DBUG_PRINT("info", ("Item_cond_and"));
|
||||||
cond_tab->select_cond= !cond_tab->select_cond ? tmp :
|
cond_tab->select_cond= !cond_tab->select_cond ? tmp :
|
||||||
new Item_cond_and(cond_tab->select_cond,tmp);
|
new Item_cond_and(cond_tab->select_cond,tmp);
|
||||||
|
DBUG_PRINT("info", ("Item_cond_and 0x%lx",
|
||||||
|
(ulong)cond_tab->select_cond));
|
||||||
if (!cond_tab->select_cond)
|
if (!cond_tab->select_cond)
|
||||||
DBUG_RETURN(1);
|
DBUG_RETURN(1);
|
||||||
cond_tab->select_cond->quick_fix_field();
|
cond_tab->select_cond->quick_fix_field();
|
||||||
@ -5700,7 +5713,7 @@ return_zero_rows(JOIN *join, select_result *result,TABLE_LIST *tables,
|
|||||||
|
|
||||||
if (send_row)
|
if (send_row)
|
||||||
{
|
{
|
||||||
for (TABLE_LIST *table= tables; table; table= table->next_local)
|
for (TABLE_LIST *table= tables; table; table= table->next_leaf)
|
||||||
mark_as_null_row(table->table); // All fields are NULL
|
mark_as_null_row(table->table); // All fields are NULL
|
||||||
if (having && having->val_int() == 0)
|
if (having && having->val_int() == 0)
|
||||||
send_row=0;
|
send_row=0;
|
||||||
@ -7729,6 +7742,7 @@ sub_select(JOIN *join,JOIN_TAB *join_tab,bool end_of_records)
|
|||||||
join->thd->send_kill_message();
|
join->thd->send_kill_message();
|
||||||
return -2; /* purecov: inspected */
|
return -2; /* purecov: inspected */
|
||||||
}
|
}
|
||||||
|
DBUG_PRINT("info", ("select cond 0x%lx", (ulong)select_cond));
|
||||||
if (!select_cond || select_cond->val_int())
|
if (!select_cond || select_cond->val_int())
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
@ -10418,7 +10432,7 @@ get_sort_by_table(ORDER *a,ORDER *b,TABLE_LIST *tables)
|
|||||||
if (!map || (map & (RAND_TABLE_BIT | OUTER_REF_TABLE_BIT)))
|
if (!map || (map & (RAND_TABLE_BIT | OUTER_REF_TABLE_BIT)))
|
||||||
DBUG_RETURN(0);
|
DBUG_RETURN(0);
|
||||||
|
|
||||||
for (; !(map & tables->table->map); tables= tables->next_local);
|
for (; !(map & tables->table->map); tables= tables->next_leaf);
|
||||||
if (map != tables->table->map)
|
if (map != tables->table->map)
|
||||||
DBUG_RETURN(0); // More than one table
|
DBUG_RETURN(0); // More than one table
|
||||||
DBUG_PRINT("exit",("sort by table: %d",tables->table->tablenr));
|
DBUG_PRINT("exit",("sort by table: %d",tables->table->tablenr));
|
||||||
|
@ -88,6 +88,28 @@ static bool check_fields(THD *thd, List<Item> &items)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Process usual UPDATE
|
||||||
|
|
||||||
|
SYNOPSIS
|
||||||
|
mysql_update()
|
||||||
|
thd thread handler
|
||||||
|
fields fields for update
|
||||||
|
values values of fields for update
|
||||||
|
conds WHERE clause expression
|
||||||
|
order_num number of elemen in ORDER BY clause
|
||||||
|
order ORDER BY clause list
|
||||||
|
limit limit clause
|
||||||
|
handle_duplicates how to handle duplicates
|
||||||
|
|
||||||
|
RETURN
|
||||||
|
0 - OK
|
||||||
|
2 - privilege check and openning table passed, but we need to convert to
|
||||||
|
multi-update because of view substitution
|
||||||
|
1 - error and error sent to client
|
||||||
|
-1 - error and error is not sent to client
|
||||||
|
*/
|
||||||
|
|
||||||
int mysql_update(THD *thd,
|
int mysql_update(THD *thd,
|
||||||
TABLE_LIST *table_list,
|
TABLE_LIST *table_list,
|
||||||
List<Item> &fields,
|
List<Item> &fields,
|
||||||
@ -120,6 +142,15 @@ int mysql_update(THD *thd,
|
|||||||
|
|
||||||
if ((error= open_and_lock_tables(thd, table_list)))
|
if ((error= open_and_lock_tables(thd, table_list)))
|
||||||
DBUG_RETURN(error);
|
DBUG_RETURN(error);
|
||||||
|
|
||||||
|
if (table_list->table == 0)
|
||||||
|
{
|
||||||
|
DBUG_ASSERT(table_list->view &&
|
||||||
|
table_list->ancestor && table_list->ancestor->next_local);
|
||||||
|
DBUG_PRINT("info", ("Switch to multi-update"));
|
||||||
|
/* convert to multiupdate */
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
thd->proc_info="init";
|
thd->proc_info="init";
|
||||||
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);
|
||||||
@ -521,8 +552,8 @@ int mysql_prepare_update(THD *thd, TABLE_LIST *table_list,
|
|||||||
tables.table= table;
|
tables.table= table;
|
||||||
tables.alias= table_list->alias;
|
tables.alias= table_list->alias;
|
||||||
|
|
||||||
if (setup_tables(thd, table_list, conds) ||
|
if (setup_tables(thd, table_list, conds, &select_lex->leaf_tables, 0) ||
|
||||||
setup_conds(thd, table_list, conds) ||
|
setup_conds(thd, table_list, select_lex->leaf_tables, conds) ||
|
||||||
select_lex->setup_ref_array(thd, order_num) ||
|
select_lex->setup_ref_array(thd, order_num) ||
|
||||||
setup_order(thd, select_lex->ref_pointer_array,
|
setup_order(thd, select_lex->ref_pointer_array,
|
||||||
table_list, all_fields, all_fields, order) ||
|
table_list, all_fields, all_fields, order) ||
|
||||||
@ -566,25 +597,31 @@ int mysql_multi_update_prepare(THD *thd)
|
|||||||
TABLE_LIST *table_list= lex->query_tables;
|
TABLE_LIST *table_list= lex->query_tables;
|
||||||
List<Item> *fields= &lex->select_lex.item_list;
|
List<Item> *fields= &lex->select_lex.item_list;
|
||||||
TABLE_LIST *tl;
|
TABLE_LIST *tl;
|
||||||
|
TABLE_LIST *leaves;
|
||||||
table_map tables_for_update= 0, readonly_tables= 0;
|
table_map tables_for_update= 0, readonly_tables= 0;
|
||||||
int res;
|
int res;
|
||||||
bool update_view= 0;
|
bool update_view= 0;
|
||||||
DBUG_ENTER("mysql_multi_update_prepare");
|
DBUG_ENTER("mysql_multi_update_prepare");
|
||||||
|
|
||||||
|
if (setup_tables(thd, table_list, &lex->select_lex.where,
|
||||||
|
&lex->select_lex.leaf_tables, 0))
|
||||||
|
DBUG_RETURN(-1);
|
||||||
/*
|
/*
|
||||||
Ensure that we have update privilege for all tables and columns in the
|
Ensure that we have update privilege for all tables and columns in the
|
||||||
SET part
|
SET part
|
||||||
*/
|
*/
|
||||||
for (tl= table_list; tl; tl= tl->next_local)
|
for (tl= (leaves= lex->select_lex.leaf_tables); tl; tl= tl->next_leaf)
|
||||||
{
|
{
|
||||||
TABLE *table= tl->table;
|
|
||||||
/*
|
/*
|
||||||
Update of derived tables is checked later
|
Update of derived tables is checked later
|
||||||
We don't check privileges here, becasue then we would get error
|
We don't check privileges here, becasue then we would get error
|
||||||
"UPDATE command denided .. for column N" instead of
|
"UPDATE command denided .. for column N" instead of
|
||||||
"Target table ... is not updatable"
|
"Target table ... is not updatable"
|
||||||
*/
|
*/
|
||||||
if (!tl->derived)
|
TABLE *table= tl->table;
|
||||||
tl->grant.want_privilege= table->grant.want_privilege=
|
TABLE_LIST *tlist;
|
||||||
|
if (!(tlist= tl->belong_to_view?tl->belong_to_view:tl)->derived)
|
||||||
|
tlist->grant.want_privilege= table->grant.want_privilege=
|
||||||
(UPDATE_ACL & ~table->grant.privilege);
|
(UPDATE_ACL & ~table->grant.privilege);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -592,8 +629,7 @@ int mysql_multi_update_prepare(THD *thd)
|
|||||||
setup_tables() need for VIEWs. JOIN::prepare() will not do it second
|
setup_tables() need for VIEWs. JOIN::prepare() will not do it second
|
||||||
time.
|
time.
|
||||||
*/
|
*/
|
||||||
if (setup_tables(thd, table_list, &lex->select_lex.where) ||
|
if ((thd->lex->select_lex.no_wrap_view_item= 1,
|
||||||
(thd->lex->select_lex.no_wrap_view_item= 1,
|
|
||||||
res= setup_fields(thd, 0, table_list, *fields, 1, 0, 0),
|
res= setup_fields(thd, 0, table_list, *fields, 1, 0, 0),
|
||||||
thd->lex->select_lex.no_wrap_view_item= 0,
|
thd->lex->select_lex.no_wrap_view_item= 0,
|
||||||
res))
|
res))
|
||||||
@ -626,30 +662,49 @@ int mysql_multi_update_prepare(THD *thd)
|
|||||||
/*
|
/*
|
||||||
Count tables and setup timestamp handling
|
Count tables and setup timestamp handling
|
||||||
*/
|
*/
|
||||||
for (tl= table_list; tl ; tl= tl->next_local)
|
for (tl= leaves; tl; tl= tl->next_leaf)
|
||||||
{
|
{
|
||||||
TABLE *table= tl->table;
|
TABLE *table= tl->table;
|
||||||
|
TABLE_LIST *tlist= tl->belong_to_view?tl->belong_to_view:tl;
|
||||||
|
|
||||||
/* We only need SELECT privilege for columns in the values list */
|
/* We only need SELECT privilege for columns in the values list */
|
||||||
tl->grant.want_privilege= table->grant.want_privilege=
|
tlist->grant.want_privilege= table->grant.want_privilege=
|
||||||
(SELECT_ACL & ~table->grant.privilege);
|
(SELECT_ACL & ~table->grant.privilege);
|
||||||
// Only set timestamp column if this is not modified
|
// Only set timestamp column if this is not modified
|
||||||
if (table->timestamp_field &&
|
if (table->timestamp_field &&
|
||||||
table->timestamp_field->query_id == thd->query_id)
|
table->timestamp_field->query_id == thd->query_id)
|
||||||
table->timestamp_on_update_now= 0;
|
table->timestamp_on_update_now= 0;
|
||||||
|
|
||||||
if (!tl->updatable || check_key_in_view(thd, tl))
|
if (!tlist->updatable || check_key_in_view(thd, tl))
|
||||||
readonly_tables|= table->map;
|
readonly_tables|= table->map;
|
||||||
}
|
}
|
||||||
if (tables_for_update & readonly_tables)
|
if (tables_for_update & readonly_tables)
|
||||||
{
|
{
|
||||||
// find readonly table/view which cause error
|
// find readonly table/view which cause error
|
||||||
for (tl= table_list; tl ; tl= tl->next_local)
|
for (tl= leaves; tl; tl= tl->next_leaf)
|
||||||
{
|
{
|
||||||
if ((readonly_tables & tl->table->map) &&
|
if ((readonly_tables & tl->table->map) &&
|
||||||
(tables_for_update & tl->table->map))
|
(tables_for_update & tl->table->map))
|
||||||
{
|
{
|
||||||
my_error(ER_NON_UPDATABLE_TABLE, MYF(0), tl->alias, "UPDATE");
|
TABLE_LIST *table= tl->belong_to_view ? tl->belong_to_view : tl;
|
||||||
|
my_error(ER_NON_UPDATABLE_TABLE, MYF(0), table->alias, "UPDATE");
|
||||||
|
DBUG_RETURN(-1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* check single table update for view compound from several tables */
|
||||||
|
for (tl= table_list; tl; tl= tl->next_local)
|
||||||
|
{
|
||||||
|
if (tl->table == 0)
|
||||||
|
{
|
||||||
|
DBUG_ASSERT(tl->view &&
|
||||||
|
tl->ancestor && tl->ancestor->next_local);
|
||||||
|
TABLE_LIST *for_update= 0;
|
||||||
|
if (tl->check_single_table(&for_update, tables_for_update))
|
||||||
|
{
|
||||||
|
my_error(ER_VIEW_MULTIUPDATE, MYF(0),
|
||||||
|
tl->view_db.str, tl->view_name.str);
|
||||||
DBUG_RETURN(-1);
|
DBUG_RETURN(-1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -665,19 +720,22 @@ int mysql_multi_update(THD *thd,
|
|||||||
COND *conds,
|
COND *conds,
|
||||||
ulong options,
|
ulong options,
|
||||||
enum enum_duplicates handle_duplicates,
|
enum enum_duplicates handle_duplicates,
|
||||||
SELECT_LEX_UNIT *unit, SELECT_LEX *select_lex)
|
SELECT_LEX_UNIT *unit, SELECT_LEX *select_lex,
|
||||||
|
bool converted)
|
||||||
{
|
{
|
||||||
int res;
|
int res= 0;
|
||||||
multi_update *result;
|
multi_update *result;
|
||||||
DBUG_ENTER("mysql_multi_update");
|
DBUG_ENTER("mysql_multi_update");
|
||||||
|
|
||||||
if ((res= open_and_lock_tables(thd, table_list)))
|
if (!converted && (res= open_and_lock_tables(thd, table_list)))
|
||||||
DBUG_RETURN(res);
|
DBUG_RETURN(res);
|
||||||
|
|
||||||
if ((res= mysql_multi_update_prepare(thd)))
|
if ((res= mysql_multi_update_prepare(thd)))
|
||||||
DBUG_RETURN(res);
|
DBUG_RETURN(res);
|
||||||
|
|
||||||
if (!(result= new multi_update(thd, table_list, fields, values,
|
if (!(result= new multi_update(thd, table_list,
|
||||||
|
thd->lex->select_lex.leaf_tables,
|
||||||
|
fields, values,
|
||||||
handle_duplicates)))
|
handle_duplicates)))
|
||||||
DBUG_RETURN(-1);
|
DBUG_RETURN(-1);
|
||||||
|
|
||||||
@ -701,12 +759,14 @@ int mysql_multi_update(THD *thd,
|
|||||||
|
|
||||||
|
|
||||||
multi_update::multi_update(THD *thd_arg, TABLE_LIST *table_list,
|
multi_update::multi_update(THD *thd_arg, TABLE_LIST *table_list,
|
||||||
|
TABLE_LIST *leaves_list,
|
||||||
List<Item> *field_list, List<Item> *value_list,
|
List<Item> *field_list, List<Item> *value_list,
|
||||||
enum enum_duplicates handle_duplicates_arg)
|
enum enum_duplicates handle_duplicates_arg)
|
||||||
:all_tables(table_list), update_tables(0), thd(thd_arg), tmp_tables(0),
|
:all_tables(table_list), leaves(leaves_list), update_tables(0),
|
||||||
updated(0), found(0), fields(field_list), values(value_list),
|
thd(thd_arg), tmp_tables(0), updated(0), found(0), fields(field_list),
|
||||||
table_count(0), copy_field(0), handle_duplicates(handle_duplicates_arg),
|
values(value_list), table_count(0), copy_field(0),
|
||||||
do_update(1), trans_safe(0), transactional_tables(1)
|
handle_duplicates(handle_duplicates_arg), do_update(1), trans_safe(0),
|
||||||
|
transactional_tables(1)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
|
||||||
@ -754,8 +814,9 @@ int multi_update::prepare(List<Item> ¬_used_values,
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
update.empty();
|
update.empty();
|
||||||
for (table_ref= all_tables; table_ref; table_ref= table_ref->next_local)
|
for (table_ref= leaves; table_ref; table_ref= table_ref->next_leaf)
|
||||||
{
|
{
|
||||||
|
/* TODO: add support of view of join support */
|
||||||
TABLE *table=table_ref->table;
|
TABLE *table=table_ref->table;
|
||||||
if (tables_to_update & table->map)
|
if (tables_to_update & table->map)
|
||||||
{
|
{
|
||||||
@ -823,7 +884,7 @@ int multi_update::prepare(List<Item> ¬_used_values,
|
|||||||
which will cause an error when reading a row.
|
which will cause an error when reading a row.
|
||||||
(This issue is mostly relevent for MyISAM tables)
|
(This issue is mostly relevent for MyISAM tables)
|
||||||
*/
|
*/
|
||||||
for (table_ref= all_tables; table_ref; table_ref= table_ref->next_local)
|
for (table_ref= leaves; table_ref; table_ref= table_ref->next_leaf)
|
||||||
{
|
{
|
||||||
TABLE *table=table_ref->table;
|
TABLE *table=table_ref->table;
|
||||||
if (!(tables_to_update & table->map) &&
|
if (!(tables_to_update & table->map) &&
|
||||||
|
@ -461,8 +461,17 @@ static int mysql_register_view(THD *thd, TABLE_LIST *view,
|
|||||||
view->updatable_view= 0;
|
view->updatable_view= 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
for (TABLE_LIST *up= tbl; up; up= up->embedding)
|
||||||
|
{
|
||||||
|
if (up->outer_join)
|
||||||
|
{
|
||||||
|
view->updatable_view= 0;
|
||||||
|
goto loop_out;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
loop_out:
|
||||||
|
|
||||||
if (view->with_check != VIEW_CHECK_NONE &&
|
if (view->with_check != VIEW_CHECK_NONE &&
|
||||||
!view->updatable_view)
|
!view->updatable_view)
|
||||||
@ -510,6 +519,7 @@ mysql_make_view(File_parser *parser, TABLE_LIST *table)
|
|||||||
SELECT_LEX *end;
|
SELECT_LEX *end;
|
||||||
THD *thd= current_thd;
|
THD *thd= current_thd;
|
||||||
LEX *old_lex= thd->lex, *lex;
|
LEX *old_lex= thd->lex, *lex;
|
||||||
|
SELECT_LEX *view_select;
|
||||||
int res= 0;
|
int res= 0;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -552,7 +562,8 @@ mysql_make_view(File_parser *parser, TABLE_LIST *table)
|
|||||||
*/
|
*/
|
||||||
table->view= lex= thd->lex= (LEX*) new(&thd->mem_root) st_lex_local;
|
table->view= lex= thd->lex= (LEX*) new(&thd->mem_root) st_lex_local;
|
||||||
mysql_init_query(thd, (uchar*)table->query.str, table->query.length, TRUE);
|
mysql_init_query(thd, (uchar*)table->query.str, table->query.length, TRUE);
|
||||||
lex->select_lex.select_number= ++thd->select_number;
|
view_select= &lex->select_lex;
|
||||||
|
view_select->select_number= ++thd->select_number;
|
||||||
old_lex->derived_tables|= DERIVED_VIEW;
|
old_lex->derived_tables|= DERIVED_VIEW;
|
||||||
{
|
{
|
||||||
ulong options= thd->options;
|
ulong options= thd->options;
|
||||||
@ -595,6 +606,7 @@ mysql_make_view(File_parser *parser, TABLE_LIST *table)
|
|||||||
table);
|
table);
|
||||||
TABLE_LIST *view_tables= lex->query_tables;
|
TABLE_LIST *view_tables= lex->query_tables;
|
||||||
TABLE_LIST *view_tables_tail= 0;
|
TABLE_LIST *view_tables_tail= 0;
|
||||||
|
TABLE_LIST *tbl;
|
||||||
|
|
||||||
if (lex->spfuns.records)
|
if (lex->spfuns.records)
|
||||||
{
|
{
|
||||||
@ -653,7 +665,7 @@ mysql_make_view(File_parser *parser, TABLE_LIST *table)
|
|||||||
old_lex->safe_to_cache_query= (old_lex->safe_to_cache_query &&
|
old_lex->safe_to_cache_query= (old_lex->safe_to_cache_query &&
|
||||||
lex->safe_to_cache_query);
|
lex->safe_to_cache_query);
|
||||||
/* move SQL_CACHE to whole query */
|
/* move SQL_CACHE to whole query */
|
||||||
if (lex->select_lex.options & OPTION_TO_QUERY_CACHE)
|
if (view_select->options & OPTION_TO_QUERY_CACHE)
|
||||||
old_lex->select_lex.options|= OPTION_TO_QUERY_CACHE;
|
old_lex->select_lex.options|= OPTION_TO_QUERY_CACHE;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -691,9 +703,6 @@ mysql_make_view(File_parser *parser, TABLE_LIST *table)
|
|||||||
old_lex->can_use_merged()) &&
|
old_lex->can_use_merged()) &&
|
||||||
!old_lex->can_not_use_merged())
|
!old_lex->can_not_use_merged())
|
||||||
{
|
{
|
||||||
/*
|
|
||||||
TODO: support multi tables substitutions
|
|
||||||
*/
|
|
||||||
/* lex should contain at least one table */
|
/* lex should contain at least one table */
|
||||||
DBUG_ASSERT(view_tables != 0);
|
DBUG_ASSERT(view_tables != 0);
|
||||||
|
|
||||||
@ -702,20 +711,50 @@ mysql_make_view(File_parser *parser, TABLE_LIST *table)
|
|||||||
table->updatable= (table->updatable_view != 0);
|
table->updatable= (table->updatable_view != 0);
|
||||||
|
|
||||||
table->ancestor= view_tables;
|
table->ancestor= view_tables;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
next table should include SELECT_LEX under this table SELECT_LEX
|
next table should include SELECT_LEX under this table SELECT_LEX
|
||||||
|
|
||||||
TODO: ehere should be loop for multi tables substitution
|
|
||||||
*/
|
*/
|
||||||
table->ancestor->select_lex= table->select_lex;
|
table->ancestor->select_lex= table->select_lex;
|
||||||
|
|
||||||
|
/*
|
||||||
|
Process upper level tables of view. As far as we do noy suport union
|
||||||
|
here we can go through local tables of view most upper SELECT
|
||||||
|
*/
|
||||||
|
for(tbl= (TABLE_LIST*)view_select->table_list.first;
|
||||||
|
tbl;
|
||||||
|
tbl= tbl->next_local)
|
||||||
|
{
|
||||||
/*
|
/*
|
||||||
move lock type (TODO: should we issue error in case of TMPTABLE
|
move lock type (TODO: should we issue error in case of TMPTABLE
|
||||||
algorithm and non-read locking)?
|
algorithm and non-read locking)?
|
||||||
*/
|
*/
|
||||||
view_tables->lock_type= table->lock_type;
|
tbl->lock_type= table->lock_type;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* multi table view */
|
||||||
|
if (view_tables->next_local)
|
||||||
|
{
|
||||||
|
/* make nested join structure for view tables */
|
||||||
|
NESTED_JOIN *nested_join;
|
||||||
|
if (!(nested_join= table->nested_join=
|
||||||
|
(NESTED_JOIN *) thd->calloc(sizeof(NESTED_JOIN))))
|
||||||
|
goto err;
|
||||||
|
nested_join->join_list= view_select->top_join_list;
|
||||||
|
|
||||||
|
/* re-nest tables of VIEW */
|
||||||
|
{
|
||||||
|
List_iterator_fast<TABLE_LIST> ti(nested_join->join_list);
|
||||||
|
while(tbl= ti++)
|
||||||
|
{
|
||||||
|
tbl->join_list= &nested_join->join_list;
|
||||||
|
tbl->embedding= table;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Store WHERE clause for postprocessing in setup_ancestor */
|
/* Store WHERE clause for postprocessing in setup_ancestor */
|
||||||
table->where= lex->select_lex.where;
|
table->where= view_select->where;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
This SELECT_LEX will be linked in global SELECT_LEX list
|
This SELECT_LEX will be linked in global SELECT_LEX list
|
||||||
@ -728,13 +767,13 @@ mysql_make_view(File_parser *parser, TABLE_LIST *table)
|
|||||||
|
|
||||||
table->effective_algorithm= VIEW_ALGORITHM_TMPTABLE;
|
table->effective_algorithm= VIEW_ALGORITHM_TMPTABLE;
|
||||||
DBUG_PRINT("info", ("algorithm: TEMPORARY TABLE"));
|
DBUG_PRINT("info", ("algorithm: TEMPORARY TABLE"));
|
||||||
lex->select_lex.linkage= DERIVED_TABLE_TYPE;
|
view_select->linkage= DERIVED_TABLE_TYPE;
|
||||||
table->updatable= 0;
|
table->updatable= 0;
|
||||||
table->with_check= VIEW_CHECK_NONE;
|
table->with_check= VIEW_CHECK_NONE;
|
||||||
|
|
||||||
/* SELECT tree link */
|
/* SELECT tree link */
|
||||||
lex->unit.include_down(table->select_lex);
|
lex->unit.include_down(table->select_lex);
|
||||||
lex->unit.slave= &lex->select_lex; // fix include_down initialisation
|
lex->unit.slave= view_select; // fix include_down initialisation
|
||||||
|
|
||||||
table->derived= &lex->unit;
|
table->derived= &lex->unit;
|
||||||
}
|
}
|
||||||
@ -745,7 +784,7 @@ ok:
|
|||||||
if (arena)
|
if (arena)
|
||||||
thd->restore_backup_item_arena(arena, &backup);
|
thd->restore_backup_item_arena(arena, &backup);
|
||||||
/* global SELECT list linking */
|
/* global SELECT list linking */
|
||||||
end= &lex->select_lex; // primary SELECT_LEX is always last
|
end= view_select; // primary SELECT_LEX is always last
|
||||||
end->link_next= old_lex->all_selects_list;
|
end->link_next= old_lex->all_selects_list;
|
||||||
old_lex->all_selects_list->link_prev= &end->link_next;
|
old_lex->all_selects_list->link_prev= &end->link_next;
|
||||||
old_lex->all_selects_list= lex->all_selects_list;
|
old_lex->all_selects_list= lex->all_selects_list;
|
||||||
@ -874,19 +913,21 @@ frm_type_enum mysql_frm_type(char *path)
|
|||||||
bool check_key_in_view(THD *thd, TABLE_LIST *view)
|
bool check_key_in_view(THD *thd, TABLE_LIST *view)
|
||||||
{
|
{
|
||||||
TABLE *table;
|
TABLE *table;
|
||||||
Item **trans;
|
Field_translator *trans;
|
||||||
KEY *key_info, *key_info_end;
|
KEY *key_info, *key_info_end;
|
||||||
uint i, elements_in_view;
|
uint i, elements_in_view;
|
||||||
DBUG_ENTER("check_key_in_view");
|
DBUG_ENTER("check_key_in_view");
|
||||||
|
|
||||||
if (!view->view)
|
if (!view->view && !view->belong_to_view)
|
||||||
DBUG_RETURN(FALSE); /* it is normal table */
|
DBUG_RETURN(FALSE); /* it is normal table */
|
||||||
table= view->table;
|
table= view->table;
|
||||||
|
if (view->belong_to_view)
|
||||||
|
view= view->belong_to_view;
|
||||||
trans= view->field_translation;
|
trans= view->field_translation;
|
||||||
key_info_end= (key_info= table->key_info)+ table->keys;
|
key_info_end= (key_info= table->key_info)+ table->keys;
|
||||||
|
|
||||||
elements_in_view= view->view->select_lex.item_list.elements;
|
elements_in_view= view->view->select_lex.item_list.elements;
|
||||||
DBUG_ASSERT(view->table != 0 && view->field_translation != 0);
|
DBUG_ASSERT(table != 0 && view->field_translation != 0);
|
||||||
|
|
||||||
/* Loop over all keys to see if a unique-not-null key is used */
|
/* Loop over all keys to see if a unique-not-null key is used */
|
||||||
for (;key_info != key_info_end ; key_info++)
|
for (;key_info != key_info_end ; key_info++)
|
||||||
@ -903,7 +944,7 @@ bool check_key_in_view(THD *thd, TABLE_LIST *view)
|
|||||||
for (k= 0; k < elements_in_view; k++)
|
for (k= 0; k < elements_in_view; k++)
|
||||||
{
|
{
|
||||||
Item_field *field;
|
Item_field *field;
|
||||||
if ((field= trans[k]->filed_for_view_update()) &&
|
if ((field= trans[k].item->filed_for_view_update()) &&
|
||||||
field->field == key_part->field)
|
field->field == key_part->field)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -924,7 +965,7 @@ bool check_key_in_view(THD *thd, TABLE_LIST *view)
|
|||||||
for (i= 0; i < elements_in_view; i++)
|
for (i= 0; i < elements_in_view; i++)
|
||||||
{
|
{
|
||||||
Item_field *field;
|
Item_field *field;
|
||||||
if ((field= trans[i]->filed_for_view_update()) &&
|
if ((field= trans[i].item->filed_for_view_update()) &&
|
||||||
field->field == *field_ptr)
|
field->field == *field_ptr)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -964,22 +1005,31 @@ bool check_key_in_view(THD *thd, TABLE_LIST *view)
|
|||||||
insert_view_fields()
|
insert_view_fields()
|
||||||
list list for insertion
|
list list for insertion
|
||||||
view view for processing
|
view view for processing
|
||||||
|
|
||||||
|
RETURN
|
||||||
|
0 - OK
|
||||||
|
-1 - error (is not sent to cliet)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void insert_view_fields(List<Item> *list, TABLE_LIST *view)
|
int insert_view_fields(List<Item> *list, TABLE_LIST *view)
|
||||||
{
|
{
|
||||||
uint elements_in_view= view->view->select_lex.item_list.elements;
|
uint elements_in_view= view->view->select_lex.item_list.elements;
|
||||||
Item **trans;
|
Field_translator *trans;
|
||||||
DBUG_ENTER("insert_view_fields");
|
DBUG_ENTER("insert_view_fields");
|
||||||
|
|
||||||
if (!(trans= view->field_translation))
|
if (!(trans= view->field_translation))
|
||||||
DBUG_VOID_RETURN;
|
DBUG_RETURN(0);
|
||||||
|
|
||||||
for (uint i= 0; i < elements_in_view; i++)
|
for (uint i= 0; i < elements_in_view; i++)
|
||||||
{
|
{
|
||||||
Item_field *fld;
|
Item_field *fld;
|
||||||
if ((fld= trans[i]->filed_for_view_update()))
|
if ((fld= trans[i].item->filed_for_view_update()))
|
||||||
list->push_back(fld);
|
list->push_back(fld);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
my_error(ER_NON_UPDATABLE_TABLE, MYF(0), view->alias, "INSERT");
|
||||||
|
DBUG_RETURN(-1);
|
||||||
}
|
}
|
||||||
DBUG_VOID_RETURN;
|
}
|
||||||
|
DBUG_RETURN(0);
|
||||||
}
|
}
|
||||||
|
@ -25,7 +25,7 @@ int mysql_drop_view(THD *thd, TABLE_LIST *view, enum_drop_mode drop_mode);
|
|||||||
|
|
||||||
bool check_key_in_view(THD *thd, TABLE_LIST * view);
|
bool check_key_in_view(THD *thd, TABLE_LIST * view);
|
||||||
|
|
||||||
void insert_view_fields(List<Item> *list, TABLE_LIST *view);
|
int insert_view_fields(List<Item> *list, TABLE_LIST *view);
|
||||||
|
|
||||||
frm_type_enum mysql_frm_type(char *path);
|
frm_type_enum mysql_frm_type(char *path);
|
||||||
|
|
||||||
|
225
sql/table.cc
225
sql/table.cc
@ -1485,10 +1485,65 @@ void st_table_list::calc_md5(char *buffer)
|
|||||||
|
|
||||||
void st_table_list::set_ancestor()
|
void st_table_list::set_ancestor()
|
||||||
{
|
{
|
||||||
if (ancestor->ancestor)
|
/* process all tables of view */
|
||||||
|
for (TABLE_LIST *tbl= ancestor; tbl; tbl= tbl->next_local)
|
||||||
|
{
|
||||||
|
if (tbl->ancestor)
|
||||||
ancestor->set_ancestor();
|
ancestor->set_ancestor();
|
||||||
|
tbl->table->grant= grant;
|
||||||
|
}
|
||||||
|
/* if view contain only one table, substitute TABLE of it */
|
||||||
|
if (!ancestor->next_local)
|
||||||
table= ancestor->table;
|
table= ancestor->table;
|
||||||
ancestor->table->grant= grant;
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Save old want_privilege and clear want_privilege
|
||||||
|
|
||||||
|
SYNOPSIS
|
||||||
|
save_and_clear_want_privilege()
|
||||||
|
*/
|
||||||
|
|
||||||
|
void st_table_list::save_and_clear_want_privilege()
|
||||||
|
{
|
||||||
|
for (TABLE_LIST *tbl= ancestor; tbl; tbl= tbl->next_local)
|
||||||
|
{
|
||||||
|
if (tbl->table)
|
||||||
|
{
|
||||||
|
privilege_backup= tbl->table->grant.want_privilege;
|
||||||
|
tbl->table->grant.want_privilege= 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DBUG_ASSERT(tbl->view && tbl->ancestor &&
|
||||||
|
tbl->ancestor->next_local);
|
||||||
|
tbl->save_and_clear_want_privilege();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
restore want_privilege saved by save_and_clear_want_privilege
|
||||||
|
|
||||||
|
SYNOPSIS
|
||||||
|
restore_want_privilege()
|
||||||
|
*/
|
||||||
|
|
||||||
|
void st_table_list::restore_want_privilege()
|
||||||
|
{
|
||||||
|
for (TABLE_LIST *tbl= ancestor; tbl; tbl= tbl->next_local)
|
||||||
|
{
|
||||||
|
if (tbl->table)
|
||||||
|
tbl->table->grant.want_privilege= privilege_backup;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DBUG_ASSERT(tbl->view && tbl->ancestor &&
|
||||||
|
tbl->ancestor->next_local);
|
||||||
|
tbl->restore_want_privilege();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1513,10 +1568,11 @@ void st_table_list::set_ancestor()
|
|||||||
|
|
||||||
bool st_table_list::setup_ancestor(THD *thd, Item **conds)
|
bool st_table_list::setup_ancestor(THD *thd, Item **conds)
|
||||||
{
|
{
|
||||||
Item **transl;
|
Field_translator *transl;
|
||||||
SELECT_LEX *select= &view->select_lex;
|
SELECT_LEX *select= &view->select_lex;
|
||||||
SELECT_LEX *current_select_save= thd->lex->current_select;
|
SELECT_LEX *current_select_save= thd->lex->current_select;
|
||||||
Item *item;
|
Item *item;
|
||||||
|
TABLE_LIST *tbl;
|
||||||
List_iterator_fast<Item> it(select->item_list);
|
List_iterator_fast<Item> it(select->item_list);
|
||||||
uint i= 0;
|
uint i= 0;
|
||||||
bool save_set_query_id= thd->set_query_id;
|
bool save_set_query_id= thd->set_query_id;
|
||||||
@ -1524,35 +1580,53 @@ bool st_table_list::setup_ancestor(THD *thd, Item **conds)
|
|||||||
bool save_allow_sum_func= thd->allow_sum_func;
|
bool save_allow_sum_func= thd->allow_sum_func;
|
||||||
DBUG_ENTER("st_table_list::setup_ancestor");
|
DBUG_ENTER("st_table_list::setup_ancestor");
|
||||||
|
|
||||||
if (ancestor->ancestor &&
|
for (tbl= ancestor; tbl; tbl= tbl->next_local)
|
||||||
ancestor->setup_ancestor(thd, conds))
|
{
|
||||||
|
if (tbl->ancestor && tbl->setup_ancestor(thd, conds))
|
||||||
DBUG_RETURN(1);
|
DBUG_RETURN(1);
|
||||||
|
}
|
||||||
|
|
||||||
if (field_translation)
|
if (field_translation)
|
||||||
{
|
{
|
||||||
/* prevent look up in SELECTs tree */
|
/* prevent look up in SELECTs tree */
|
||||||
thd->lex->current_select= &thd->lex->select_lex;
|
thd->lex->current_select= &thd->lex->select_lex;
|
||||||
|
thd->lex->select_lex.no_wrap_view_item= 1;
|
||||||
thd->set_query_id= 1;
|
thd->set_query_id= 1;
|
||||||
/* this view was prepared already on previous PS/SP execution */
|
/* this view was prepared already on previous PS/SP execution */
|
||||||
Item **end= field_translation + select->item_list.elements;
|
Field_translator *end= field_translation + select->item_list.elements;
|
||||||
for (Item **item= field_translation; item < end; item++)
|
|
||||||
{
|
|
||||||
/* TODO: fix for several tables in VIEW */
|
|
||||||
uint want_privilege= ancestor->table->grant.want_privilege;
|
|
||||||
/* real rights will be checked in VIEW field */
|
/* real rights will be checked in VIEW field */
|
||||||
ancestor->table->grant.want_privilege= 0;
|
save_and_clear_want_privilege();
|
||||||
/* aggregate function are allowed */
|
/* aggregate function are allowed */
|
||||||
thd->allow_sum_func= 1;
|
thd->allow_sum_func= 1;
|
||||||
if (!(*item)->fixed && (*item)->fix_fields(thd, ancestor, item))
|
for (transl= field_translation; transl < end; transl++)
|
||||||
|
{
|
||||||
|
if (!transl->item->fixed &&
|
||||||
|
transl->item->fix_fields(thd, ancestor, &transl->item))
|
||||||
goto err;
|
goto err;
|
||||||
ancestor->table->grant.want_privilege= want_privilege;
|
}
|
||||||
|
for (tbl= ancestor; tbl; tbl= tbl->next_local)
|
||||||
|
{
|
||||||
|
if (tbl->on_expr && !tbl->on_expr->fixed &&
|
||||||
|
tbl->on_expr->fix_fields(thd, ancestor, &tbl->on_expr))
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
if (where && !where->fixed && where->fix_fields(thd, ancestor, &where))
|
||||||
|
goto err;
|
||||||
|
restore_want_privilege();
|
||||||
|
|
||||||
|
/* WHERE/ON resolved => we can rename fields */
|
||||||
|
for (transl= field_translation; transl < end; transl++)
|
||||||
|
{
|
||||||
|
transl->item->rename((char *)transl->name);
|
||||||
}
|
}
|
||||||
goto ok;
|
goto ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* view fields translation table */
|
/* view fields translation table */
|
||||||
if (!(transl=
|
if (!(transl=
|
||||||
(Item**)(thd->current_arena->alloc(select->item_list.elements * sizeof(Item*)))))
|
(Field_translator*)(thd->current_arena->
|
||||||
|
alloc(select->item_list.elements *
|
||||||
|
sizeof(Field_translator)))))
|
||||||
{
|
{
|
||||||
DBUG_RETURN(1);
|
DBUG_RETURN(1);
|
||||||
}
|
}
|
||||||
@ -1568,22 +1642,29 @@ bool st_table_list::setup_ancestor(THD *thd, Item **conds)
|
|||||||
used fields correctly.
|
used fields correctly.
|
||||||
*/
|
*/
|
||||||
thd->set_query_id= 1;
|
thd->set_query_id= 1;
|
||||||
while ((item= it++))
|
|
||||||
{
|
|
||||||
/* TODO: fix for several tables in VIEW */
|
|
||||||
uint want_privilege= ancestor->table->grant.want_privilege;
|
|
||||||
/* real rights will be checked in VIEW field */
|
/* real rights will be checked in VIEW field */
|
||||||
ancestor->table->grant.want_privilege= 0;
|
save_and_clear_want_privilege();
|
||||||
/* aggregate function are allowed */
|
/* aggregate function are allowed */
|
||||||
thd->allow_sum_func= 1;
|
thd->allow_sum_func= 1;
|
||||||
|
while ((item= it++))
|
||||||
|
{
|
||||||
|
/* save original name of view column */
|
||||||
|
char *name= item->name;
|
||||||
if (!item->fixed && item->fix_fields(thd, ancestor, &item))
|
if (!item->fixed && item->fix_fields(thd, ancestor, &item))
|
||||||
goto err;
|
goto err;
|
||||||
ancestor->table->grant.want_privilege= want_privilege;
|
/* set new item get in fix fields and original column name */
|
||||||
transl[i++]= item;
|
transl[i].name= name;
|
||||||
|
transl[i++].item= item;
|
||||||
}
|
}
|
||||||
field_translation= transl;
|
field_translation= transl;
|
||||||
/* TODO: sort this list? Use hash for big number of fields */
|
/* TODO: sort this list? Use hash for big number of fields */
|
||||||
|
|
||||||
|
for (tbl= ancestor; tbl; tbl= tbl->next_local)
|
||||||
|
{
|
||||||
|
if (tbl->on_expr && !tbl->on_expr->fixed &&
|
||||||
|
tbl->on_expr->fix_fields(thd, ancestor, &tbl->on_expr))
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
if (where)
|
if (where)
|
||||||
{
|
{
|
||||||
Item_arena *arena= thd->current_arena, backup;
|
Item_arena *arena= thd->current_arena, backup;
|
||||||
@ -1653,6 +1734,8 @@ bool st_table_list::setup_ancestor(THD *thd, Item **conds)
|
|||||||
if (arena)
|
if (arena)
|
||||||
thd->restore_backup_item_arena(arena, &backup);
|
thd->restore_backup_item_arena(arena, &backup);
|
||||||
}
|
}
|
||||||
|
restore_want_privilege();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
fix_fields do not need tables, because new are only AND operation and we
|
fix_fields do not need tables, because new are only AND operation and we
|
||||||
just need recollect statistics
|
just need recollect statistics
|
||||||
@ -1661,6 +1744,15 @@ bool st_table_list::setup_ancestor(THD *thd, Item **conds)
|
|||||||
check_option->fix_fields(thd, 0, &check_option))
|
check_option->fix_fields(thd, 0, &check_option))
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
|
/* WHERE/ON resolved => we can rename fields */
|
||||||
|
{
|
||||||
|
Field_translator *end= field_translation + select->item_list.elements;
|
||||||
|
for (transl= field_translation; transl < end; transl++)
|
||||||
|
{
|
||||||
|
transl->item->rename((char *)transl->name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* full text function moving to current select */
|
/* full text function moving to current select */
|
||||||
if (view->select_lex.ftfunc_list->elements)
|
if (view->select_lex.ftfunc_list->elements)
|
||||||
{
|
{
|
||||||
@ -1727,6 +1819,95 @@ int st_table_list::view_check_option(THD *thd, bool ignore_failure)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Find table in underlaying tables by mask and check that only this
|
||||||
|
table sbelong to given mask
|
||||||
|
|
||||||
|
SYNOPSIS
|
||||||
|
st_table_list::check_single_table()
|
||||||
|
table reference on variable where to store found table
|
||||||
|
(should be 0 on call, to find table, or point to table for
|
||||||
|
unique test)
|
||||||
|
map bit mask of tables
|
||||||
|
|
||||||
|
RETURN
|
||||||
|
0 table not found or found only one
|
||||||
|
1 found several tables
|
||||||
|
*/
|
||||||
|
|
||||||
|
bool st_table_list::check_single_table(st_table_list **table, table_map map)
|
||||||
|
{
|
||||||
|
for (TABLE_LIST *tbl= ancestor; tbl; tbl= tbl->next_local)
|
||||||
|
{
|
||||||
|
if (tbl->table)
|
||||||
|
{
|
||||||
|
if (tbl->table->map & map)
|
||||||
|
{
|
||||||
|
if (*table)
|
||||||
|
return 1;
|
||||||
|
else
|
||||||
|
*table= tbl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if (tbl->check_single_table(table, map))
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Set insert_values buffer
|
||||||
|
|
||||||
|
SYNOPSIS
|
||||||
|
set_insert_values()
|
||||||
|
mem_root memory pool for allocating
|
||||||
|
|
||||||
|
RETURN
|
||||||
|
FALSE - OK
|
||||||
|
TRUE - out of memory
|
||||||
|
*/
|
||||||
|
|
||||||
|
bool st_table_list::set_insert_values(MEM_ROOT *mem_root)
|
||||||
|
{
|
||||||
|
if (table)
|
||||||
|
{
|
||||||
|
if (!table->insert_values &&
|
||||||
|
!(table->insert_values= (byte *)alloc_root(mem_root,
|
||||||
|
table->rec_buff_length)))
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DBUG_ASSERT(view && ancestor && ancestor->next_local);
|
||||||
|
for (TABLE_LIST *tbl= ancestor; tbl; tbl= tbl->next_local)
|
||||||
|
if (tbl->set_insert_values(mem_root))
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
clear insert_values reference
|
||||||
|
|
||||||
|
SYNOPSIS
|
||||||
|
clear_insert_values()
|
||||||
|
*/
|
||||||
|
|
||||||
|
void st_table_list::clear_insert_values()
|
||||||
|
{
|
||||||
|
if (table)
|
||||||
|
table->insert_values= 0;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DBUG_ASSERT(view && ancestor && ancestor->next_local);
|
||||||
|
for (TABLE_LIST *tbl= ancestor; tbl; tbl= tbl->next_local)
|
||||||
|
tbl->clear_insert_values();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void Field_iterator_view::set(TABLE_LIST *table)
|
void Field_iterator_view::set(TABLE_LIST *table)
|
||||||
{
|
{
|
||||||
ptr= table->field_translation;
|
ptr= table->field_translation;
|
||||||
@ -1748,7 +1929,7 @@ Item *Field_iterator_table::item(THD *thd)
|
|||||||
|
|
||||||
const char *Field_iterator_view::name()
|
const char *Field_iterator_view::name()
|
||||||
{
|
{
|
||||||
return (*ptr)->name;
|
return ptr->name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
21
sql/table.h
21
sql/table.h
@ -200,6 +200,13 @@ struct st_table {
|
|||||||
|
|
||||||
struct st_lex;
|
struct st_lex;
|
||||||
|
|
||||||
|
|
||||||
|
struct Field_translator
|
||||||
|
{
|
||||||
|
Item *item;
|
||||||
|
const char *name;
|
||||||
|
};
|
||||||
|
|
||||||
typedef struct st_table_list
|
typedef struct st_table_list
|
||||||
{
|
{
|
||||||
/* link in a local table list (used by SQL_LIST) */
|
/* link in a local table list (used by SQL_LIST) */
|
||||||
@ -225,13 +232,15 @@ typedef struct st_table_list
|
|||||||
/* link to select_lex where this table was used */
|
/* link to select_lex where this table was used */
|
||||||
st_select_lex *select_lex;
|
st_select_lex *select_lex;
|
||||||
st_lex *view; /* link on VIEW lex for merging */
|
st_lex *view; /* link on VIEW lex for merging */
|
||||||
Item **field_translation; /* array of VIEW fields */
|
Field_translator *field_translation; /* array of VIEW fields */
|
||||||
/* ancestor of this table (VIEW merge algorithm) */
|
/* ancestor of this table (VIEW merge algorithm) */
|
||||||
st_table_list *ancestor;
|
st_table_list *ancestor;
|
||||||
/* most upper view this table belongs to */
|
/* most upper view this table belongs to */
|
||||||
st_table_list *belong_to_view;
|
st_table_list *belong_to_view;
|
||||||
/* next_global before adding VIEW tables */
|
/* next_global before adding VIEW tables */
|
||||||
st_table_list *old_next;
|
st_table_list *old_next;
|
||||||
|
/* list of join table tree leaves */
|
||||||
|
st_table_list *next_leaf;
|
||||||
Item *where; /* VIEW WHERE clause condition */
|
Item *where; /* VIEW WHERE clause condition */
|
||||||
Item *check_option; /* WITH CHECK OPTION condition */
|
Item *check_option; /* WITH CHECK OPTION condition */
|
||||||
LEX_STRING query; /* text of (CRETE/SELECT) statement */
|
LEX_STRING query; /* text of (CRETE/SELECT) statement */
|
||||||
@ -246,6 +255,7 @@ typedef struct st_table_list
|
|||||||
ulonglong algorithm; /* 0 any, 1 tmp tables , 2 merging */
|
ulonglong algorithm; /* 0 any, 1 tmp tables , 2 merging */
|
||||||
ulonglong with_check; /* WITH CHECK OPTION */
|
ulonglong with_check; /* WITH CHECK OPTION */
|
||||||
uint effective_algorithm; /* which algorithm was really used */
|
uint effective_algorithm; /* which algorithm was really used */
|
||||||
|
uint privilege_backup; /* place for saving privileges */
|
||||||
GRANT_INFO grant;
|
GRANT_INFO grant;
|
||||||
thr_lock_type lock_type;
|
thr_lock_type lock_type;
|
||||||
uint outer_join; /* Which join type */
|
uint outer_join; /* Which join type */
|
||||||
@ -279,6 +289,11 @@ typedef struct st_table_list
|
|||||||
bool setup_ancestor(THD *thd, Item **conds);
|
bool setup_ancestor(THD *thd, Item **conds);
|
||||||
bool placeholder() {return derived || view; }
|
bool placeholder() {return derived || view; }
|
||||||
void print(THD *thd, String *str);
|
void print(THD *thd, String *str);
|
||||||
|
void save_and_clear_want_privilege();
|
||||||
|
void restore_want_privilege();
|
||||||
|
bool check_single_table(st_table_list **table, table_map map);
|
||||||
|
bool set_insert_values(MEM_ROOT *mem_root);
|
||||||
|
void clear_insert_values();
|
||||||
inline st_table_list *next_independent()
|
inline st_table_list *next_independent()
|
||||||
{
|
{
|
||||||
if (view)
|
if (view)
|
||||||
@ -319,14 +334,14 @@ public:
|
|||||||
|
|
||||||
class Field_iterator_view: public Field_iterator
|
class Field_iterator_view: public Field_iterator
|
||||||
{
|
{
|
||||||
Item **ptr, **array_end;
|
Field_translator *ptr, *array_end;
|
||||||
public:
|
public:
|
||||||
Field_iterator_view() :ptr(0), array_end(0) {}
|
Field_iterator_view() :ptr(0), array_end(0) {}
|
||||||
void set(TABLE_LIST *table);
|
void set(TABLE_LIST *table);
|
||||||
void next() { ptr++; }
|
void next() { ptr++; }
|
||||||
bool end_of_fields() { return ptr == array_end; }
|
bool end_of_fields() { return ptr == array_end; }
|
||||||
const char *name();
|
const char *name();
|
||||||
Item *item(THD *thd) { return *ptr; }
|
Item *item(THD *thd) { return ptr->item; }
|
||||||
Field *field() { return 0; }
|
Field *field() { return 0; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user