diff options
-rw-r--r-- | mysql-test/r/information_schema.result | 7 | ||||
-rw-r--r-- | mysql-test/r/information_schema_db.result | 14 | ||||
-rw-r--r-- | mysql-test/r/ndb_partition_key.result | 63 | ||||
-rw-r--r-- | mysql-test/r/partition.result | 129 | ||||
-rw-r--r-- | mysql-test/r/query_cache_notembedded.result | 30 | ||||
-rw-r--r-- | mysql-test/t/disabled.def | 2 | ||||
-rw-r--r-- | mysql-test/t/information_schema.test | 5 | ||||
-rw-r--r-- | mysql-test/t/information_schema_db.test | 31 | ||||
-rw-r--r-- | mysql-test/t/ndb_partition_key.test | 45 | ||||
-rw-r--r-- | mysql-test/t/partition.test | 90 | ||||
-rw-r--r-- | mysql-test/t/query_cache_notembedded.test | 40 | ||||
-rw-r--r-- | sql/ha_innodb.cc | 47 | ||||
-rw-r--r-- | sql/lex.h | 2 | ||||
-rw-r--r-- | sql/sql_acl.cc | 7 | ||||
-rw-r--r-- | sql/sql_insert.cc | 53 | ||||
-rw-r--r-- | sql/sql_lex.h | 1 | ||||
-rw-r--r-- | sql/sql_parse.cc | 13 | ||||
-rw-r--r-- | sql/sql_partition.cc | 147 | ||||
-rw-r--r-- | sql/sql_show.cc | 5 | ||||
-rw-r--r-- | sql/sql_table.cc | 1 | ||||
-rw-r--r-- | sql/sql_yacc.yy | 39 | ||||
-rw-r--r-- | storage/ndb/src/ndbapi/NdbDictionaryImpl.cpp | 3 | ||||
-rw-r--r-- | vio/viosocket.c | 22 |
23 files changed, 701 insertions, 95 deletions
diff --git a/mysql-test/r/information_schema.result b/mysql-test/r/information_schema.result index d467ad23cea..e4a8226bb37 100644 --- a/mysql-test/r/information_schema.result +++ b/mysql-test/r/information_schema.result @@ -294,6 +294,13 @@ sub1 sub1 select count(*) from information_schema.ROUTINES; count(*) 2 +create view v1 as select routine_schema, routine_name from information_schema.routines +order by routine_schema, routine_name; +select * from v1; +routine_schema routine_name +test sel2 +test sub1 +drop view v1; select ROUTINE_NAME, ROUTINE_DEFINITION from information_schema.ROUTINES; ROUTINE_NAME ROUTINE_DEFINITION show create function sub1; diff --git a/mysql-test/r/information_schema_db.result b/mysql-test/r/information_schema_db.result index b9f19368635..584e1701a14 100644 --- a/mysql-test/r/information_schema_db.result +++ b/mysql-test/r/information_schema_db.result @@ -33,4 +33,18 @@ create database `inf%`; use `inf%`; show tables; Tables_in_inf% +grant all privileges on `inf%`.* to 'mysqltest_1'@'localhost'; +create table t1 (f1 int); +create function func1(curr_int int) returns int +begin +declare ret_val int; +select max(f1) from t1 into ret_val; +return ret_val; +end| +create view v1 as select f1 from t1 where f1 = func1(f1); +select * from information_schema.tables; +drop user mysqltest_1@localhost; +drop view v1; +drop function func1; +drop table t1; drop database `inf%`; diff --git a/mysql-test/r/ndb_partition_key.result b/mysql-test/r/ndb_partition_key.result index 90ecde51e9f..87b019c83e2 100644 --- a/mysql-test/r/ndb_partition_key.result +++ b/mysql-test/r/ndb_partition_key.result @@ -89,6 +89,69 @@ ALTER TABLE t1 PARTITION BY KEY(a) (PARTITION p0 ENGINE = NDB, PARTITION p1 ENGINE = NDB); drop table t1; +create table t1 (a int) +engine=ndb +partition by key(a) +(partition p0, partition p1); +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` int(11) DEFAULT NULL +) ENGINE=ndbcluster DEFAULT CHARSET=latin1 PARTITION BY KEY (a) (PARTITION p0 ENGINE = ndbcluster, PARTITION p1 ENGINE = ndbcluster) +alter table t1 engine=heap; +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` int(11) DEFAULT NULL +) ENGINE=MEMORY DEFAULT CHARSET=latin1 PARTITION BY KEY (a) (PARTITION p0 ENGINE = MEMORY, PARTITION p1 ENGINE = MEMORY) +alter table t1 engine=ndb; +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` int(11) DEFAULT NULL +) ENGINE=ndbcluster DEFAULT CHARSET=latin1 PARTITION BY KEY (a) (PARTITION p0 ENGINE = ndbcluster, PARTITION p1 ENGINE = ndbcluster) +alter table t1 engine=heap remove partitioning; +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` int(11) DEFAULT NULL +) ENGINE=MEMORY DEFAULT CHARSET=latin1 +alter table t1 engine=ndb +partition by key(a) +(partition p0, partition p1 engine = ndb); +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` int(11) DEFAULT NULL +) ENGINE=ndbcluster DEFAULT CHARSET=latin1 PARTITION BY KEY (a) (PARTITION p0 ENGINE = ndbcluster, PARTITION p1 ENGINE = ndbcluster) +alter table t1 +partition by key (a) +(partition p0 engine=ndb, partition p1 engine=ndb); +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` int(11) DEFAULT NULL +) ENGINE=ndbcluster DEFAULT CHARSET=latin1 PARTITION BY KEY (a) (PARTITION p0 ENGINE = ndbcluster, PARTITION p1 ENGINE = ndbcluster) +alter table t1 remove partitioning; +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` int(11) DEFAULT NULL +) ENGINE=ndbcluster DEFAULT CHARSET=latin1 PARTITION BY KEY () +alter table t1 +partition by key(a) +(partition p0 engine=ndb, partition p1); +ERROR HY000: The mix of handlers in the partitions is not allowed in this version of MySQL +alter table t1 +engine=ndb +partition by key(a) +(partition p0 engine=ndb, partition p1 engine = ndb); +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` int(11) DEFAULT NULL +) ENGINE=ndbcluster DEFAULT CHARSET=latin1 PARTITION BY KEY (a) (PARTITION p0 ENGINE = ndbcluster, PARTITION p1 ENGINE = ndbcluster) +drop table t1; CREATE TABLE t1 ( c1 MEDIUMINT NOT NULL AUTO_INCREMENT, c2 TEXT NOT NULL, diff --git a/mysql-test/r/partition.result b/mysql-test/r/partition.result index 51a4707f5b1..7244dd6ccbf 100644 --- a/mysql-test/r/partition.result +++ b/mysql-test/r/partition.result @@ -315,6 +315,135 @@ drop table t1; create table t1 (s1 int, unique (s1)) partition by list (s1) (partition x1 VALUES in (10), partition x2 values in (20)); alter table t1 add partition (partition x3 values in (30)); drop table t1; +create table t1 (a int) +partition by key(a) +partitions 2 +(partition p0 engine=myisam, partition p1 engine=myisam); +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` int(11) DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 PARTITION BY KEY (a) (PARTITION p0 ENGINE = MyISAM, PARTITION p1 ENGINE = MyISAM) +alter table t1; +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` int(11) DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 PARTITION BY KEY (a) (PARTITION p0 ENGINE = MyISAM, PARTITION p1 ENGINE = MyISAM) +alter table t1 engine=myisam; +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` int(11) DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 PARTITION BY KEY (a) (PARTITION p0 ENGINE = MyISAM, PARTITION p1 ENGINE = MyISAM) +alter table t1 engine=heap; +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` int(11) DEFAULT NULL +) ENGINE=MEMORY DEFAULT CHARSET=latin1 PARTITION BY KEY (a) (PARTITION p0 ENGINE = MEMORY, PARTITION p1 ENGINE = MEMORY) +alter table t1 remove partitioning; +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` int(11) DEFAULT NULL +) ENGINE=MEMORY DEFAULT CHARSET=latin1 +drop table t1; +create table t1 (a int) +engine=myisam +partition by key(a) +partitions 2 +(partition p0 engine=myisam, partition p1 engine=myisam); +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` int(11) DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 PARTITION BY KEY (a) (PARTITION p0 ENGINE = MyISAM, PARTITION p1 ENGINE = MyISAM) +alter table t1 add column b int remove partitioning; +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` int(11) DEFAULT NULL, + `b` int(11) DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +alter table t1 +engine=myisam +partition by key(a) +(partition p0 engine=myisam, partition p1); +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` int(11) DEFAULT NULL, + `b` int(11) DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 PARTITION BY KEY (a) (PARTITION p0 ENGINE = MyISAM, PARTITION p1 ENGINE = MyISAM) +alter table t1 +engine=heap +partition by key(a) +(partition p0, partition p1 engine=heap); +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` int(11) DEFAULT NULL, + `b` int(11) DEFAULT NULL +) ENGINE=MEMORY DEFAULT CHARSET=latin1 PARTITION BY KEY (a) (PARTITION p0 ENGINE = MEMORY, PARTITION p1 ENGINE = MEMORY) +alter table t1 engine=myisam, add column c int remove partitioning; +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` int(11) DEFAULT NULL, + `b` int(11) DEFAULT NULL, + `c` int(11) DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +alter table t1 +engine=heap +partition by key (a) +(partition p0, partition p1); +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` int(11) DEFAULT NULL, + `b` int(11) DEFAULT NULL, + `c` int(11) DEFAULT NULL +) ENGINE=MEMORY DEFAULT CHARSET=latin1 PARTITION BY KEY (a) (PARTITION p0 ENGINE = MEMORY, PARTITION p1 ENGINE = MEMORY) +alter table t1 +partition by key (a) +(partition p0, partition p1); +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` int(11) DEFAULT NULL, + `b` int(11) DEFAULT NULL, + `c` int(11) DEFAULT NULL +) ENGINE=MEMORY DEFAULT CHARSET=latin1 PARTITION BY KEY (a) (PARTITION p0 ENGINE = MEMORY, PARTITION p1 ENGINE = MEMORY) +alter table t1 +engine=heap +partition by key (a) +(partition p0, partition p1); +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` int(11) DEFAULT NULL, + `b` int(11) DEFAULT NULL, + `c` int(11) DEFAULT NULL +) ENGINE=MEMORY DEFAULT CHARSET=latin1 PARTITION BY KEY (a) (PARTITION p0 ENGINE = MEMORY, PARTITION p1 ENGINE = MEMORY) +alter table t1 +partition by key(a) +(partition p0, partition p1 engine=heap); +ERROR HY000: The mix of handlers in the partitions is not allowed in this version of MySQL +alter table t1 +partition by key(a) +(partition p0 engine=heap, partition p1); +ERROR HY000: The mix of handlers in the partitions is not allowed in this version of MySQL +alter table t1 +engine=heap +partition by key (a) +(partition p0 engine=heap, partition p1 engine=myisam); +ERROR HY000: The mix of handlers in the partitions is not allowed in this version of MySQL +alter table t1 +partition by key (a) +(partition p0 engine=heap, partition p1 engine=myisam); +ERROR HY000: The mix of handlers in the partitions is not allowed in this version of MySQL +drop table t1; CREATE TABLE t1 ( f_int1 INTEGER, f_int2 INTEGER, f_char1 CHAR(10), f_char2 CHAR(10), f_charbig VARCHAR(1000) diff --git a/mysql-test/r/query_cache_notembedded.result b/mysql-test/r/query_cache_notembedded.result index 77fa198eb80..4226738725a 100644 --- a/mysql-test/r/query_cache_notembedded.result +++ b/mysql-test/r/query_cache_notembedded.result @@ -314,4 +314,34 @@ drop procedure f2; drop procedure f3; drop procedure f4; drop table t1; +reset query cache; +drop function if exists f1; +create table t1 (id int); +create function f1 () +returns int +begin +declare i_var int; +set i_var = sleep(3); +insert into t1 values(3); +set i_var = sleep(3); +return 0; +end;| + select f1(); +select sleep(4); +sleep(4) +0 +select * from t1; +id +3 +f1() +0 +select * from t1; +id +3 +reset query cache; +select * from t1; +id +3 +drop table t1; +drop function f1; set GLOBAL query_cache_size=0; diff --git a/mysql-test/t/disabled.def b/mysql-test/t/disabled.def index 2c6973b4558..91f8c986cc4 100644 --- a/mysql-test/t/disabled.def +++ b/mysql-test/t/disabled.def @@ -34,7 +34,7 @@ rpl_ndb_ddl : master hangs rpl_ndb_innodb2ndb : Bug#18261: Cluster Replication: tests rpl_ndb_xxx2ndb fails rpl_ndb_insert_ignore : Bugs: #17431: INSERT IGNORE INTO returns failed: 1296 rpl_ndb_myisam2ndb : Bug#18261: Cluster Replication: tests rpl_ndb_xxx2ndb fails -#rpl_ndb_log : result not deterministic +rpl_ndb_log : result not deterministic, TBD if should remove rpl_ndb_relay_space : Bug#16993 #rpl_ndb_multi_update3 : Bug#17400: delete & update of rows in table without pk fails rpl_ndb_sp007 : Bug #17290 diff --git a/mysql-test/t/information_schema.test b/mysql-test/t/information_schema.test index 6a1a9f60bc5..f9bd4bddff9 100644 --- a/mysql-test/t/information_schema.test +++ b/mysql-test/t/information_schema.test @@ -146,6 +146,11 @@ select a.ROUTINE_NAME, b.name from information_schema.ROUTINES a, mysql.proc b where a.ROUTINE_NAME = convert(b.name using utf8) order by 1; select count(*) from information_schema.ROUTINES; +create view v1 as select routine_schema, routine_name from information_schema.routines +order by routine_schema, routine_name; +select * from v1; +drop view v1; + connect (user1,localhost,mysqltest_1,,); connection user1; select ROUTINE_NAME, ROUTINE_DEFINITION from information_schema.ROUTINES; diff --git a/mysql-test/t/information_schema_db.test b/mysql-test/t/information_schema_db.test index efb738d682c..b65135a621d 100644 --- a/mysql-test/t/information_schema_db.test +++ b/mysql-test/t/information_schema_db.test @@ -8,4 +8,35 @@ show tables from INFORMATION_SCHEMA like 'T%'; create database `inf%`; use `inf%`; show tables; + +# +# Bug#18113 SELECT * FROM information_schema.xxx crashes server +# Crash happened when one selected data from one of INFORMATION_SCHEMA +# tables and in order to build its contents server had to open view which +# used stored function and table or view on which one had not global or +# database-level privileges (e.g. had only table-level or had no +# privileges at all). +# +grant all privileges on `inf%`.* to 'mysqltest_1'@'localhost'; +create table t1 (f1 int); +delimiter |; +create function func1(curr_int int) returns int +begin + declare ret_val int; + select max(f1) from t1 into ret_val; + return ret_val; +end| +delimiter ;| +create view v1 as select f1 from t1 where f1 = func1(f1); +connect (user1,localhost,mysqltest_1,,); +connection user1; +--disable_result_log +select * from information_schema.tables; +--enable_result_log +connection default; +drop user mysqltest_1@localhost; +drop view v1; +drop function func1; +drop table t1; + drop database `inf%`; diff --git a/mysql-test/t/ndb_partition_key.test b/mysql-test/t/ndb_partition_key.test index 22c84bf132e..d43dc7e49e4 100644 --- a/mysql-test/t/ndb_partition_key.test +++ b/mysql-test/t/ndb_partition_key.test @@ -81,6 +81,51 @@ PARTITION BY KEY(a) drop table t1; # +# Bug #17754 Improper handling of removal of partitioning in ALTER TABLE +# Also added a number of general test cases in the same area +# +create table t1 (a int) +engine=ndb +partition by key(a) +(partition p0, partition p1); +show create table t1; + +alter table t1 engine=heap; +show create table t1; + +alter table t1 engine=ndb; +show create table t1; + +alter table t1 engine=heap remove partitioning; +show create table t1; + +alter table t1 engine=ndb +partition by key(a) +(partition p0, partition p1 engine = ndb); +show create table t1; + +alter table t1 +partition by key (a) +(partition p0 engine=ndb, partition p1 engine=ndb); +show create table t1; + +alter table t1 remove partitioning; +show create table t1; + +--error ER_MIX_HANDLER_ERROR +alter table t1 +partition by key(a) +(partition p0 engine=ndb, partition p1); + +alter table t1 +engine=ndb +partition by key(a) +(partition p0 engine=ndb, partition p1 engine = ndb); +show create table t1; + +drop table t1; + +# # BUG 16810 Out of memory when coalesce partition # CREATE TABLE t1 ( diff --git a/mysql-test/t/partition.test b/mysql-test/t/partition.test index 9da52b916de..ad01977a458 100644 --- a/mysql-test/t/partition.test +++ b/mysql-test/t/partition.test @@ -409,6 +409,96 @@ alter table t1 add partition (partition x3 values in (30)); drop table t1; # +# Bug #17754 Change to explicit removal of partitioning scheme +# Also added a number of tests to ensure that proper engine is +# choosen in all kinds of scenarios. +# + +create table t1 (a int) +partition by key(a) +partitions 2 +(partition p0 engine=myisam, partition p1 engine=myisam); +show create table t1; + +alter table t1; +show create table t1; + +alter table t1 engine=myisam; +show create table t1; + +alter table t1 engine=heap; +show create table t1; + +alter table t1 remove partitioning; +show create table t1; + +drop table t1; + +create table t1 (a int) +engine=myisam +partition by key(a) +partitions 2 +(partition p0 engine=myisam, partition p1 engine=myisam); +show create table t1; + +alter table t1 add column b int remove partitioning; +show create table t1; + +alter table t1 +engine=myisam +partition by key(a) +(partition p0 engine=myisam, partition p1); +show create table t1; + +alter table t1 +engine=heap +partition by key(a) +(partition p0, partition p1 engine=heap); +show create table t1; + +alter table t1 engine=myisam, add column c int remove partitioning; +show create table t1; + +alter table t1 +engine=heap +partition by key (a) +(partition p0, partition p1); +show create table t1; + +alter table t1 +partition by key (a) +(partition p0, partition p1); +show create table t1; + +alter table t1 +engine=heap +partition by key (a) +(partition p0, partition p1); +show create table t1; + +--error ER_MIX_HANDLER_ERROR +alter table t1 +partition by key(a) +(partition p0, partition p1 engine=heap); + +--error ER_MIX_HANDLER_ERROR +alter table t1 +partition by key(a) +(partition p0 engine=heap, partition p1); + +--error ER_MIX_HANDLER_ERROR +alter table t1 +engine=heap +partition by key (a) +(partition p0 engine=heap, partition p1 engine=myisam); + +--error ER_MIX_HANDLER_ERROR +alter table t1 +partition by key (a) +(partition p0 engine=heap, partition p1 engine=myisam); + +drop table t1; + # Bug #17432: Partition functions containing NULL values should return # LONGLONG_MIN # diff --git a/mysql-test/t/query_cache_notembedded.test b/mysql-test/t/query_cache_notembedded.test index 5e1ab7051e5..97be9f9f7ca 100644 --- a/mysql-test/t/query_cache_notembedded.test +++ b/mysql-test/t/query_cache_notembedded.test @@ -180,5 +180,45 @@ drop procedure f3; drop procedure f4; drop table t1; +# +# bug#14767: INSERT in SF + concurrent SELECT with query cache +# +reset query cache; +--disable_warnings +drop function if exists f1; +--enable_warnings +create table t1 (id int); +delimiter |; +create function f1 () + returns int +begin + declare i_var int; + set i_var = sleep(3); + insert into t1 values(3); + set i_var = sleep(3); + return 0; +end;| +delimiter ;| + +connect (con1,localhost,root,,); +connect (con2,localhost,root,,); + +connection con1; +send select f1(); +connection con2; +select sleep(4); +select * from t1; +connection con1; +reap; +connection con2; +# This gives wrong result i.e. 't' table seems to be empty +select * from t1; +reset query cache; +select * from t1; +drop table t1; +drop function f1; +disconnect con1; +disconnect con2; +connection default; set GLOBAL query_cache_size=0; diff --git a/sql/ha_innodb.cc b/sql/ha_innodb.cc index 6c8559a1077..416d67aec39 100644 --- a/sql/ha_innodb.cc +++ b/sql/ha_innodb.cc @@ -534,16 +534,23 @@ convert_error_code_to_mysql( } else if (error == (int) DB_CORRUPTION) { - return(HA_ERR_CRASHED); - } else if (error == (int) DB_NO_SAVEPOINT) { + return(HA_ERR_CRASHED); + } else if (error == (int) DB_NO_SAVEPOINT) { - return(HA_ERR_NO_SAVEPOINT); - } else if (error == (int) DB_LOCK_TABLE_FULL) { + return(HA_ERR_NO_SAVEPOINT); + } else if (error == (int) DB_LOCK_TABLE_FULL) { + /* Since we rolled back the whole transaction, we must + tell it also to MySQL so that MySQL knows to empty the + cached binlog for this transaction */ - return(HA_ERR_LOCK_TABLE_FULL); - } else { - return(-1); // Unknown error - } + if (thd) { + ha_rollback(thd); + } + + return(HA_ERR_LOCK_TABLE_FULL); + } else { + return(-1); // Unknown error + } } /***************************************************************** @@ -6950,25 +6957,25 @@ ha_innobase::store_lock( } /* If we are not doing a LOCK TABLE, DISCARD/IMPORT - TABLESPACE or TRUNCATE TABLE then allow multiple + TABLESPACE or TRUNCATE TABLE then allow multiple writers. Note that ALTER TABLE uses a TL_WRITE_ALLOW_READ < TL_WRITE_CONCURRENT_INSERT. - We especially allow multiple writers if MySQL is at the - start of a stored procedure call (SQLCOM_CALL) + We especially allow multiple writers if MySQL is at the + start of a stored procedure call (SQLCOM_CALL) (MySQL does have thd->in_lock_tables TRUE there). */ - if ((lock_type >= TL_WRITE_CONCURRENT_INSERT - && lock_type <= TL_WRITE) - && (!thd->in_lock_tables - || thd->lex->sql_command == SQLCOM_CALL) - && !thd->tablespace_op - && thd->lex->sql_command != SQLCOM_TRUNCATE - && thd->lex->sql_command != SQLCOM_OPTIMIZE - && thd->lex->sql_command != SQLCOM_CREATE_TABLE) { + if ((lock_type >= TL_WRITE_CONCURRENT_INSERT + && lock_type <= TL_WRITE) + && !(thd->in_lock_tables + && thd->lex->sql_command == SQLCOM_LOCK_TABLES) + && !thd->tablespace_op + && thd->lex->sql_command != SQLCOM_TRUNCATE + && thd->lex->sql_command != SQLCOM_OPTIMIZE + && thd->lex->sql_command != SQLCOM_CREATE_TABLE) { lock_type = TL_WRITE_ALLOW_WRITE; - } + } /* In queries of type INSERT INTO t1 SELECT ... FROM t2 ... MySQL would use the lock TL_READ_NO_INSERT on t2, and that diff --git a/sql/lex.h b/sql/lex.h index 574d7036c8a..9fd8cae1325 100644 --- a/sql/lex.h +++ b/sql/lex.h @@ -391,6 +391,7 @@ static SYMBOL symbols[] = { { "PARSER", SYM(PARSER_SYM)}, { "PARTIAL", SYM(PARTIAL)}, { "PARTITION", SYM(PARTITION_SYM)}, + { "PARTITIONING", SYM(PARTITIONING_SYM)}, { "PARTITIONS", SYM(PARTITIONS_SYM)}, { "PASSWORD", SYM(PASSWORD)}, { "PHASE", SYM(PHASE_SYM)}, @@ -428,6 +429,7 @@ static SYMBOL symbols[] = { { "RELAY_THREAD", SYM(RELAY_THREAD)}, { "RELEASE", SYM(RELEASE_SYM)}, { "RELOAD", SYM(RELOAD)}, + { "REMOVE", SYM(REMOVE_SYM)}, { "RENAME", SYM(RENAME)}, { "REORGANIZE", SYM(REORGANIZE_SYM)}, { "REPAIR", SYM(REPAIR)}, diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index f6da9fc588a..aa426cb33f9 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -3668,6 +3668,13 @@ end: RETURN 0 ok 1 Error: User did not have the requested privileges + + NOTE + This functions assumes that either number of tables to be inspected + by it is limited explicitly (i.e. is is not UINT_MAX) or table list + used and thd->lex->query_tables_own_last value correspond to each + other (the latter should be either 0 or point to next_global member + of one of elements of this table list). ****************************************************************************/ bool check_grant(THD *thd, ulong want_access, TABLE_LIST *tables, diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index 6e797f558d4..13e1f80f512 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -272,6 +272,7 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list, bool log_on= (thd->options & OPTION_BIN_LOG) || (!(thd->security_ctx->master_access & SUPER_ACL)); bool transactional_table, joins_freed= FALSE; + bool changed; uint value_count; ulong counter = 1; ulonglong id; @@ -558,35 +559,33 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list, else if (table->next_number_field && info.copied) id=table->next_number_field->val_int(); // Return auto_increment value - /* - Invalidate the table in the query cache if something changed. - For the transactional algorithm to work the invalidation must be - before binlog writing and ha_autocommit_or_rollback - */ - if (info.copied || info.deleted || info.updated) - { - query_cache_invalidate3(thd, table_list, 1); - } - transactional_table= table->file->has_transactions(); - if ((info.copied || info.deleted || info.updated) && - (error <= 0 || !transactional_table)) + if ((changed= (info.copied || info.deleted || info.updated))) { - if (mysql_bin_log.is_open()) + /* + Invalidate the table in the query cache if something changed. + For the transactional algorithm to work the invalidation must be + before binlog writing and ha_autocommit_or_rollback + */ + query_cache_invalidate3(thd, table_list, 1); + if (error <= 0 || !transactional_table) { - if (error <= 0) - thd->clear_error(); - if (thd->binlog_query(THD::ROW_QUERY_TYPE, - thd->query, thd->query_length, - transactional_table, FALSE) && - transactional_table) + if (mysql_bin_log.is_open()) { - error=1; + if (error <= 0) + thd->clear_error(); + if (thd->binlog_query(THD::ROW_QUERY_TYPE, + thd->query, thd->query_length, + transactional_table, FALSE) && + transactional_table) + { + error=1; + } } + if (!transactional_table) + thd->options|=OPTION_STATUS_NO_TRANS_UPDATE; } - if (!transactional_table) - thd->options|=OPTION_STATUS_NO_TRANS_UPDATE; } if (transactional_table) error=ha_autocommit_or_rollback(thd,error); @@ -594,6 +593,16 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list, if (thd->lock) { mysql_unlock_tables(thd, thd->lock); + /* + Invalidate the table in the query cache if something changed + after unlocking when changes become fisible. + TODO: this is workaround. right way will be move invalidating in + the unlock procedure. + */ + if (lock_type == TL_WRITE_CONCURRENT_INSERT && changed) + { + query_cache_invalidate3(thd, table_list, 1); + } thd->lock=0; } } diff --git a/sql/sql_lex.h b/sql/sql_lex.h index 5e67b60cb85..1fea4971c4d 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -705,6 +705,7 @@ typedef class st_select_lex SELECT_LEX; #define ALTER_ANALYZE_PARTITION (1L << 22) #define ALTER_CHECK_PARTITION (1L << 23) #define ALTER_REPAIR_PARTITION (1L << 24) +#define ALTER_REMOVE_PARTITIONING (1L << 25) typedef struct st_alter_info { diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index cb231a7adea..eea2ae57e75 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -3351,6 +3351,19 @@ end_with_restore_list: select_lex->context.table_list= select_lex->context.first_name_resolution_table= second_table; res= handle_select(thd, lex, result, OPTION_SETUP_TABLES_DONE); + /* + Invalidate the table in the query cache if something changed + after unlocking when changes become visible. + TODO: this is workaround. right way will be move invalidating in + the unlock procedure. + */ + if (first_table->lock_type == TL_WRITE_CONCURRENT_INSERT && + thd->lock) + { + mysql_unlock_tables(thd, thd->lock); + query_cache_invalidate3(thd, first_table, 1); + thd->lock=0; + } delete result; } /* revert changes for SP */ diff --git a/sql/sql_partition.cc b/sql/sql_partition.cc index 608db994f66..62c48ba37dc 100644 --- a/sql/sql_partition.cc +++ b/sql/sql_partition.cc @@ -3820,6 +3820,42 @@ end: /* + Set engine type on all partition element objects + SYNOPSIS + set_engine_all_partitions() + part_info Partition info + engine_type Handlerton reference of engine + RETURN VALUES + NONE +*/ + +static +void +set_engine_all_partitions(partition_info *part_info, + handlerton *engine_type) +{ + uint i= 0; + List_iterator<partition_element> part_it(part_info->partitions); + do + { + partition_element *part_elem= part_it++; + + part_elem->engine_type= engine_type; + if (part_info->is_sub_partitioned()) + { + List_iterator<partition_element> sub_it(part_elem->subpartitions); + uint j= 0; + + do + { + partition_element *sub_elem= sub_it++; + + sub_elem->engine_type= engine_type; + } while (++j < part_info->no_subparts); + } + } while (++i < part_info->no_parts); +} +/* SYNOPSIS fast_alter_partition_error_handler() lpt Container for parameters @@ -3921,17 +3957,34 @@ static bool check_engine_condition(partition_element *p_elem, handlerton **engine_type, bool *first) { + DBUG_ENTER("check_engine_condition"); + + DBUG_PRINT("enter", ("def_eng = %u, first = %u", default_engine, *first)); + if (*engine_type) + DBUG_PRINT("info", ("engine_type = %s", (*engine_type)->name)); + else + DBUG_PRINT("info", ("engine_type = NULL")); if (*first && default_engine) + { *engine_type= p_elem->engine_type; + if (*engine_type) + DBUG_PRINT("info", ("engine_type changed to = %s", (*engine_type)->name)); + else + DBUG_PRINT("info", ("engine_type changed to = NULL")); + } *first= FALSE; if ((!default_engine && - (p_elem->engine_type != *engine_type && - !p_elem->engine_type)) || + (p_elem->engine_type != (*engine_type) && + p_elem->engine_type)) || (default_engine && - p_elem->engine_type != *engine_type)) - return TRUE; + p_elem->engine_type != (*engine_type))) + { + DBUG_RETURN(TRUE); + } else - return FALSE; + { + DBUG_RETURN(FALSE); + } } /* @@ -3968,8 +4021,8 @@ static bool check_native_partitioned(HA_CREATE_INFO *create_info,bool *ret_val, uint no_parts= part_info->partitions.elements; DBUG_ENTER("check_native_partitioned"); - default_engine= (create_info->used_fields | HA_CREATE_USED_ENGINE) ? - TRUE : FALSE; + default_engine= (create_info->used_fields & HA_CREATE_USED_ENGINE) ? + FALSE : TRUE; DBUG_PRINT("info", ("engine_type = %u, default = %u", ha_legacy_type(engine_type), default_engine)); @@ -4028,6 +4081,7 @@ error: Mixed engines not yet supported but when supported it will need the partition handler */ + my_error(ER_MIX_HANDLER_ERROR, MYF(0)); *ret_val= FALSE; DBUG_RETURN(TRUE); } @@ -4811,7 +4865,7 @@ the generated partition syntax in a correct manner. Case IIa: There was a partitioning before and there is no new one defined. - Also the user has not specified an explicit engine to use. + Also the user has not specified to remove partitioning explicitly. We use the old partitioning also for the new table. We do this by assigning the partition_info from the table loaded in @@ -4820,12 +4874,11 @@ the generated partition syntax in a correct manner. Case IIb: There was a partitioning before and there is no new one defined. - The user has specified an explicit engine to use. + The user has specified explicitly to remove partitioning - Since the user has specified an explicit engine to use we override - the old partitioning info and create a new table using the specified - engine. This is the reason for the extra check if old and new engine - is equal. + Since the user has specified explicitly to remove partitioning + we override the old partitioning info and create a new table using + the specified engine. In this case the partition also is changed. Case III: @@ -4848,12 +4901,41 @@ the generated partition syntax in a correct manner. */ if (table->part_info) { - if (!thd->work_part_info && - create_info->db_type == old_db_type) + if (thd->lex->alter_info.flags & ALTER_REMOVE_PARTITIONING) + { + DBUG_PRINT("info", ("Remove partitioning")); + if (!(thd->lex->create_info.used_fields & HA_CREATE_USED_ENGINE)) + { + DBUG_PRINT("info", ("No explicit engine used")); + create_info->db_type= table->part_info->default_engine_type; + } + DBUG_PRINT("info", ("New engine type = %s", + create_info->db_type->name)); + thd->work_part_info= NULL; + *partition_changed= TRUE; + } + else if (!thd->work_part_info) + { + /* + Retain partitioning but possibly with a new storage engine + beneath. + */ thd->work_part_info= table->part_info; + if (thd->lex->create_info.used_fields & HA_CREATE_USED_ENGINE && + create_info->db_type != table->part_info->default_engine_type) + { + /* + Make sure change of engine happens to all partitions. + */ + set_engine_all_partitions(thd->work_part_info, create_info->db_type); + *partition_changed= TRUE; + } + } } if (thd->work_part_info) { + partition_info *part_info= thd->work_part_info; + bool is_native_partitioned= FALSE; /* Need to cater for engine types that can handle partition without using the partition handler. @@ -4861,35 +4943,20 @@ the generated partition syntax in a correct manner. if (thd->work_part_info != table->part_info) *partition_changed= TRUE; if (create_info->db_type == &partition_hton) + part_info->default_engine_type= table->part_info->default_engine_type; + else + part_info->default_engine_type= create_info->db_type; + if (check_native_partitioned(create_info, &is_native_partitioned, + part_info, thd)) { - if (table->part_info) - { - thd->work_part_info->default_engine_type= - table->part_info->default_engine_type; - } - else - { - thd->work_part_info->default_engine_type= - ha_checktype(thd, DB_TYPE_DEFAULT, FALSE, FALSE); - } + DBUG_RETURN(TRUE); } - else + if (!is_native_partitioned) { - bool is_native_partitioned= FALSE; - partition_info *part_info= thd->work_part_info; - part_info->default_engine_type= create_info->db_type; - if (check_native_partitioned(create_info, &is_native_partitioned, - part_info, thd)) - { - DBUG_RETURN(TRUE); - } - if (!is_native_partitioned) - { - DBUG_ASSERT(create_info->db_type != &default_hton); - create_info->db_type= &partition_hton; - } + DBUG_ASSERT(create_info->db_type != &default_hton); + create_info->db_type= &partition_hton; } - DBUG_PRINT("info", ("default_db_type = %s", + DBUG_PRINT("info", ("default_engine_type = %s", thd->work_part_info->default_engine_type->name)); } } diff --git a/sql/sql_show.cc b/sql/sql_show.cc index 9310b65e44a..da372d9063d 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -476,7 +476,7 @@ mysql_find_files(THD *thd,List<char> *files, const char *db,const char *path, table_list.table_name= file->name; table_list.table_name_length= strlen(file->name); table_list.grant.privilege=col_access; - if (check_grant(thd, TABLE_ACLS, &table_list, 1, UINT_MAX, 1)) + if (check_grant(thd, TABLE_ACLS, &table_list, 1, 1, 1)) continue; } #endif @@ -4664,7 +4664,8 @@ bool get_schema_tables_result(JOIN *join) TABLE_LIST *table_list= tab->table->pos_in_table_list; if (table_list->schema_table && thd->fill_derived_tables()) { - bool is_subselect= (&lex->unit != lex->current_select->master_unit()); + bool is_subselect= (&lex->unit != lex->current_select->master_unit() && + lex->current_select->master_unit()->item); /* The schema table is already processed and the statement is not a subselect. diff --git a/sql/sql_table.cc b/sql/sql_table.cc index caf32659eb8..de7b273d57e 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -2054,6 +2054,7 @@ bool mysql_create_table_internal(THD *thd, DBUG_RETURN(TRUE); } file->set_auto_partitions(part_info); + part_info->default_engine_type= create_info->db_type; } if (part_info) { diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 9accacbd7b4..9304bc3f27c 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -495,6 +495,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); %token PARSER_SYM %token PARTIAL %token PARTITION_SYM +%token PARTITIONING_SYM %token PARTITIONS_SYM %token PASSWORD %token PARAM_MARKER @@ -537,6 +538,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); %token RELAY_THREAD %token RELEASE_SYM %token RELOAD +%token REMOVE_SYM %token RENAME %token REORGANIZE_SYM %token REPAIR @@ -4908,6 +4910,9 @@ alter_commands: | IMPORT TABLESPACE { Lex->alter_info.tablespace_op= IMPORT_TABLESPACE; } | alter_list opt_partitioning + | alter_list + remove_partitioning + | remove_partitioning | partitioning /* This part was added for release 5.1 by Mikael Ronström. @@ -4973,6 +4978,13 @@ alter_commands: | reorg_partition_rule ; +remove_partitioning: + REMOVE_SYM PARTITIONING_SYM + { + Lex->alter_info.flags|= ALTER_REMOVE_PARTITIONING; + } + ; + all_or_alt_part_name_list: ALL { @@ -7809,7 +7821,19 @@ replace: ; insert_lock_option: - /* empty */ { $$= TL_WRITE_CONCURRENT_INSERT; } + /* empty */ + { +#ifdef HAVE_QUERY_CACHE + /* + If it is SP we do not allow insert optimisation whan result of + insert visible only after the table unlocking but everyone can + read table. + */ + $$= (Lex->sphead ? TL_WRITE :TL_WRITE_CONCURRENT_INSERT); +#else + $$= TL_WRITE_CONCURRENT_INSERT; +#endif + } | LOW_PRIORITY { $$= TL_WRITE_LOW_PRIORITY; } | DELAYED_SYM { $$= TL_WRITE_DELAYED; } | HIGH_PRIORITY { $$= TL_WRITE; } @@ -8728,7 +8752,16 @@ opt_local: load_data_lock: /* empty */ { $$= YYTHD->update_lock_default; } - | CONCURRENT { $$= TL_WRITE_CONCURRENT_INSERT ; } + | CONCURRENT + { +#ifdef HAVE_QUERY_CACHE + /* + Ignore this option in SP to avoid problem with query cache + */ + if (Lex->sphead != 0) +#endif + $$= TL_WRITE_CONCURRENT_INSERT; + } | LOW_PRIORITY { $$= TL_WRITE_LOW_PRIORITY; }; @@ -9326,6 +9359,7 @@ keyword: | PARTITION_SYM {} | PLUGIN_SYM {} | PREPARE_SYM {} + | REMOVE_SYM {} | REPAIR {} | RESET_SYM {} | RESTORE_SYM {} @@ -9500,6 +9534,7 @@ keyword_sp: | ONE_SYM {} | PACK_KEYS_SYM {} | PARTIAL {} + | PARTITIONING_SYM {} | PARTITIONS_SYM {} | PASSWORD {} | PHASE_SYM {} diff --git a/storage/ndb/src/ndbapi/NdbDictionaryImpl.cpp b/storage/ndb/src/ndbapi/NdbDictionaryImpl.cpp index 6d8eb9faba1..130ae44c057 100644 --- a/storage/ndb/src/ndbapi/NdbDictionaryImpl.cpp +++ b/storage/ndb/src/ndbapi/NdbDictionaryImpl.cpp @@ -3829,6 +3829,9 @@ NdbDictionaryImpl::dropBlobEvents(const NdbEventImpl& evnt) } else { // loop over MAX_ATTRIBUTES_IN_TABLE ... Uint32 i; + DBUG_PRINT("info", ("missing table definition, looping over " + "MAX_ATTRIBUTES_IN_TABLE(%d)", + MAX_ATTRIBUTES_IN_TABLE)); for (i = 0; i < MAX_ATTRIBUTES_IN_TABLE; i++) { char bename[MAX_TAB_NAME_SIZE]; // XXX should get name from NdbBlob diff --git a/vio/viosocket.c b/vio/viosocket.c index 5e0ed20b039..710f7a93607 100644 --- a/vio/viosocket.c +++ b/vio/viosocket.c @@ -560,14 +560,20 @@ int vio_close_shared_memory(Vio * vio) Close all handlers. UnmapViewOfFile and CloseHandle return non-zero result if they are success. */ - r= UnmapViewOfFile(vio->handle_map) || CloseHandle(vio->event_server_wrote) || - CloseHandle(vio->event_server_read) || CloseHandle(vio->event_client_wrote) || - CloseHandle(vio->event_client_read) || CloseHandle(vio->handle_file_map); - if (!r) - { - DBUG_PRINT("vio_error", ("close() failed, error: %d",r)); - /* FIXME: error handling (not critical for MySQL) */ - } + if (UnmapViewOfFile(vio->handle_map) == 0) + DBUG_PRINT("vio_error", ("UnmapViewOfFile() failed")); + if (CloseHandle(vio->event_server_wrote) == 0) + DBUG_PRINT("vio_error", ("CloseHandle(vio->esw) failed")); + if (CloseHandle(vio->event_server_read) == 0) + DBUG_PRINT("vio_error", ("CloseHandle(vio->esr) failed")); + if (CloseHandle(vio->event_client_wrote) == 0) + DBUG_PRINT("vio_error", ("CloseHandle(vio->ecw) failed")); + if (CloseHandle(vio->event_client_read) == 0) + DBUG_PRINT("vio_error", ("CloseHandle(vio->ecr) failed")); + if (CloseHandle(vio->handle_file_map) == 0) + DBUG_PRINT("vio_error", ("CloseHandle(vio->hfm) failed")); + if (CloseHandle(vio->event_conn_closed) == 0) + DBUG_PRINT("vio_error", ("CloseHandle(vio->ecc) failed")); } vio->type= VIO_CLOSED; vio->sd= -1; |