mirror of
https://github.com/MariaDB/server.git
synced 2025-07-30 16:24:05 +03:00
Merge bk-internal.mysql.com:/home/bk/mysql-5.1-runtime
into mockturtle.local:/home/dlenev/src/mysql-5.1-like-2
This commit is contained in:
@ -162,3 +162,86 @@ t1 CREATE TABLE `t1` (
|
|||||||
`j` int(11) DEFAULT NULL
|
`j` int(11) DEFAULT NULL
|
||||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1
|
) ENGINE=MyISAM DEFAULT CHARSET=latin1
|
||||||
drop table t1, t2, t3;
|
drop table t1, t2, t3;
|
||||||
|
drop table if exists t1,t2;
|
||||||
|
create table t1 (i int);
|
||||||
|
set session debug="+d,sleep_create_like_before_check_if_exists";
|
||||||
|
reset master;
|
||||||
|
create table t2 like t1;;
|
||||||
|
insert into t1 values (1);
|
||||||
|
drop table t1;
|
||||||
|
show create table t2;
|
||||||
|
Table Create Table
|
||||||
|
t2 CREATE TABLE `t2` (
|
||||||
|
`i` int(11) DEFAULT NULL
|
||||||
|
) ENGINE=MyISAM DEFAULT CHARSET=latin1
|
||||||
|
drop table t2;
|
||||||
|
show binlog events in 'master-bin.000001' from 106;
|
||||||
|
Log_name Pos Event_type Server_id End_log_pos Info
|
||||||
|
master-bin.000001 # Query 1 # use `test`; insert into t1 values (1)
|
||||||
|
master-bin.000001 # Query 1 # use `test`; create table t2 like t1
|
||||||
|
master-bin.000001 # Query 1 # use `test`; drop table t1
|
||||||
|
master-bin.000001 # Query 1 # use `test`; drop table t2
|
||||||
|
create table t1 (i int);
|
||||||
|
set session debug="-d,sleep_create_like_before_check_if_exists:+d,sleep_create_like_before_copy";
|
||||||
|
create table t2 like t1;;
|
||||||
|
create table if not exists t2 (j int);
|
||||||
|
Warnings:
|
||||||
|
Note 1050 Table 't2' already exists
|
||||||
|
show create table t2;
|
||||||
|
Table Create Table
|
||||||
|
t2 CREATE TABLE `t2` (
|
||||||
|
`i` int(11) DEFAULT NULL
|
||||||
|
) ENGINE=MyISAM DEFAULT CHARSET=latin1
|
||||||
|
drop table t2;
|
||||||
|
reset master;
|
||||||
|
create table t2 like t1;;
|
||||||
|
drop table t1;
|
||||||
|
drop table t2;
|
||||||
|
show binlog events in 'master-bin.000001' from 106;
|
||||||
|
Log_name Pos Event_type Server_id End_log_pos Info
|
||||||
|
master-bin.000001 # Query 1 # use `test`; create table t2 like t1
|
||||||
|
master-bin.000001 # Query 1 # use `test`; drop table t1
|
||||||
|
master-bin.000001 # Query 1 # use `test`; drop table t2
|
||||||
|
create table t1 (i int);
|
||||||
|
set session debug="-d,sleep_create_like_before_copy:+d,sleep_create_like_before_ha_create";
|
||||||
|
reset master;
|
||||||
|
create table t2 like t1;;
|
||||||
|
insert into t2 values (1);
|
||||||
|
drop table t2;
|
||||||
|
create table t2 like t1;;
|
||||||
|
drop table t2;
|
||||||
|
create table t2 like t1;;
|
||||||
|
drop table t1;
|
||||||
|
drop table t2;
|
||||||
|
show binlog events in 'master-bin.000001' from 106;
|
||||||
|
Log_name Pos Event_type Server_id End_log_pos Info
|
||||||
|
master-bin.000001 # Query 1 # use `test`; create table t2 like t1
|
||||||
|
master-bin.000001 # Query 1 # use `test`; insert into t2 values (1)
|
||||||
|
master-bin.000001 # Query 1 # use `test`; drop table t2
|
||||||
|
master-bin.000001 # Query 1 # use `test`; create table t2 like t1
|
||||||
|
master-bin.000001 # Query 1 # use `test`; drop table t2
|
||||||
|
master-bin.000001 # Query 1 # use `test`; create table t2 like t1
|
||||||
|
master-bin.000001 # Query 1 # use `test`; drop table t1
|
||||||
|
master-bin.000001 # Query 1 # use `test`; drop table t2
|
||||||
|
create table t1 (i int);
|
||||||
|
set session debug="-d,sleep_create_like_before_ha_create:+d,sleep_create_like_before_binlogging";
|
||||||
|
reset master;
|
||||||
|
create table t2 like t1;;
|
||||||
|
insert into t2 values (1);
|
||||||
|
drop table t2;
|
||||||
|
create table t2 like t1;;
|
||||||
|
drop table t2;
|
||||||
|
create table t2 like t1;;
|
||||||
|
drop table t1;
|
||||||
|
drop table t2;
|
||||||
|
show binlog events in 'master-bin.000001' from 106;
|
||||||
|
Log_name Pos Event_type Server_id End_log_pos Info
|
||||||
|
master-bin.000001 # Query 1 # use `test`; create table t2 like t1
|
||||||
|
master-bin.000001 # Query 1 # use `test`; insert into t2 values (1)
|
||||||
|
master-bin.000001 # Query 1 # use `test`; drop table t2
|
||||||
|
master-bin.000001 # Query 1 # use `test`; create table t2 like t1
|
||||||
|
master-bin.000001 # Query 1 # use `test`; drop table t2
|
||||||
|
master-bin.000001 # Query 1 # use `test`; create table t2 like t1
|
||||||
|
master-bin.000001 # Query 1 # use `test`; drop table t1
|
||||||
|
master-bin.000001 # Query 1 # use `test`; drop table t2
|
||||||
|
set session debug="-d,sleep_create_like_before_binlogging";
|
@ -371,7 +371,7 @@ ERROR 42S01: Table 't3' already exists
|
|||||||
create table non_existing_database.t1 like t1;
|
create table non_existing_database.t1 like t1;
|
||||||
ERROR 42000: Unknown database 'non_existing_database'
|
ERROR 42000: Unknown database 'non_existing_database'
|
||||||
create table t3 like non_existing_table;
|
create table t3 like non_existing_table;
|
||||||
ERROR 42S02: Unknown table 'non_existing_table'
|
ERROR 42S02: Table 'test.non_existing_table' doesn't exist
|
||||||
create temporary table t3 like t1;
|
create temporary table t3 like t1;
|
||||||
ERROR 42S01: Table 't3' already exists
|
ERROR 42S01: Table 't3' already exists
|
||||||
drop table t1, t2, t3;
|
drop table t1, t2, t3;
|
||||||
|
@ -381,3 +381,26 @@ drop table t2;
|
|||||||
REVOKE ALL PRIVILEGES, GRANT OPTION FROM `a@`@localhost;
|
REVOKE ALL PRIVILEGES, GRANT OPTION FROM `a@`@localhost;
|
||||||
drop user `a@`@localhost;
|
drop user `a@`@localhost;
|
||||||
SET GLOBAL log_bin_trust_function_creators = 0;
|
SET GLOBAL log_bin_trust_function_creators = 0;
|
||||||
|
drop database if exists mysqltest_1;
|
||||||
|
drop database if exists mysqltest_2;
|
||||||
|
drop user mysqltest_u1@localhost;
|
||||||
|
create database mysqltest_1;
|
||||||
|
create database mysqltest_2;
|
||||||
|
grant all on mysqltest_1.* to mysqltest_u1@localhost;
|
||||||
|
use mysqltest_2;
|
||||||
|
create table t1 (i int);
|
||||||
|
show create table mysqltest_2.t1;
|
||||||
|
ERROR 42000: SELECT command denied to user 'mysqltest_u1'@'localhost' for table 't1'
|
||||||
|
create table t1 like mysqltest_2.t1;
|
||||||
|
ERROR 42000: SELECT command denied to user 'mysqltest_u1'@'localhost' for table 't1'
|
||||||
|
grant select on mysqltest_2.t1 to mysqltest_u1@localhost;
|
||||||
|
show create table mysqltest_2.t1;
|
||||||
|
Table Create Table
|
||||||
|
t1 CREATE TABLE `t1` (
|
||||||
|
`i` int(11) DEFAULT NULL
|
||||||
|
) ENGINE=MyISAM DEFAULT CHARSET=latin1
|
||||||
|
create table t1 like mysqltest_2.t1;
|
||||||
|
use test;
|
||||||
|
drop database mysqltest_1;
|
||||||
|
drop database mysqltest_2;
|
||||||
|
drop user mysqltest_u1@localhost;
|
||||||
|
@ -1,12 +1,17 @@
|
|||||||
# Tests for various aspects of CREATE TABLE ... SELECT implementation
|
# Tests for various concurrency-related aspects of CREATE TABLE ... SELECT
|
||||||
|
# and CREATE TABLE like implementation.
|
||||||
#
|
#
|
||||||
# Note that we don't test general CREATE TABLE ... SELECT functionality here as
|
# Note that we don't test general CREATE TABLE ... SELECT/LIKE functionality
|
||||||
# it is already covered by create.test. We are more interested in extreme cases.
|
# here as it is already covered by create.test. We are more interested in
|
||||||
|
# extreme cases.
|
||||||
#
|
#
|
||||||
# This test takes rather long time so let us run it only in --big-test mode
|
# This test takes rather long time so let us run it only in --big-test mode
|
||||||
--source include/big_test.inc
|
--source include/big_test.inc
|
||||||
# We are using some debug-only features in this test
|
# We are using some debug-only features in this test
|
||||||
--source include/have_debug.inc
|
--source include/have_debug.inc
|
||||||
|
# Some of tests below also use binlog to check that statements are
|
||||||
|
# executed and logged in correct order
|
||||||
|
--source include/have_binlog_format_mixed_or_statement.inc
|
||||||
|
|
||||||
# Create auxilliary connections
|
# Create auxilliary connections
|
||||||
connect (addconroot1, localhost, root,,);
|
connect (addconroot1, localhost, root,,);
|
||||||
@ -20,7 +25,7 @@ drop table if exists t1,t2,t3,t4,t5;
|
|||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# Tests for concurrency problems.
|
# Tests for concurrency problems in CREATE TABLE ... SELECT
|
||||||
#
|
#
|
||||||
# We introduce delays between various stages of table creation
|
# We introduce delays between various stages of table creation
|
||||||
# and check that other statements dealing with this table cannot
|
# and check that other statements dealing with this table cannot
|
||||||
@ -266,3 +271,122 @@ connection default;
|
|||||||
select * from t1;
|
select * from t1;
|
||||||
show create table t1;
|
show create table t1;
|
||||||
drop table t1, t2, t3;
|
drop table t1, t2, t3;
|
||||||
|
|
||||||
|
|
||||||
|
# Tests for possible concurrency issues with CREATE TABLE ... LIKE
|
||||||
|
#
|
||||||
|
# Bug #18950 "create table like does not obtain LOCK_open"
|
||||||
|
# Bug #23667 "CREATE TABLE LIKE is not isolated from alteration by other
|
||||||
|
# connections"
|
||||||
|
#
|
||||||
|
# Again the idea of this test is that we introduce artificial delays on
|
||||||
|
# various stages of table creation and check that concurrent statements
|
||||||
|
# for tables from CREATE TABLE ... LIKE are not interfering.
|
||||||
|
|
||||||
|
--disable_warnings
|
||||||
|
drop table if exists t1,t2;
|
||||||
|
--enable_warnings
|
||||||
|
|
||||||
|
# What happens if some statements sneak in right after we have
|
||||||
|
# opened source table ?
|
||||||
|
create table t1 (i int);
|
||||||
|
set session debug="+d,sleep_create_like_before_check_if_exists";
|
||||||
|
# Reset binlog to have clear start
|
||||||
|
reset master;
|
||||||
|
--send create table t2 like t1;
|
||||||
|
connection addconroot1;
|
||||||
|
--sleep 2
|
||||||
|
# DML on source table should be allowed to run concurrently
|
||||||
|
insert into t1 values (1);
|
||||||
|
# And DDL should wait
|
||||||
|
drop table t1;
|
||||||
|
connection default;
|
||||||
|
--reap
|
||||||
|
show create table t2;
|
||||||
|
drop table t2;
|
||||||
|
# Let us check that statements were executed/binlogged in correct order
|
||||||
|
--replace_column 2 # 5 #
|
||||||
|
show binlog events in 'master-bin.000001' from 106;
|
||||||
|
|
||||||
|
# Now let us check the gap between check for target table
|
||||||
|
# existance and copying of .frm file.
|
||||||
|
create table t1 (i int);
|
||||||
|
set session debug="-d,sleep_create_like_before_check_if_exists:+d,sleep_create_like_before_copy";
|
||||||
|
# It should be impossible to create target table concurrently
|
||||||
|
--send create table t2 like t1;
|
||||||
|
connection addconroot1;
|
||||||
|
--sleep 2
|
||||||
|
create table if not exists t2 (j int);
|
||||||
|
connection default;
|
||||||
|
--reap
|
||||||
|
show create table t2;
|
||||||
|
drop table t2;
|
||||||
|
# And concurrent DDL on the source table should be still disallowed
|
||||||
|
reset master;
|
||||||
|
--send create table t2 like t1;
|
||||||
|
connection addconroot1;
|
||||||
|
--sleep 2
|
||||||
|
drop table t1;
|
||||||
|
connection default;
|
||||||
|
--reap
|
||||||
|
drop table t2;
|
||||||
|
--replace_column 2 # 5 #
|
||||||
|
show binlog events in 'master-bin.000001' from 106;
|
||||||
|
|
||||||
|
# And now he gap between copying of .frm file and ha_create_table() call.
|
||||||
|
create table t1 (i int);
|
||||||
|
set session debug="-d,sleep_create_like_before_copy:+d,sleep_create_like_before_ha_create";
|
||||||
|
# Both DML and DDL on target table should wait till operation completes
|
||||||
|
reset master;
|
||||||
|
--send create table t2 like t1;
|
||||||
|
connection addconroot1;
|
||||||
|
--sleep 2
|
||||||
|
insert into t2 values (1);
|
||||||
|
connection default;
|
||||||
|
--reap
|
||||||
|
drop table t2;
|
||||||
|
--send create table t2 like t1;
|
||||||
|
connection addconroot1;
|
||||||
|
--sleep 2
|
||||||
|
drop table t2;
|
||||||
|
connection default;
|
||||||
|
--reap
|
||||||
|
# Concurrent DDL on the source table still waits
|
||||||
|
--send create table t2 like t1;
|
||||||
|
connection addconroot1;
|
||||||
|
--sleep 2
|
||||||
|
drop table t1;
|
||||||
|
connection default;
|
||||||
|
--reap
|
||||||
|
drop table t2;
|
||||||
|
--replace_column 2 # 5 #
|
||||||
|
show binlog events in 'master-bin.000001' from 106;
|
||||||
|
|
||||||
|
# Finally we check the gap between ha_create_table() and binlogging
|
||||||
|
create table t1 (i int);
|
||||||
|
set session debug="-d,sleep_create_like_before_ha_create:+d,sleep_create_like_before_binlogging";
|
||||||
|
reset master;
|
||||||
|
--send create table t2 like t1;
|
||||||
|
connection addconroot1;
|
||||||
|
--sleep 2
|
||||||
|
insert into t2 values (1);
|
||||||
|
connection default;
|
||||||
|
--reap
|
||||||
|
drop table t2;
|
||||||
|
--send create table t2 like t1;
|
||||||
|
connection addconroot1;
|
||||||
|
--sleep 2
|
||||||
|
drop table t2;
|
||||||
|
connection default;
|
||||||
|
--reap
|
||||||
|
--send create table t2 like t1;
|
||||||
|
connection addconroot1;
|
||||||
|
--sleep 2
|
||||||
|
drop table t1;
|
||||||
|
connection default;
|
||||||
|
--reap
|
||||||
|
drop table t2;
|
||||||
|
--replace_column 2 # 5 #
|
||||||
|
show binlog events in 'master-bin.000001' from 106;
|
||||||
|
|
||||||
|
set session debug="-d,sleep_create_like_before_binlogging";
|
@ -306,7 +306,7 @@ create table t3 like t1;
|
|||||||
create table t3 like mysqltest.t3;
|
create table t3 like mysqltest.t3;
|
||||||
--error 1049
|
--error 1049
|
||||||
create table non_existing_database.t1 like t1;
|
create table non_existing_database.t1 like t1;
|
||||||
--error 1051
|
--error ER_NO_SUCH_TABLE
|
||||||
create table t3 like non_existing_table;
|
create table t3 like non_existing_table;
|
||||||
--error 1050
|
--error 1050
|
||||||
create temporary table t3 like t1;
|
create temporary table t3 like t1;
|
||||||
|
@ -30,7 +30,6 @@ rpl_ddl : BUG#26418 2007-03-01 mleich Slave out of sync after C
|
|||||||
rpl_ndb_innodb2ndb : Bug #19710 Cluster replication to partition table fails on DELETE FROM statement
|
rpl_ndb_innodb2ndb : Bug #19710 Cluster replication to partition table fails on DELETE FROM statement
|
||||||
rpl_ndb_myisam2ndb : Bug #19710 Cluster replication to partition table fails on DELETE FROM statement
|
rpl_ndb_myisam2ndb : Bug #19710 Cluster replication to partition table fails on DELETE FROM statement
|
||||||
rpl_row_blob_innodb : BUG#18980 2006-04-10 kent Test fails randomly
|
rpl_row_blob_innodb : BUG#18980 2006-04-10 kent Test fails randomly
|
||||||
synchronization : Bug#24529 Test 'synchronization' fails on Mac pushbuild; Also on Linux 64 bit.
|
|
||||||
|
|
||||||
# the below testcase have been reworked to avoid the bug, test contains comment, keep bug open
|
# the below testcase have been reworked to avoid the bug, test contains comment, keep bug open
|
||||||
#ndb_binlog_ddl_multi : BUG#18976 2006-04-10 kent CRBR: multiple binlog, second binlog may miss schema log events
|
#ndb_binlog_ddl_multi : BUG#18976 2006-04-10 kent CRBR: multiple binlog, second binlog may miss schema log events
|
||||||
|
@ -513,3 +513,44 @@ REVOKE ALL PRIVILEGES, GRANT OPTION FROM `a@`@localhost;
|
|||||||
drop user `a@`@localhost;
|
drop user `a@`@localhost;
|
||||||
|
|
||||||
SET GLOBAL log_bin_trust_function_creators = 0;
|
SET GLOBAL log_bin_trust_function_creators = 0;
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# Bug#25578 "CREATE TABLE LIKE does not require any privileges on source table"
|
||||||
|
#
|
||||||
|
--disable_warnings
|
||||||
|
drop database if exists mysqltest_1;
|
||||||
|
drop database if exists mysqltest_2;
|
||||||
|
--enable_warnings
|
||||||
|
--error 0,ER_CANNOT_USER
|
||||||
|
drop user mysqltest_u1@localhost;
|
||||||
|
|
||||||
|
create database mysqltest_1;
|
||||||
|
create database mysqltest_2;
|
||||||
|
grant all on mysqltest_1.* to mysqltest_u1@localhost;
|
||||||
|
use mysqltest_2;
|
||||||
|
create table t1 (i int);
|
||||||
|
|
||||||
|
# Connect as user with all rights on mysqltest_1 but with no rights on mysqltest_2.
|
||||||
|
connect (user1,localhost,mysqltest_u1,,mysqltest_1);
|
||||||
|
connection user1;
|
||||||
|
# As expected error is emitted
|
||||||
|
--error ER_TABLEACCESS_DENIED_ERROR
|
||||||
|
show create table mysqltest_2.t1;
|
||||||
|
# This should emit error as well
|
||||||
|
--error ER_TABLEACCESS_DENIED_ERROR
|
||||||
|
create table t1 like mysqltest_2.t1;
|
||||||
|
|
||||||
|
# Now let us check that SELECT privilege on the source is enough
|
||||||
|
connection default;
|
||||||
|
grant select on mysqltest_2.t1 to mysqltest_u1@localhost;
|
||||||
|
connection user1;
|
||||||
|
show create table mysqltest_2.t1;
|
||||||
|
create table t1 like mysqltest_2.t1;
|
||||||
|
|
||||||
|
# Clean-up
|
||||||
|
connection default;
|
||||||
|
use test;
|
||||||
|
drop database mysqltest_1;
|
||||||
|
drop database mysqltest_2;
|
||||||
|
drop user mysqltest_u1@localhost;
|
||||||
|
@ -223,6 +223,7 @@
|
|||||||
|
|
||||||
#define HA_LEX_CREATE_TMP_TABLE 1
|
#define HA_LEX_CREATE_TMP_TABLE 1
|
||||||
#define HA_LEX_CREATE_IF_NOT_EXISTS 2
|
#define HA_LEX_CREATE_IF_NOT_EXISTS 2
|
||||||
|
#define HA_LEX_CREATE_TABLE_LIKE 4
|
||||||
#define HA_OPTION_NO_CHECKSUM (1L << 17)
|
#define HA_OPTION_NO_CHECKSUM (1L << 17)
|
||||||
#define HA_OPTION_NO_DELAY_KEY_WRITE (1L << 18)
|
#define HA_OPTION_NO_DELAY_KEY_WRITE (1L << 18)
|
||||||
#define HA_MAX_REC_LENGTH 65535
|
#define HA_MAX_REC_LENGTH 65535
|
||||||
|
@ -978,9 +978,8 @@ bool mysql_alter_table(THD *thd, char *new_db, char *new_name,
|
|||||||
uint order_num, ORDER *order, bool ignore,
|
uint order_num, ORDER *order, bool ignore,
|
||||||
ALTER_INFO *alter_info, bool do_send_ok);
|
ALTER_INFO *alter_info, bool do_send_ok);
|
||||||
bool mysql_recreate_table(THD *thd, TABLE_LIST *table_list, bool do_send_ok);
|
bool mysql_recreate_table(THD *thd, TABLE_LIST *table_list, bool do_send_ok);
|
||||||
bool mysql_create_like_table(THD *thd, TABLE_LIST *table,
|
bool mysql_create_like_table(THD *thd, TABLE_LIST *table, TABLE_LIST *src_table,
|
||||||
HA_CREATE_INFO *create_info,
|
HA_CREATE_INFO *create_info);
|
||||||
Table_ident *src_table);
|
|
||||||
bool mysql_rename_table(handlerton *base, const char *old_db,
|
bool mysql_rename_table(handlerton *base, const char *old_db,
|
||||||
const char * old_name, const char *new_db,
|
const char * old_name, const char *new_db,
|
||||||
const char * new_name, uint flags);
|
const char * new_name, uint flags);
|
||||||
|
@ -1066,7 +1066,6 @@ typedef struct st_lex : public Query_tables_list
|
|||||||
|
|
||||||
char *length,*dec,*change;
|
char *length,*dec,*change;
|
||||||
LEX_STRING name;
|
LEX_STRING name;
|
||||||
Table_ident *like_name;
|
|
||||||
char *help_arg;
|
char *help_arg;
|
||||||
char *backup_dir; /* For RESTORE/BACKUP */
|
char *backup_dir; /* For RESTORE/BACKUP */
|
||||||
char* to_log; /* For PURGE MASTER LOGS TO */
|
char* to_log; /* For PURGE MASTER LOGS TO */
|
||||||
|
@ -39,6 +39,7 @@
|
|||||||
"FUNCTION" : "PROCEDURE")
|
"FUNCTION" : "PROCEDURE")
|
||||||
|
|
||||||
static bool execute_sqlcom_select(THD *thd, TABLE_LIST *all_tables);
|
static bool execute_sqlcom_select(THD *thd, TABLE_LIST *all_tables);
|
||||||
|
static bool check_show_create_table_access(THD *thd, TABLE_LIST *table);
|
||||||
|
|
||||||
const char *any_db="*any*"; // Special symbol for check_access
|
const char *any_db="*any*"; // Special symbol for check_access
|
||||||
|
|
||||||
@ -2231,9 +2232,9 @@ mysql_execute_command(THD *thd)
|
|||||||
if (lex->create_info.options & HA_LEX_CREATE_TMP_TABLE)
|
if (lex->create_info.options & HA_LEX_CREATE_TMP_TABLE)
|
||||||
thd->options|= OPTION_KEEP_LOG;
|
thd->options|= OPTION_KEEP_LOG;
|
||||||
/* regular create */
|
/* regular create */
|
||||||
if (lex->like_name)
|
if (lex->create_info.options & HA_LEX_CREATE_TABLE_LIKE)
|
||||||
res= mysql_create_like_table(thd, create_table, &lex->create_info,
|
res= mysql_create_like_table(thd, create_table, select_tables,
|
||||||
lex->like_name);
|
&lex->create_info);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
res= mysql_create_table(thd, create_table->db,
|
res= mysql_create_table(thd, create_table->db,
|
||||||
@ -2423,12 +2424,7 @@ end_with_restore_list:
|
|||||||
/* Ignore temporary tables if this is "SHOW CREATE VIEW" */
|
/* Ignore temporary tables if this is "SHOW CREATE VIEW" */
|
||||||
if (lex->only_view)
|
if (lex->only_view)
|
||||||
first_table->skip_temporary= 1;
|
first_table->skip_temporary= 1;
|
||||||
|
if (check_show_create_table_access(thd, first_table))
|
||||||
if (check_access(thd, SELECT_ACL | EXTRA_ACL, first_table->db,
|
|
||||||
&first_table->grant.privilege, 0, 0,
|
|
||||||
test(first_table->schema_table)))
|
|
||||||
goto error;
|
|
||||||
if (grant_option && check_grant(thd, SELECT_ACL, all_tables, 2, UINT_MAX, 0))
|
|
||||||
goto error;
|
goto error;
|
||||||
res= mysqld_show_create(thd, first_table);
|
res= mysqld_show_create(thd, first_table);
|
||||||
break;
|
break;
|
||||||
@ -6845,6 +6841,25 @@ bool insert_precheck(THD *thd, TABLE_LIST *tables)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
@brief Check privileges for SHOW CREATE TABLE statement.
|
||||||
|
|
||||||
|
@param thd Thread context
|
||||||
|
@param table Target table
|
||||||
|
|
||||||
|
@retval TRUE Failure
|
||||||
|
@retval FALSE Success
|
||||||
|
*/
|
||||||
|
|
||||||
|
static bool check_show_create_table_access(THD *thd, TABLE_LIST *table)
|
||||||
|
{
|
||||||
|
return check_access(thd, SELECT_ACL | EXTRA_ACL, table->db,
|
||||||
|
&table->grant.privilege, 0, 0,
|
||||||
|
test(table->schema_table)) ||
|
||||||
|
grant_option && check_grant(thd, SELECT_ACL, table, 2, UINT_MAX, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
CREATE TABLE query pre-check
|
CREATE TABLE query pre-check
|
||||||
|
|
||||||
@ -6910,6 +6925,11 @@ bool create_table_precheck(THD *thd, TABLE_LIST *tables,
|
|||||||
if (tables && check_table_access(thd, SELECT_ACL, tables,0))
|
if (tables && check_table_access(thd, SELECT_ACL, tables,0))
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
else if (lex->create_info.options & HA_LEX_CREATE_TABLE_LIKE)
|
||||||
|
{
|
||||||
|
if (check_show_create_table_access(thd, tables))
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
error= FALSE;
|
error= FALSE;
|
||||||
|
|
||||||
err:
|
err:
|
||||||
|
@ -3776,20 +3776,15 @@ bool mysql_unpack_partition(THD *thd,
|
|||||||
ha_legacy_type(default_db_type)));
|
ha_legacy_type(default_db_type)));
|
||||||
if (is_create_table_ind && old_lex->sql_command == SQLCOM_CREATE_TABLE)
|
if (is_create_table_ind && old_lex->sql_command == SQLCOM_CREATE_TABLE)
|
||||||
{
|
{
|
||||||
if (old_lex->like_name)
|
if (old_lex->create_info.options & HA_LEX_CREATE_TABLE_LIKE)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
This code is executed when we do a CREATE TABLE t1 LIKE t2
|
This code is executed when we create table in CREATE TABLE t1 LIKE t2.
|
||||||
old_lex->like_name contains the t2 and the table we are opening has
|
old_lex->query_tables contains table list element for t2 and the table
|
||||||
name t1.
|
we are opening has name t1.
|
||||||
*/
|
*/
|
||||||
Table_ident *table_ident= old_lex->like_name;
|
if (partition_default_handling(table, part_info, FALSE,
|
||||||
char *src_db= table_ident->db.str ? table_ident->db.str : thd->db;
|
old_lex->query_tables->table->s->path.str))
|
||||||
char *src_table= table_ident->table.str;
|
|
||||||
char buf[FN_REFLEN];
|
|
||||||
build_table_filename(buf, sizeof(buf), src_db, src_table, "", 0);
|
|
||||||
if (partition_default_handling(table, part_info,
|
|
||||||
FALSE, buf))
|
|
||||||
{
|
{
|
||||||
result= TRUE;
|
result= TRUE;
|
||||||
goto end;
|
goto end;
|
||||||
|
137
sql/sql_table.cc
137
sql/sql_table.cc
@ -4665,114 +4665,51 @@ bool mysql_preload_keys(THD* thd, TABLE_LIST* tables)
|
|||||||
SYNOPSIS
|
SYNOPSIS
|
||||||
mysql_create_like_table()
|
mysql_create_like_table()
|
||||||
thd Thread object
|
thd Thread object
|
||||||
table Table list (one table only)
|
table Table list element for target table
|
||||||
|
src_table Table list element for source table
|
||||||
create_info Create info
|
create_info Create info
|
||||||
table_ident Src table_ident
|
|
||||||
|
|
||||||
RETURN VALUES
|
RETURN VALUES
|
||||||
FALSE OK
|
FALSE OK
|
||||||
TRUE error
|
TRUE error
|
||||||
*/
|
*/
|
||||||
|
|
||||||
bool mysql_create_like_table(THD* thd, TABLE_LIST* table,
|
bool mysql_create_like_table(THD* thd, TABLE_LIST* table, TABLE_LIST* src_table,
|
||||||
HA_CREATE_INFO *lex_create_info,
|
HA_CREATE_INFO *lex_create_info)
|
||||||
Table_ident *table_ident)
|
|
||||||
{
|
{
|
||||||
TABLE *tmp_table, *name_lock= 0;
|
TABLE *name_lock= 0;
|
||||||
char src_path[FN_REFLEN], dst_path[FN_REFLEN];
|
char src_path[FN_REFLEN], dst_path[FN_REFLEN];
|
||||||
char src_table_name_buff[FN_REFLEN], src_db_name_buff[FN_REFLEN];
|
|
||||||
uint dst_path_length;
|
uint dst_path_length;
|
||||||
char *db= table->db;
|
char *db= table->db;
|
||||||
char *table_name= table->table_name;
|
char *table_name= table->table_name;
|
||||||
char *src_db;
|
|
||||||
char *src_table= table_ident->table.str;
|
|
||||||
int err;
|
int err;
|
||||||
bool res= TRUE;
|
bool res= TRUE;
|
||||||
enum legacy_db_type not_used;
|
uint not_used;
|
||||||
HA_CREATE_INFO *create_info;
|
HA_CREATE_INFO *create_info;
|
||||||
#ifdef WITH_PARTITION_STORAGE_ENGINE
|
#ifdef WITH_PARTITION_STORAGE_ENGINE
|
||||||
char tmp_path[FN_REFLEN];
|
char tmp_path[FN_REFLEN];
|
||||||
#endif
|
#endif
|
||||||
char ts_name[FN_LEN];
|
char ts_name[FN_LEN];
|
||||||
TABLE_LIST src_tables_list;
|
|
||||||
DBUG_ENTER("mysql_create_like_table");
|
DBUG_ENTER("mysql_create_like_table");
|
||||||
|
|
||||||
if (!(create_info= copy_create_info(lex_create_info)))
|
if (!(create_info= copy_create_info(lex_create_info)))
|
||||||
{
|
{
|
||||||
DBUG_RETURN(TRUE);
|
DBUG_RETURN(TRUE);
|
||||||
}
|
}
|
||||||
DBUG_ASSERT(table_ident->db.str); /* Must be set in the parser */
|
|
||||||
src_db= table_ident->db.str;
|
/* CREATE TABLE ... LIKE is not allowed for views. */
|
||||||
|
src_table->required_type= FRMTYPE_TABLE;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Validate the source table
|
By opening source table we guarantee that it exists and no concurrent
|
||||||
|
DDL operation will mess with it. Later we also take an exclusive
|
||||||
|
name-lock on target table name, which makes copying of .frm file,
|
||||||
|
call to ha_create_table() and binlogging atomic against concurrent DML
|
||||||
|
and DDL operations on target table. Thus by holding both these "locks"
|
||||||
|
we ensure that our statement is properly isolated from all concurrent
|
||||||
|
operations which matter.
|
||||||
*/
|
*/
|
||||||
if (check_string_char_length(&table_ident->table, "", NAME_CHAR_LEN,
|
if (open_tables(thd, &src_table, ¬_used, 0))
|
||||||
system_charset_info, 1) ||
|
|
||||||
(table_ident->table.length &&
|
|
||||||
check_table_name(src_table,table_ident->table.length)))
|
|
||||||
{
|
|
||||||
my_error(ER_WRONG_TABLE_NAME, MYF(0), src_table);
|
|
||||||
DBUG_RETURN(TRUE);
|
|
||||||
}
|
|
||||||
if (!src_db || check_db_name(&table_ident->db))
|
|
||||||
{
|
|
||||||
my_error(ER_WRONG_DB_NAME, MYF(0), src_db ? src_db : "NULL");
|
|
||||||
DBUG_RETURN(-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((tmp_table= find_temporary_table(thd, src_db, src_table)))
|
|
||||||
strxmov(src_path, tmp_table->s->path.str, reg_ext, NullS);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
build_table_filename(src_path, sizeof(src_path),
|
|
||||||
src_db, src_table, reg_ext, 0);
|
|
||||||
/* Resolve symlinks (for windows) */
|
|
||||||
unpack_filename(src_path, src_path);
|
|
||||||
if (lower_case_table_names)
|
|
||||||
my_casedn_str(files_charset_info, src_path);
|
|
||||||
if (access(src_path, F_OK))
|
|
||||||
{
|
|
||||||
my_error(ER_BAD_TABLE_ERROR, MYF(0), src_table);
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
create like should be not allowed for Views, Triggers, ...
|
|
||||||
*/
|
|
||||||
if (mysql_frm_type(thd, src_path, ¬_used) != FRMTYPE_TABLE)
|
|
||||||
{
|
|
||||||
my_error(ER_WRONG_OBJECT, MYF(0), src_db, src_table, "BASE TABLE");
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (lower_case_table_names)
|
|
||||||
{
|
|
||||||
if (src_db)
|
|
||||||
{
|
|
||||||
strmake(src_db_name_buff, src_db,
|
|
||||||
min(sizeof(src_db_name_buff) - 1, table_ident->db.length));
|
|
||||||
my_casedn_str(files_charset_info, src_db_name_buff);
|
|
||||||
src_db= src_db_name_buff;
|
|
||||||
}
|
|
||||||
if (src_table)
|
|
||||||
{
|
|
||||||
strmake(src_table_name_buff, src_table,
|
|
||||||
min(sizeof(src_table_name_buff) - 1, table_ident->table.length));
|
|
||||||
my_casedn_str(files_charset_info, src_table_name_buff);
|
|
||||||
src_table= src_table_name_buff;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bzero((gptr)&src_tables_list, sizeof(src_tables_list));
|
|
||||||
src_tables_list.db= src_db;
|
|
||||||
src_tables_list.db_length= table_ident->db.length;
|
|
||||||
src_tables_list.lock_type= TL_READ;
|
|
||||||
src_tables_list.table_name= src_table;
|
|
||||||
src_tables_list.alias= src_table;
|
|
||||||
|
|
||||||
if (simple_open_n_lock_tables(thd, &src_tables_list))
|
|
||||||
DBUG_RETURN(TRUE);
|
DBUG_RETURN(TRUE);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -4781,17 +4718,19 @@ bool mysql_create_like_table(THD* thd, TABLE_LIST* table,
|
|||||||
Add something to get possible tablespace info from src table,
|
Add something to get possible tablespace info from src table,
|
||||||
it can get valid tablespace name only for disk-base ndb table
|
it can get valid tablespace name only for disk-base ndb table
|
||||||
*/
|
*/
|
||||||
if ((src_tables_list.table->file->get_tablespace_name(thd, ts_name, FN_LEN)))
|
if ((src_table->table->file->get_tablespace_name(thd, ts_name, FN_LEN)))
|
||||||
{
|
{
|
||||||
create_info->tablespace= ts_name;
|
create_info->tablespace= ts_name;
|
||||||
create_info->storage_media= HA_SM_DISK;
|
create_info->storage_media= HA_SM_DISK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
strxmov(src_path, src_table->table->s->path.str, reg_ext, NullS);
|
||||||
Validate the destination table
|
|
||||||
|
|
||||||
skip the destination table name checking as this is already
|
DBUG_EXECUTE_IF("sleep_create_like_before_check_if_exists", my_sleep(6000000););
|
||||||
validated.
|
|
||||||
|
/*
|
||||||
|
Check that destination tables does not exist. Note that its name
|
||||||
|
was already checked when it was added to the table list.
|
||||||
*/
|
*/
|
||||||
if (create_info->options & HA_LEX_CREATE_TMP_TABLE)
|
if (create_info->options & HA_LEX_CREATE_TMP_TABLE)
|
||||||
{
|
{
|
||||||
@ -4812,15 +4751,29 @@ bool mysql_create_like_table(THD* thd, TABLE_LIST* table,
|
|||||||
goto table_exists;
|
goto table_exists;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DBUG_EXECUTE_IF("sleep_create_like_before_copy", my_sleep(6000000););
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Create a new table by copying from source table
|
Create a new table by copying from source table
|
||||||
|
|
||||||
|
Altough exclusive name-lock on target table protects us from concurrent
|
||||||
|
DML and DDL operations on it we still want to wrap .FRM creation and call
|
||||||
|
to ha_create_table() in critical section protected by LOCK_open in order
|
||||||
|
to provide minimal atomicity against operations which disregard name-locks,
|
||||||
|
like I_S implementation, for example. This is a temporary and should not
|
||||||
|
be copied. Instead we should fix our code to always honor name-locks.
|
||||||
|
|
||||||
|
Also some engines (e.g. NDB cluster) require that LOCK_open should be held
|
||||||
|
during the call to ha_create_table(). See bug #28614 for more info.
|
||||||
*/
|
*/
|
||||||
|
VOID(pthread_mutex_lock(&LOCK_open));
|
||||||
if (my_copy(src_path, dst_path, MYF(MY_DONT_OVERWRITE_FILE)))
|
if (my_copy(src_path, dst_path, MYF(MY_DONT_OVERWRITE_FILE)))
|
||||||
{
|
{
|
||||||
if (my_errno == ENOENT)
|
if (my_errno == ENOENT)
|
||||||
my_error(ER_BAD_DB_ERROR,MYF(0),db);
|
my_error(ER_BAD_DB_ERROR,MYF(0),db);
|
||||||
else
|
else
|
||||||
my_error(ER_CANT_CREATE_FILE,MYF(0),dst_path,my_errno);
|
my_error(ER_CANT_CREATE_FILE,MYF(0),dst_path,my_errno);
|
||||||
|
VOID(pthread_mutex_unlock(&LOCK_open));
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4842,10 +4795,12 @@ bool mysql_create_like_table(THD* thd, TABLE_LIST* table,
|
|||||||
strmov(src_path, tmp_path);
|
strmov(src_path, tmp_path);
|
||||||
my_copy(src_path, dst_path, MYF(MY_DONT_OVERWRITE_FILE));
|
my_copy(src_path, dst_path, MYF(MY_DONT_OVERWRITE_FILE));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
DBUG_EXECUTE_IF("sleep_create_like_before_ha_create", my_sleep(6000000););
|
||||||
|
|
||||||
dst_path[dst_path_length - reg_ext_length]= '\0'; // Remove .frm
|
dst_path[dst_path_length - reg_ext_length]= '\0'; // Remove .frm
|
||||||
pthread_mutex_lock(&LOCK_open);
|
|
||||||
err= ha_create_table(thd, dst_path, db, table_name, create_info, 1);
|
err= ha_create_table(thd, dst_path, db, table_name, create_info, 1);
|
||||||
pthread_mutex_unlock(&LOCK_open);
|
VOID(pthread_mutex_unlock(&LOCK_open));
|
||||||
if (create_info->options & HA_LEX_CREATE_TMP_TABLE)
|
if (create_info->options & HA_LEX_CREATE_TMP_TABLE)
|
||||||
{
|
{
|
||||||
if (err || !open_temporary_table(thd, dst_path, db, table_name, 1))
|
if (err || !open_temporary_table(thd, dst_path, db, table_name, 1))
|
||||||
@ -4862,6 +4817,8 @@ bool mysql_create_like_table(THD* thd, TABLE_LIST* table,
|
|||||||
goto err; /* purecov: inspected */
|
goto err; /* purecov: inspected */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DBUG_EXECUTE_IF("sleep_create_like_before_binlogging", my_sleep(6000000););
|
||||||
|
|
||||||
/*
|
/*
|
||||||
We have to write the query before we unlock the tables.
|
We have to write the query before we unlock the tables.
|
||||||
*/
|
*/
|
||||||
@ -4881,14 +4838,10 @@ bool mysql_create_like_table(THD* thd, TABLE_LIST* table,
|
|||||||
3 temporary normal Nothing
|
3 temporary normal Nothing
|
||||||
4 temporary temporary Nothing
|
4 temporary temporary Nothing
|
||||||
==== ========= ========= ==============================
|
==== ========= ========= ==============================
|
||||||
|
|
||||||
The variable 'tmp_table' below is used to see if the source
|
|
||||||
table is a temporary table: if it is set, then the source table
|
|
||||||
was a temporary table and we can take apropriate actions.
|
|
||||||
*/
|
*/
|
||||||
if (!(create_info->options & HA_LEX_CREATE_TMP_TABLE))
|
if (!(create_info->options & HA_LEX_CREATE_TMP_TABLE))
|
||||||
{
|
{
|
||||||
if (tmp_table) // Case 2
|
if (src_table->table->s->tmp_table) // Case 2
|
||||||
{
|
{
|
||||||
char buf[2048];
|
char buf[2048];
|
||||||
String query(buf, sizeof(buf), system_charset_info);
|
String query(buf, sizeof(buf), system_charset_info);
|
||||||
|
@ -1579,7 +1579,6 @@ create:
|
|||||||
lex->create_info.default_table_charset= NULL;
|
lex->create_info.default_table_charset= NULL;
|
||||||
lex->name.str= 0;
|
lex->name.str= 0;
|
||||||
lex->name.length= 0;
|
lex->name.length= 0;
|
||||||
lex->like_name= 0;
|
|
||||||
}
|
}
|
||||||
create2
|
create2
|
||||||
{
|
{
|
||||||
@ -3603,27 +3602,15 @@ create2:
|
|||||||
create3 {}
|
create3 {}
|
||||||
| LIKE table_ident
|
| LIKE table_ident
|
||||||
{
|
{
|
||||||
THD *thd= YYTHD;
|
Lex->create_info.options|= HA_LEX_CREATE_TABLE_LIKE;
|
||||||
LEX *lex= thd->lex;
|
if (!Lex->select_lex.add_table_to_list(YYTHD, $2, NULL, 0, TL_READ))
|
||||||
if (!(lex->like_name= $2))
|
|
||||||
MYSQL_YYABORT;
|
MYSQL_YYABORT;
|
||||||
if ($2->db.str == NULL &&
|
|
||||||
thd->copy_db_to(&($2->db.str), &($2->db.length)))
|
|
||||||
{
|
|
||||||
MYSQL_YYABORT;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
| '(' LIKE table_ident ')'
|
| '(' LIKE table_ident ')'
|
||||||
{
|
{
|
||||||
THD *thd= YYTHD;
|
Lex->create_info.options|= HA_LEX_CREATE_TABLE_LIKE;
|
||||||
LEX *lex= thd->lex;
|
if (!Lex->select_lex.add_table_to_list(YYTHD, $3, NULL, 0, TL_READ))
|
||||||
if (!(lex->like_name= $3))
|
|
||||||
MYSQL_YYABORT;
|
MYSQL_YYABORT;
|
||||||
if ($3->db.str == NULL &&
|
|
||||||
thd->copy_db_to(&($3->db.str), &($3->db.length)))
|
|
||||||
{
|
|
||||||
MYSQL_YYABORT;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
@ -5112,7 +5099,6 @@ alter:
|
|||||||
lex->key_list.empty();
|
lex->key_list.empty();
|
||||||
lex->col_list.empty();
|
lex->col_list.empty();
|
||||||
lex->select_lex.init_order();
|
lex->select_lex.init_order();
|
||||||
lex->like_name= 0;
|
|
||||||
lex->select_lex.db=
|
lex->select_lex.db=
|
||||||
((TABLE_LIST*) lex->select_lex.table_list.first)->db;
|
((TABLE_LIST*) lex->select_lex.table_list.first)->db;
|
||||||
bzero((char*) &lex->create_info,sizeof(lex->create_info));
|
bzero((char*) &lex->create_info,sizeof(lex->create_info));
|
||||||
|
Reference in New Issue
Block a user