mirror of
https://github.com/MariaDB/server.git
synced 2025-12-24 11:21:21 +03:00
MDEV 13679 Enabled sequences to be used in DEFAULT
Other changes done to get this to work: - Added 'internal_tables' to TABLE object to list which sequence tables is needed to use the table. - Mark any expression using DEFAULT() with LEX->default_used. This is needed when deciding if we should open internal sequence tables when a table is opened (we don't need to open sequence tables if the main table is only used with SELECT). - Create_and_open_temporary_table() can now also open all internal sequence tables. - Added option MYSQL_LOCK_USE_MALLOC to mysql_lock_tables() to force memory allocation to be used with malloc instead of memroot. - Added flag to MYSQL_LOCK to remember if allocation was done with malloc or memroot (makes code simpler and safer). - init_one_table_for_prelocking() now takes argument for what lock to use instead of it's a routine or something else. - Renamed prelocking placeholders to make them more understandable as they are now used in more code. - Changed test in check_lock_and_start_stmt() if found table has correct locks. The old test didn't work for tables that has lock TL_WRITE_ALLOW_WRITE, which is what sequence tables are using. - Added VCOL_NOT_VIRTUAL option to ensure that sequence functions can't be used with virtual columns - More sequence tests
This commit is contained in:
171
mysql-test/suite/sql_sequence/default.result
Normal file
171
mysql-test/suite/sql_sequence/default.result
Normal file
@@ -0,0 +1,171 @@
|
||||
drop table if exists t1,s1,s2;
|
||||
Warnings:
|
||||
Note 1051 Unknown table 'test.t1'
|
||||
Note 1051 Unknown table 'test.s1'
|
||||
Note 1051 Unknown table 'test.s2'
|
||||
drop view if exists v1;
|
||||
Warnings:
|
||||
Note 4092 Unknown VIEW: 'test.v1'
|
||||
#
|
||||
# Test DEFAULT
|
||||
#
|
||||
CREATE SEQUENCE s1 nocache engine=myisam;
|
||||
CREATE table t1 (a int default next value for s1, b int);
|
||||
show create table t1;
|
||||
Table Create Table
|
||||
t1 CREATE TABLE `t1` (
|
||||
`a` int(11) DEFAULT nextval(`test`.`s1`),
|
||||
`b` int(11) DEFAULT NULL
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1
|
||||
insert into t1 SET b=1;
|
||||
insert into t1 SET b=2;
|
||||
insert into t1 (b) values (3),(4);
|
||||
select * from t1;
|
||||
a b
|
||||
1 1
|
||||
2 2
|
||||
3 3
|
||||
4 4
|
||||
update t1 set b=5 where a=1;
|
||||
delete from t1 where b=1;
|
||||
select * from t1;
|
||||
a b
|
||||
1 5
|
||||
2 2
|
||||
3 3
|
||||
4 4
|
||||
#
|
||||
# Executing DEFAULT function
|
||||
#
|
||||
INSERT into t1 values(default(a),10);
|
||||
INSERT into t1 values(default(a),default(a));
|
||||
update t1 set a=default(a), b=12 where b=2;
|
||||
select * from t1;
|
||||
a b
|
||||
1 5
|
||||
8 12
|
||||
3 3
|
||||
4 4
|
||||
5 10
|
||||
6 7
|
||||
select default(a), a, b from t1;
|
||||
default(a) a b
|
||||
9 1 5
|
||||
10 8 12
|
||||
11 3 3
|
||||
12 4 4
|
||||
13 5 10
|
||||
14 6 7
|
||||
select * from s1;
|
||||
next_not_cached_value minimum_value maximum_value start_value increment cache_size cycle_option cycle_count
|
||||
15 1 9223372036854775806 1 1 0 0 0
|
||||
select * from t1 where default(a) > 0;
|
||||
a b
|
||||
1 5
|
||||
8 12
|
||||
3 3
|
||||
4 4
|
||||
5 10
|
||||
6 7
|
||||
select * from s1;
|
||||
next_not_cached_value minimum_value maximum_value start_value increment cache_size cycle_option cycle_count
|
||||
16 1 9223372036854775806 1 1 0 0 0
|
||||
#
|
||||
# View
|
||||
#
|
||||
create view v1 as select * from t1;
|
||||
insert into v1 set b=20;
|
||||
select * from v1;
|
||||
a b
|
||||
1 5
|
||||
8 12
|
||||
3 3
|
||||
4 4
|
||||
5 10
|
||||
6 7
|
||||
16 20
|
||||
drop view v1;
|
||||
#
|
||||
# Alter table
|
||||
#
|
||||
CREATE SEQUENCE s2 nocache engine=myisam;
|
||||
alter table t1 add column c int default next value for s2, add column d int default previous value for s2;
|
||||
show create table t1;
|
||||
Table Create Table
|
||||
t1 CREATE TABLE `t1` (
|
||||
`a` int(11) DEFAULT nextval(`test`.`s1`),
|
||||
`b` int(11) DEFAULT NULL,
|
||||
`c` int(11) DEFAULT nextval(`test`.`s2`),
|
||||
`d` int(11) DEFAULT lastval(`test`.`s2`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1
|
||||
select * from t1;
|
||||
a b c d
|
||||
1 5 1 1
|
||||
8 12 2 2
|
||||
3 3 3 3
|
||||
4 4 4 4
|
||||
5 10 5 5
|
||||
6 7 6 6
|
||||
16 20 7 7
|
||||
drop sequence s2;
|
||||
show create table t1;
|
||||
Table Create Table
|
||||
t1 CREATE TABLE `t1` (
|
||||
`a` int(11) DEFAULT nextval(`test`.`s1`),
|
||||
`b` int(11) DEFAULT NULL,
|
||||
`c` int(11) DEFAULT nextval(`test`.`s2`),
|
||||
`d` int(11) DEFAULT lastval(`test`.`s2`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1
|
||||
drop table t1;
|
||||
drop sequence s1;
|
||||
#
|
||||
# LOCK TABLES
|
||||
#
|
||||
CREATE SEQUENCE s1 nocache engine=myisam;
|
||||
CREATE table t1 (a int default next value for s1, b int);
|
||||
insert into t1 (b) values (3),(4);
|
||||
LOCK TABLE t1 WRITE;
|
||||
insert into t1 (b) values (5),(6);
|
||||
ERROR HY000: Table 's1' was not locked with LOCK TABLES
|
||||
UNLOCK TABLES;
|
||||
LOCK TABLE t1 WRITE, s1 WRITE;
|
||||
insert into t1 (b) values (5),(6);
|
||||
select default(a) from t1;
|
||||
default(a)
|
||||
5
|
||||
6
|
||||
7
|
||||
8
|
||||
UNLOCK TABLES;
|
||||
LOCK TABLE t1 READ;
|
||||
insert into t1 (b) values (5),(6);
|
||||
ERROR HY000: Table 's1' was not locked with LOCK TABLES
|
||||
select default(a) from t1;
|
||||
ERROR HY000: Table 's1' was not locked with LOCK TABLES
|
||||
UNLOCK TABLES;
|
||||
LOCK TABLE t1 READ, s1 read;
|
||||
insert into t1 (b) values (5),(6);
|
||||
ERROR HY000: Table 't1' was locked with a READ lock and can't be updated
|
||||
select default(a) from t1;
|
||||
ERROR HY000: Table 's1' was locked with a READ lock and can't be updated
|
||||
UNLOCK TABLES;
|
||||
drop table t1;
|
||||
drop sequence s1;
|
||||
#
|
||||
# Wrong usage of default
|
||||
#
|
||||
CREATE table t1 (a int default next value for s1, b int);
|
||||
ERROR 42S02: Table 'test.s1' doesn't exist
|
||||
CREATE SEQUENCE s1 nocache engine=myisam;
|
||||
CREATE table t1 (a int default next value for s1, b int);
|
||||
DROP SEQUENCE s1;
|
||||
insert into t1 (b) values (5),(6);
|
||||
ERROR 42S02: Table 'test.s1' doesn't exist
|
||||
ALTER TABLE t1 add column c int;
|
||||
ERROR 42S02: Table 'test.s1' doesn't exist
|
||||
CREATE SEQUENCE s1 nocache engine=myisam;
|
||||
ALTER TABLE t1 add column c int;
|
||||
ALTER TABLE t1 add column d int default next value for s_not_exits;
|
||||
ERROR 42S02: Table 'test.s_not_exits' doesn't exist
|
||||
drop table t1;
|
||||
drop sequence s1;
|
||||
111
mysql-test/suite/sql_sequence/default.test
Normal file
111
mysql-test/suite/sql_sequence/default.test
Normal file
@@ -0,0 +1,111 @@
|
||||
#
|
||||
# Testing sequence in DEFAULT clause
|
||||
#
|
||||
--source include/have_sequence.inc
|
||||
|
||||
drop table if exists t1,s1,s2;
|
||||
drop view if exists v1;
|
||||
|
||||
--echo #
|
||||
--echo # Test DEFAULT
|
||||
--echo #
|
||||
|
||||
CREATE SEQUENCE s1 nocache engine=myisam;
|
||||
CREATE table t1 (a int default next value for s1, b int);
|
||||
show create table t1;
|
||||
insert into t1 SET b=1;
|
||||
insert into t1 SET b=2;
|
||||
insert into t1 (b) values (3),(4);
|
||||
select * from t1;
|
||||
update t1 set b=5 where a=1;
|
||||
delete from t1 where b=1;
|
||||
select * from t1;
|
||||
|
||||
--echo #
|
||||
--echo # Executing DEFAULT function
|
||||
--echo #
|
||||
|
||||
INSERT into t1 values(default(a),10);
|
||||
INSERT into t1 values(default(a),default(a));
|
||||
update t1 set a=default(a), b=12 where b=2;
|
||||
select * from t1;
|
||||
select default(a), a, b from t1;
|
||||
select * from s1;
|
||||
select * from t1 where default(a) > 0;
|
||||
select * from s1;
|
||||
|
||||
--echo #
|
||||
--echo # View
|
||||
--echo #
|
||||
|
||||
create view v1 as select * from t1;
|
||||
insert into v1 set b=20;
|
||||
select * from v1;
|
||||
drop view v1;
|
||||
|
||||
--echo #
|
||||
--echo # Alter table
|
||||
--echo #
|
||||
|
||||
CREATE SEQUENCE s2 nocache engine=myisam;
|
||||
alter table t1 add column c int default next value for s2, add column d int default previous value for s2;
|
||||
show create table t1;
|
||||
select * from t1;
|
||||
drop sequence s2;
|
||||
show create table t1;
|
||||
drop table t1;
|
||||
drop sequence s1;
|
||||
|
||||
--echo #
|
||||
--echo # LOCK TABLES
|
||||
--echo #
|
||||
|
||||
CREATE SEQUENCE s1 nocache engine=myisam;
|
||||
CREATE table t1 (a int default next value for s1, b int);
|
||||
insert into t1 (b) values (3),(4);
|
||||
LOCK TABLE t1 WRITE;
|
||||
--error ER_TABLE_NOT_LOCKED
|
||||
insert into t1 (b) values (5),(6);
|
||||
UNLOCK TABLES;
|
||||
|
||||
LOCK TABLE t1 WRITE, s1 WRITE;
|
||||
insert into t1 (b) values (5),(6);
|
||||
select default(a) from t1;
|
||||
UNLOCK TABLES;
|
||||
|
||||
LOCK TABLE t1 READ;
|
||||
--error ER_TABLE_NOT_LOCKED
|
||||
insert into t1 (b) values (5),(6);
|
||||
--error ER_TABLE_NOT_LOCKED
|
||||
select default(a) from t1;
|
||||
UNLOCK TABLES;
|
||||
|
||||
LOCK TABLE t1 READ, s1 read;
|
||||
--error ER_TABLE_NOT_LOCKED_FOR_WRITE
|
||||
insert into t1 (b) values (5),(6);
|
||||
--error ER_TABLE_NOT_LOCKED_FOR_WRITE
|
||||
select default(a) from t1;
|
||||
UNLOCK TABLES;
|
||||
|
||||
drop table t1;
|
||||
drop sequence s1;
|
||||
|
||||
--echo #
|
||||
--echo # Wrong usage of default
|
||||
--echo #
|
||||
|
||||
--error ER_NO_SUCH_TABLE
|
||||
CREATE table t1 (a int default next value for s1, b int);
|
||||
CREATE SEQUENCE s1 nocache engine=myisam;
|
||||
CREATE table t1 (a int default next value for s1, b int);
|
||||
DROP SEQUENCE s1;
|
||||
--error ER_NO_SUCH_TABLE
|
||||
insert into t1 (b) values (5),(6);
|
||||
--error ER_NO_SUCH_TABLE
|
||||
ALTER TABLE t1 add column c int;
|
||||
CREATE SEQUENCE s1 nocache engine=myisam;
|
||||
ALTER TABLE t1 add column c int;
|
||||
--error ER_NO_SUCH_TABLE
|
||||
ALTER TABLE t1 add column d int default next value for s_not_exits;
|
||||
drop table t1;
|
||||
drop sequence s1;
|
||||
@@ -162,3 +162,16 @@ select next value for s1;
|
||||
ERROR HY000: Can't execute the query because you have a conflicting read lock
|
||||
unlock tables;
|
||||
drop sequence s1;
|
||||
#
|
||||
# Don't allow SQUENCE to be used with CHECK or virtual fields
|
||||
#
|
||||
CREATE SEQUENCE s1 nocache engine=myisam;
|
||||
CREATE table t1 (a int check (next value for s1 > 0));
|
||||
ERROR HY000: Function or expression 'nextval()' cannot be used in the CHECK clause of `a`
|
||||
CREATE table t1 (a int check (previous value for s1 > 0));
|
||||
ERROR HY000: Function or expression 'lastval()' cannot be used in the CHECK clause of `a`
|
||||
CREATE table t1 (a int check (setval(s1,10)));
|
||||
ERROR HY000: Function or expression 'setval()' cannot be used in the CHECK clause of `a`
|
||||
CREATE TABLE t1 (a int, b int as (next value for s1 > 0));
|
||||
ERROR HY000: Function or expression 'nextval()' cannot be used in the GENERATED ALWAYS AS clause of `b`
|
||||
drop sequence s1;
|
||||
|
||||
@@ -131,3 +131,18 @@ create sequence s2;
|
||||
select next value for s1;
|
||||
unlock tables;
|
||||
drop sequence s1;
|
||||
|
||||
--echo #
|
||||
--echo # Don't allow SQUENCE to be used with CHECK or virtual fields
|
||||
--echo #
|
||||
|
||||
CREATE SEQUENCE s1 nocache engine=myisam;
|
||||
--error ER_GENERATED_COLUMN_FUNCTION_IS_NOT_ALLOWED
|
||||
CREATE table t1 (a int check (next value for s1 > 0));
|
||||
--error ER_GENERATED_COLUMN_FUNCTION_IS_NOT_ALLOWED
|
||||
CREATE table t1 (a int check (previous value for s1 > 0));
|
||||
--error ER_GENERATED_COLUMN_FUNCTION_IS_NOT_ALLOWED
|
||||
CREATE table t1 (a int check (setval(s1,10)));
|
||||
--error ER_GENERATED_COLUMN_FUNCTION_IS_NOT_ALLOWED
|
||||
CREATE TABLE t1 (a int, b int as (next value for s1 > 0));
|
||||
drop sequence s1;
|
||||
|
||||
@@ -1056,6 +1056,35 @@ select next value for s1, cycle_count from s1;
|
||||
next value for s1 cycle_count
|
||||
9223372036854775805 3
|
||||
drop sequence s1;
|
||||
###########################################
|
||||
test default()
|
||||
###########################################
|
||||
connection master;
|
||||
CREATE SEQUENCE s1 nocache engine=myisam;
|
||||
CREATE table t1 (a int default next value for s1, b int);
|
||||
insert into t1 (b) values (1),(2);
|
||||
select default(a) from t1;
|
||||
default(a)
|
||||
3
|
||||
4
|
||||
select * from t1;
|
||||
a b
|
||||
1 1
|
||||
2 2
|
||||
select * from s1;
|
||||
next_not_cached_value minimum_value maximum_value start_value increment cache_size cycle_option cycle_count
|
||||
5 1 9223372036854775806 1 1 0 0 0
|
||||
connection slave;
|
||||
connection s_normal_3;
|
||||
select * from t1;
|
||||
a b
|
||||
1 1
|
||||
2 2
|
||||
select * from s1;
|
||||
next_not_cached_value minimum_value maximum_value start_value increment cache_size cycle_option cycle_count
|
||||
5 1 9223372036854775806 1 1 0 0 0
|
||||
connection master;
|
||||
drop table t1,s1;
|
||||
connection master;
|
||||
drop database s_db;
|
||||
drop user normal_1@'%';
|
||||
|
||||
@@ -851,6 +851,28 @@ select next value for s1, cycle_count from s1;
|
||||
select next value for s1, cycle_count from s1;
|
||||
drop sequence s1;
|
||||
|
||||
--echo ###########################################
|
||||
--echo test default()
|
||||
--echo ###########################################
|
||||
connection master;
|
||||
|
||||
CREATE SEQUENCE s1 nocache engine=myisam;
|
||||
CREATE table t1 (a int default next value for s1, b int);
|
||||
insert into t1 (b) values (1),(2);
|
||||
select default(a) from t1;
|
||||
select * from t1;
|
||||
select * from s1;
|
||||
--sync_slave_with_master
|
||||
connection s_normal_3;
|
||||
select * from t1;
|
||||
select * from s1;
|
||||
connection master;
|
||||
drop table t1,s1;
|
||||
|
||||
#
|
||||
# Cleanup
|
||||
#
|
||||
|
||||
connection master;
|
||||
drop database s_db;
|
||||
drop user normal_1@'%';
|
||||
|
||||
@@ -6686,14 +6686,22 @@ longlong Item_func_nextval::val_int()
|
||||
longlong value;
|
||||
int error;
|
||||
const char *key;
|
||||
TABLE *table= table_list->table;
|
||||
uint length= get_table_def_key(table_list, &key);
|
||||
THD *thd= table->in_use;
|
||||
THD *thd;
|
||||
SEQUENCE_LAST_VALUE *entry;
|
||||
char buff[80];
|
||||
String key_buff(buff,sizeof(buff), &my_charset_bin);
|
||||
DBUG_ASSERT(table && table->s->sequence);
|
||||
DBUG_ENTER("Item_func_nextval::val_int");
|
||||
update_table();
|
||||
DBUG_ASSERT(table && table->s->sequence);
|
||||
thd= table->in_use;
|
||||
|
||||
if (thd->count_cuted_fields == CHECK_FIELD_EXPRESSION)
|
||||
{
|
||||
/* Alter table checking if function works */
|
||||
null_value= 0;
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
|
||||
if (table->s->tmp_table != NO_TMP_TABLE)
|
||||
{
|
||||
@@ -6745,7 +6753,7 @@ void Item_func_nextval::print(String *str, enum_query_type query_type)
|
||||
char d_name_buff[MAX_ALIAS_NAME], t_name_buff[MAX_ALIAS_NAME];
|
||||
const char *d_name= table_list->db, *t_name= table_list->table_name;
|
||||
bool use_db_name= d_name && d_name[0];
|
||||
THD *thd= current_thd;
|
||||
THD *thd= current_thd; // Don't trust 'table'
|
||||
|
||||
str->append(func_name());
|
||||
str->append('(');
|
||||
@@ -6785,12 +6793,14 @@ longlong Item_func_lastval::val_int()
|
||||
const char *key;
|
||||
SEQUENCE_LAST_VALUE *entry;
|
||||
uint length= get_table_def_key(table_list, &key);
|
||||
THD *thd= table_list->table->in_use;
|
||||
THD *thd;
|
||||
char buff[80];
|
||||
String key_buff(buff,sizeof(buff), &my_charset_bin);
|
||||
DBUG_ENTER("Item_func_lastval::val_int");
|
||||
update_table();
|
||||
thd= table->in_use;
|
||||
|
||||
if (table_list->table->s->tmp_table != NO_TMP_TABLE)
|
||||
if (table->s->tmp_table != NO_TMP_TABLE)
|
||||
{
|
||||
/*
|
||||
Temporary tables has an extra \0 at end to distinguish it from
|
||||
@@ -6809,7 +6819,7 @@ longlong Item_func_lastval::val_int()
|
||||
null_value= 1;
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
if (entry->check_version(table_list->table))
|
||||
if (entry->check_version(table))
|
||||
{
|
||||
/* Table droped and re-created, remove current version */
|
||||
my_hash_delete(&thd->sequences, (uchar*) entry);
|
||||
@@ -6834,10 +6844,20 @@ longlong Item_func_setval::val_int()
|
||||
{
|
||||
longlong value;
|
||||
int error;
|
||||
TABLE *table= table_list->table;
|
||||
DBUG_ASSERT(table && table->s->sequence);
|
||||
THD *thd;
|
||||
DBUG_ENTER("Item_func_setval::val_int");
|
||||
|
||||
update_table();
|
||||
DBUG_ASSERT(table && table->s->sequence);
|
||||
thd= table->in_use;
|
||||
|
||||
if (thd->count_cuted_fields == CHECK_FIELD_EXPRESSION)
|
||||
{
|
||||
/* Alter table checking if function works */
|
||||
null_value= 0;
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
|
||||
value= nextval;
|
||||
error= table->s->sequence->set_value(table, nextval, round, is_used);
|
||||
if (error)
|
||||
@@ -6856,7 +6876,7 @@ void Item_func_setval::print(String *str, enum_query_type query_type)
|
||||
char d_name_buff[MAX_ALIAS_NAME], t_name_buff[MAX_ALIAS_NAME];
|
||||
const char *d_name= table_list->db, *t_name= table_list->table_name;
|
||||
bool use_db_name= d_name && d_name[0];
|
||||
THD *thd= table_list->table->in_use;
|
||||
THD *thd= current_thd; // Don't trust 'table'
|
||||
|
||||
str->append(func_name());
|
||||
str->append('(');
|
||||
|
||||
@@ -2981,9 +2981,10 @@ class Item_func_nextval :public Item_longlong_func
|
||||
{
|
||||
protected:
|
||||
TABLE_LIST *table_list;
|
||||
TABLE *table;
|
||||
public:
|
||||
Item_func_nextval(THD *thd, TABLE_LIST *table):
|
||||
Item_longlong_func(thd), table_list(table) {}
|
||||
Item_func_nextval(THD *thd, TABLE_LIST *table_list_arg):
|
||||
Item_longlong_func(thd), table_list(table_list_arg) {}
|
||||
longlong val_int();
|
||||
const char *func_name() const { return "nextval"; }
|
||||
void fix_length_and_dec()
|
||||
@@ -2992,6 +2993,22 @@ public:
|
||||
max_length= MAX_BIGINT_WIDTH;
|
||||
maybe_null= 1; /* In case of errors */
|
||||
}
|
||||
/*
|
||||
update_table() function must be called during the value function
|
||||
as in case of DEFAULT the sequence table may not yet be open
|
||||
while fix_fields() are called
|
||||
*/
|
||||
void update_table()
|
||||
{
|
||||
if (!(table= table_list->table))
|
||||
{
|
||||
/*
|
||||
If nextval was used in DEFAULT then next_local points to
|
||||
the table_list used by to open the sequence table
|
||||
*/
|
||||
table= table_list->next_local->table;
|
||||
}
|
||||
}
|
||||
bool const_item() const { return 0; }
|
||||
Item *get_copy(THD *thd)
|
||||
{ return get_item_copy<Item_func_nextval>(thd, this); }
|
||||
@@ -2999,7 +3016,8 @@ public:
|
||||
bool check_vcol_func_processor(void *arg)
|
||||
{
|
||||
return mark_unsupported_function(func_name(), "()", arg,
|
||||
VCOL_NON_DETERMINISTIC);
|
||||
(VCOL_NON_DETERMINISTIC |
|
||||
VCOL_NOT_VIRTUAL));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -3009,8 +3027,8 @@ public:
|
||||
class Item_func_lastval :public Item_func_nextval
|
||||
{
|
||||
public:
|
||||
Item_func_lastval(THD *thd, TABLE_LIST *table):
|
||||
Item_func_nextval(thd, table) {}
|
||||
Item_func_lastval(THD *thd, TABLE_LIST *table_list_arg):
|
||||
Item_func_nextval(thd, table_list_arg) {}
|
||||
longlong val_int();
|
||||
const char *func_name() const { return "lastval"; }
|
||||
Item *get_copy(THD *thd)
|
||||
@@ -3026,9 +3044,9 @@ class Item_func_setval :public Item_func_nextval
|
||||
ulonglong round;
|
||||
bool is_used;
|
||||
public:
|
||||
Item_func_setval(THD *thd, TABLE_LIST *table, longlong nextval_arg,
|
||||
Item_func_setval(THD *thd, TABLE_LIST *table_list_arg, longlong nextval_arg,
|
||||
ulonglong round_arg, bool is_used_arg)
|
||||
: Item_func_nextval(thd, table),
|
||||
: Item_func_nextval(thd, table_list_arg),
|
||||
nextval(nextval_arg), round(round_arg), is_used(is_used_arg)
|
||||
{}
|
||||
longlong val_int();
|
||||
|
||||
10
sql/lock.cc
10
sql/lock.cc
@@ -294,7 +294,8 @@ MYSQL_LOCK *mysql_lock_tables(THD *thd, TABLE **tables, uint count, uint flags)
|
||||
if (lock_tables_check(thd, tables, count, flags))
|
||||
DBUG_RETURN(NULL);
|
||||
|
||||
if (!(thd->variables.option_bits & OPTION_TABLE_LOCK))
|
||||
if (!(thd->variables.option_bits & OPTION_TABLE_LOCK) &&
|
||||
!(flags & MYSQL_LOCK_USE_MALLOC))
|
||||
gld_flags|= GET_LOCK_ON_THD;
|
||||
|
||||
if (! (sql_lock= get_lock_data(thd, tables, count, gld_flags)))
|
||||
@@ -415,7 +416,8 @@ static int lock_external(THD *thd, TABLE **tables, uint count)
|
||||
void mysql_unlock_tables(THD *thd, MYSQL_LOCK *sql_lock)
|
||||
{
|
||||
mysql_unlock_tables(thd, sql_lock,
|
||||
thd->variables.option_bits & OPTION_TABLE_LOCK);
|
||||
(thd->variables.option_bits & OPTION_TABLE_LOCK) ||
|
||||
!(sql_lock->flags & GET_LOCK_ON_THD));
|
||||
}
|
||||
|
||||
|
||||
@@ -433,7 +435,10 @@ void mysql_unlock_tables(THD *thd, MYSQL_LOCK *sql_lock, bool free_lock)
|
||||
if (sql_lock->lock_count)
|
||||
thr_multi_unlock(sql_lock->locks, sql_lock->lock_count, 0);
|
||||
if (free_lock)
|
||||
{
|
||||
DBUG_ASSERT(!(sql_lock->flags & GET_LOCK_ON_THD));
|
||||
my_free(sql_lock);
|
||||
}
|
||||
if (!errors)
|
||||
thd->clear_error();
|
||||
THD_STAGE_INFO(thd, org_stage);
|
||||
@@ -782,6 +787,7 @@ MYSQL_LOCK *get_lock_data(THD *thd, TABLE **table_ptr, uint count, uint flags)
|
||||
locks= locks_buf= sql_lock->locks= (THR_LOCK_DATA**) (sql_lock + 1);
|
||||
to= table_buf= sql_lock->table= (TABLE**) (locks + lock_count * 2);
|
||||
sql_lock->table_count= table_count;
|
||||
sql_lock->flags= flags;
|
||||
|
||||
for (i=0 ; i < count ; i++)
|
||||
{
|
||||
|
||||
@@ -4654,7 +4654,8 @@ sp_head::add_used_tables_to_table_list(THD *thd,
|
||||
table->init_one_table_for_prelocking(key_buff, stab->db_length,
|
||||
key_buff + stab->db_length + 1, stab->table_name_length,
|
||||
key_buff + stab->db_length + stab->table_name_length + 2,
|
||||
stab->lock_type, true, belong_to_view, stab->trg_event_map,
|
||||
stab->lock_type, TABLE_LIST::PRELOCK_ROUTINE, belong_to_view,
|
||||
stab->trg_event_map,
|
||||
query_tables_last_ptr);
|
||||
|
||||
tab_buff+= ALIGN_SIZE(sizeof(TABLE_LIST));
|
||||
|
||||
126
sql/sql_base.cc
126
sql/sql_base.cc
@@ -3528,7 +3528,7 @@ open_and_process_table(THD *thd, LEX *lex, TABLE_LIST *tables,
|
||||
*/
|
||||
if (thd->locked_tables_mode <= LTM_LOCK_TABLES &&
|
||||
! has_prelocking_list &&
|
||||
tables->lock_type >= TL_WRITE_ALLOW_WRITE)
|
||||
(tables->lock_type >= TL_WRITE_ALLOW_WRITE || thd->lex->default_used))
|
||||
{
|
||||
bool need_prelocking= FALSE;
|
||||
TABLE_LIST **save_query_tables_last= lex->query_tables_last;
|
||||
@@ -4234,7 +4234,7 @@ static bool table_already_fk_prelocked(TABLE_LIST *tl, LEX_CSTRING *db,
|
||||
for (; tl; tl= tl->next_global )
|
||||
{
|
||||
if (tl->lock_type >= lock_type &&
|
||||
tl->prelocking_placeholder == TABLE_LIST::FK &&
|
||||
tl->prelocking_placeholder == TABLE_LIST::PRELOCK_FK &&
|
||||
strcmp(tl->db, db->str) == 0 &&
|
||||
strcmp(tl->table_name, table->str) == 0)
|
||||
return true;
|
||||
@@ -4243,6 +4243,34 @@ static bool table_already_fk_prelocked(TABLE_LIST *tl, LEX_CSTRING *db,
|
||||
}
|
||||
|
||||
|
||||
static bool
|
||||
add_internal_tables(THD *thd, Query_tables_list *prelocking_ctx,
|
||||
TABLE_LIST *global_table_list, TABLE_LIST *tables)
|
||||
{
|
||||
do
|
||||
{
|
||||
TABLE_LIST *tl= (TABLE_LIST *) thd->alloc(sizeof(TABLE_LIST));
|
||||
if (!tl)
|
||||
return TRUE;
|
||||
tl->init_one_table_for_prelocking(tables->db,
|
||||
strlen(tables->db),
|
||||
tables->table_name,
|
||||
strlen(tables->table_name),
|
||||
NULL, tables->lock_type,
|
||||
TABLE_LIST::PRELOCK_NONE,
|
||||
0, 0,
|
||||
&prelocking_ctx->query_tables_last);
|
||||
/*
|
||||
Store link to the new table_list that will be used by open so that
|
||||
Item_func_nextval() can find it
|
||||
*/
|
||||
tables->next_local= tl;
|
||||
} while ((tables= tables->next_global));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
Defines how prelocking algorithm for DML statements should handle table list
|
||||
elements:
|
||||
@@ -4269,21 +4297,23 @@ bool DML_prelocking_strategy::
|
||||
handle_table(THD *thd, Query_tables_list *prelocking_ctx,
|
||||
TABLE_LIST *table_list, bool *need_prelocking)
|
||||
{
|
||||
TABLE *table= table_list->table;
|
||||
/* We rely on a caller to check that table is going to be changed. */
|
||||
DBUG_ASSERT(table_list->lock_type >= TL_WRITE_ALLOW_WRITE);
|
||||
DBUG_ASSERT(table_list->lock_type >= TL_WRITE_ALLOW_WRITE ||
|
||||
thd->lex->default_used);
|
||||
|
||||
if (table_list->trg_event_map)
|
||||
{
|
||||
if (table_list->table->triggers)
|
||||
if (table->triggers)
|
||||
{
|
||||
*need_prelocking= TRUE;
|
||||
|
||||
if (table_list->table->triggers->
|
||||
if (table->triggers->
|
||||
add_tables_and_routines_for_triggers(thd, prelocking_ctx, table_list))
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if (table_list->table->file->referenced_by_foreign_key())
|
||||
if (table->file->referenced_by_foreign_key())
|
||||
{
|
||||
List <FOREIGN_KEY_INFO> fk_list;
|
||||
List_iterator<FOREIGN_KEY_INFO> fk_list_it(fk_list);
|
||||
@@ -4292,7 +4322,7 @@ handle_table(THD *thd, Query_tables_list *prelocking_ctx,
|
||||
|
||||
arena= thd->activate_stmt_arena_if_needed(&backup);
|
||||
|
||||
table_list->table->file->get_parent_foreign_key_list(thd, &fk_list);
|
||||
table->file->get_parent_foreign_key_list(thd, &fk_list);
|
||||
if (thd->is_error())
|
||||
{
|
||||
if (arena)
|
||||
@@ -4321,20 +4351,87 @@ handle_table(THD *thd, Query_tables_list *prelocking_ctx,
|
||||
continue;
|
||||
|
||||
TABLE_LIST *tl= (TABLE_LIST *) thd->alloc(sizeof(TABLE_LIST));
|
||||
tl->init_one_table_for_prelocking(fk->foreign_db->str, fk->foreign_db->length,
|
||||
fk->foreign_table->str, fk->foreign_table->length,
|
||||
NULL, lock_type, false, table_list->belong_to_view,
|
||||
op, &prelocking_ctx->query_tables_last);
|
||||
tl->init_one_table_for_prelocking(fk->foreign_db->str,
|
||||
fk->foreign_db->length,
|
||||
fk->foreign_table->str,
|
||||
fk->foreign_table->length,
|
||||
NULL, lock_type,
|
||||
TABLE_LIST::PRELOCK_FK,
|
||||
table_list->belong_to_view, op,
|
||||
&prelocking_ctx->query_tables_last);
|
||||
}
|
||||
if (arena)
|
||||
thd->restore_active_arena(arena, &backup);
|
||||
}
|
||||
}
|
||||
|
||||
/* Open any tables used by DEFAULT (like sequence tables) */
|
||||
if (table->internal_tables &&
|
||||
((sql_command_flags[thd->lex->sql_command] & CF_INSERTS_DATA) ||
|
||||
thd->lex->default_used) &&
|
||||
add_internal_tables(thd, prelocking_ctx, table_list,
|
||||
table->internal_tables))
|
||||
{
|
||||
*need_prelocking= TRUE;
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Open all tables used by DEFAULT functions.
|
||||
|
||||
This is different from normal open_and_lock_tables() as we may
|
||||
already have other tables opened and locked and we have to merge the
|
||||
new table with the old ones.
|
||||
*/
|
||||
|
||||
bool open_and_lock_internal_tables(TABLE *table, bool lock_table)
|
||||
{
|
||||
THD *thd= table->in_use;
|
||||
TABLE_LIST *tl;
|
||||
MYSQL_LOCK *save_lock,*new_lock;
|
||||
DBUG_ENTER("open_internal_tables");
|
||||
|
||||
/* remove pointer to old select_lex which is already destroyed */
|
||||
for (tl= table->internal_tables ; tl ; tl= tl->next_global)
|
||||
tl->select_lex= 0;
|
||||
|
||||
uint counter;
|
||||
MDL_savepoint mdl_savepoint= thd->mdl_context.mdl_savepoint();
|
||||
TABLE_LIST *tmp= table->internal_tables;
|
||||
DML_prelocking_strategy prelocking_strategy;
|
||||
|
||||
if (open_tables(thd, thd->lex->create_info, &tmp, &counter, 0,
|
||||
&prelocking_strategy))
|
||||
goto err;
|
||||
|
||||
if (lock_table)
|
||||
{
|
||||
save_lock= thd->lock;
|
||||
thd->lock= 0;
|
||||
if (lock_tables(thd, table->internal_tables, counter,
|
||||
MYSQL_LOCK_USE_MALLOC))
|
||||
goto err;
|
||||
|
||||
if (!(new_lock= mysql_lock_merge(save_lock, thd->lock)))
|
||||
{
|
||||
thd->lock= save_lock;
|
||||
mysql_unlock_tables(thd, save_lock, 1);
|
||||
/* We don't have to close tables as caller will do that */
|
||||
goto err;
|
||||
}
|
||||
thd->lock= new_lock;
|
||||
}
|
||||
DBUG_RETURN(0);
|
||||
|
||||
err:
|
||||
thd->mdl_context.rollback_to_savepoint(mdl_savepoint);
|
||||
DBUG_RETURN(1);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Defines how prelocking algorithm for DML statements should handle view -
|
||||
all view routines should be added to the prelocking set.
|
||||
@@ -4486,7 +4583,7 @@ static bool check_lock_and_start_stmt(THD *thd,
|
||||
Prelocking placeholder is not set for TABLE_LIST that
|
||||
are directly used by TOP level statement.
|
||||
*/
|
||||
DBUG_ASSERT(table_list->prelocking_placeholder == false);
|
||||
DBUG_ASSERT(table_list->prelocking_placeholder == TABLE_LIST::PRELOCK_NONE);
|
||||
|
||||
/*
|
||||
TL_WRITE_DEFAULT and TL_READ_DEFAULT are supposed to be parser only
|
||||
@@ -4499,7 +4596,6 @@ static bool check_lock_and_start_stmt(THD *thd,
|
||||
Last argument routine_modifies_data for read_lock_type_for_table()
|
||||
is ignored, as prelocking placeholder will never be set here.
|
||||
*/
|
||||
DBUG_ASSERT(table_list->prelocking_placeholder == false);
|
||||
if (table_list->lock_type == TL_WRITE_DEFAULT)
|
||||
lock_type= thd->update_lock_default;
|
||||
else if (table_list->lock_type == TL_READ_DEFAULT)
|
||||
@@ -4507,8 +4603,8 @@ static bool check_lock_and_start_stmt(THD *thd,
|
||||
else
|
||||
lock_type= table_list->lock_type;
|
||||
|
||||
if ((int) lock_type > (int) TL_WRITE_ALLOW_WRITE &&
|
||||
(int) table_list->table->reginfo.lock_type <= (int) TL_WRITE_ALLOW_WRITE)
|
||||
if ((int) lock_type >= (int) TL_WRITE_ALLOW_WRITE &&
|
||||
(int) table_list->table->reginfo.lock_type < (int) TL_WRITE_ALLOW_WRITE)
|
||||
{
|
||||
my_error(ER_TABLE_NOT_LOCKED_FOR_WRITE, MYF(0),
|
||||
table_list->table->alias.c_ptr());
|
||||
|
||||
@@ -100,6 +100,7 @@ TABLE *open_ltable(THD *thd, TABLE_LIST *table_list, thr_lock_type update,
|
||||
*/
|
||||
#define MYSQL_OPEN_SKIP_SCOPED_MDL_LOCK 0x1000
|
||||
#define MYSQL_LOCK_NOT_TEMPORARY 0x2000
|
||||
#define MYSQL_LOCK_USE_MALLOC 0x4000
|
||||
/**
|
||||
Only check THD::killed if waits happen (e.g. wait on MDL, wait on
|
||||
table flush, wait on thr_lock.c locks) while opening and locking table.
|
||||
@@ -257,6 +258,7 @@ bool open_normal_and_derived_tables(THD *thd, TABLE_LIST *tables, uint flags,
|
||||
uint dt_phases);
|
||||
bool open_tables_only_view_structure(THD *thd, TABLE_LIST *tables,
|
||||
bool can_deadlock);
|
||||
bool open_and_lock_internal_tables(TABLE *table, bool lock);
|
||||
bool lock_tables(THD *thd, TABLE_LIST *tables, uint counter, uint flags);
|
||||
int decide_logging_format(THD *thd, TABLE_LIST *tables);
|
||||
void close_thread_table(THD *thd, TABLE **table_ptr);
|
||||
|
||||
@@ -4688,7 +4688,7 @@ TABLE *find_fk_open_table(THD *thd, const char *db, size_t db_len,
|
||||
{
|
||||
if (t->s->db.length == db_len && t->s->table_name.length == table_len &&
|
||||
!strcmp(t->s->db.str, db) && !strcmp(t->s->table_name.str, table) &&
|
||||
t->pos_in_table_list->prelocking_placeholder == TABLE_LIST::FK)
|
||||
t->pos_in_table_list->prelocking_placeholder == TABLE_LIST::PRELOCK_FK)
|
||||
return t;
|
||||
}
|
||||
return NULL;
|
||||
@@ -6081,7 +6081,7 @@ int THD::decide_logging_format(TABLE_LIST *tables)
|
||||
replicated_tables_count++;
|
||||
|
||||
if (table->lock_type <= TL_READ_NO_INSERT &&
|
||||
table->prelocking_placeholder != TABLE_LIST::FK)
|
||||
table->prelocking_placeholder != TABLE_LIST::PRELOCK_FK)
|
||||
has_read_tables= true;
|
||||
else if (table->table->found_next_number_field &&
|
||||
(table->lock_type >= TL_WRITE_ALLOW_WRITE))
|
||||
|
||||
@@ -373,8 +373,9 @@ public:
|
||||
typedef struct st_mysql_lock
|
||||
{
|
||||
TABLE **table;
|
||||
uint table_count,lock_count;
|
||||
THR_LOCK_DATA **locks;
|
||||
uint table_count,lock_count;
|
||||
uint flags;
|
||||
} MYSQL_LOCK;
|
||||
|
||||
|
||||
@@ -4406,7 +4407,8 @@ public:
|
||||
const char *path,
|
||||
const char *db,
|
||||
const char *table_name,
|
||||
bool open_in_engine);
|
||||
bool open_in_engine,
|
||||
bool open_internal_tables);
|
||||
|
||||
TABLE *find_temporary_table(const char *db, const char *table_name);
|
||||
TABLE *find_temporary_table(const TABLE_LIST *tl);
|
||||
|
||||
@@ -196,8 +196,9 @@ init_lex_with_single_table(THD *thd, TABLE *table, LEX *lex)
|
||||
lex_start(thd);
|
||||
context->init();
|
||||
if ((!(table_ident= new Table_ident(thd,
|
||||
&table->s->db,
|
||||
&table->s->table_name,
|
||||
&table->s->db, TRUE))) ||
|
||||
TRUE))) ||
|
||||
(!(table_list= select_lex->add_table_to_list(thd,
|
||||
table_ident,
|
||||
NULL,
|
||||
@@ -737,6 +738,7 @@ void LEX::start(THD *thd_arg)
|
||||
spcont= NULL;
|
||||
proc_list.first= 0;
|
||||
escape_used= FALSE;
|
||||
default_used= FALSE;
|
||||
query_tables= 0;
|
||||
reset_query_tables_list(FALSE);
|
||||
expr_allows_subselect= TRUE;
|
||||
@@ -3025,7 +3027,7 @@ LEX::LEX()
|
||||
: explain(NULL),
|
||||
result(0), arena_for_set_stmt(0), mem_root_for_set_stmt(0),
|
||||
option_type(OPT_DEFAULT), context_analysis_only(0), sphead(0),
|
||||
is_lex_started(0), limit_rows_examined_cnt(ULONGLONG_MAX)
|
||||
default_used(0), is_lex_started(0), limit_rows_examined_cnt(ULONGLONG_MAX)
|
||||
{
|
||||
|
||||
init_dynamic_array2(&plugins, sizeof(plugin_ref), plugins_static_buffer,
|
||||
|
||||
@@ -2937,6 +2937,7 @@ public:
|
||||
st_alter_tablespace *alter_tablespace_info;
|
||||
|
||||
bool escape_used;
|
||||
bool default_used; /* using default() function */
|
||||
bool is_lex_started; /* If lex_start() did run. For debugging. */
|
||||
|
||||
/*
|
||||
|
||||
@@ -4894,7 +4894,8 @@ int create_table_impl(THD *thd,
|
||||
if (!frm_only && create_info->tmp_table())
|
||||
{
|
||||
TABLE *table= thd->create_and_open_tmp_table(create_info->db_type, frm,
|
||||
path, db, table_name, true);
|
||||
path, db, table_name, true,
|
||||
false);
|
||||
|
||||
if (!table)
|
||||
{
|
||||
@@ -9296,7 +9297,7 @@ bool mysql_alter_table(THD *thd, const char *new_db, const char *new_name,
|
||||
thd->create_and_open_tmp_table(new_db_type, &frm,
|
||||
alter_ctx.get_tmp_path(),
|
||||
alter_ctx.new_db, alter_ctx.tmp_name,
|
||||
false)))
|
||||
false, true)))
|
||||
goto err_new_table_cleanup;
|
||||
|
||||
/* Set markers for fields in TABLE object for altered table. */
|
||||
@@ -9441,7 +9442,8 @@ bool mysql_alter_table(THD *thd, const char *new_db, const char *new_name,
|
||||
}
|
||||
|
||||
// It's now safe to take the table level lock.
|
||||
if (lock_tables(thd, table_list, alter_ctx.tables_opened, 0))
|
||||
if (lock_tables(thd, table_list, alter_ctx.tables_opened,
|
||||
MYSQL_LOCK_USE_MALLOC))
|
||||
goto err_new_table_cleanup;
|
||||
|
||||
if (ha_create_table(thd, alter_ctx.get_tmp_path(),
|
||||
@@ -9458,7 +9460,7 @@ bool mysql_alter_table(THD *thd, const char *new_db, const char *new_name,
|
||||
thd->create_and_open_tmp_table(new_db_type, &frm,
|
||||
alter_ctx.get_tmp_path(),
|
||||
alter_ctx.new_db, alter_ctx.tmp_name,
|
||||
true);
|
||||
true, true);
|
||||
if (!tmp_table)
|
||||
{
|
||||
goto err_new_table_cleanup;
|
||||
@@ -9492,7 +9494,7 @@ bool mysql_alter_table(THD *thd, const char *new_db, const char *new_name,
|
||||
thd->create_and_open_tmp_table(new_db_type, &frm,
|
||||
alter_ctx.get_tmp_path(),
|
||||
alter_ctx.new_db, alter_ctx.tmp_name,
|
||||
true);
|
||||
true, true);
|
||||
}
|
||||
if (!new_table)
|
||||
goto err_new_table_cleanup;
|
||||
|
||||
@@ -9670,6 +9670,7 @@ column_default_non_parenthesized_expr:
|
||||
$3);
|
||||
if ($$ == NULL)
|
||||
MYSQL_YYABORT;
|
||||
Lex->default_used= TRUE;
|
||||
}
|
||||
| VALUE_SYM '(' simple_ident_nospvar ')'
|
||||
{
|
||||
|
||||
@@ -9500,6 +9500,7 @@ column_default_non_parenthesized_expr:
|
||||
$3);
|
||||
if ($$ == NULL)
|
||||
MYSQL_YYABORT;
|
||||
Lex->default_used= TRUE;
|
||||
}
|
||||
| VALUE_SYM '(' simple_ident_nospvar ')'
|
||||
{
|
||||
|
||||
@@ -2965,6 +2965,14 @@ unpack_vcol_info_from_frm(THD *thd, MEM_ROOT *mem_root, TABLE *table,
|
||||
if (error)
|
||||
goto end;
|
||||
|
||||
if (lex.current_select->table_list.first[0].next_global)
|
||||
{
|
||||
/* We are using NEXT VALUE FOR sequence. Remember table name for open */
|
||||
TABLE_LIST *sequence= lex.current_select->table_list.first[0].next_global;
|
||||
sequence->next_global= table->internal_tables;
|
||||
table->internal_tables= sequence;
|
||||
}
|
||||
|
||||
vcol_storage.vcol_info->set_vcol_type(vcol->get_vcol_type());
|
||||
vcol_storage.vcol_info->stored_in_db= vcol->stored_in_db;
|
||||
vcol_storage.vcol_info->name= vcol->name;
|
||||
|
||||
17
sql/table.h
17
sql/table.h
@@ -1097,6 +1097,8 @@ public:
|
||||
TABLE_LIST *pos_in_table_list;/* Element referring to this table */
|
||||
/* Position in thd->locked_table_list under LOCK TABLES */
|
||||
TABLE_LIST *pos_in_locked_tables;
|
||||
/* Tables used in DEFAULT and CHECK CONSTRAINT (normally sequence tables) */
|
||||
TABLE_LIST *internal_tables;
|
||||
|
||||
/*
|
||||
Not-null for temporary tables only. Non-null values means this table is
|
||||
@@ -1748,6 +1750,11 @@ struct TABLE_LIST
|
||||
{
|
||||
TABLE_LIST() {} /* Remove gcc warning */
|
||||
|
||||
enum prelocking_types
|
||||
{
|
||||
PRELOCK_NONE, PRELOCK_ROUTINE, PRELOCK_FK
|
||||
};
|
||||
|
||||
/**
|
||||
Prepare TABLE_LIST that consists of one table instance to use in
|
||||
open_and_lock_tables
|
||||
@@ -1778,7 +1785,7 @@ struct TABLE_LIST
|
||||
size_t table_name_length_arg,
|
||||
const char *alias_arg,
|
||||
enum thr_lock_type lock_type_arg,
|
||||
bool routine,
|
||||
prelocking_types prelocking_type,
|
||||
TABLE_LIST *belong_to_view_arg,
|
||||
uint8 trg_event_map_arg,
|
||||
TABLE_LIST ***last_ptr)
|
||||
@@ -1786,8 +1793,10 @@ struct TABLE_LIST
|
||||
init_one_table(db_name_arg, db_length_arg, table_name_arg,
|
||||
table_name_length_arg, alias_arg, lock_type_arg);
|
||||
cacheable_table= 1;
|
||||
prelocking_placeholder= routine ? ROUTINE : FK;
|
||||
open_type= routine ? OT_TEMPORARY_OR_BASE : OT_BASE_ONLY;
|
||||
prelocking_placeholder= prelocking_type;
|
||||
open_type= (prelocking_type == PRELOCK_ROUTINE ?
|
||||
OT_TEMPORARY_OR_BASE :
|
||||
OT_BASE_ONLY);
|
||||
belong_to_view= belong_to_view_arg;
|
||||
trg_event_map= trg_event_map_arg;
|
||||
|
||||
@@ -2076,7 +2085,7 @@ struct TABLE_LIST
|
||||
This TABLE_LIST object is just placeholder for prelocking, it will be
|
||||
used for implicit LOCK TABLES only and won't be used in real statement.
|
||||
*/
|
||||
enum { USER, ROUTINE, FK } prelocking_placeholder;
|
||||
prelocking_types prelocking_placeholder;
|
||||
/**
|
||||
Indicates that if TABLE_LIST object corresponds to the table/view
|
||||
which requires special handling.
|
||||
|
||||
@@ -65,7 +65,8 @@ TABLE *THD::create_and_open_tmp_table(handlerton *hton,
|
||||
const char *path,
|
||||
const char *db,
|
||||
const char *table_name,
|
||||
bool open_in_engine)
|
||||
bool open_in_engine,
|
||||
bool open_internal_tables)
|
||||
{
|
||||
DBUG_ENTER("THD::create_and_open_tmp_table");
|
||||
|
||||
@@ -90,6 +91,15 @@ TABLE *THD::create_and_open_tmp_table(handlerton *hton,
|
||||
|
||||
/* Free the TMP_TABLE_SHARE. */
|
||||
free_tmp_table_share(share, false);
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
|
||||
/* Open any related tables */
|
||||
if (open_internal_tables && table->internal_tables &&
|
||||
open_and_lock_internal_tables(table, open_in_engine))
|
||||
{
|
||||
drop_temporary_table(table, NULL, false);
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user