From 2d788ff5ca24d88853d3e201253a724392135f06 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Tue, 9 Apr 2013 16:07:35 +0200 Subject: [PATCH] test_sql_discovery storage engine use it to test main test cases with need_full_discover_for_existence > 0 --- sql/sql_base.cc | 9 - sql/sql_rename.cc | 13 +- sql/sql_rename.h | 3 - sql/sql_table.cc | 1 - storage/test_sql_discovery/CMakeLists.txt | 2 + .../mysql-test/archive/discover.test | 3 + .../main/r/partition_disabled.rdiff | 11 + .../mysql-test/main/r/plugin.rdiff | 11 + .../mysql-test/main/t/create.test | 3 + .../mysql-test/main/t/drop.test | 3 + .../mysql-test/main/t/mdl_sync.test | 3 + .../mysql-test/main/t/partition_disabled.test | 3 + .../mysql-test/main/t/plugin.test | 3 + .../mysql-test/main/t/rename.test | 3 + .../mysql-test/sql_discovery/inc.inc | 4 + .../mysql-test/sql_discovery/inc.opt | 1 + .../mysql-test/sql_discovery/simple.result | 199 ++++++++++++++++++ .../mysql-test/sql_discovery/simple.test | 133 ++++++++++++ .../test_sql_discovery/test_sql_discovery.cc | 175 +++++++++++++++ 19 files changed, 565 insertions(+), 18 deletions(-) create mode 100644 storage/test_sql_discovery/CMakeLists.txt create mode 100644 storage/test_sql_discovery/mysql-test/archive/discover.test create mode 100644 storage/test_sql_discovery/mysql-test/main/r/partition_disabled.rdiff create mode 100644 storage/test_sql_discovery/mysql-test/main/r/plugin.rdiff create mode 100644 storage/test_sql_discovery/mysql-test/main/t/create.test create mode 100644 storage/test_sql_discovery/mysql-test/main/t/drop.test create mode 100644 storage/test_sql_discovery/mysql-test/main/t/mdl_sync.test create mode 100644 storage/test_sql_discovery/mysql-test/main/t/partition_disabled.test create mode 100644 storage/test_sql_discovery/mysql-test/main/t/plugin.test create mode 100644 storage/test_sql_discovery/mysql-test/main/t/rename.test create mode 100644 storage/test_sql_discovery/mysql-test/sql_discovery/inc.inc create mode 100644 storage/test_sql_discovery/mysql-test/sql_discovery/inc.opt create mode 100644 storage/test_sql_discovery/mysql-test/sql_discovery/simple.result create mode 100644 storage/test_sql_discovery/mysql-test/sql_discovery/simple.test create mode 100644 storage/test_sql_discovery/test_sql_discovery.cc diff --git a/sql/sql_base.cc b/sql/sql_base.cc index f88a3ef05f9..15eab7f32df 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -713,15 +713,6 @@ end: */ share= (TABLE_SHARE*) 1; } - else - { - /* - To be able perform any operation on table we should own - some kind of metadata lock on it. - */ - DBUG_ASSERT(thd->mdl_context.is_lock_owner(MDL_key::TABLE, db, table_name, - MDL_SHARED)); - } mysql_mutex_unlock(&LOCK_open); DBUG_RETURN(share); diff --git a/sql/sql_rename.cc b/sql/sql_rename.cc index 2c75de6e8a6..c957076ac4f 100644 --- a/sql/sql_rename.cc +++ b/sql/sql_rename.cc @@ -32,6 +32,9 @@ static TABLE_LIST *rename_tables(THD *thd, TABLE_LIST *table_list, bool skip_error); +static bool do_rename(THD *thd, TABLE_LIST *ren_table, char *new_db, + char *new_table_name, char *new_table_alias, + bool skip_error); static TABLE_LIST *reverse_table_list(TABLE_LIST *table_list); @@ -144,10 +147,6 @@ bool mysql_rename_tables(THD *thd, TABLE_LIST *table_list, bool silent) MYSQL_OPEN_SKIP_TEMPORARY)) goto err; - for (ren_table= table_list; ren_table; ren_table= ren_table->next_local) - tdc_remove_table(thd, TDC_RT_REMOVE_ALL, ren_table->db, - ren_table->table_name, FALSE); - error=0; /* An exclusive lock on table names is satisfactory to ensure @@ -235,7 +234,7 @@ static TABLE_LIST *reverse_table_list(TABLE_LIST *table_list) true rename failed */ -bool +static bool do_rename(THD *thd, TABLE_LIST *ren_table, char *new_db, char *new_table_name, char *new_table_alias, bool skip_error) { @@ -269,6 +268,10 @@ do_rename(THD *thd, TABLE_LIST *ren_table, char *new_db, char *new_table_name, if (old_exists) { + DBUG_ASSERT(!thd->locked_tables_mode); + tdc_remove_table(thd, TDC_RT_REMOVE_ALL, + ren_table->db, ren_table->table_name, false); + if (hton != view_pseudo_hton) { if (!(rc= mysql_rename_table(hton, ren_table->db, old_alias, diff --git a/sql/sql_rename.h b/sql/sql_rename.h index 039a3b8b4a1..aaf09a8d030 100644 --- a/sql/sql_rename.h +++ b/sql/sql_rename.h @@ -20,8 +20,5 @@ class THD; struct TABLE_LIST; bool mysql_rename_tables(THD *thd, TABLE_LIST *table_list, bool silent); -bool do_rename(THD *thd, TABLE_LIST *ren_table, char *new_db, - char *new_table_name, char *new_table_alias, - bool skip_error); #endif /* SQL_RENAME_INCLUDED */ diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 0a02e674c07..8f2320b9b30 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -22,7 +22,6 @@ #include "unireg.h" #include "debug_sync.h" #include "sql_table.h" -#include "sql_rename.h" // do_rename #include "sql_parse.h" // test_if_data_home_dir #include "sql_cache.h" // query_cache_* #include "sql_base.h" // open_table_uncached, lock_table_names diff --git a/storage/test_sql_discovery/CMakeLists.txt b/storage/test_sql_discovery/CMakeLists.txt new file mode 100644 index 00000000000..2039b08123c --- /dev/null +++ b/storage/test_sql_discovery/CMakeLists.txt @@ -0,0 +1,2 @@ +MYSQL_ADD_PLUGIN(test_sql_discovery test_sql_discovery.cc STORAGE_ENGINE + COMPONENT Test) diff --git a/storage/test_sql_discovery/mysql-test/archive/discover.test b/storage/test_sql_discovery/mysql-test/archive/discover.test new file mode 100644 index 00000000000..6d7414280c5 --- /dev/null +++ b/storage/test_sql_discovery/mysql-test/archive/discover.test @@ -0,0 +1,3 @@ +# run the normal test file with need_full_discover_for_existence>0 +--source ../sql_discovery/inc.inc +--source discover.test diff --git a/storage/test_sql_discovery/mysql-test/main/r/partition_disabled.rdiff b/storage/test_sql_discovery/mysql-test/main/r/partition_disabled.rdiff new file mode 100644 index 00000000000..3bb52b39d29 --- /dev/null +++ b/storage/test_sql_discovery/mysql-test/main/r/partition_disabled.rdiff @@ -0,0 +1,11 @@ +--- r/partition_disabled.result 2013-04-07 12:36:57.000000000 +0200 ++++ /usr/home/serg/Abk/mysql/10.0-serg/storage/test_sql_discovery/mysql-test/main/r/partition_disabled.reject 2013-04-07 23:19:14.000000000 +0200 +@@ -3,7 +3,7 @@ + SELECT * FROM t1; + ERROR HY000: The MariaDB server is running with the --skip-partition option so it cannot execute this statement + TRUNCATE TABLE t1; +-ERROR 42S02: Table 'test.t1' doesn't exist ++ERROR HY000: The MariaDB server is running with the --skip-partition option so it cannot execute this statement + ANALYZE TABLE t1; + Table Op Msg_type Msg_text + test.t1 analyze Error The MariaDB server is running with the --skip-partition option so it cannot execute this statement diff --git a/storage/test_sql_discovery/mysql-test/main/r/plugin.rdiff b/storage/test_sql_discovery/mysql-test/main/r/plugin.rdiff new file mode 100644 index 00000000000..b9288d70f4b --- /dev/null +++ b/storage/test_sql_discovery/mysql-test/main/r/plugin.rdiff @@ -0,0 +1,11 @@ +--- r/plugin.result 2013-02-21 19:46:59.000000000 +0100 ++++ r/plugin.reject 2013-02-27 11:13:22.000000000 +0100 +@@ -71,6 +71,8 @@ + SELECT * FROM t2; + ERROR 42000: Unknown storage engine 'EXAMPLE' + DROP TABLE t2; ++Warnings: ++Error 1286 Unknown storage engine 'EXAMPLE' + UNINSTALL PLUGIN EXAMPLE; + ERROR 42000: PLUGIN EXAMPLE does not exist + UNINSTALL PLUGIN non_exist; diff --git a/storage/test_sql_discovery/mysql-test/main/t/create.test b/storage/test_sql_discovery/mysql-test/main/t/create.test new file mode 100644 index 00000000000..4b3dd16c0a2 --- /dev/null +++ b/storage/test_sql_discovery/mysql-test/main/t/create.test @@ -0,0 +1,3 @@ +# run the normal test file with need_full_discover_for_existence>0 +--source ../sql_discovery/inc.inc +--source create.test diff --git a/storage/test_sql_discovery/mysql-test/main/t/drop.test b/storage/test_sql_discovery/mysql-test/main/t/drop.test new file mode 100644 index 00000000000..2b3f864ec6b --- /dev/null +++ b/storage/test_sql_discovery/mysql-test/main/t/drop.test @@ -0,0 +1,3 @@ +# run the normal test file with need_full_discover_for_existence>0 +--source ../sql_discovery/inc.inc +--source drop.test diff --git a/storage/test_sql_discovery/mysql-test/main/t/mdl_sync.test b/storage/test_sql_discovery/mysql-test/main/t/mdl_sync.test new file mode 100644 index 00000000000..9c052839d93 --- /dev/null +++ b/storage/test_sql_discovery/mysql-test/main/t/mdl_sync.test @@ -0,0 +1,3 @@ +# run the normal test file with need_full_discover_for_existence>0 +--source ../sql_discovery/inc.inc +--source mdl_sync.test diff --git a/storage/test_sql_discovery/mysql-test/main/t/partition_disabled.test b/storage/test_sql_discovery/mysql-test/main/t/partition_disabled.test new file mode 100644 index 00000000000..7fccc33fdbd --- /dev/null +++ b/storage/test_sql_discovery/mysql-test/main/t/partition_disabled.test @@ -0,0 +1,3 @@ +# run the normal test file with need_full_discover_for_existence>0 +--source ../sql_discovery/inc.inc +--source partition_disabled.test diff --git a/storage/test_sql_discovery/mysql-test/main/t/plugin.test b/storage/test_sql_discovery/mysql-test/main/t/plugin.test new file mode 100644 index 00000000000..52315af0645 --- /dev/null +++ b/storage/test_sql_discovery/mysql-test/main/t/plugin.test @@ -0,0 +1,3 @@ +# run the normal test file with need_full_discover_for_existence>0 +--source ../sql_discovery/inc.inc +--source plugin.test diff --git a/storage/test_sql_discovery/mysql-test/main/t/rename.test b/storage/test_sql_discovery/mysql-test/main/t/rename.test new file mode 100644 index 00000000000..ba645131401 --- /dev/null +++ b/storage/test_sql_discovery/mysql-test/main/t/rename.test @@ -0,0 +1,3 @@ +# run the normal test file with need_full_discover_for_existence>0 +--source ../sql_discovery/inc.inc +--source rename.test diff --git a/storage/test_sql_discovery/mysql-test/sql_discovery/inc.inc b/storage/test_sql_discovery/mysql-test/sql_discovery/inc.inc new file mode 100644 index 00000000000..b13cbd7d12b --- /dev/null +++ b/storage/test_sql_discovery/mysql-test/sql_discovery/inc.inc @@ -0,0 +1,4 @@ +if (`SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.ENGINES WHERE engine = 'test_sql_discovery' AND support='YES'`) +{ + --skip Test requires test_sql_discovery engine +} diff --git a/storage/test_sql_discovery/mysql-test/sql_discovery/inc.opt b/storage/test_sql_discovery/mysql-test/sql_discovery/inc.opt new file mode 100644 index 00000000000..32a5e3a294e --- /dev/null +++ b/storage/test_sql_discovery/mysql-test/sql_discovery/inc.opt @@ -0,0 +1 @@ +--plugin-load=$HA_TEST_SQL_DISCOVERY_SO diff --git a/storage/test_sql_discovery/mysql-test/sql_discovery/simple.result b/storage/test_sql_discovery/mysql-test/sql_discovery/simple.result new file mode 100644 index 00000000000..c2b9160f7c3 --- /dev/null +++ b/storage/test_sql_discovery/mysql-test/sql_discovery/simple.result @@ -0,0 +1,199 @@ +show variables like 'test_sql_discovery%'; +Variable_name Value +test_sql_discovery_statement +test_sql_discovery_write_frm ON +set sql_quote_show_create=0; +create table t1 (a int) engine=test_sql_discovery; +ERROR HY000: Can't create table 'test.t1' (errno: 131 "Command not supported by database") +select * from t1; +ERROR 42S02: Table 'test.t1' doesn't exist +set @@test_sql_discovery_statement='t1:foobar bwa-ha-ha'; +select * from t0; +ERROR 42S02: Table 'test.t0' doesn't exist +select * from t1; +ERROR 42S02: Table 'test.t1' doesn't exist +show warnings; +Level Code Message +Error 1064 You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'foobar bwa-ha-ha' at line 1 +Error 1146 Table 'test.t1' doesn't exist +Error 1030 Got error 130 "Incorrect file format" from storage engine +set @@test_sql_discovery_statement='t1:select 1'; +select * from t1; +ERROR 42S02: Table 'test.t1' doesn't exist +show warnings; +Level Code Message +Error 1939 Engine TEST_SQL_DISCOVERY failed to discover table `test`.`t1` with 'select 1' +Error 1146 Table 'test.t1' doesn't exist +Error 1030 Got error 130 "Incorrect file format" from storage engine +set @@test_sql_discovery_statement='t1:create table t1 (a int primary key) partition by hash(id) partitions 2'; +select * from t1; +ERROR 42S02: Table 'test.t1' doesn't exist +show warnings; +Level Code Message +Error 1290 The MariaDB server is running with the --skip-partition option so it cannot execute this statement +Error 1146 Table 'test.t1' doesn't exist +Error 1030 Got error 130 "Incorrect file format" from storage engine +set @@test_sql_discovery_statement='t1:create table t1 (a int) union=(t3,t4)'; +select * from t1; +ERROR 42S02: Table 'test.t1' doesn't exist +show warnings; +Level Code Message +Error 1939 Engine TEST_SQL_DISCOVERY failed to discover table `test`.`t1` with 'create table t1 (a int) union=(t3,t4)' +Error 1146 Table 'test.t1' doesn't exist +Error 1030 Got error 130 "Incorrect file format" from storage engine +set @@test_sql_discovery_statement='t1:create table t1 like t2'; +select * from t1; +ERROR 42S02: Table 'test.t1' doesn't exist +show warnings; +Level Code Message +Error 1939 Engine TEST_SQL_DISCOVERY failed to discover table `test`.`t1` with 'create table t1 like t2' +Error 1146 Table 'test.t1' doesn't exist +Error 1030 Got error 130 "Incorrect file format" from storage engine +set @@test_sql_discovery_statement='t1:create table t1 select * from t2'; +select * from t1; +ERROR 42S02: Table 'test.t1' doesn't exist +show warnings; +Level Code Message +Error 1939 Engine TEST_SQL_DISCOVERY failed to discover table `test`.`t1` with 'create table t1 select * from t2' +Error 1146 Table 'test.t1' doesn't exist +Error 1030 Got error 130 "Incorrect file format" from storage engine +set @@test_sql_discovery_statement='t1:create table t1 (a int) index directory="/tmp"'; +select * from t1; +ERROR 42S02: Table 'test.t1' doesn't exist +show warnings; +Level Code Message +Error 1939 Engine TEST_SQL_DISCOVERY failed to discover table `test`.`t1` with 'create table t1 (a int) index directory="/tmp"' +Error 1146 Table 'test.t1' doesn't exist +Error 1030 Got error 130 "Incorrect file format" from storage engine +set @@test_sql_discovery_statement='t1:create table t1 (a int) data directory="/tmp"'; +select * from t1; +ERROR 42S02: Table 'test.t1' doesn't exist +show warnings; +Level Code Message +Error 1939 Engine TEST_SQL_DISCOVERY failed to discover table `test`.`t1` with 'create table t1 (a int) data directory="/tmp"' +Error 1146 Table 'test.t1' doesn't exist +Error 1030 Got error 130 "Incorrect file format" from storage engine +set @@test_sql_discovery_statement='t1:create table t1 (a int) engine=myisam'; +select * from t1; +ERROR 42S02: Table 'test.t1' doesn't exist +show warnings; +Level Code Message +Error 1939 Engine TEST_SQL_DISCOVERY failed to discover table `test`.`t1` with 'create table t1 (a int) engine=myisam' +Error 1146 Table 'test.t1' doesn't exist +Error 1030 Got error 130 "Incorrect file format" from storage engine +set @@test_sql_discovery_statement='t1:create temporary table t1 (a int)'; +select * from t1; +ERROR 42S02: Table 'test.t1' doesn't exist +show warnings; +Level Code Message +Error 1939 Engine TEST_SQL_DISCOVERY failed to discover table `test`.`t1` with 'create temporary table t1 (a int)' +Error 1146 Table 'test.t1' doesn't exist +Error 1030 Got error 130 "Incorrect file format" from storage engine +set @@test_sql_discovery_statement='t1:create table if not exists t1 (a int)'; +select * from t1; +ERROR 42S02: Table 'test.t1' doesn't exist +show warnings; +Level Code Message +Error 1939 Engine TEST_SQL_DISCOVERY failed to discover table `test`.`t1` with 'create table if not exists t1 (a int)' +Error 1146 Table 'test.t1' doesn't exist +Error 1030 Got error 130 "Incorrect file format" from storage engine +set @@test_sql_discovery_statement='t1:create table t1 (a int)'; +select * from t1; +a +show create table t1; +Table Create Table +t1 CREATE TABLE t1 ( + a int(11) DEFAULT NULL +) ENGINE=TEST_SQL_DISCOVERY DEFAULT CHARSET=latin1 +drop table t1; +set @@test_sql_discovery_statement='t1:create table t2 (a int)'; +select * from t1; +a +select * from t2; +ERROR 42S02: Table 'test.t2' doesn't exist +drop table t1; +set @@test_sql_discovery_statement='t1: +create table t1 ( + a int not null default 5 primary key, + b timestamp, + c tinyblob, + d decimal(5,2), + e varchar(30) character set ascii, + f geometry not null, + index (d,b), + unique index (c(10)), + fulltext (e), + spatial (f) +) comment="abc" default character set utf8 max_rows=100 min_rows=10 checksum=1'; +show status like 'handler_discover'; +Variable_name Value +Handler_discover 13 +show create table t1; +Table Create Table +t1 CREATE TABLE t1 ( + a int(11) NOT NULL DEFAULT '5', + b timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', + c tinyblob, + d decimal(5,2) DEFAULT NULL, + e varchar(30) CHARACTER SET ascii DEFAULT NULL, + f geometry NOT NULL, + PRIMARY KEY (a), + UNIQUE KEY c (c(10)), + KEY d (d,b), + SPATIAL KEY f (f), + FULLTEXT KEY e (e) +) ENGINE=TEST_SQL_DISCOVERY DEFAULT CHARSET=utf8 MIN_ROWS=10 MAX_ROWS=100 CHECKSUM=1 COMMENT='abc' +show status like 'handler_discover'; +Variable_name Value +Handler_discover 14 +---- +t1.frm +---- +show open tables from test; +Database Table In_use Name_locked +test t1 0 0 +select * from t1; +a b c d e f +show status like 'handler_discover'; +Variable_name Value +Handler_discover 14 +flush tables; +select * from t1; +a b c d e f +show status like 'handler_discover'; +Variable_name Value +Handler_discover 14 +drop table t1; +set @@test_sql_discovery_write_frm=0; +set @@test_sql_discovery_statement='t1:create table t1 (a int)'; +show status like 'handler_discover'; +Variable_name Value +Handler_discover 14 +show create table t1; +Table Create Table +t1 CREATE TABLE t1 ( + a int(11) DEFAULT NULL +) ENGINE=TEST_SQL_DISCOVERY DEFAULT CHARSET=latin1 +show status like 'handler_discover'; +Variable_name Value +Handler_discover 15 +---- +---- +show open tables from test; +Database Table In_use Name_locked +test t1 0 0 +select * from t1; +a +show status like 'handler_discover'; +Variable_name Value +Handler_discover 15 +flush tables; +select * from t1; +a +show status like 'handler_discover'; +Variable_name Value +Handler_discover 16 +drop table t1; +show status like 'handler_discover'; +Variable_name Value +Handler_discover 16 diff --git a/storage/test_sql_discovery/mysql-test/sql_discovery/simple.test b/storage/test_sql_discovery/mysql-test/sql_discovery/simple.test new file mode 100644 index 00000000000..4aa5ac2864e --- /dev/null +++ b/storage/test_sql_discovery/mysql-test/sql_discovery/simple.test @@ -0,0 +1,133 @@ +--source inc.inc + +show variables like 'test_sql_discovery%'; +set sql_quote_show_create=0; +let $mysqld_datadir= `select @@datadir`; + +--error ER_CANT_CREATE_TABLE +create table t1 (a int) engine=test_sql_discovery; + +--error ER_NO_SUCH_TABLE +select * from t1; + +set @@test_sql_discovery_statement='t1:foobar bwa-ha-ha'; +--error ER_NO_SUCH_TABLE +select * from t0; +--error ER_NO_SUCH_TABLE +select * from t1; +show warnings; + +# +# test different invalid discovering statements +# + +set @@test_sql_discovery_statement='t1:select 1'; +--error ER_NO_SUCH_TABLE +select * from t1; +show warnings; + +set @@test_sql_discovery_statement='t1:create table t1 (a int primary key) partition by hash(id) partitions 2'; +--error ER_NO_SUCH_TABLE +select * from t1; +show warnings; + +set @@test_sql_discovery_statement='t1:create table t1 (a int) union=(t3,t4)'; +--error ER_NO_SUCH_TABLE +select * from t1; +show warnings; + +set @@test_sql_discovery_statement='t1:create table t1 like t2'; +--error ER_NO_SUCH_TABLE +select * from t1; +show warnings; + +set @@test_sql_discovery_statement='t1:create table t1 select * from t2'; +--error ER_NO_SUCH_TABLE +select * from t1; +show warnings; + +set @@test_sql_discovery_statement='t1:create table t1 (a int) index directory="/tmp"'; +--error ER_NO_SUCH_TABLE +select * from t1; +show warnings; + +set @@test_sql_discovery_statement='t1:create table t1 (a int) data directory="/tmp"'; +--error ER_NO_SUCH_TABLE +select * from t1; +show warnings; + +set @@test_sql_discovery_statement='t1:create table t1 (a int) engine=myisam'; +--error ER_NO_SUCH_TABLE +select * from t1; +show warnings; + +set @@test_sql_discovery_statement='t1:create temporary table t1 (a int)'; +--error ER_NO_SUCH_TABLE +select * from t1; +show warnings; + +set @@test_sql_discovery_statement='t1:create table if not exists t1 (a int)'; +--error ER_NO_SUCH_TABLE +select * from t1; +show warnings; + +# +# this should work: +# +set @@test_sql_discovery_statement='t1:create table t1 (a int)'; +select * from t1; +show create table t1; +drop table t1; + +# table name in the create table statement is ignored +set @@test_sql_discovery_statement='t1:create table t2 (a int)'; +select * from t1; +--error ER_NO_SUCH_TABLE +select * from t2; +drop table t1; + +# and something more complex +set @@test_sql_discovery_statement='t1: +create table t1 ( + a int not null default 5 primary key, + b timestamp, + c tinyblob, + d decimal(5,2), + e varchar(30) character set ascii, + f geometry not null, + index (d,b), + unique index (c(10)), + fulltext (e), + spatial (f) +) comment="abc" default character set utf8 max_rows=100 min_rows=10 checksum=1'; +show status like 'handler_discover'; +show create table t1; +show status like 'handler_discover'; +--echo ---- +--list_files $mysqld_datadir/test t* +--echo ---- +show open tables from test; +select * from t1; +show status like 'handler_discover'; +flush tables; +select * from t1; +show status like 'handler_discover'; +drop table t1; + +set @@test_sql_discovery_write_frm=0; +set @@test_sql_discovery_statement='t1:create table t1 (a int)'; +show status like 'handler_discover'; +show create table t1; +show status like 'handler_discover'; +--echo ---- +--list_files $mysqld_datadir/test t* +--echo ---- +show open tables from test; +select * from t1; +show status like 'handler_discover'; +flush tables; +select * from t1; +show status like 'handler_discover'; +drop table t1; +show status like 'handler_discover'; + diff --git a/storage/test_sql_discovery/test_sql_discovery.cc b/storage/test_sql_discovery/test_sql_discovery.cc new file mode 100644 index 00000000000..00d488e4ad6 --- /dev/null +++ b/storage/test_sql_discovery/test_sql_discovery.cc @@ -0,0 +1,175 @@ +/* + Copyright (c) 2013 Monty Program Ab + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; version 2 of + the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +/* + a really minimal engine to test table discovery via sql statements. + See the archive engine if you're interested in real-life usable engine that + uses discovery via frm shipping. +*/ + +#include +#include +#include + +static MYSQL_THDVAR_STR(statement, PLUGIN_VAR_MEMALLOC, + "The table name and the SQL statement to discover the next table", + NULL, NULL, 0); + +static MYSQL_THDVAR_BOOL(write_frm, 0, + "Whether to cache discovered table metadata in frm files", + NULL, NULL, TRUE); + +static struct st_mysql_sys_var *sysvars[] = { + MYSQL_SYSVAR(statement), + MYSQL_SYSVAR(write_frm), + NULL +}; + +typedef struct st_share { + const char *name; + THR_LOCK lock; + uint use_count; + struct st_share *next; +} SHARE; + +class ha_tsd: public handler +{ +private: + THR_LOCK_DATA lock; + SHARE *share; + +public: + ha_tsd(handlerton *hton, TABLE_SHARE *table_arg) + : handler(hton, table_arg) { } + ulonglong table_flags() const + { // NO_TRANSACTIONS and everything that affects CREATE TABLE + return HA_NO_TRANSACTIONS | HA_CAN_GEOMETRY | HA_NULL_IN_KEY | + HA_CAN_INDEX_BLOBS | HA_AUTO_PART_KEY | HA_CAN_RTREEKEYS | + HA_CAN_FULLTEXT; + } + + ulong index_flags(uint inx, uint part, bool all_parts) const { return 0; } + + THR_LOCK_DATA **store_lock(THD *thd, THR_LOCK_DATA **to, + enum thr_lock_type lock_type) + { + if (lock_type != TL_IGNORE && lock.type == TL_UNLOCK) + lock.type = lock_type; + *to ++= &lock; + return to; + } + + int rnd_init(bool scan) { return 0; } + int rnd_next(unsigned char *buf) { return HA_ERR_END_OF_FILE; } + void position(const uchar *record) { } + int rnd_pos(uchar *buf, uchar *pos) { return HA_ERR_END_OF_FILE; } + int info(uint flag) { return 0; } + uint max_supported_keys() const { return 16; } + int create(const char *name, TABLE *table_arg, + HA_CREATE_INFO *create_info) { return HA_ERR_WRONG_COMMAND; } + + int open(const char *name, int mode, uint test_if_locked); + int close(void); +}; + +static SHARE *find_or_create_share(const char *table_name, TABLE *table) +{ + SHARE *share; + for (share = (SHARE*)table->s->ha_data; share; share = share->next) + if (my_strcasecmp(table_alias_charset, table_name, share->name) == 0) + return share; + + share = (SHARE*)alloc_root(&table->s->mem_root, sizeof(*share)); + bzero(share, sizeof(*share)); + share->name = strdup_root(&table->s->mem_root, table_name); + share->next = (SHARE*)table->s->ha_data; + table->s->ha_data = share; + return share; +} + +int ha_tsd::open(const char *name, int mode, uint test_if_locked) +{ + mysql_mutex_lock(&table->s->LOCK_ha_data); + share = find_or_create_share(name, table); + if (share->use_count++ == 0) + thr_lock_init(&share->lock); + mysql_mutex_unlock(&table->s->LOCK_ha_data); + thr_lock_data_init(&share->lock,&lock,NULL); + + return 0; +} + +int ha_tsd::close(void) +{ + mysql_mutex_lock(&table->s->LOCK_ha_data); + if (--share->use_count == 0) + thr_lock_delete(&share->lock); + mysql_mutex_unlock(&table->s->LOCK_ha_data); + return 0; +} + +static handler *create_handler(handlerton *hton, TABLE_SHARE *table, + MEM_ROOT *mem_root) +{ + return new (mem_root) ha_tsd(hton, table); +} + +static int discover_table(handlerton *hton, THD* thd, TABLE_SHARE *share) +{ + const char *sql= THDVAR(thd, statement); + + // the table is discovered if sql starts from "table_name:" + if (!sql || + strncmp(sql, share->table_name.str, share->table_name.length) || + sql[share->table_name.length] != ':') + return HA_ERR_NO_SUCH_TABLE; + + sql+= share->table_name.length + 1; + return share->init_from_sql_statement_string(thd, THDVAR(thd, write_frm), + sql, strlen(sql)); +} + +static int init(void *p) +{ + handlerton *hton = (handlerton *)p; + hton->create = create_handler; + hton->discover_table = discover_table; + return 0; +} + +struct st_mysql_storage_engine descriptor = +{ MYSQL_HANDLERTON_INTERFACE_VERSION }; + +maria_declare_plugin(tsd) +{ + MYSQL_STORAGE_ENGINE_PLUGIN, + &descriptor, + "TEST_SQL_DISCOVERY", + "Sergei Golubchik", + "Minimal engine to test table discovery via sql statements", + PLUGIN_LICENSE_GPL, + init, + NULL, + 0x0001, + NULL, + sysvars, + "0.1", + MariaDB_PLUGIN_MATURITY_EXPERIMENTAL +} +maria_declare_plugin_end; +