diff options
author | Marko Mäkelä <marko.makela@mariadb.com> | 2019-02-03 17:22:05 +0200 |
---|---|---|
committer | Marko Mäkelä <marko.makela@mariadb.com> | 2019-02-03 17:22:05 +0200 |
commit | a249e57b684a23dce4cbb870ca3eb30c77cb9fd6 (patch) | |
tree | 9c50673311474f7efa0d5d110461ad324c7a62e6 | |
parent | 261ce5286f266f1a5fab5e8adc2c08adef658d13 (diff) | |
parent | 955c7b32226c816b24a2ed1750e12bc0256565ad (diff) | |
download | mariadb-git-a249e57b684a23dce4cbb870ca3eb30c77cb9fd6.tar.gz |
Merge 10.1 into 10.2
Temporarily disable a test for
commit 2175bfce3e9da8332f10ab0e0286dc93915533a2
because fixing it in 10.2 requires updating libmariadb.
96 files changed, 2536 insertions, 7269 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index d1d12869a70..cfd04884e53 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -238,8 +238,14 @@ ENDIF() MY_CHECK_AND_SET_COMPILER_FLAG(-ggdb3 DEBUG) -OPTION(ENABLED_LOCAL_INFILE - "If we should should enable LOAD DATA LOCAL by default" ${IF_WIN}) +SET(ENABLED_LOCAL_INFILE "AUTO" CACHE STRING "If we should should enable LOAD DATA LOCAL by default (OFF/ON/AUTO)") +IF (ENABLED_LOCAL_INFILE MATCHES "^(0|FALSE)$") + SET(ENABLED_LOCAL_INFILE OFF) +ELSEIF(ENABLED_LOCAL_INFILE MATCHES "^(1|TRUE)$") + SET(ENABLED_LOCAL_INFILE ON) +ELSEIF (NOT ENABLED_LOCAL_INFILE MATCHES "^(ON|OFF|AUTO)$") + MESSAGE(FATAL_ERROR "ENABLED_LOCAL_INFILE must be one of OFF, ON, AUTO") +ENDIF() # Set DBUG_OFF and other optional release-only flags for non-debug project types FOREACH(BUILD_TYPE RELEASE RELWITHDEBINFO MINSIZEREL) diff --git a/client/mysqltest.cc b/client/mysqltest.cc index 0d7b54acf8e..00bea466912 100644 --- a/client/mysqltest.cc +++ b/client/mysqltest.cc @@ -6090,7 +6090,6 @@ void do_connect(struct st_command *command) #endif if (opt_compress || con_compress) mysql_options(con_slot->mysql, MYSQL_OPT_COMPRESS, NullS); - mysql_options(con_slot->mysql, MYSQL_OPT_LOCAL_INFILE, 0); mysql_options(con_slot->mysql, MYSQL_SET_CHARSET_NAME, csname?csname: charset_info->csname); if (opt_charsets_dir) @@ -6190,6 +6189,11 @@ void do_connect(struct st_command *command) if (con_slot == next_con) next_con++; /* if we used the next_con slot, advance the pointer */ } + else // Failed to connect. Free the memory. + { + mysql_close(con_slot->mysql); + con_slot->mysql= NULL; + } dynstr_free(&ds_connection_name); dynstr_free(&ds_host); @@ -9297,7 +9301,6 @@ int main(int argc, char **argv) (void *) &opt_connect_timeout); if (opt_compress) mysql_options(con->mysql,MYSQL_OPT_COMPRESS,NullS); - mysql_options(con->mysql, MYSQL_OPT_LOCAL_INFILE, 0); mysql_options(con->mysql, MYSQL_SET_CHARSET_NAME, charset_info->csname); if (opt_charsets_dir) diff --git a/cmake/build_configurations/mysql_release.cmake b/cmake/build_configurations/mysql_release.cmake index c3c42efa7a0..65ae04fcab1 100644 --- a/cmake/build_configurations/mysql_release.cmake +++ b/cmake/build_configurations/mysql_release.cmake @@ -86,7 +86,6 @@ IF(FEATURE_SET) ENDIF() ENDIF() -OPTION(ENABLED_LOCAL_INFILE "" ON) SET(WITH_INNODB_SNAPPY OFF CACHE STRING "") IF(WIN32) SET(INSTALL_MYSQLTESTDIR "" CACHE STRING "") diff --git a/cmake/ssl.cmake b/cmake/ssl.cmake index 5747cb4ad89..65deaf6056a 100644 --- a/cmake/ssl.cmake +++ b/cmake/ssl.cmake @@ -128,11 +128,6 @@ MACRO (MYSQL_CHECK_SSL) FIND_PACKAGE(OpenSSL) IF(OPENSSL_FOUND) SET(OPENSSL_LIBRARY ${OPENSSL_SSL_LIBRARY}) - INCLUDE(CheckSymbolExists) - SET(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIR}) - CHECK_SYMBOL_EXISTS(SHA512_DIGEST_LENGTH "openssl/sha.h" - HAVE_SHA512_DIGEST_LENGTH) - SET(CMAKE_REQUIRED_INCLUDES) SET(SSL_SOURCES "") SET(SSL_LIBRARIES ${OPENSSL_SSL_LIBRARY} ${OPENSSL_CRYPTO_LIBRARY}) IF(CMAKE_SYSTEM_NAME MATCHES "SunOS") diff --git a/config.h.cmake b/config.h.cmake index bbeb457fd13..94c720a8491 100644 --- a/config.h.cmake +++ b/config.h.cmake @@ -453,7 +453,11 @@ /* MySQL features */ -#cmakedefine ENABLED_LOCAL_INFILE 1 +#define LOCAL_INFILE_MODE_OFF 0 +#define LOCAL_INFILE_MODE_ON 1 +#define LOCAL_INFILE_MODE_AUTO 2 +#define ENABLED_LOCAL_INFILE LOCAL_INFILE_MODE_@ENABLED_LOCAL_INFILE@ + #cmakedefine ENABLED_PROFILING 1 #cmakedefine EXTRA_DEBUG 1 #cmakedefine USE_SYMDIR 1 diff --git a/include/my_valgrind.h b/include/my_valgrind.h index cb0886bda46..cf3037da98b 100644 --- a/include/my_valgrind.h +++ b/include/my_valgrind.h @@ -42,7 +42,7 @@ https://github.com/google/sanitizers/wiki/AddressSanitizerManualPoisoning */ # define MEM_CHECK_ADDRESSABLE(a,len) ((void) 0) # define MEM_CHECK_DEFINED(a,len) ((void) 0) #else -# define MEM_UNDEFINED(a,len) ((void) 0) +# define MEM_UNDEFINED(a,len) ((void) (a), (void) (len)) # define MEM_NOACCESS(a,len) ((void) 0) # define MEM_CHECK_ADDRESSABLE(a,len) ((void) 0) # define MEM_CHECK_DEFINED(a,len) ((void) 0) @@ -51,7 +51,7 @@ https://github.com/google/sanitizers/wiki/AddressSanitizerManualPoisoning */ #ifndef DBUG_OFF #define TRASH_FILL(A,B,C) do { const size_t trash_tmp= (B); MEM_UNDEFINED(A, trash_tmp); memset(A, C, trash_tmp); } while (0) #else -#define TRASH_FILL(A,B,C) do { const size_t trash_tmp __attribute__((unused))= (B); MEM_UNDEFINED(A,trash_tmp); } while (0) +#define TRASH_FILL(A,B,C) do { MEM_UNDEFINED((A), (B)); } while (0) #endif #define TRASH_ALLOC(A,B) do { TRASH_FILL(A,B,0xA5); MEM_UNDEFINED(A,B); } while(0) diff --git a/include/mysql.h b/include/mysql.h index 8d8e0589282..4b9a7d27ad2 100644 --- a/include/mysql.h +++ b/include/mysql.h @@ -294,7 +294,7 @@ typedef struct st_mysql /* session-wide random string */ char scramble[SCRAMBLE_LENGTH+1]; - my_bool unused1; + my_bool auto_local_infile; void *unused2, *unused3, *unused4, *unused5; LIST *stmts; /* list of all statements */ diff --git a/include/mysql.h.pp b/include/mysql.h.pp index 78947c972f9..73b9f9f588b 100644 --- a/include/mysql.h.pp +++ b/include/mysql.h.pp @@ -378,7 +378,7 @@ typedef struct st_mysql my_bool free_me; my_bool reconnect; char scramble[20 +1]; - my_bool unused1; + my_bool auto_local_infile; void *unused2, *unused3, *unused4, *unused5; LIST *stmts; const struct st_mysql_methods *methods; diff --git a/mysql-test/disabled.def b/mysql-test/disabled.def index b489139a59f..b6991cc1d37 100644 --- a/mysql-test/disabled.def +++ b/mysql-test/disabled.def @@ -21,3 +21,4 @@ innodb-wl5522-debug-zip : broken upstream innodb_bug12902967 : broken upstream file_contents : MDEV-6526 these files are not installed anymore max_statement_time : cannot possibly work, depends on timing +partition_open_files_limit : open_files_limit check broken by MDEV-18360 diff --git a/mysql-test/r/alter_table.test b/mysql-test/r/alter_table.test deleted file mode 100644 index aea1a880a81..00000000000 --- a/mysql-test/r/alter_table.test +++ /dev/null @@ -1,1908 +0,0 @@ -if (`select plugin_auth_version < "5.6.26" from information_schema.plugins where plugin_name='innodb'`) -{ - --skip Not fixed in XtraDB below 5.6.26 -} ---source include/have_innodb.inc -# -# Test of alter table -# ---disable_warnings -drop table if exists t1,t2; -drop database if exists mysqltest; ---enable_warnings - -create table t1 ( -col1 int not null auto_increment primary key, -col2 varchar(30) not null, -col3 varchar (20) not null, -col4 varchar(4) not null, -col5 enum('PENDING', 'ACTIVE', 'DISABLED') not null, -col6 int not null, to_be_deleted int); -insert into t1 values (2,4,3,5,"PENDING",1,7); -alter table t1 -add column col4_5 varchar(20) not null after col4, -add column col7 varchar(30) not null after col5, -add column col8 datetime not null, drop column to_be_deleted, -change column col2 fourth varchar(30) not null after col3, -modify column col6 int not null first; -select * from t1; -drop table t1; - -create table t1 (bandID MEDIUMINT UNSIGNED NOT NULL PRIMARY KEY, payoutID SMALLINT UNSIGNED NOT NULL); -insert into t1 (bandID,payoutID) VALUES (1,6),(2,6),(3,4),(4,9),(5,10),(6,1),(7,12),(8,12); -alter table t1 add column new_col int, order by payoutid,bandid; -select * from t1; -alter table t1 order by bandid,payoutid; -select * from t1; -drop table t1; - -# Check that pack_keys and dynamic length rows are not forced. - -CREATE TABLE t1 ( -GROUP_ID int(10) unsigned DEFAULT '0' NOT NULL, -LANG_ID smallint(5) unsigned DEFAULT '0' NOT NULL, -NAME varchar(80) DEFAULT '' NOT NULL, -PRIMARY KEY (GROUP_ID,LANG_ID), -KEY NAME (NAME)); -#show table status like "t1"; -ALTER TABLE t1 CHANGE NAME NAME CHAR(80) not null; ---replace_column 8 # -SHOW FULL COLUMNS FROM t1; -DROP TABLE t1; - -# -# Test of ALTER TABLE ... ORDER BY -# - -create table t1 (n int); -insert into t1 values(9),(3),(12),(10); -alter table t1 order by n; -select * from t1; -drop table t1; - -CREATE TABLE t1 ( - id int(11) unsigned NOT NULL default '0', - category_id tinyint(4) unsigned NOT NULL default '0', - type_id tinyint(4) unsigned NOT NULL default '0', - body text NOT NULL, - user_id int(11) unsigned NOT NULL default '0', - status enum('new','old') NOT NULL default 'new', - PRIMARY KEY (id) -) ENGINE=MyISAM; - -ALTER TABLE t1 ORDER BY t1.id, t1.status, t1.type_id, t1.user_id, t1.body; -DROP TABLE t1; - -# -# The following combination found a hang-bug in MyISAM -# - -CREATE TABLE t1 (AnamneseId int(10) unsigned NOT NULL auto_increment,B BLOB,PRIMARY KEY (AnamneseId)) engine=myisam; -insert into t1 values (null,"hello"); -LOCK TABLES t1 WRITE; -ALTER TABLE t1 ADD Column new_col int not null; -UNLOCK TABLES; -OPTIMIZE TABLE t1; -DROP TABLE t1; - -# -# Drop and add an auto_increment column -# - -create table t1 (i int unsigned not null auto_increment primary key); -insert into t1 values (null),(null),(null),(null); -alter table t1 drop i,add i int unsigned not null auto_increment, drop primary key, add primary key (i); -select * from t1; -drop table t1; - -# -# Bug #2628: 'alter table t1 rename mysqltest.t1' silently drops mysqltest.t1 -# if it exists -# -create table t1 (name char(15)); -insert into t1 (name) values ("current"); -create database mysqltest; -create table mysqltest.t1 (name char(15)); -insert into mysqltest.t1 (name) values ("mysqltest"); -select * from t1; -select * from mysqltest.t1; ---error ER_TABLE_EXISTS_ERROR -alter table t1 rename mysqltest.t1; -select * from t1; -select * from mysqltest.t1; -drop table t1; -drop database mysqltest; - -# -# ALTER TABLE ... ENABLE/DISABLE KEYS - -create table t1 (n1 int not null, n2 int, n3 int, n4 float, - unique(n1), - key (n1, n2, n3, n4), - key (n2, n3, n4, n1), - key (n3, n4, n1, n2), - key (n4, n1, n2, n3) ); -alter table t1 disable keys; -show keys from t1; -#let $1=10000; -let $1=10; ---disable_query_log -begin; -while ($1) -{ - eval insert into t1 values($1,RAND()*1000,RAND()*1000,RAND()); - dec $1; -} -commit; ---enable_query_log -alter table t1 enable keys; -show keys from t1; -drop table t1; - -# -# Alter table and rename -# - -create table t1 (i int unsigned not null auto_increment primary key); -alter table t1 rename t2; -alter table t2 rename t1, add c char(10) comment "no comment"; -show columns from t1; -drop table t1; - -# implicit analyze - -create table t1 (a int, b int); -let $1=100; ---disable_query_log -begin; -while ($1) -{ - eval insert into t1 values(1,$1), (2,$1), (3, $1); - dec $1; -} -commit; ---enable_query_log -alter table t1 add unique (a,b), add key (b); -show keys from t1; -analyze table t1; -show keys from t1; -drop table t1; - -# -# Test of ALTER TABLE DELAYED -# - -CREATE TABLE t1 (i int(10), index(i) ) ENGINE=MyISAM; -ALTER TABLE t1 DISABLE KEYS; -INSERT DELAYED INTO t1 VALUES(1),(2),(3); -ALTER TABLE t1 ENABLE KEYS; -drop table t1; - -# -# Test ALTER TABLE ENABLE/DISABLE keys when things are locked -# - -CREATE TABLE t1 ( - Host varchar(16) binary NOT NULL default '', - User varchar(16) binary NOT NULL default '', - PRIMARY KEY (Host,User) -) ENGINE=MyISAM; - -ALTER TABLE t1 DISABLE KEYS; -LOCK TABLES t1 WRITE; -INSERT INTO t1 VALUES ('localhost','root'),('localhost',''),('games','monty'); -SHOW INDEX FROM t1; -ALTER TABLE t1 ENABLE KEYS; -UNLOCK TABLES; -CHECK TABLES t1; -DROP TABLE t1; - -# -# Test with two keys -# - -CREATE TABLE t1 ( - Host varchar(16) binary NOT NULL default '', - User varchar(16) binary NOT NULL default '', - PRIMARY KEY (Host,User), - KEY (Host) -) ENGINE=MyISAM; - -ALTER TABLE t1 DISABLE KEYS; -SHOW INDEX FROM t1; -LOCK TABLES t1 WRITE; -INSERT INTO t1 VALUES ('localhost','root'),('localhost',''); -SHOW INDEX FROM t1; -ALTER TABLE t1 ENABLE KEYS; -SHOW INDEX FROM t1; -UNLOCK TABLES; -CHECK TABLES t1; - -# Test RENAME with LOCK TABLES -LOCK TABLES t1 WRITE; -ALTER TABLE t1 RENAME t2; -UNLOCK TABLES; -select * from t2; -DROP TABLE t2; - -# -# Test disable keys with locking -# -CREATE TABLE t1 ( - Host varchar(16) binary NOT NULL default '', - User varchar(16) binary NOT NULL default '', - PRIMARY KEY (Host,User), - KEY (Host) -) ENGINE=MyISAM; - -LOCK TABLES t1 WRITE; -ALTER TABLE t1 DISABLE KEYS; -SHOW INDEX FROM t1; -DROP TABLE t1; - -# -# BUG#4717 - check for valid table names -# -create table t1 (a int); ---error ER_WRONG_TABLE_NAME -alter table t1 rename to ``; ---error ER_WRONG_TABLE_NAME -rename table t1 to ``; -drop table t1; - -# -# BUG#6236 - ALTER TABLE MODIFY should set implicit NOT NULL on PK columns -# -drop table if exists t1, t2; -create table t1 ( a varchar(10) not null primary key ) engine=myisam; -create table t2 ( a varchar(10) not null primary key ) engine=merge union=(t1); -flush tables; -alter table t1 modify a varchar(10); -show create table t2; -flush tables; -alter table t1 modify a varchar(10) not null; -show create table t2; -drop table if exists t1, t2; - -# The following is also part of bug #6236 (CREATE TABLE didn't properly count -# not null columns for primary keys) - -create table t1 (a int, b int, c int, d int, e int, f int, g int, h int,i int, primary key (a,b,c,d,e,f,g,i,h)) engine=MyISAM; -insert into t1 (a) values(1); ---replace_column 7 X 8 X 9 X 10 X 11 X 12 X 13 X 14 X -show table status like 't1'; -alter table t1 modify a int; ---replace_column 7 X 8 X 9 X 10 X 11 X 12 X 13 X 14 X -show table status like 't1'; -drop table t1; -create table t1 (a int not null, b int not null, c int not null, d int not null, e int not null, f int not null, g int not null, h int not null,i int not null, primary key (a,b,c,d,e,f,g,i,h)) engine=MyISAM; -insert into t1 (a) values(1); ---replace_column 7 X 8 X 9 X 10 X 11 X 12 X 13 X 14 X -show table status like 't1'; -drop table t1; - -# -# Test that data get converted when character set is changed -# Test that data doesn't get converted when src or dst is BINARY/BLOB -# -set names koi8r; -create table t1 (a char(10) character set koi8r); -insert into t1 values ('ÔÅÓÔ'); -select a,hex(a) from t1; -alter table t1 change a a char(10) character set cp1251; -select a,hex(a) from t1; -alter table t1 change a a binary(4); -select a,hex(a) from t1; -alter table t1 change a a char(10) character set cp1251; -select a,hex(a) from t1; -alter table t1 change a a char(10) character set koi8r; -select a,hex(a) from t1; -alter table t1 change a a varchar(10) character set cp1251; -select a,hex(a) from t1; -alter table t1 change a a char(10) character set koi8r; -select a,hex(a) from t1; -alter table t1 change a a text character set cp1251; -select a,hex(a) from t1; -alter table t1 change a a char(10) character set koi8r; -select a,hex(a) from t1; -delete from t1; - -# -# Test ALTER TABLE .. CHARACTER SET .. -# -show create table t1; -alter table t1 DEFAULT CHARACTER SET latin1; -show create table t1; -alter table t1 CONVERT TO CHARACTER SET latin1; -show create table t1; -alter table t1 DEFAULT CHARACTER SET cp1251; -show create table t1; - -drop table t1; - -# -# Bug#2821 -# Test that table CHARACTER SET does not affect blobs -# -create table t1 (myblob longblob,mytext longtext) -default charset latin1 collate latin1_general_cs; -show create table t1; -alter table t1 character set latin2; -show create table t1; -drop table t1; - -# -# Bug 2361 (Don't drop UNIQUE with DROP PRIMARY KEY) -# - -CREATE TABLE t1 (a int PRIMARY KEY, b INT UNIQUE); -ALTER TABLE t1 DROP PRIMARY KEY; -SHOW CREATE TABLE t1; ---error ER_CANT_DROP_FIELD_OR_KEY -ALTER TABLE t1 DROP PRIMARY KEY; -DROP TABLE t1; - -# BUG#3899 -create table t1 (a int, b int, key(a)); -insert into t1 values (1,1), (2,2); ---error ER_CANT_DROP_FIELD_OR_KEY -alter table t1 drop key no_such_key; -alter table t1 drop key a; -drop table t1; - -# -# BUG 12207 alter table ... discard table space on MyISAM table causes ERROR 2013 (HY000) -# -# Some platforms (Mac OS X, Windows) will send the error message using small letters. -CREATE TABLE T12207(a int) ENGINE=MYISAM; ---replace_result t12207 T12207 ---error ER_ILLEGAL_HA -ALTER TABLE T12207 DISCARD TABLESPACE; -DROP TABLE T12207; - -# -# Bug #6479 ALTER TABLE ... changing charset fails for TEXT columns -# -# The column's character set was changed but the actual data was not -# modified. In other words, the values were reinterpreted -# as UTF8 instead of being converted. -create table t1 (a text) character set koi8r; -insert into t1 values (_koi8r'ÔÅÓÔ'); -select hex(a) from t1; -alter table t1 convert to character set cp1251; -select hex(a) from t1; -drop table t1; - -# -# Test for bug #7884 "Able to add invalid unique index on TIMESTAMP prefix" -# MySQL should not think that packed field with non-zero decimals is -# geometry field and allow to create prefix index which is -# shorter than packed field length. -# -create table t1 ( a timestamp ); ---error ER_WRONG_SUB_KEY -alter table t1 add unique ( a(1) ); -drop table t1; - -# -# Bug #24395: ALTER TABLE DISABLE KEYS doesn't work when modifying the table -# -# This problem happens if the data change is compatible. -# Changing to the same type is compatible for example. -# ---disable_warnings -drop table if exists t1; ---enable_warnings -create table t1 (a int, key(a)); -show indexes from t1; ---echo "this used not to disable the index" -alter table t1 modify a int, disable keys; -show indexes from t1; - -alter table t1 enable keys; -show indexes from t1; - -alter table t1 modify a bigint, disable keys; -show indexes from t1; - -alter table t1 enable keys; -show indexes from t1; - -alter table t1 add b char(10), disable keys; -show indexes from t1; - -alter table t1 add c decimal(10,2), enable keys; -show indexes from t1; - ---echo "this however did" -alter table t1 disable keys; -show indexes from t1; - -desc t1; - -alter table t1 add d decimal(15,5); ---echo "The key should still be disabled" -show indexes from t1; - -drop table t1; - ---echo "Now will test with one unique index" -create table t1(a int, b char(10), unique(a)); -show indexes from t1; -alter table t1 disable keys; -show indexes from t1; -alter table t1 enable keys; - ---echo "If no copy on noop change, this won't touch the data file" ---echo "Unique index, no change" -alter table t1 modify a int, disable keys; -show indexes from t1; - ---echo "Change the type implying data copy" ---echo "Unique index, no change" -alter table t1 modify a bigint, disable keys; -show indexes from t1; - -alter table t1 modify a bigint; -show indexes from t1; - -alter table t1 modify a int; -show indexes from t1; - -drop table t1; - ---echo "Now will test with one unique and one non-unique index" -create table t1(a int, b char(10), unique(a), key(b)); -show indexes from t1; -alter table t1 disable keys; -show indexes from t1; -alter table t1 enable keys; - - ---echo "If no copy on noop change, this won't touch the data file" ---echo "The non-unique index will be disabled" -alter table t1 modify a int, disable keys; -show indexes from t1; -alter table t1 enable keys; -show indexes from t1; - ---echo "Change the type implying data copy" ---echo "The non-unique index will be disabled" -alter table t1 modify a bigint, disable keys; -show indexes from t1; - ---echo "Change again the type, but leave the indexes as_is" -alter table t1 modify a int; -show indexes from t1; ---echo "Try the same. When data is no copied on similar tables, this is noop" -alter table t1 modify a int; -show indexes from t1; - -drop table t1; - - -# -# Bug#11493 - Alter table rename to default database does not work without -# db name qualifying -# -create database mysqltest; -create table t1 (c1 int); -# Move table to other database. -alter table t1 rename mysqltest.t1; -# Assure that it has moved. ---error ER_BAD_TABLE_ERROR -drop table t1; -# Move table back. -alter table mysqltest.t1 rename t1; -# Assure that it is back. -drop table t1; -# Now test for correct message if no database is selected. -# Create t1 in 'test'. -create table t1 (c1 int); -# Change to other db. -use mysqltest; -# Drop the current db. This de-selects any db. -drop database mysqltest; -# Now test for correct message. ---error ER_NO_DB_ERROR -alter table test.t1 rename t1; -# Check that explicit qualifying works even with no selected db. -alter table test.t1 rename test.t1; -# Go back to standard 'test' db. -use test; -drop table t1; - -# -# BUG#23404 - ROW_FORMAT=FIXED option is lost is an index is added to the -# table -# -CREATE TABLE t1(a INT) ROW_FORMAT=FIXED; -CREATE INDEX i1 ON t1(a); -SHOW CREATE TABLE t1; -DROP INDEX i1 ON t1; -SHOW CREATE TABLE t1; -DROP TABLE t1; - -# -# Bug#24219 - ALTER TABLE ... RENAME TO ... , DISABLE KEYS leads to crash -# ---disable_warnings -DROP TABLE IF EXISTS bug24219; -DROP TABLE IF EXISTS bug24219_2; ---enable_warnings - -CREATE TABLE bug24219 (a INT, INDEX(a)); - -SHOW INDEX FROM bug24219; - -ALTER TABLE bug24219 RENAME TO bug24219_2, DISABLE KEYS; - -SHOW INDEX FROM bug24219_2; - -DROP TABLE bug24219_2; - -# -# Bug#24562 (ALTER TABLE ... ORDER BY ... with complex expression asserts) -# - ---disable_warnings -drop table if exists table_24562; ---enable_warnings - -create table table_24562( - section int, - subsection int, - title varchar(50)); - -insert into table_24562 values -(1, 0, "Introduction"), -(1, 1, "Authors"), -(1, 2, "Acknowledgements"), -(2, 0, "Basics"), -(2, 1, "Syntax"), -(2, 2, "Client"), -(2, 3, "Server"), -(3, 0, "Intermediate"), -(3, 1, "Complex queries"), -(3, 2, "Stored Procedures"), -(3, 3, "Stored Functions"), -(4, 0, "Advanced"), -(4, 1, "Replication"), -(4, 2, "Load balancing"), -(4, 3, "High availability"), -(5, 0, "Conclusion"); - -select * from table_24562; - -alter table table_24562 add column reviewer varchar(20), -order by title; - -select * from table_24562; - -update table_24562 set reviewer="Me" where section=2; -update table_24562 set reviewer="You" where section=3; - -alter table table_24562 -order by section ASC, subsection DESC; - -select * from table_24562; - -alter table table_24562 -order by table_24562.subsection ASC, table_24562.section DESC; - -select * from table_24562; - ---error ER_PARSE_ERROR -alter table table_24562 order by 12; ---error ER_PARSE_ERROR -alter table table_24562 order by (section + 12); ---error ER_PARSE_ERROR -alter table table_24562 order by length(title); ---error ER_PARSE_ERROR -alter table table_24562 order by (select 12 from dual); - ---error ER_BAD_FIELD_ERROR -alter table table_24562 order by no_such_col; - -drop table table_24562; - -# End of 4.1 tests - -# -# Bug #14693 (ALTER SET DEFAULT doesn't work) -# - -create table t1 (mycol int(10) not null); -alter table t1 alter column mycol set default 0; -desc t1; -drop table t1; - -# -# Bug#25262 Auto Increment lost when changing Engine type -# - -create table t1(id int(8) primary key auto_increment) engine=heap; - -insert into t1 values (null); -insert into t1 values (null); - -select * from t1; - -# Set auto increment to 50 -alter table t1 auto_increment = 50; - -# Alter to myisam -alter table t1 engine = myisam; - -# This insert should get id 50 -insert into t1 values (null); -select * from t1; - -# Alter to heap again -alter table t1 engine = heap; -insert into t1 values (null); -select * from t1; - -drop table t1; - -# -# Bug#27507: Wrong DATETIME value was allowed by ALTER TABLE in the -# NO_ZERO_DATE mode. -# -set @orig_sql_mode = @@sql_mode; -set sql_mode="no_zero_date"; -create table t1(f1 int); -alter table t1 add column f2 datetime not null, add column f21 date not null; -insert into t1 values(1,'2000-01-01','2000-01-01'); ---error 1292 -alter table t1 add column f3 datetime not null; ---error 1292 -alter table t1 add column f3 date not null; ---error 1292 -alter table t1 add column f4 datetime not null default '2002-02-02', - add column f41 date not null; -alter table t1 add column f4 datetime not null default '2002-02-02', - add column f41 date not null default '2002-02-02'; -select * from t1; -drop table t1; -set sql_mode= @orig_sql_mode; - -# -# Some additional tests for new, faster alter table. Note that most of the -# whole alter table code is being tested all around the test suite already. -# - -create table t1 (v varchar(32)); -insert into t1 values ('def'),('abc'),('hij'),('3r4f'); -select * from t1; -# Fast alter, no copy performed -alter table t1 change v v2 varchar(32); -select * from t1; -# Fast alter, no copy performed -alter table t1 change v2 v varchar(64); -select * from t1; -update t1 set v = 'lmn' where v = 'hij'; -select * from t1; -# Regular alter table -alter table t1 add i int auto_increment not null primary key first; -select * from t1; -update t1 set i=5 where i=3; -select * from t1; -alter table t1 change i i bigint; -select * from t1; -alter table t1 add unique key (i, v); -select * from t1 where i between 2 and 4 and v in ('def','3r4f','lmn'); -drop table t1; - -# -# Bug#6073 "ALTER table minor glich": ALTER TABLE complains that an index -# without # prefix is not allowed for TEXT columns, while index -# is defined with prefix. -# -create table t1 (t varchar(255) default null, key t (t(80))) -engine=myisam default charset=latin1; -alter table t1 change t t text; -drop table t1; - -# -# Bug #26794: Adding an index with a prefix on a SPATIAL type breaks ALTER -# TABLE -# -CREATE TABLE t1 (a varchar(500)); - -ALTER TABLE t1 ADD b GEOMETRY NOT NULL, ADD SPATIAL INDEX(b); -SHOW CREATE TABLE t1; -ALTER TABLE t1 ADD KEY(b(50)); -SHOW CREATE TABLE t1; - -ALTER TABLE t1 ADD c POINT; -SHOW CREATE TABLE t1; - ---error ER_WRONG_SUB_KEY -CREATE TABLE t2 (a INT, KEY (a(20))); - -ALTER TABLE t1 ADD d INT; ---error ER_WRONG_SUB_KEY -ALTER TABLE t1 ADD KEY (d(20)); - -# the 5.1 part of the test ---error ER_WRONG_SUB_KEY -ALTER TABLE t1 ADD e GEOMETRY NOT NULL, ADD SPATIAL KEY (e(30)); - -DROP TABLE t1; - -# -# Bug#18038 MySQL server corrupts binary columns data -# - -CREATE TABLE t1 (s CHAR(8) BINARY); -INSERT INTO t1 VALUES ('test'); -SELECT LENGTH(s) FROM t1; -ALTER TABLE t1 MODIFY s CHAR(10) BINARY; -SELECT LENGTH(s) FROM t1; -DROP TABLE t1; - -CREATE TABLE t1 (s BINARY(8)); -INSERT INTO t1 VALUES ('test'); -SELECT LENGTH(s) FROM t1; -SELECT HEX(s) FROM t1; -ALTER TABLE t1 MODIFY s BINARY(10); -SELECT HEX(s) FROM t1; -SELECT LENGTH(s) FROM t1; -DROP TABLE t1; - -# -# Bug#19386: Multiple alter causes crashed table -# The trailing column would get corrupted data, or server could not even read -# it. -# - -CREATE TABLE t1 (v VARCHAR(3), b INT); -INSERT INTO t1 VALUES ('abc', 5); -SELECT * FROM t1; -ALTER TABLE t1 MODIFY COLUMN v VARCHAR(4); -SELECT * FROM t1; -DROP TABLE t1; - - -# -# Bug#31291 ALTER TABLE CONVERT TO CHARACTER SET does not change some data types -# -create table t1 (a tinytext character set latin1); -alter table t1 convert to character set utf8; -show create table t1; -drop table t1; -create table t1 (a mediumtext character set latin1); -alter table t1 convert to character set utf8; -show create table t1; -drop table t1; - ---echo End of 5.0 tests - -# -# Extended test coverage for ALTER TABLE behaviour under LOCK TABLES -# It should be consistent across all platforms and for all engines -# (Before 5.1 this was not true as behavior was different between -# Unix/Windows and transactional/non-transactional tables). -# See also innodb_mysql.test -# ---disable_warnings -drop table if exists t1, t2, t3; ---enable_warnings -create table t1 (i int); -create table t3 (j int); -insert into t1 values (); -insert into t3 values (); -# Table which is altered under LOCK TABLES it should stay in list of locked -# tables and be available after alter takes place unless ALTER contains RENAME -# clause. We should see the new definition of table, of course. -lock table t1 write, t3 read; -# Example of so-called 'fast' ALTER TABLE -alter table t1 modify i int default 1; -insert into t1 values (); -select * from t1; -# And now full-blown ALTER TABLE -alter table t1 change i c char(10) default "Two"; -insert into t1 values (); -select * from t1; -# If table is renamed then it should be removed from the list -# of locked tables. 'Fast' ALTER TABLE with RENAME clause: -alter table t1 modify c char(10) default "Three", rename to t2; ---error ER_TABLE_NOT_LOCKED -select * from t1; ---error ER_TABLE_NOT_LOCKED -select * from t2; -select * from t3; -unlock tables; -insert into t2 values (); -select * from t2; -lock table t2 write, t3 read; -# Full ALTER TABLE with RENAME -alter table t2 change c vc varchar(100) default "Four", rename to t1; ---error ER_TABLE_NOT_LOCKED -select * from t1; ---error ER_TABLE_NOT_LOCKED -select * from t2; -select * from t3; -unlock tables; -insert into t1 values (); -select * from t1; -drop tables t1, t3; - - -# -# Bug#18775 - Temporary table from alter table visible to other threads -# -# Check if special characters work and duplicates are detected. ---disable_warnings -DROP TABLE IF EXISTS `t+1`, `t+2`; ---enable_warnings -CREATE TABLE `t+1` (c1 INT); -ALTER TABLE `t+1` RENAME `t+2`; -CREATE TABLE `t+1` (c1 INT); ---error ER_TABLE_EXISTS_ERROR -ALTER TABLE `t+1` RENAME `t+2`; -DROP TABLE `t+1`, `t+2`; -# -# Same for temporary tables though these names do not become file names. -CREATE TEMPORARY TABLE `tt+1` (c1 INT); -ALTER TABLE `tt+1` RENAME `tt+2`; -CREATE TEMPORARY TABLE `tt+1` (c1 INT); ---error ER_TABLE_EXISTS_ERROR -ALTER TABLE `tt+1` RENAME `tt+2`; -SHOW CREATE TABLE `tt+1`; -SHOW CREATE TABLE `tt+2`; -DROP TABLE `tt+1`, `tt+2`; -# -# Check if special characters as in tmp_file_prefix work. -CREATE TABLE `#sql1` (c1 INT); -CREATE TABLE `@0023sql2` (c1 INT); -SHOW TABLES; -RENAME TABLE `#sql1` TO `@0023sql1`; -RENAME TABLE `@0023sql2` TO `#sql2`; -SHOW TABLES; -ALTER TABLE `@0023sql1` RENAME `#sql-1`; -ALTER TABLE `#sql2` RENAME `@0023sql-2`; -SHOW TABLES; -INSERT INTO `#sql-1` VALUES (1); -INSERT INTO `@0023sql-2` VALUES (2); -DROP TABLE `#sql-1`, `@0023sql-2`; -# -# Same for temporary tables though these names do not become file names. -CREATE TEMPORARY TABLE `#sql1` (c1 INT); -CREATE TEMPORARY TABLE `@0023sql2` (c1 INT); -SHOW TABLES; -ALTER TABLE `#sql1` RENAME `@0023sql1`; -ALTER TABLE `@0023sql2` RENAME `#sql2`; -SHOW TABLES; -INSERT INTO `#sql2` VALUES (1); -INSERT INTO `@0023sql1` VALUES (2); -SHOW CREATE TABLE `#sql2`; -SHOW CREATE TABLE `@0023sql1`; -DROP TABLE `#sql2`, `@0023sql1`; - -# -# Bug #22369: Alter table rename combined with other alterations causes lost tables -# -# This problem happens if the data change is compatible. -# Changing to the same type is compatible for example. -# ---disable_warnings -DROP TABLE IF EXISTS t1; -DROP TABLE IF EXISTS t2; ---enable_warnings -CREATE TABLE t1 ( - int_field INTEGER UNSIGNED NOT NULL, - char_field CHAR(10), - INDEX(`int_field`) -); - -DESCRIBE t1; - -SHOW INDEXES FROM t1; - -INSERT INTO t1 VALUES (1, "edno"), (1, "edno"), (2, "dve"), (3, "tri"), (5, "pet"); ---echo "Non-copy data change - new frm, but old data and index files" -ALTER TABLE t1 - CHANGE int_field unsigned_int_field INTEGER UNSIGNED NOT NULL, - RENAME t2; - ---error ER_NO_SUCH_TABLE -SELECT * FROM t1 ORDER BY int_field; -SELECT * FROM t2 ORDER BY unsigned_int_field; -DESCRIBE t2; -DESCRIBE t2; -ALTER TABLE t2 MODIFY unsigned_int_field BIGINT UNSIGNED NOT NULL; -DESCRIBE t2; - -DROP TABLE t2; - -# -# Bug#28427: Columns were renamed instead of moving by ALTER TABLE. -# -CREATE TABLE t1 (f1 INT, f2 INT, f3 INT); -INSERT INTO t1 VALUES (1, 2, NULL); -SELECT * FROM t1; -ALTER TABLE t1 MODIFY COLUMN f3 INT AFTER f1; -SELECT * FROM t1; -ALTER TABLE t1 MODIFY COLUMN f3 INT AFTER f2; -SELECT * FROM t1; -DROP TABLE t1; - -# -# BUG#29957 - alter_table.test fails -# -create table t1 (c char(10) default "Two"); -lock table t1 write; -insert into t1 values (); -alter table t1 modify c char(10) default "Three"; -unlock tables; -select * from t1; -check table t1; -drop table t1; - -# -# Bug#33873: Fast ALTER TABLE doesn't work with multibyte character sets -# - ---disable_warnings -DROP TABLE IF EXISTS t1; ---enable_warnings -CREATE TABLE t1 (id int, c int) character set latin1; -INSERT INTO t1 VALUES (1,1); ---enable_info -ALTER TABLE t1 CHANGE c d int; -ALTER TABLE t1 CHANGE d c int; -ALTER TABLE t1 MODIFY c VARCHAR(10); -ALTER TABLE t1 CHANGE c d varchar(10); -ALTER TABLE t1 CHANGE d c varchar(10); ---disable_info -DROP TABLE t1; - ---disable_warnings -DROP TABLE IF EXISTS t1; ---enable_warnings -CREATE TABLE t1 (id int, c int) character set utf8; -INSERT INTO t1 VALUES (1,1); ---enable_info -ALTER TABLE t1 CHANGE c d int; -ALTER TABLE t1 CHANGE d c int; -ALTER TABLE t1 MODIFY c VARCHAR(10); -ALTER TABLE t1 CHANGE c d varchar(10); -ALTER TABLE t1 CHANGE d c varchar(10); ---disable_info -DROP TABLE t1; - -# -# Bug#39372 "Smart" ALTER TABLE not so smart after all. -# -create table t1(f1 int not null, f2 int not null, key (f1), key (f2)); -let $count= 50; ---disable_query_log -begin; -while ($count) -{ - EVAL insert into t1 values (1,1),(1,1),(1,1),(1,1),(1,1); - EVAL insert into t1 values (2,2),(2,2),(2,2),(2,2),(2,2); - dec $count ; -} -commit; ---enable_query_log - -select index_length into @unpaked_keys_size from -information_schema.tables where table_name='t1'; -alter table t1 pack_keys=1; -select index_length into @paked_keys_size from -information_schema.tables where table_name='t1'; -select (@unpaked_keys_size > @paked_keys_size); - -select max_data_length into @orig_max_data_length from -information_schema.tables where table_name='t1'; -alter table t1 max_rows=100; -select max_data_length into @changed_max_data_length from -information_schema.tables where table_name='t1'; -select (@orig_max_data_length > @changed_max_data_length); - -drop table t1; - -# -# Bug #23113: Different behavior on altering ENUM fields between 5.0 and 5.1 -# -CREATE TABLE t1(a INT AUTO_INCREMENT PRIMARY KEY, - b ENUM('a', 'b', 'c') NOT NULL); -INSERT INTO t1 (b) VALUES ('a'), ('c'), ('b'), ('b'), ('a'); -ALTER TABLE t1 MODIFY b ENUM('a', 'z', 'b', 'c') NOT NULL; -SELECT * FROM t1; -DROP TABLE t1; - -# -# Test for ALTER column DROP DEFAULT -# - -SET @save_sql_mode=@@sql_mode; -SET sql_mode=strict_all_tables; - -CREATE TABLE t1 (a int NOT NULL default 42); -INSERT INTO t1 values (); -SELECT * FROM t1; -ALTER TABLE t1 ALTER COLUMN a DROP DEFAULT; ---error 1364 -INSERT INTO t1 values (); -INSERT INTO t1 (a) VALUES (11); -SELECT * FROM t1 ORDER BY a; -DROP TABLE t1; -SET @@sql_mode=@save_sql_mode; ---echo # ---echo # Bug#45567: Fast ALTER TABLE broken for enum and set ---echo # - ---disable_warnings -DROP TABLE IF EXISTS t1; ---enable_warnings - -CREATE TABLE t1 (a ENUM('a1','a2')); -INSERT INTO t1 VALUES ('a1'),('a2'); ---enable_info ---echo # No copy: No modification -ALTER TABLE t1 MODIFY COLUMN a ENUM('a1','a2'); ---echo # No copy: Add new enumeration to the end -ALTER TABLE t1 MODIFY COLUMN a ENUM('a1','a2','a3'); ---echo # Copy: Modify and add new to the end -ALTER TABLE t1 MODIFY COLUMN a ENUM('a1','a2','xx','a5'); ---echo # Copy: Remove from the end -ALTER TABLE t1 MODIFY COLUMN a ENUM('a1','a2','xx'); ---echo # Copy: Add new enumeration -ALTER TABLE t1 MODIFY COLUMN a ENUM('a1','a2','a0','xx'); ---echo # No copy: Add new enumerations to the end -ALTER TABLE t1 MODIFY COLUMN a ENUM('a1','a2','a0','xx','a5','a6'); ---disable_info -DROP TABLE t1; - -CREATE TABLE t1 (a SET('a1','a2')); -INSERT INTO t1 VALUES ('a1'),('a2'); ---enable_info ---echo # No copy: No modification -ALTER TABLE t1 MODIFY COLUMN a SET('a1','a2'); ---echo # No copy: Add new to the end -ALTER TABLE t1 MODIFY COLUMN a SET('a1','a2','a3'); ---echo # Copy: Modify and add new to the end -ALTER TABLE t1 MODIFY COLUMN a SET('a1','a2','xx','a5'); ---echo # Copy: Remove from the end -ALTER TABLE t1 MODIFY COLUMN a SET('a1','a2','xx'); ---echo # Copy: Add new member -ALTER TABLE t1 MODIFY COLUMN a SET('a1','a2','a0','xx'); ---echo # No copy: Add new to the end -ALTER TABLE t1 MODIFY COLUMN a SET('a1','a2','a0','xx','a5','a6'); ---echo # Copy: Numerical incrase (pack lenght) -ALTER TABLE t1 MODIFY COLUMN a SET('a1','a2','a0','xx','a5','a6','a7','a8','a9','a10'); ---disable_info -DROP TABLE t1; - -# -# Bug#43508: Renaming timestamp or date column triggers table copy -# - -CREATE TABLE t1 (f1 TIMESTAMP NULL DEFAULT NULL, - f2 INT(11) DEFAULT NULL) ENGINE=MYISAM DEFAULT CHARSET=utf8; - -INSERT INTO t1 VALUES (NULL, NULL), ("2009-10-09 11:46:19", 2); - ---echo this should affect no rows as there is no real change ---enable_info -ALTER TABLE t1 CHANGE COLUMN f1 f1_no_real_change TIMESTAMP NULL DEFAULT NULL; ---disable_info -DROP TABLE t1; - - ---echo # ---echo # Bug #31145: ALTER TABLE DROP COLUMN, ADD COLUMN crashes (linux) ---echo # or freezes (win) the server ---echo # - -CREATE TABLE t1 (a TEXT, id INT, b INT); -ALTER TABLE t1 DROP COLUMN a, ADD COLUMN c TEXT FIRST; - -DROP TABLE t1; - - ---echo # ---echo # Test for bug #12652385 - "61493: REORDERING COLUMNS TO POSITION ---echo # FIRST CAN CAUSE DATA TO BE CORRUPTED". ---echo # ---disable_warnings -drop table if exists t1; ---enable_warnings ---echo # Use MyISAM engine as the fact that InnoDB doesn't support ---echo # in-place ALTER TABLE in cases when columns are being renamed ---echo # hides some bugs. -create table t1 (i int, j int) engine=myisam; -insert into t1 value (1, 2); ---echo # First, test for original problem described in the bug report. -select * from t1; ---echo # Change of column order by the below ALTER TABLE statement should ---echo # affect both column names and column contents. -alter table t1 modify column j int first; -select * from t1; ---echo # Now test for similar problem with the same root. ---echo # The below ALTER TABLE should change not only the name but ---echo # also the value for the last column of the table. -alter table t1 drop column i, add column k int default 0; -select * from t1; ---echo # Clean-up. -drop table t1; - - ---echo End of 5.1 tests - -# -# Bug #31031 ALTER TABLE regression in 5.0 -# -# The ALTER TABLE operation failed with -# ERROR 1089 (HY000): Incorrect sub part key; ... -# -CREATE TABLE t1(c CHAR(10), - i INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY); -INSERT INTO t1 VALUES('a',2),('b',4),('c',6); -ALTER TABLE t1 - DROP i, - ADD i INT UNSIGNED NOT NULL AUTO_INCREMENT, - AUTO_INCREMENT = 1; -DROP TABLE t1; - - -# -# Bug#50542 5.5.x doesn't check length of key prefixes: -# corruption and crash results -# -# This case is related to Bug#31031 (above) -# A statement where the index key is larger/wider than -# the column type, should cause an error -# ---error ER_WRONG_SUB_KEY -CREATE TABLE t1 (a CHAR(1), PRIMARY KEY (a(255))); - -# Test other variants of creating indices -CREATE TABLE t1 (a CHAR(1)); -# ALTER TABLE ---error ER_WRONG_SUB_KEY -ALTER TABLE t1 ADD PRIMARY KEY (a(20)); ---error ER_WRONG_SUB_KEY -ALTER TABLE t1 ADD KEY (a(20)); -# CREATE INDEX ---error ER_WRONG_SUB_KEY -CREATE UNIQUE INDEX i1 ON t1 (a(20)); ---error ER_WRONG_SUB_KEY -CREATE INDEX i2 ON t1 (a(20)); -# cleanup -DROP TABLE t1; - - -# -# Bug #45052 ALTER TABLE ADD COLUMN crashes server with multiple foreign key columns -# The alter table fails if 2 or more new fields added and -# also added a key with these fields -# -CREATE TABLE t1 (id int); -INSERT INTO t1 VALUES (1), (2); -ALTER TABLE t1 ADD COLUMN (f1 INT), ADD COLUMN (f2 INT), ADD KEY f2k(f2); -DROP TABLE t1; - - ---echo # ---echo # Test for bug #53820 "ALTER a MEDIUMINT column table causes full ---echo # table copy". ---echo # ---disable_warnings -DROP TABLE IF EXISTS t1; ---enable_warnings -CREATE TABLE t1 (a INT, b MEDIUMINT); -INSERT INTO t1 VALUES (1, 1), (2, 2); ---echo # The below ALTER should not copy table and so no rows should ---echo # be shown as affected. ---enable_info -ALTER TABLE t1 CHANGE a id INT; ---disable_info -DROP TABLE t1; - - ---echo # ---echo # Bug#11754461 CANNOT ALTER TABLE WHEN KEY PREFIX TOO LONG ---echo # - ---disable_warnings -DROP DATABASE IF EXISTS db1; ---enable_warnings - -CREATE DATABASE db1 CHARACTER SET utf8; -CREATE TABLE db1.t1 (bar TINYTEXT, KEY (bar(100))); -ALTER TABLE db1.t1 ADD baz INT; - -DROP DATABASE db1; - - ---echo # Additional coverage for refactoring which is made as part ---echo # of fix for bug #27480 "Extend CREATE TEMPORARY TABLES privilege ---echo # to allow temp table operations". ---echo # ---echo # At some point the below test case failed on assertion. - ---disable_warnings -DROP TABLE IF EXISTS t1; ---enable_warnings - -CREATE TEMPORARY TABLE t1 (i int) ENGINE=MyISAM; - ---error ER_ILLEGAL_HA -ALTER TABLE t1 DISCARD TABLESPACE; - -DROP TABLE t1; - - ---echo # ---echo # Bug#11938039 RE-EXECUTION OF FRM-ONLY ALTER TABLE WITH RENAME ---echo # CLAUSE FAILS OR ABORTS SERVER. ---echo # ---disable_warnings -drop table if exists t1; ---enable_warnings -create table t1 (a int); -prepare stmt1 from 'alter table t1 alter column a set default 1, rename to t2'; -execute stmt1; -rename table t2 to t1; ---echo # The below statement should succeed and not emit error or abort server. -execute stmt1; -deallocate prepare stmt1; -drop table t2; - ---echo # ---echo # MDEV-8960 Can't refer the same column twice in one ALTER TABLE ---echo # - -CREATE TABLE t1 ( - `a` int(11) DEFAULT NULL -) DEFAULT CHARSET=utf8; - -ALTER TABLE t1 ADD COLUMN `consultant_id` integer NOT NULL, -ALTER COLUMN `consultant_id` DROP DEFAULT; - -SHOW CREATE TABLE t1; -DROP TABLE t1; - -CREATE TABLE t1 ( - `a` int(11) DEFAULT NULL -) DEFAULT CHARSET=utf8; - -ALTER TABLE t1 ADD COLUMN `consultant_id` integer NOT NULL, -ALTER COLUMN `consultant_id` SET DEFAULT 2; -SHOW CREATE TABLE t1; -DROP TABLE t1; - -CREATE TABLE t1 ( - `a` int(11) DEFAULT NULL -) DEFAULT CHARSET=utf8; - -ALTER TABLE t1 ADD COLUMN `consultant_id` integer NOT NULL DEFAULT 2, -ALTER COLUMN `consultant_id` DROP DEFAULT; -SHOW CREATE TABLE t1; -DROP TABLE t1; - -CREATE TABLE t1 ( - `a` int(11) DEFAULT NULL -) DEFAULT CHARSET=utf8; - -ALTER TABLE t1 ADD COLUMN `consultant_id` integer NOT NULL DEFAULT 2, -ALTER COLUMN `consultant_id` DROP DEFAULT, -MODIFY COLUMN `consultant_id` BIGINT; -SHOW CREATE TABLE t1; -DROP TABLE t1; - ---echo # ---echo # BUG#27788685: NO WARNING WHEN TRUNCATING A STRING WITH DATA LOSS ---echo # - -SET GLOBAL max_allowed_packet=17825792; - ---connect(con1, localhost, root,,) -CREATE TABLE t1 (t1_fld1 TEXT); -CREATE TABLE t2 (t2_fld1 MEDIUMTEXT); -CREATE TABLE t3 (t3_fld1 LONGTEXT); - -INSERT INTO t1 VALUES (REPEAT('a',300)); -INSERT INTO t2 VALUES (REPEAT('b',65680)); -INSERT INTO t3 VALUES (REPEAT('c',16777300)); - -SELECT LENGTH(t1_fld1) FROM t1; -SELECT LENGTH(t2_fld1) FROM t2; -SELECT LENGTH(t3_fld1) FROM t3; - ---echo # With strict mode -SET SQL_MODE='STRICT_ALL_TABLES'; - ---error ER_DATA_TOO_LONG -ALTER TABLE t1 CHANGE `t1_fld1` `my_t1_fld1` TINYTEXT; ---error ER_DATA_TOO_LONG -ALTER TABLE t2 CHANGE `t2_fld1` `my_t2_fld1` TEXT; ---error ER_DATA_TOO_LONG -ALTER TABLE t3 CHANGE `t3_fld1` `my_t3_fld1` MEDIUMTEXT; - ---echo # With non-strict mode -SET SQL_MODE=''; - -ALTER TABLE t1 CHANGE `t1_fld1` `my_t1_fld1` TINYTEXT; -ALTER TABLE t2 CHANGE `t2_fld1` `my_t2_fld1` TEXT; -ALTER TABLE t3 CHANGE `t3_fld1` `my_t3_fld1` MEDIUMTEXT; - -SELECT LENGTH(my_t1_fld1) FROM t1; -SELECT LENGTH(my_t2_fld1) FROM t2; -SELECT LENGTH(my_t3_fld1) FROM t3; - -# Cleanup ---disconnect con1 ---source include/wait_until_disconnected.inc - ---connection default -DROP TABLE t1, t2, t3; - -SET SQL_MODE=default; -SET GLOBAL max_allowed_packet=default; - -# -# Test of ALTER TABLE IF [NOT] EXISTS -# - -CREATE TABLE t1 ( - id INT(11) NOT NULL, - x_param INT(11) DEFAULT NULL, - PRIMARY KEY (id) -) ENGINE=MYISAM; - -ALTER TABLE t1 ADD COLUMN IF NOT EXISTS id INT, - ADD COLUMN IF NOT EXISTS lol INT AFTER id; -ALTER TABLE t1 ADD COLUMN IF NOT EXISTS lol INT AFTER id; -ALTER TABLE t1 DROP COLUMN IF EXISTS lol; -ALTER TABLE t1 DROP COLUMN IF EXISTS lol; - -ALTER TABLE t1 ADD KEY IF NOT EXISTS x_param(x_param); -ALTER TABLE t1 ADD KEY IF NOT EXISTS x_param(x_param); -ALTER TABLE t1 MODIFY IF EXISTS lol INT; - -DROP INDEX IF EXISTS x_param ON t1; -DROP INDEX IF EXISTS x_param ON t1; -CREATE INDEX IF NOT EXISTS x_param1 ON t1(x_param); -CREATE INDEX IF NOT EXISTS x_param1 ON t1(x_param); -SHOW CREATE TABLE t1; -DROP TABLE t1; - -CREATE TABLE t1 ( - id INT(11) NOT NULL, - x_param INT(11) DEFAULT NULL, - PRIMARY KEY (id) -) ENGINE=INNODB; - -CREATE TABLE t2 ( - id INT(11) NOT NULL) ENGINE=INNODB; - -ALTER TABLE t1 ADD COLUMN IF NOT EXISTS id INT, - ADD COLUMN IF NOT EXISTS lol INT AFTER id; -ALTER TABLE t1 ADD COLUMN IF NOT EXISTS lol INT AFTER id; -ALTER TABLE t1 DROP COLUMN IF EXISTS lol; -ALTER TABLE t1 DROP COLUMN IF EXISTS lol; - -ALTER TABLE t1 ADD KEY IF NOT EXISTS x_param(x_param); -ALTER TABLE t1 ADD KEY IF NOT EXISTS x_param(x_param); -ALTER TABLE t1 MODIFY IF EXISTS lol INT; - -DROP INDEX IF EXISTS x_param ON t1; -DROP INDEX IF EXISTS x_param ON t1; -CREATE INDEX IF NOT EXISTS x_param1 ON t1(x_param); -CREATE INDEX IF NOT EXISTS x_param1 ON t1(x_param); -SHOW CREATE TABLE t1; - -ALTER TABLE t2 ADD FOREIGN KEY IF NOT EXISTS fk(id) REFERENCES t1(id); -ALTER TABLE t2 ADD FOREIGN KEY IF NOT EXISTS fk(id) REFERENCES t1(id); -ALTER TABLE t2 DROP FOREIGN KEY IF EXISTS fk; -ALTER TABLE t2 DROP FOREIGN KEY IF EXISTS fk; -SHOW CREATE TABLE t2; -ALTER TABLE t2 ADD FOREIGN KEY (id) REFERENCES t1(id); -ALTER TABLE t2 ADD FOREIGN KEY IF NOT EXISTS t2_ibfk_1(id) REFERENCES t1(id); -ALTER TABLE t2 DROP FOREIGN KEY IF EXISTS t2_ibfk_1; -ALTER TABLE t2 DROP FOREIGN KEY IF EXISTS t2_ibfk_1; -SHOW CREATE TABLE t2; - -DROP TABLE t2; -CREATE TABLE t2 ( - id INT(11) NOT NULL); -ALTER TABLE t2 ADD COLUMN a INT, ADD COLUMN IF NOT EXISTS a INT; -ALTER TABLE t2 ADD KEY k_id(id), ADD KEY IF NOT EXISTS k_id(id); -SHOW CREATE TABLE t2; -ALTER TABLE t2 DROP KEY k_id, DROP KEY IF EXISTS k_id; -ALTER TABLE t2 DROP COLUMN a, DROP COLUMN IF EXISTS a; -SHOW CREATE TABLE t2; - -DROP TABLE t2; -DROP TABLE t1; - -CREATE TABLE t1 ( - `transaction_id` int(11) NOT NULL DEFAULT '0', - KEY `transaction_id` (`transaction_id`)); -ALTER TABLE t1 DROP KEY IF EXISTS transaction_id, ADD PRIMARY KEY IF NOT EXISTS (transaction_id); -SHOW CREATE TABLE t1; - -DROP TABLE t1; - ---echo # Bug#11748057 (formerly known as 34972): ALTER TABLE statement doesn't ---echo # identify correct column name. ---echo # - -CREATE TABLE t1 (c1 int unsigned , c2 char(100) not null default ''); -ALTER TABLE t1 ADD c3 char(16) NOT NULL DEFAULT '' AFTER c2, - MODIFY c2 char(100) NOT NULL DEFAULT '' AFTER c1; -SHOW CREATE TABLE t1; -DROP TABLE t1; - ---echo # ---echo # WL#5534 Online ALTER, Phase 1 ---echo # - ---echo # Single thread tests. ---echo # See innodb_mysql_sync.test for multi thread tests. - ---disable_warnings -DROP TABLE IF EXISTS t1; ---enable_warnings - -CREATE TABLE t1(a INT PRIMARY KEY, b INT) engine=InnoDB; -CREATE TABLE m1(a INT PRIMARY KEY, b INT) engine=MyISAM; -INSERT INTO t1 VALUES (1,1), (2,2); -INSERT INTO m1 VALUES (1,1), (2,2); - ---echo # ---echo # 1: Test ALGORITHM keyword ---echo # - ---echo # --enable_info allows us to see how many rows were updated ---echo # by ALTER TABLE. in-place will show 0 rows, while copy > 0. - ---enable_info -ALTER TABLE t1 ADD INDEX i1(b); -ALTER TABLE t1 ADD INDEX i2(b), ALGORITHM= DEFAULT; -ALTER TABLE t1 ADD INDEX i3(b), ALGORITHM= COPY; -ALTER TABLE t1 ADD INDEX i4(b), ALGORITHM= INPLACE; ---error ER_UNKNOWN_ALTER_ALGORITHM -ALTER TABLE t1 ADD INDEX i5(b), ALGORITHM= INVALID; - -ALTER TABLE m1 ENABLE KEYS; -ALTER TABLE m1 ENABLE KEYS, ALGORITHM= DEFAULT; -ALTER TABLE m1 ENABLE KEYS, ALGORITHM= COPY; -ALTER TABLE m1 ENABLE KEYS, ALGORITHM= INPLACE; ---disable_info - -ALTER TABLE t1 DROP INDEX i1, DROP INDEX i2, DROP INDEX i3, DROP INDEX i4; - ---echo # ---echo # 2: Test ALGORITHM + old_alter_table ---echo # - ---enable_info -SET SESSION old_alter_table= 1; -ALTER TABLE t1 ADD INDEX i1(b); -ALTER TABLE t1 ADD INDEX i2(b), ALGORITHM= DEFAULT; -ALTER TABLE t1 ADD INDEX i3(b), ALGORITHM= COPY; -ALTER TABLE t1 ADD INDEX i4(b), ALGORITHM= INPLACE; -SET SESSION old_alter_table= 0; ---disable_info - -ALTER TABLE t1 DROP INDEX i1, DROP INDEX i2, DROP INDEX i3, DROP INDEX i4; - ---echo # ---echo # 3: Test unsupported in-place operation ---echo # - -ALTER TABLE t1 ADD COLUMN (c1 INT); -ALTER TABLE t1 ADD COLUMN (c2 INT), ALGORITHM= DEFAULT; -ALTER TABLE t1 ADD COLUMN (c3 INT), ALGORITHM= COPY; -ALTER TABLE t1 ADD COLUMN (c4 INT), ALGORITHM= INPLACE; - -ALTER TABLE t1 DROP COLUMN c1, DROP COLUMN c2, DROP COLUMN c3, DROP COLUMN c4; - ---echo # ---echo # 4: Test LOCK keyword ---echo # - ---enable_info -ALTER TABLE t1 ADD INDEX i1(b), LOCK= DEFAULT; -ALTER TABLE t1 ADD INDEX i2(b), LOCK= NONE; -ALTER TABLE t1 ADD INDEX i3(b), LOCK= SHARED; -ALTER TABLE t1 ADD INDEX i4(b), LOCK= EXCLUSIVE; ---error ER_UNKNOWN_ALTER_LOCK -ALTER TABLE t1 ADD INDEX i5(b), LOCK= INVALID; ---disable_info - -ALTER TABLE m1 ENABLE KEYS, LOCK= DEFAULT; ---error ER_ALTER_OPERATION_NOT_SUPPORTED -ALTER TABLE m1 ENABLE KEYS, LOCK= NONE; ---error ER_ALTER_OPERATION_NOT_SUPPORTED -ALTER TABLE m1 ENABLE KEYS, LOCK= SHARED; -ALTER TABLE m1 ENABLE KEYS, LOCK= EXCLUSIVE; - -ALTER TABLE t1 DROP INDEX i1, DROP INDEX i2, DROP INDEX i3, DROP INDEX i4; - ---echo # ---echo # 5: Test ALGORITHM + LOCK ---echo # - ---enable_info -ALTER TABLE t1 ADD INDEX i1(b), ALGORITHM= INPLACE, LOCK= NONE; -ALTER TABLE t1 ADD INDEX i2(b), ALGORITHM= INPLACE, LOCK= SHARED; -ALTER TABLE t1 ADD INDEX i3(b), ALGORITHM= INPLACE, LOCK= EXCLUSIVE; ---error ER_ALTER_OPERATION_NOT_SUPPORTED_REASON -ALTER TABLE t1 ADD INDEX i4(b), ALGORITHM= COPY, LOCK= NONE; -ALTER TABLE t1 ADD INDEX i5(b), ALGORITHM= COPY, LOCK= SHARED; -ALTER TABLE t1 ADD INDEX i6(b), ALGORITHM= COPY, LOCK= EXCLUSIVE; - ---error ER_ALTER_OPERATION_NOT_SUPPORTED -ALTER TABLE m1 ENABLE KEYS, ALGORITHM= INPLACE, LOCK= NONE; ---error ER_ALTER_OPERATION_NOT_SUPPORTED -ALTER TABLE m1 ENABLE KEYS, ALGORITHM= INPLACE, LOCK= SHARED; -ALTER TABLE m1 ENABLE KEYS, ALGORITHM= INPLACE, LOCK= EXCLUSIVE; ---error ER_ALTER_OPERATION_NOT_SUPPORTED_REASON -ALTER TABLE m1 ENABLE KEYS, ALGORITHM= COPY, LOCK= NONE; -# This works because the lock will be SNW for the copy phase. -# It will still require exclusive lock for actually enabling keys. -ALTER TABLE m1 ENABLE KEYS, ALGORITHM= COPY, LOCK= SHARED; -ALTER TABLE m1 ENABLE KEYS, ALGORITHM= COPY, LOCK= EXCLUSIVE; ---disable_info - -DROP TABLE t1, m1; - ---echo # ---echo # 6: Possible deadlock involving thr_lock.c ---echo # - -CREATE TABLE t1(a INT PRIMARY KEY, b INT); -INSERT INTO t1 VALUES (1,1), (2,2); - -START TRANSACTION; -INSERT INTO t1 VALUES (3,3); - ---echo # Connection con1 -connect (con1, localhost, root); ---echo # Sending: ---send ALTER TABLE t1 DISABLE KEYS - ---echo # Connection default -connection default; ---echo # Waiting until ALTER TABLE is blocked. -let $wait_condition= - SELECT COUNT(*) = 1 FROM information_schema.processlist - WHERE state = "Waiting for table metadata lock" AND - info = "ALTER TABLE t1 DISABLE KEYS"; ---source include/wait_condition.inc -UPDATE t1 SET b = 4; -COMMIT; - ---echo # Connection con1 -connection con1; ---echo # Reaping: ALTER TABLE t1 DISABLE KEYS ---reap -disconnect con1; ---source include/wait_until_disconnected.inc - ---echo # Connection default -connection default; -DROP TABLE t1; - ---echo # ---echo # 7: Which operations require copy and which can be done in-place? ---echo # ---echo # Test which ALTER TABLE operations are done in-place and ---echo # which operations are done using temporary table copy. ---echo # ---echo # --enable_info allows us to see how many rows were updated ---echo # by ALTER TABLE. in-place will show 0 rows, while copy > 0. ---echo # - ---disable_warnings -DROP TABLE IF EXISTS ti1, ti2, ti3, tm1, tm2, tm3; ---enable_warnings - ---echo # Single operation tests - -CREATE TABLE ti1(a INT NOT NULL, b INT, c INT) engine=InnoDB; -CREATE TABLE tm1(a INT NOT NULL, b INT, c INT) engine=MyISAM; -CREATE TABLE ti2(a INT PRIMARY KEY AUTO_INCREMENT, b INT, c INT) engine=InnoDB; -CREATE TABLE tm2(a INT PRIMARY KEY AUTO_INCREMENT, b INT, c INT) engine=MyISAM; -INSERT INTO ti1 VALUES (1,1,1), (2,2,2); -INSERT INTO ti2 VALUES (1,1,1), (2,2,2); -INSERT INTO tm1 VALUES (1,1,1), (2,2,2); -INSERT INTO tm2 VALUES (1,1,1), (2,2,2); - ---enable_info -ALTER TABLE ti1; -ALTER TABLE tm1; - -ALTER TABLE ti1 ADD COLUMN d VARCHAR(200); -ALTER TABLE tm1 ADD COLUMN d VARCHAR(200); -ALTER TABLE ti1 ADD COLUMN d2 VARCHAR(200); -ALTER TABLE tm1 ADD COLUMN d2 VARCHAR(200); -ALTER TABLE ti1 ADD COLUMN e ENUM('a', 'b') FIRST; -ALTER TABLE tm1 ADD COLUMN e ENUM('a', 'b') FIRST; -ALTER TABLE ti1 ADD COLUMN f INT AFTER a; -ALTER TABLE tm1 ADD COLUMN f INT AFTER a; - -ALTER TABLE ti1 ADD INDEX ii1(b); -ALTER TABLE tm1 ADD INDEX im1(b); -ALTER TABLE ti1 ADD UNIQUE INDEX ii2 (c); -ALTER TABLE tm1 ADD UNIQUE INDEX im2 (c); -ALTER TABLE ti1 ADD FULLTEXT INDEX ii3 (d); -ALTER TABLE tm1 ADD FULLTEXT INDEX im3 (d); -ALTER TABLE ti1 ADD FULLTEXT INDEX ii4 (d2); -ALTER TABLE tm1 ADD FULLTEXT INDEX im4 (d2); - -# Bug#14140038 INCONSISTENT HANDLING OF FULLTEXT INDEXES IN ALTER TABLE ---error ER_ALTER_OPERATION_NOT_SUPPORTED_REASON -ALTER TABLE ti1 ADD PRIMARY KEY(a), ALGORITHM=INPLACE; -ALTER TABLE ti1 ADD PRIMARY KEY(a); -ALTER TABLE tm1 ADD PRIMARY KEY(a); - -ALTER TABLE ti1 DROP INDEX ii3; -ALTER TABLE tm1 DROP INDEX im3; - -ALTER TABLE ti1 DROP COLUMN d2; -ALTER TABLE tm1 DROP COLUMN d2; - -ALTER TABLE ti1 ADD CONSTRAINT fi1 FOREIGN KEY (b) REFERENCES ti2(a); -ALTER TABLE tm1 ADD CONSTRAINT fm1 FOREIGN KEY (b) REFERENCES tm2(a); - -ALTER TABLE ti1 ALTER COLUMN b SET DEFAULT 1; -ALTER TABLE tm1 ALTER COLUMN b SET DEFAULT 1; -ALTER TABLE ti1 ALTER COLUMN b DROP DEFAULT; -ALTER TABLE tm1 ALTER COLUMN b DROP DEFAULT; - -# This will set both ALTER_COLUMN_NAME and COLUMN_DEFAULT_VALUE -ALTER TABLE ti1 CHANGE COLUMN f g INT; -ALTER TABLE tm1 CHANGE COLUMN f g INT; -ALTER TABLE ti1 CHANGE COLUMN g h VARCHAR(20); -ALTER TABLE tm1 CHANGE COLUMN g h VARCHAR(20); -ALTER TABLE ti1 MODIFY COLUMN e ENUM('a', 'b', 'c'); -ALTER TABLE tm1 MODIFY COLUMN e ENUM('a', 'b', 'c'); -ALTER TABLE ti1 MODIFY COLUMN e INT; -ALTER TABLE tm1 MODIFY COLUMN e INT; -# This will set both ALTER_COLUMN_ORDER and COLUMN_DEFAULT_VALUE -ALTER TABLE ti1 MODIFY COLUMN e INT AFTER h; -ALTER TABLE tm1 MODIFY COLUMN e INT AFTER h; -ALTER TABLE ti1 MODIFY COLUMN e INT FIRST; -ALTER TABLE tm1 MODIFY COLUMN e INT FIRST; -# This will set both ALTER_COLUMN_NOT_NULLABLE and COLUMN_DEFAULT_VALUE ---disable_info -# NULL -> NOT NULL only allowed INPLACE if strict sql_mode is on. -SET @orig_sql_mode = @@sql_mode; -SET @@sql_mode = 'STRICT_TRANS_TABLES'; ---enable_info -ALTER TABLE ti1 MODIFY COLUMN c INT NOT NULL; ---disable_info -SET @@sql_mode = @orig_sql_mode; ---enable_info -ALTER TABLE tm1 MODIFY COLUMN c INT NOT NULL; -# This will set both ALTER_COLUMN_NULLABLE and COLUMN_DEFAULT_VALUE -ALTER TABLE ti1 MODIFY COLUMN c INT NULL; -ALTER TABLE tm1 MODIFY COLUMN c INT NULL; -# This will set both ALTER_COLUMN_EQUAL_PACK_LENGTH and COLUMN_DEFAULT_VALUE -ALTER TABLE ti1 MODIFY COLUMN h VARCHAR(30); -ALTER TABLE tm1 MODIFY COLUMN h VARCHAR(30); -ALTER TABLE ti1 MODIFY COLUMN h VARCHAR(30) AFTER d; -ALTER TABLE tm1 MODIFY COLUMN h VARCHAR(30) AFTER d; - -ALTER TABLE ti1 DROP COLUMN h; -ALTER TABLE tm1 DROP COLUMN h; - -ALTER TABLE ti1 DROP INDEX ii2; -ALTER TABLE tm1 DROP INDEX im2; -ALTER TABLE ti1 DROP PRIMARY KEY; -ALTER TABLE tm1 DROP PRIMARY KEY; - -ALTER TABLE ti1 DROP FOREIGN KEY fi1; -ALTER TABLE tm1 DROP FOREIGN KEY fm1; - -ALTER TABLE ti1 RENAME TO ti3; -ALTER TABLE tm1 RENAME TO tm3; -ALTER TABLE ti3 RENAME TO ti1; -ALTER TABLE tm3 RENAME TO tm1; - -ALTER TABLE ti1 ORDER BY b; -ALTER TABLE tm1 ORDER BY b; - -ALTER TABLE ti1 CONVERT TO CHARACTER SET utf16; -ALTER TABLE tm1 CONVERT TO CHARACTER SET utf16; -ALTER TABLE ti1 DEFAULT CHARACTER SET utf8; -ALTER TABLE tm1 DEFAULT CHARACTER SET utf8; - -ALTER TABLE ti1 FORCE; -ALTER TABLE tm1 FORCE; - -ALTER TABLE ti1 AUTO_INCREMENT 3; -ALTER TABLE tm1 AUTO_INCREMENT 3; -ALTER TABLE ti1 AVG_ROW_LENGTH 10; -ALTER TABLE tm1 AVG_ROW_LENGTH 10; -ALTER TABLE ti1 CHECKSUM 1; -ALTER TABLE tm1 CHECKSUM 1; -ALTER TABLE ti1 COMMENT 'test'; -ALTER TABLE tm1 COMMENT 'test'; -ALTER TABLE ti1 MAX_ROWS 100; -ALTER TABLE tm1 MAX_ROWS 100; -ALTER TABLE ti1 MIN_ROWS 1; -ALTER TABLE tm1 MIN_ROWS 1; -ALTER TABLE ti1 PACK_KEYS 1; -ALTER TABLE tm1 PACK_KEYS 1; - ---disable_info -DROP TABLE ti1, ti2, tm1, tm2; - ---echo # Tests of >1 operation (InnoDB) - -CREATE TABLE ti1(a INT PRIMARY KEY AUTO_INCREMENT, b INT) engine=InnoDB; -INSERT INTO ti1(b) VALUES (1), (2); - ---enable_info -ALTER TABLE ti1 RENAME TO ti3, ADD INDEX ii1(b); - -ALTER TABLE ti3 DROP INDEX ii1, AUTO_INCREMENT 5; ---disable_info -INSERT INTO ti3(b) VALUES (5); ---enable_info -ALTER TABLE ti3 ADD INDEX ii1(b), AUTO_INCREMENT 7; ---disable_info -INSERT INTO ti3(b) VALUES (7); -SELECT * FROM ti3; - -DROP TABLE ti3; - ---echo # ---echo # 8: Scenario in which ALTER TABLE was returning an unwarranted ---echo # ER_ILLEGAL_HA error at some point during work on this WL. ---echo # - -CREATE TABLE tm1(i INT DEFAULT 1) engine=MyISAM; -ALTER TABLE tm1 ADD INDEX ii1(i), ALTER COLUMN i DROP DEFAULT; -DROP TABLE tm1; - -# -# MDEV-4435 Server crashes in my_strcasecmp_utf8 on ADD KEY IF NOT EXISTS with implicit name when the key exists. -# -create table if not exists t1 (i int); -alter table t1 add key (i); -alter table t1 add key if not exists (i); -DROP TABLE t1; - -# -# MDEV-4436 CHANGE COLUMN IF EXISTS does not work and throws wrong warning. -# -create table t1 (a int); -alter table t1 change column if exists a b bigint; -show create table t1; -DROP TABLE t1; - -# -# MDEV-4437 ALTER TABLE .. ADD UNIQUE INDEX IF NOT EXISTS causes syntax error. -# - -create table t1 (i int); -alter table t1 add unique index if not exists idx(i); -alter table t1 add unique index if not exists idx(i); -show create table t1; -DROP TABLE t1; - -# -# MDEV-8358 ADD PRIMARY KEY IF NOT EXISTS -> ERROR 1068 (42000): Multiple primary key -# - -CREATE TABLE t1 ( - `event_id` bigint(20) unsigned NOT NULL DEFAULT '0', - `market_id` bigint(20) unsigned NOT NULL DEFAULT '0', - PRIMARY KEY (`event_id`,`market_id`) - ); -ALTER TABLE t1 ADD PRIMARY KEY IF NOT EXISTS event_id (event_id,market_id); -DROP TABLE t1; - ---echo # ---echo # MDEV-11126 Crash while altering persistent virtual column ---echo # - -CREATE TABLE `tab1` ( - `id` bigint(20) NOT NULL AUTO_INCREMENT, - `field2` set('option1','option2','option3','option4') NOT NULL, - `field3` set('option1','option2','option3','option4','option5') NOT NULL, - `field4` set('option1','option2','option3','option4') NOT NULL, - `field5` varchar(32) NOT NULL, - `field6` varchar(32) NOT NULL, - `field7` varchar(32) NOT NULL, - `field8` varchar(32) NOT NULL, - `field9` int(11) NOT NULL DEFAULT '1', - `field10` varchar(16) NOT NULL, - `field11` enum('option1','option2','option3') NOT NULL DEFAULT 'option1', - `v_col` varchar(128) AS (IF(field11='option1',CONCAT_WS(":","field1",field2,field3,field4,field5,field6,field7,field8,field9,field10), CONCAT_WS(":","field1",field11,field2,field3,field4,field5,field6,field7,field8,field9,field10))) PERSISTENT, - PRIMARY KEY (`id`) -) DEFAULT CHARSET=latin1; - -ALTER TABLE `tab1` CHANGE COLUMN v_col `v_col` varchar(128); -SHOW CREATE TABLE `tab1`; -ALTER TABLE `tab1` CHANGE COLUMN v_col `v_col` varchar(128) AS (IF(field11='option1',CONCAT_WS(":","field1",field2,field3,field4,field5,field6,field7,field8,field9,field10), CONCAT_WS(":","field1",field11,field2,field3,field4,field5,field6,field7,field8,field9,field10))) PERSISTENT; -SHOW CREATE TABLE `tab1`; -DROP TABLE `tab1`; - ---echo # ---echo # MDEV-11548 Reproducible server crash after the 2nd ALTER TABLE ADD FOREIGN KEY IF NOT EXISTS ---echo # - -CREATE TABLE t1 (id INT UNSIGNED NOT NULL PRIMARY KEY); -CREATE TABLE t2 (id1 INT UNSIGNED NOT NULL); - -ALTER TABLE t2 -ADD FOREIGN KEY IF NOT EXISTS (id1) - REFERENCES t1 (id); - -ALTER TABLE t2 -ADD FOREIGN KEY IF NOT EXISTS (id1) -REFERENCES t1 (id); - -DROP TABLE t2; -DROP TABLE t1; - - ---echo # ---echo # MDEV-6390 CONVERT TO CHARACTER SET utf8 doesn't change DEFAULT CHARSET. ---echo # - -CREATE TABLE t1 (id int(11) NOT NULL, a int(11) NOT NULL, b int(11)) - ENGINE=InnoDB DEFAULT CHARSET=latin1; -SHOW CREATE TABLE t1; -ALTER TABLE t1 CONVERT TO CHARACTER SET utf8; -SHOW CREATE TABLE t1; -DROP TABLE t1; - ---echo # ---echo # ---echo # MDEV-15308 ---echo # Assertion `ha_alter_info->alter_info->drop_list.elements > 0' failed ---echo # in ha_innodb::prepare_inplace_alter_table ---echo # - -CREATE TABLE t1 (a INT, b INT) ENGINE=InnoDB; -ALTER TABLE t1 DROP FOREIGN KEY IF EXISTS fk, DROP COLUMN b; -SHOW CREATE TABLE t1; -DROP TABLE t1; - -CREATE TABLE t1 (a INT, b INT) ENGINE=InnoDB; -ALTER TABLE t1 DROP INDEX IF EXISTS fk, DROP COLUMN b; -SHOW CREATE TABLE t1; -DROP TABLE t1; - -CREATE TABLE t1 (a INT, b INT, c INT, KEY(c)) ENGINE=InnoDB; -ALTER TABLE t1 DROP FOREIGN KEY IF EXISTS fk, DROP COLUMN c; -SHOW CREATE TABLE t1; -DROP TABLE t1; - -CREATE TABLE t1 (a INT, b INT, c INT, KEY c1(c)) ENGINE=InnoDB; -ALTER TABLE t1 DROP FOREIGN KEY IF EXISTS fk, DROP INDEX c1; -SHOW CREATE TABLE t1; -DROP TABLE t1; - -CREATE TABLE t1 (a INT, b INT) ENGINE=InnoDB; -ALTER TABLE t1 DROP INDEX IF EXISTS fk, DROP COLUMN IF EXISTS c; -SHOW CREATE TABLE t1; -DROP TABLE t1; - ---echo # ---echo # MDEV-14668 ADD PRIMARY KEY IF NOT EXISTS on composite key ---echo # -CREATE TABLE t1 ( - `ID` BIGINT(20) NOT NULL, - `RANK` MEDIUMINT(4) NOT NULL, - `CHECK_POINT` BIGINT(20) NOT NULL, - UNIQUE INDEX `HORIZON_UIDX01` (`ID`, `RANK`) - ) ENGINE=InnoDB; - -ALTER TABLE t1 ADD PRIMARY KEY IF NOT EXISTS (`ID`, `CHECK_POINT`); -SHOW CREATE TABLE t1; -ALTER TABLE t1 ADD PRIMARY KEY IF NOT EXISTS (`ID`, `CHECK_POINT`); -DROP TABLE t1; diff --git a/mysql-test/r/grant.test b/mysql-test/r/grant.test deleted file mode 100644 index f2dfb01cc39..00000000000 --- a/mysql-test/r/grant.test +++ /dev/null @@ -1,2291 +0,0 @@ -# Test of GRANT commands - -# Grant tests not performed with embedded server --- source include/not_embedded.inc - -# Save the initial number of concurrent sessions ---source include/count_sessions.inc - -SET @old_log_bin_trust_function_creators= @@global.log_bin_trust_function_creators; -SET GLOBAL log_bin_trust_function_creators = 1; - -# Cleanup ---disable_warnings -drop table if exists t1; -drop database if exists mysqltest; ---enable_warnings - -connect (master,localhost,root,,); -connection master; -SET NAMES binary; - -# -# Test that SSL options works properly -# - -delete from mysql.user where user='mysqltest_1'; -delete from mysql.db where user='mysqltest_1'; -flush privileges; -grant select on mysqltest.* to mysqltest_1@localhost require cipher "EDH-RSA-DES-CBC3-SHA"; -show grants for mysqltest_1@localhost; -grant delete on mysqltest.* to mysqltest_1@localhost; -query_vertical select * from mysql.user where user="mysqltest_1"; -show grants for mysqltest_1@localhost; -revoke delete on mysqltest.* from mysqltest_1@localhost; -show grants for mysqltest_1@localhost; -grant select on mysqltest.* to mysqltest_1@localhost require NONE; -show grants for mysqltest_1@localhost; -grant USAGE on mysqltest.* to mysqltest_1@localhost require cipher "EDH-RSA-DES-CBC3-SHA" AND SUBJECT "testsubject" ISSUER "Monty Program Ab"; -show grants for mysqltest_1@localhost; -revoke all privileges on mysqltest.* from mysqltest_1@localhost; -show grants for mysqltest_1@localhost; -delete from mysql.user where user='mysqltest_1'; -flush privileges; - -# -# Test of GRANTS specifying user limits -# -delete from mysql.user where user='mysqltest_1'; -flush privileges; -grant usage on *.* to mysqltest_1@localhost with max_queries_per_hour 10; -query_vertical select * from mysql.user where user="mysqltest_1"; -show grants for mysqltest_1@localhost; -grant usage on *.* to mysqltest_1@localhost with max_updates_per_hour 20 max_connections_per_hour 30; -query_vertical select * from mysql.user where user="mysqltest_1"; -show grants for mysqltest_1@localhost; -# This is just to double check that one won't ignore results of selects -flush privileges; -show grants for mysqltest_1@localhost; -delete from mysql.user where user='mysqltest_1'; -flush privileges; - -# -# Test that the new db privileges are stored/retrieved correctly -# - -grant CREATE TEMPORARY TABLES, LOCK TABLES on mysqltest.* to mysqltest_1@localhost; -show grants for mysqltest_1@localhost; -flush privileges; -show grants for mysqltest_1@localhost; -revoke CREATE TEMPORARY TABLES on mysqltest.* from mysqltest_1@localhost; -show grants for mysqltest_1@localhost; -grant ALL PRIVILEGES on mysqltest.* to mysqltest_1@localhost with GRANT OPTION; -flush privileges; -show grants for mysqltest_1@localhost; -revoke LOCK TABLES, ALTER on mysqltest.* from mysqltest_1@localhost; -show grants for mysqltest_1@localhost; -revoke all privileges on mysqltest.* from mysqltest_1@localhost; -delete from mysql.user where user='mysqltest_1'; -flush privileges; -grant usage on test.* to mysqltest_1@localhost with grant option; -show grants for mysqltest_1@localhost; -delete from mysql.user where user='mysqltest_1'; -delete from mysql.db where user='mysqltest_1'; -delete from mysql.tables_priv where user='mysqltest_1'; -delete from mysql.columns_priv where user='mysqltest_1'; -flush privileges; ---error ER_NONEXISTING_GRANT -show grants for mysqltest_1@localhost; - -# -# Test what happens when you have same table and colum level grants -# - -create table t1 (a int); -GRANT select,update,insert on t1 to mysqltest_1@localhost; -GRANT select (a), update (a),insert(a), references(a) on t1 to mysqltest_1@localhost; -show grants for mysqltest_1@localhost; -select table_priv,column_priv from mysql.tables_priv where user="mysqltest_1"; -REVOKE select (a), update on t1 from mysqltest_1@localhost; -show grants for mysqltest_1@localhost; -REVOKE select,update,insert,insert (a) on t1 from mysqltest_1@localhost; -show grants for mysqltest_1@localhost; -GRANT select,references on t1 to mysqltest_1@localhost; -select table_priv,column_priv from mysql.tables_priv where user="mysqltest_1"; -grant all on test.* to mysqltest_3@localhost with grant option; -revoke all on test.* from mysqltest_3@localhost; -show grants for mysqltest_3@localhost; -revoke grant option on test.* from mysqltest_3@localhost; -show grants for mysqltest_3@localhost; -grant all on test.t1 to mysqltest_2@localhost with grant option; -revoke all on test.t1 from mysqltest_2@localhost; -show grants for mysqltest_2@localhost; -revoke grant option on test.t1 from mysqltest_2@localhost; -show grants for mysqltest_2@localhost; -delete from mysql.user where user='mysqltest_1' or user="mysqltest_2" or user="mysqltest_3"; -delete from mysql.db where user='mysqltest_1' or user="mysqltest_2" or user="mysqltest_3"; -delete from mysql.tables_priv where user='mysqltest_1' or user="mysqltest_2" or user="mysqltest_3"; -delete from mysql.columns_priv where user='mysqltest_1' or user="mysqltest_2" or user="mysqltest_3"; -flush privileges; -drop table t1; - -# -# Test some error conditions -# ---error ER_WRONG_USAGE -GRANT FILE on mysqltest.* to mysqltest_1@localhost; -select 1; # To test that the previous command didn't cause problems - -# -# Bug#4898 User privileges depending on ORDER BY Settings of table db -# -insert into mysql.user (host, user) values ('localhost', 'test11'); -insert into mysql.db (host, db, user, select_priv) values -('localhost', 'a%', 'test11', 'Y'), ('localhost', 'ab%', 'test11', 'Y'); -alter table mysql.db order by db asc; -flush privileges; -show grants for test11@localhost; -alter table mysql.db order by db desc; -flush privileges; -show grants for test11@localhost; -delete from mysql.user where user='test11'; -delete from mysql.db where user='test11'; - -# -# Bug#6123 GRANT USAGE inserts useless Db row -# -create database mysqltest1; -grant usage on mysqltest1.* to test6123 identified by 'magic123'; -select host,db,user,select_priv,insert_priv from mysql.db where db="mysqltest1"; -delete from mysql.user where user='test6123'; -drop database mysqltest1; - -# -# Test for 'drop user', 'revoke privileges, grant' -# - -create table t1 (a int); -grant ALL PRIVILEGES on *.* to drop_user2@localhost with GRANT OPTION; -show grants for drop_user2@localhost; -revoke all privileges, grant option from drop_user2@localhost; -drop user drop_user2@localhost; - -grant ALL PRIVILEGES on *.* to drop_user@localhost with GRANT OPTION; -grant ALL PRIVILEGES on test.* to drop_user@localhost with GRANT OPTION; -grant select(a) on test.t1 to drop_user@localhost; -show grants for drop_user@localhost; - -# -# Bug#3086 SHOW GRANTS doesn't follow ANSI_QUOTES -# -set sql_mode=ansi_quotes; -show grants for drop_user@localhost; -set sql_mode=default; - -set sql_quote_show_create=0; -show grants for drop_user@localhost; -set sql_mode="ansi_quotes"; -show grants for drop_user@localhost; -set sql_quote_show_create=1; -show grants for drop_user@localhost; -set sql_mode=""; -show grants for drop_user@localhost; - -revoke all privileges, grant option from drop_user@localhost; -show grants for drop_user@localhost; -drop user drop_user@localhost; ---error ER_REVOKE_GRANTS -revoke all privileges, grant option from drop_user@localhost; - -grant select(a) on test.t1 to drop_user1@localhost; -grant select on test.t1 to drop_user2@localhost; -grant select on test.* to drop_user3@localhost; -grant select on *.* to drop_user4@localhost; -# Drop user now implicitly revokes all privileges. -drop user drop_user1@localhost, drop_user2@localhost, drop_user3@localhost, -drop_user4@localhost; ---error ER_REVOKE_GRANTS -revoke all privileges, grant option from drop_user1@localhost, drop_user2@localhost, -drop_user3@localhost, drop_user4@localhost; ---error ER_CANNOT_USER -drop user drop_user1@localhost, drop_user2@localhost, drop_user3@localhost, -drop_user4@localhost; -drop table t1; -grant usage on *.* to mysqltest_1@localhost identified by "password"; -grant select, update, insert on test.* to mysqltest_1@localhost; -show grants for mysqltest_1@localhost; -drop user mysqltest_1@localhost; - -# -# Bug#3403 Wrong encoding in SHOW GRANTS output -# -SET NAMES koi8r; -CREATE DATABASE ÂÄ; -USE ÂÄ; -CREATE TABLE ÔÁ (ËÏÌ INT); - -GRANT SELECT ON ÂÄ.* TO ÀÚÅÒ@localhost; -SHOW GRANTS FOR ÀÚÅÒ@localhost; -REVOKE SELECT ON ÂÄ.* FROM ÀÚÅÒ@localhost; - -GRANT SELECT ON ÂÄ.ÔÁ TO ÀÚÅÒ@localhost; -SHOW GRANTS FOR ÀÚÅÒ@localhost; -REVOKE SELECT ON ÂÄ.ÔÁ FROM ÀÚÅÒ@localhost; - -GRANT SELECT (ËÏÌ) ON ÂÄ.ÔÁ TO ÀÚÅÒ@localhost; -SHOW GRANTS FOR ÀÚÅÒ@localhost; -REVOKE SELECT (ËÏÌ) ON ÂÄ.ÔÁ FROM ÀÚÅÒ@localhost; - -# Revoke does not drop user. Leave a clean user table for the next tests. -DROP USER ÀÚÅÒ@localhost; - -DROP DATABASE ÂÄ; -SET NAMES latin1; - -# -# Bug#5831 REVOKE ALL PRIVILEGES, GRANT OPTION does not revoke everything -# -USE test; -CREATE TABLE t1 (a int ); -CREATE TABLE t2 LIKE t1; -CREATE TABLE t3 LIKE t1; -CREATE TABLE t4 LIKE t1; -CREATE TABLE t5 LIKE t1; -CREATE TABLE t6 LIKE t1; -CREATE TABLE t7 LIKE t1; -CREATE TABLE t8 LIKE t1; -CREATE TABLE t9 LIKE t1; -CREATE TABLE t10 LIKE t1; -CREATE DATABASE testdb1; -CREATE DATABASE testdb2; -CREATE DATABASE testdb3; -CREATE DATABASE testdb4; -CREATE DATABASE testdb5; -CREATE DATABASE testdb6; -CREATE DATABASE testdb7; -CREATE DATABASE testdb8; -CREATE DATABASE testdb9; -CREATE DATABASE testdb10; -GRANT ALL ON testdb1.* TO testuser@localhost; -GRANT ALL ON testdb2.* TO testuser@localhost; -GRANT ALL ON testdb3.* TO testuser@localhost; -GRANT ALL ON testdb4.* TO testuser@localhost; -GRANT ALL ON testdb5.* TO testuser@localhost; -GRANT ALL ON testdb6.* TO testuser@localhost; -GRANT ALL ON testdb7.* TO testuser@localhost; -GRANT ALL ON testdb8.* TO testuser@localhost; -GRANT ALL ON testdb9.* TO testuser@localhost; -GRANT ALL ON testdb10.* TO testuser@localhost; -GRANT SELECT ON test.t1 TO testuser@localhost; -GRANT SELECT ON test.t2 TO testuser@localhost; -GRANT SELECT ON test.t3 TO testuser@localhost; -GRANT SELECT ON test.t4 TO testuser@localhost; -GRANT SELECT ON test.t5 TO testuser@localhost; -GRANT SELECT ON test.t6 TO testuser@localhost; -GRANT SELECT ON test.t7 TO testuser@localhost; -GRANT SELECT ON test.t8 TO testuser@localhost; -GRANT SELECT ON test.t9 TO testuser@localhost; -GRANT SELECT ON test.t10 TO testuser@localhost; -GRANT SELECT (a) ON test.t1 TO testuser@localhost; -GRANT SELECT (a) ON test.t2 TO testuser@localhost; -GRANT SELECT (a) ON test.t3 TO testuser@localhost; -GRANT SELECT (a) ON test.t4 TO testuser@localhost; -GRANT SELECT (a) ON test.t5 TO testuser@localhost; -GRANT SELECT (a) ON test.t6 TO testuser@localhost; -GRANT SELECT (a) ON test.t7 TO testuser@localhost; -GRANT SELECT (a) ON test.t8 TO testuser@localhost; -GRANT SELECT (a) ON test.t9 TO testuser@localhost; -GRANT SELECT (a) ON test.t10 TO testuser@localhost; -REVOKE ALL PRIVILEGES, GRANT OPTION FROM testuser@localhost; -SHOW GRANTS FOR testuser@localhost; -DROP USER testuser@localhost; -DROP TABLE t1,t2,t3,t4,t5,t6,t7,t8,t9,t10; -DROP DATABASE testdb1; -DROP DATABASE testdb2; -DROP DATABASE testdb3; -DROP DATABASE testdb4; -DROP DATABASE testdb5; -DROP DATABASE testdb6; -DROP DATABASE testdb7; -DROP DATABASE testdb8; -DROP DATABASE testdb9; -DROP DATABASE testdb10; - -# -# Bug#6932 a problem with 'revoke ALL PRIVILEGES' -# - -create table t1(a int, b int, c int, d int); -grant insert(b), insert(c), insert(d), insert(a) on t1 to grant_user@localhost; -show grants for grant_user@localhost; -select Host,Db,User,Table_name,Column_name,Column_priv from mysql.columns_priv order by Column_name; -revoke ALL PRIVILEGES on t1 from grant_user@localhost; -show grants for grant_user@localhost; -select Host,Db,User,Table_name,Column_name,Column_priv from mysql.columns_priv; -drop user grant_user@localhost; -drop table t1; - -# -# Bug#7391 Cross-database multi-table UPDATE security problem -# -create database mysqltest_1; -create database mysqltest_2; -create table mysqltest_1.t1 select 1 a, 2 q; -create table mysqltest_1.t2 select 1 b, 2 r; -create table mysqltest_2.t1 select 1 c, 2 s; -create table mysqltest_2.t2 select 1 d, 2 t; - -# test the column privileges -grant update (a) on mysqltest_1.t1 to mysqltest_3@localhost; -grant select (b) on mysqltest_1.t2 to mysqltest_3@localhost; -grant select (c) on mysqltest_2.t1 to mysqltest_3@localhost; -grant update (d) on mysqltest_2.t2 to mysqltest_3@localhost; -connect (conn1,localhost,mysqltest_3,,); -connection conn1; -SELECT * FROM INFORMATION_SCHEMA.COLUMN_PRIVILEGES - WHERE GRANTEE = '''mysqltest_3''@''localhost''' - ORDER BY TABLE_NAME,COLUMN_NAME,PRIVILEGE_TYPE; -SELECT * FROM INFORMATION_SCHEMA.TABLE_PRIVILEGES - WHERE GRANTEE = '''mysqltest_3''@''localhost''' - ORDER BY TABLE_NAME,PRIVILEGE_TYPE; -SELECT * from INFORMATION_SCHEMA.SCHEMA_PRIVILEGES - WHERE GRANTEE = '''mysqltest_3''@''localhost''' - ORDER BY TABLE_SCHEMA,PRIVILEGE_TYPE; -SELECT * from INFORMATION_SCHEMA.USER_PRIVILEGES - WHERE GRANTEE = '''mysqltest_3''@''localhost''' - ORDER BY TABLE_CATALOG,PRIVILEGE_TYPE; ---error ER_COLUMNACCESS_DENIED_ERROR -update mysqltest_1.t1, mysqltest_1.t2 set q=10 where b=1; ---error ER_COLUMNACCESS_DENIED_ERROR -update mysqltest_1.t2, mysqltest_2.t2 set d=20 where d=1; ---error ER_TABLEACCESS_DENIED_ERROR -update mysqltest_1.t1, mysqltest_2.t2 set d=20 where d=1; ---error ER_TABLEACCESS_DENIED_ERROR -update mysqltest_2.t1, mysqltest_1.t2 set c=20 where b=1; ---error ER_COLUMNACCESS_DENIED_ERROR -update mysqltest_2.t1, mysqltest_2.t2 set d=10 where s=2; -# the following two should work -update mysqltest_1.t1, mysqltest_2.t2 set a=10,d=10; -update mysqltest_1.t1, mysqltest_2.t1 set a=20 where c=20; -connection master; -select t1.*,t2.* from mysqltest_1.t1,mysqltest_1.t2; -select t1.*,t2.* from mysqltest_2.t1,mysqltest_2.t2; -revoke all on mysqltest_1.t1 from mysqltest_3@localhost; -revoke all on mysqltest_1.t2 from mysqltest_3@localhost; -revoke all on mysqltest_2.t1 from mysqltest_3@localhost; -revoke all on mysqltest_2.t2 from mysqltest_3@localhost; - -# test the db/table level privileges -grant all on mysqltest_2.* to mysqltest_3@localhost; -grant select on *.* to mysqltest_3@localhost; -# Next grant is needed to trigger bug#7391. Do not optimize! -grant select on mysqltest_2.t1 to mysqltest_3@localhost; -flush privileges; -disconnect conn1; -connect (conn2,localhost,mysqltest_3,,); -connection conn2; -use mysqltest_1; -update mysqltest_2.t1, mysqltest_2.t2 set c=500,d=600; -# the following failed before, should fail now. ---error ER_TABLEACCESS_DENIED_ERROR -update mysqltest_1.t1, mysqltest_1.t2 set a=100,b=200; -use mysqltest_2; -# the following used to succeed, it must fail now. ---error ER_TABLEACCESS_DENIED_ERROR -update mysqltest_1.t1, mysqltest_1.t2 set a=100,b=200; ---error ER_TABLEACCESS_DENIED_ERROR -update mysqltest_2.t1, mysqltest_1.t2 set c=100,b=200; ---error ER_TABLEACCESS_DENIED_ERROR -update mysqltest_1.t1, mysqltest_2.t2 set a=100,d=200; -# lets see the result -connection master; -select t1.*,t2.* from mysqltest_1.t1,mysqltest_1.t2; -select t1.*,t2.* from mysqltest_2.t1,mysqltest_2.t2; - -delete from mysql.user where user='mysqltest_3'; -delete from mysql.db where user="mysqltest_3"; -delete from mysql.tables_priv where user="mysqltest_3"; -delete from mysql.columns_priv where user="mysqltest_3"; -flush privileges; -drop database mysqltest_1; -drop database mysqltest_2; -disconnect conn2; - -# -# just SHOW PRIVILEGES test -# -SHOW PRIVILEGES; - -# -# Rights for renaming test (Bug#3270) -# -connect (root,localhost,root,,test,$MASTER_MYPORT,$MASTER_MYSOCK); -connection root; ---disable_warnings -create database mysqltest; ---enable_warnings -create table mysqltest.t1 (a int,b int,c int); -grant all on mysqltest.t1 to mysqltest_1@localhost; -connect (user1,localhost,mysqltest_1,,mysqltest,$MASTER_MYPORT,$MASTER_MYSOCK); -connection user1; --- error ER_TABLEACCESS_DENIED_ERROR -alter table t1 rename t2; -disconnect user1; -connection root; -revoke all privileges on mysqltest.t1 from mysqltest_1@localhost; -delete from mysql.user where user=_binary'mysqltest_1'; -drop database mysqltest; -connection default; -disconnect root; - -# -# check all new table privileges -# -CREATE USER dummy@localhost; -CREATE DATABASE mysqltest; -CREATE TABLE mysqltest.dummytable (dummyfield INT); -CREATE VIEW mysqltest.dummyview AS SELECT dummyfield FROM mysqltest.dummytable; -GRANT ALL PRIVILEGES ON mysqltest.dummytable TO dummy@localhost; -GRANT ALL PRIVILEGES ON mysqltest.dummyview TO dummy@localhost; -SHOW GRANTS FOR dummy@localhost; -use INFORMATION_SCHEMA; -SELECT TABLE_SCHEMA, TABLE_NAME, GROUP_CONCAT(PRIVILEGE_TYPE ORDER BY -PRIVILEGE_TYPE SEPARATOR ', ') AS PRIVILEGES FROM TABLE_PRIVILEGES WHERE GRANTEE -= '\'dummy\'@\'localhost\'' GROUP BY TABLE_SCHEMA, TABLE_NAME; -FLUSH PRIVILEGES; -SHOW GRANTS FOR dummy@localhost; -SELECT TABLE_SCHEMA, TABLE_NAME, GROUP_CONCAT(PRIVILEGE_TYPE ORDER BY -PRIVILEGE_TYPE SEPARATOR ', ') AS PRIVILEGES FROM TABLE_PRIVILEGES WHERE GRANTEE -= '\'dummy\'@\'localhost\'' GROUP BY TABLE_SCHEMA, TABLE_NAME; -SHOW FIELDS FROM mysql.tables_priv; -use test; -REVOKE ALL PRIVILEGES, GRANT OPTION FROM dummy@localhost; -DROP USER dummy@localhost; -DROP DATABASE mysqltest; -# check view only privileges -CREATE USER dummy@localhost; -CREATE DATABASE mysqltest; -CREATE TABLE mysqltest.dummytable (dummyfield INT); -CREATE VIEW mysqltest.dummyview AS SELECT dummyfield FROM mysqltest.dummytable; -GRANT CREATE VIEW ON mysqltest.dummytable TO dummy@localhost; -GRANT CREATE VIEW ON mysqltest.dummyview TO dummy@localhost; -SHOW GRANTS FOR dummy@localhost; -use INFORMATION_SCHEMA; -SELECT TABLE_SCHEMA, TABLE_NAME, GROUP_CONCAT(PRIVILEGE_TYPE ORDER BY -PRIVILEGE_TYPE SEPARATOR ', ') AS PRIVILEGES FROM TABLE_PRIVILEGES WHERE GRANTEE -= '\'dummy\'@\'localhost\'' GROUP BY TABLE_SCHEMA, TABLE_NAME; -FLUSH PRIVILEGES; -SHOW GRANTS FOR dummy@localhost; -SELECT TABLE_SCHEMA, TABLE_NAME, GROUP_CONCAT(PRIVILEGE_TYPE ORDER BY -PRIVILEGE_TYPE SEPARATOR ', ') AS PRIVILEGES FROM TABLE_PRIVILEGES WHERE GRANTEE -= '\'dummy\'@\'localhost\'' GROUP BY TABLE_SCHEMA, TABLE_NAME; -use test; -REVOKE ALL PRIVILEGES, GRANT OPTION FROM dummy@localhost; -DROP USER dummy@localhost; -DROP DATABASE mysqltest; -CREATE USER dummy@localhost; -CREATE DATABASE mysqltest; -CREATE TABLE mysqltest.dummytable (dummyfield INT); -CREATE VIEW mysqltest.dummyview AS SELECT dummyfield FROM mysqltest.dummytable; -GRANT SHOW VIEW ON mysqltest.dummytable TO dummy@localhost; -GRANT SHOW VIEW ON mysqltest.dummyview TO dummy@localhost; -SHOW GRANTS FOR dummy@localhost; -use INFORMATION_SCHEMA; -SELECT TABLE_SCHEMA, TABLE_NAME, GROUP_CONCAT(PRIVILEGE_TYPE ORDER BY -PRIVILEGE_TYPE SEPARATOR ', ') AS PRIVILEGES FROM TABLE_PRIVILEGES WHERE GRANTEE -= '\'dummy\'@\'localhost\'' GROUP BY TABLE_SCHEMA, TABLE_NAME; -FLUSH PRIVILEGES; -SHOW GRANTS FOR dummy@localhost; -SELECT TABLE_SCHEMA, TABLE_NAME, GROUP_CONCAT(PRIVILEGE_TYPE ORDER BY -PRIVILEGE_TYPE SEPARATOR ', ') AS PRIVILEGES FROM TABLE_PRIVILEGES WHERE GRANTEE -= '\'dummy\'@\'localhost\'' GROUP BY TABLE_SCHEMA, TABLE_NAME; -use test; -REVOKE ALL PRIVILEGES, GRANT OPTION FROM dummy@localhost; -DROP USER dummy@localhost; -DROP DATABASE mysqltest; -# -# Bug#11330 Entry in tables_priv with host = '' causes crash -# -connection default; -use mysql; -insert into tables_priv values ('','test_db','mysqltest_1','test_table','test_grantor',CURRENT_TIMESTAMP,'Select','Select'); -flush privileges; -delete from tables_priv where host = '' and user = 'mysqltest_1'; -flush privileges; -use test; - -# -# Bug#10892 user variables not auto cast for comparisons -# Check that we don't get illegal mix of collations -# -set @user123="non-existent"; -select * from mysql.db where user=@user123; - -set names koi8r; -create database ÂÄ; -grant select on ÂÄ.* to root@localhost; -select hex(Db) from mysql.db where Db='ÂÄ'; -show grants for root@localhost; -flush privileges; -show grants for root@localhost; -drop database ÂÄ; -revoke all privileges on ÂÄ.* from root@localhost; -show grants for root@localhost; -set names latin1; - -# -# Bug#15598 Server crashes in specific case during setting new password -# - Caused by a user with host '' -# -create user mysqltest_7@; -set password for mysqltest_7@ = password('systpass'); -show grants for mysqltest_7@; -drop user mysqltest_7@; ---error ER_NONEXISTING_GRANT -show grants for mysqltest_7@; - -# -# Bug#14385 GRANT and mapping to correct user account problems -# -create database mysqltest; -use mysqltest; -create table t1(f1 int); -GRANT DELETE ON mysqltest.t1 TO mysqltest1@'%'; -GRANT SELECT ON mysqltest.t1 TO mysqltest1@'192.%'; -show grants for mysqltest1@'192.%'; -show grants for mysqltest1@'%'; -delete from mysql.user where user='mysqltest1'; -delete from mysql.db where user='mysqltest1'; -delete from mysql.tables_priv where user='mysqltest1'; -flush privileges; -drop database mysqltest; - -# -# Bug#27515 DROP previlege is not required for RENAME TABLE -# -connection master; -create database db27515; -use db27515; -create table t1 (a int); -grant alter on db27515.t1 to user27515@localhost; -grant insert, create on db27515.t2 to user27515@localhost; - -connect (conn27515, localhost, user27515, , db27515); -connection conn27515; ---error ER_TABLEACCESS_DENIED_ERROR -rename table t1 to t2; -disconnect conn27515; - -connection master; -revoke all privileges, grant option from user27515@localhost; -drop user user27515@localhost; -drop database db27515; - ---echo End of 4.1 tests - -# -# Bug#16297 In memory grant tables not flushed when users's hostname is "" -# -use test; -create table t1 (a int); - -# Backup anonymous users and remove them. (They get in the way of -# the one we test with here otherwise.) -create table t2 as select * from mysql.user where user=''; -delete from mysql.user where user=''; -flush privileges; - -# Create some users with different hostnames -create user mysqltest_8@''; -create user mysqltest_8@host8; - -# Try to create them again ---error ER_CANNOT_USER -create user mysqltest_8@''; ---error ER_CANNOT_USER -create user mysqltest_8; ---error ER_CANNOT_USER -create user mysqltest_8@host8; - -select user, QUOTE(host) from mysql.user where user="mysqltest_8"; - ---echo Schema privileges -grant select on mysqltest.* to mysqltest_8@''; -show grants for mysqltest_8@''; -grant select on mysqltest.* to mysqltest_8@; -show grants for mysqltest_8@; -grant select on mysqltest.* to mysqltest_8; -show grants for mysqltest_8; -select * from information_schema.schema_privileges -where grantee like "'mysqltest_8'%"; -connect (conn3,localhost,mysqltest_8,,); -select * from t1; -disconnect conn3; -connection master; -revoke select on mysqltest.* from mysqltest_8@''; -show grants for mysqltest_8@''; -show grants for mysqltest_8; -select * from information_schema.schema_privileges -where grantee like "'mysqltest_8'%"; -flush privileges; -show grants for mysqltest_8@''; -show grants for mysqltest_8@; -grant select on mysqltest.* to mysqltest_8@''; -flush privileges; -show grants for mysqltest_8@; -revoke select on mysqltest.* from mysqltest_8@''; -flush privileges; - ---echo Column privileges -grant update (a) on t1 to mysqltest_8@''; -grant update (a) on t1 to mysqltest_8; -show grants for mysqltest_8@''; -show grants for mysqltest_8; -flush privileges; -show grants for mysqltest_8@''; -show grants for mysqltest_8; -select * from information_schema.column_privileges; -connect (conn4,localhost,mysqltest_8,,); -select * from t1; -disconnect conn4; -connection master; -revoke update (a) on t1 from mysqltest_8@''; -show grants for mysqltest_8@''; -show grants for mysqltest_8; -select * from information_schema.column_privileges; -flush privileges; -show grants for mysqltest_8@''; -show grants for mysqltest_8; - ---echo Table privileges -grant update on t1 to mysqltest_8@''; -grant update on t1 to mysqltest_8; -show grants for mysqltest_8@''; -show grants for mysqltest_8; -flush privileges; -show grants for mysqltest_8@''; -show grants for mysqltest_8; -select * from information_schema.table_privileges; -connect (conn5,localhost,mysqltest_8,,); -select * from t1; -disconnect conn5; -connection master; -revoke update on t1 from mysqltest_8@''; -show grants for mysqltest_8@''; -show grants for mysqltest_8; -select * from information_schema.table_privileges; -flush privileges; -show grants for mysqltest_8@''; -show grants for mysqltest_8; - ---echo "DROP USER" should clear privileges -grant all privileges on mysqltest.* to mysqltest_8@''; -grant select on mysqltest.* to mysqltest_8@''; -grant update on t1 to mysqltest_8@''; -grant update (a) on t1 to mysqltest_8@''; -grant all privileges on mysqltest.* to mysqltest_8; -show grants for mysqltest_8@''; -show grants for mysqltest_8; -select * from information_schema.user_privileges -where grantee like "'mysqltest_8'%"; -connect (conn5,localhost,mysqltest_8,,); -select * from t1; -disconnect conn5; -connection master; -flush privileges; -show grants for mysqltest_8@''; -show grants for mysqltest_8; -drop user mysqltest_8@''; ---error ER_NONEXISTING_GRANT -show grants for mysqltest_8@''; ---replace_result $MASTER_MYSOCK MASTER_SOCKET $MASTER_MYPORT MASTER_PORT ---error ER_ACCESS_DENIED_ERROR -connect (conn6,localhost,mysqltest_8,,); -connection master; ---error ER_NONEXISTING_GRANT -show grants for mysqltest_8; -drop user mysqltest_8@host8; ---error ER_NONEXISTING_GRANT -show grants for mysqltest_8@host8; - -# Restore the anonymous users. -insert into mysql.user select * from t2; -flush privileges; -drop table t2; -drop table t1; - -# -# Bug#20214 Incorrect error when user calls SHOW CREATE VIEW on non -# privileged view -# - -connection master; - -CREATE DATABASE mysqltest3; -USE mysqltest3; - -CREATE TABLE t_nn (c1 INT); -CREATE VIEW v_nn AS SELECT * FROM t_nn; - -CREATE DATABASE mysqltest2; -USE mysqltest2; - -CREATE TABLE t_nn (c1 INT); -CREATE VIEW v_nn AS SELECT * FROM t_nn; -CREATE VIEW v_yn AS SELECT * FROM t_nn; -CREATE VIEW v_gy AS SELECT * FROM t_nn; -CREATE VIEW v_ny AS SELECT * FROM t_nn; -CREATE VIEW v_yy AS SELECT * FROM t_nn WHERE c1=55; - -GRANT SHOW VIEW ON mysqltest2.v_ny TO 'mysqltest_1'@'localhost' IDENTIFIED BY 'mysqltest_1'; -GRANT SELECT ON mysqltest2.v_yn TO 'mysqltest_1'@'localhost' IDENTIFIED BY 'mysqltest_1'; -GRANT SELECT ON mysqltest2.* TO 'mysqltest_1'@'localhost' IDENTIFIED BY 'mysqltest_1'; -GRANT SHOW VIEW,SELECT ON mysqltest2.v_yy TO 'mysqltest_1'@'localhost' IDENTIFIED BY 'mysqltest_1'; - -connect (mysqltest_1, localhost, mysqltest_1, mysqltest_1,); - -# fail because of missing SHOW VIEW (have generic SELECT) ---error ER_TABLEACCESS_DENIED_ERROR -SHOW CREATE VIEW mysqltest2.v_nn; ---error ER_TABLEACCESS_DENIED_ERROR -SHOW CREATE TABLE mysqltest2.v_nn; - -# fail because of missing SHOW VIEW ---error ER_TABLEACCESS_DENIED_ERROR -SHOW CREATE VIEW mysqltest2.v_yn; ---error ER_TABLEACCESS_DENIED_ERROR -SHOW CREATE TABLE mysqltest2.v_yn; - -# succeed (despite of missing SELECT, having SHOW VIEW bails us out) -SHOW CREATE TABLE mysqltest2.v_ny; - -# succeed (despite of missing SELECT, having SHOW VIEW bails us out) -SHOW CREATE VIEW mysqltest2.v_ny; - -# fail because of missing (specific or generic) SELECT ---error ER_TABLEACCESS_DENIED_ERROR -SHOW CREATE TABLE mysqltest3.t_nn; - -# fail because of missing (specific or generic) SELECT (not because it's not a view!) ---error ER_TABLEACCESS_DENIED_ERROR -SHOW CREATE VIEW mysqltest3.t_nn; - -# fail because of missing missing (specific or generic) SELECT (and SHOW VIEW) ---error ER_TABLEACCESS_DENIED_ERROR -SHOW CREATE VIEW mysqltest3.v_nn; ---error ER_TABLEACCESS_DENIED_ERROR -SHOW CREATE TABLE mysqltest3.v_nn; - -# succeed thanks to generic SELECT -SHOW CREATE TABLE mysqltest2.t_nn; - -# fail because it's not a view! (have generic SELECT though) ---error ER_WRONG_OBJECT -SHOW CREATE VIEW mysqltest2.t_nn; - -# succeed, have SELECT and SHOW VIEW -SHOW CREATE VIEW mysqltest2.v_yy; - -# succeed, have SELECT and SHOW VIEW -SHOW CREATE TABLE mysqltest2.v_yy; - -# clean-up -connection master; - -# succeed, we're root -SHOW CREATE TABLE mysqltest2.v_nn; -SHOW CREATE VIEW mysqltest2.v_nn; - -SHOW CREATE TABLE mysqltest2.t_nn; - -# fail because it's not a view! ---error ER_WRONG_OBJECT -SHOW CREATE VIEW mysqltest2.t_nn; - -DROP VIEW mysqltest2.v_nn; -DROP VIEW mysqltest2.v_yn; -DROP VIEW mysqltest2.v_ny; -DROP VIEW mysqltest2.v_yy; -DROP TABLE mysqltest2.t_nn; -DROP DATABASE mysqltest2; -DROP VIEW mysqltest3.v_nn; -DROP TABLE mysqltest3.t_nn; -DROP DATABASE mysqltest3; -disconnect mysqltest_1; -REVOKE ALL PRIVILEGES, GRANT OPTION FROM 'mysqltest_1'@'localhost'; -DROP USER 'mysqltest_1'@'localhost'; - -# restore the original database -USE test; -connection default; -disconnect master; - - -# -# Bug#10668 CREATE USER does not enforce username length limit -# ---error ER_WRONG_STRING_LENGTH -create user longer_than_80_456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789; - -# -# Test for Bug#16899 Possible buffer overflow in handling of DEFINER-clause. -# -# These checks are intended to ensure that appropriate errors are risen when -# illegal user name or hostname is specified in user-clause of GRANT/REVOKE -# statements. -# - -# -# Bug#22369 Alter table rename combined with other alterations causes lost tables -# -CREATE DATABASE mysqltest1; -CREATE TABLE mysqltest1.t1 ( - int_field INTEGER UNSIGNED NOT NULL, - char_field CHAR(10), - INDEX(`int_field`) -); -CREATE TABLE mysqltest1.t2 (int_field INT); - ---echo "Now check that we require equivalent grants for " ---echo "RENAME TABLE and ALTER TABLE" -CREATE USER mysqltest_1@localhost; -GRANT SELECT ON mysqltest1.t1 TO mysqltest_1@localhost; - -connect (conn42,localhost,mysqltest_1,,mysqltest1); -SELECT USER(); -SHOW GRANTS; ---error ER_TABLEACCESS_DENIED_ERROR -RENAME TABLE t1 TO t2; ---error ER_TABLEACCESS_DENIED_ERROR -ALTER TABLE t1 RENAME TO t2; ---disconnect conn42 ---connection default -GRANT DROP ON mysqltest1.t1 TO mysqltest_1@localhost; - -connect (conn42,localhost,mysqltest_1,,mysqltest1); ---error ER_TABLEACCESS_DENIED_ERROR -RENAME TABLE t1 TO t2; ---error ER_TABLEACCESS_DENIED_ERROR -ALTER TABLE t1 RENAME TO t2; ---disconnect conn42 ---connection default -GRANT ALTER ON mysqltest1.t1 TO mysqltest_1@localhost; - -connect (conn42,localhost,mysqltest_1,,mysqltest1); -SHOW GRANTS; ---error ER_TABLEACCESS_DENIED_ERROR -RENAME TABLE t1 TO t2; ---error ER_TABLEACCESS_DENIED_ERROR -ALTER TABLE t1 RENAME TO t2; ---disconnect conn42 ---connection default -GRANT INSERT, CREATE ON mysqltest1.t1 TO mysqltest_1@localhost; -connect (conn42,localhost,mysqltest_1,,mysqltest1); -SHOW GRANTS; ---error ER_TABLEACCESS_DENIED_ERROR ---disconnect conn42 ---connection default -GRANT INSERT, SELECT, CREATE, ALTER, DROP ON mysqltest1.t2 TO mysqltest_1@localhost; -DROP TABLE mysqltest1.t2; - -connect (conn42,localhost,mysqltest_1,,mysqltest1); -SHOW GRANTS; -RENAME TABLE t1 TO t2; -RENAME TABLE t2 TO t1; -ALTER TABLE t1 RENAME TO t2; -ALTER TABLE t2 RENAME TO t1; ---disconnect conn42 ---connection default -REVOKE DROP, INSERT ON mysqltest1.t1 FROM mysqltest_1@localhost; -REVOKE DROP, INSERT ON mysqltest1.t2 FROM mysqltest_1@localhost; - -connect (conn42,localhost,mysqltest_1,,mysqltest1); -SHOW GRANTS; ---error ER_TABLEACCESS_DENIED_ERROR -RENAME TABLE t1 TO t2; ---error ER_TABLEACCESS_DENIED_ERROR -ALTER TABLE t1 RENAME TO t2; ---disconnect conn42 ---connection default - -DROP USER mysqltest_1@localhost; -DROP DATABASE mysqltest1; -USE test; - -# Working with database-level privileges. - ---error ER_WRONG_STRING_LENGTH -GRANT CREATE ON mysqltest.* TO longer_than_80_456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789@localhost; - ---error ER_WRONG_STRING_LENGTH -GRANT CREATE ON mysqltest.* TO some_user_name@1234567890abcdefghij1234567890abcdefghij1234567890abcdefghijQWERTY; - ---error ER_WRONG_STRING_LENGTH -REVOKE CREATE ON mysqltest.* FROM longer_than_80_456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789@localhost; - ---error ER_WRONG_STRING_LENGTH -REVOKE CREATE ON mysqltest.* FROM some_user_name@1234567890abcdefghij1234567890abcdefghij1234567890abcdefghijQWERTY; - -# Working with table-level privileges. - ---error ER_WRONG_STRING_LENGTH -GRANT CREATE ON t1 TO longer_than_80_456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789@localhost; - ---error ER_WRONG_STRING_LENGTH -GRANT CREATE ON t1 TO some_user_name@1234567890abcdefghij1234567890abcdefghij1234567890abcdefghijQWERTY; - ---error ER_WRONG_STRING_LENGTH -REVOKE CREATE ON t1 FROM longer_than_80_456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789@localhost; - ---error ER_WRONG_STRING_LENGTH -REVOKE CREATE ON t1 FROM some_user_name@1234567890abcdefghij1234567890abcdefghij1234567890abcdefghijQWERTY; - -# Working with routine-level privileges. - ---error ER_WRONG_STRING_LENGTH -GRANT EXECUTE ON PROCEDURE p1 TO longer_than_80_456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789@localhost; - ---error ER_WRONG_STRING_LENGTH -GRANT EXECUTE ON PROCEDURE p1 TO some_user_name@1234567890abcdefghij1234567890abcdefghij1234567890abcdefghijQWERTY; - ---error ER_WRONG_STRING_LENGTH -REVOKE EXECUTE ON PROCEDURE p1 FROM longer_than_80_456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789@localhost; - ---error ER_WRONG_STRING_LENGTH -REVOKE EXECUTE ON PROCEDURE t1 FROM some_user_name@1234567890abcdefghij1234567890abcdefghij1234567890abcdefghijQWERTY; - - -# -# Bug#23556 TRUNCATE TABLE still maps to DELETE -# -CREATE USER bug23556@localhost; -CREATE DATABASE bug23556; -GRANT SELECT ON bug23556.* TO bug23556@localhost; -connect (bug23556,localhost,bug23556,,bug23556); - -connection default; -USE bug23556; -CREATE TABLE t1 (a INT PRIMARY KEY); INSERT INTO t1 VALUES (1),(2),(3),(4),(5); -GRANT DELETE ON t1 TO bug23556@localhost; - -connection bug23556; -USE bug23556; ---error ER_TABLEACCESS_DENIED_ERROR -TRUNCATE t1; - -connection default; -USE bug23556; -REVOKE DELETE ON t1 FROM bug23556@localhost; -GRANT DROP ON t1 TO bug23556@localhost; - -connection bug23556; -USE bug23556; -TRUNCATE t1; - -connection default; -USE bug23556; -DROP TABLE t1; -USE test; -DROP DATABASE bug23556; -DROP USER bug23556@localhost; -connection default; -disconnect bug23556; - - -# -# Bug#6774 Replication fails with Wrong usage of DB GRANT and GLOBAL PRIVILEGES -# -# Check if GRANT ... ON * ... fails when no database is selected -connect (con1, localhost, root,,*NO-ONE*); -connection con1; ---error ER_NO_DB_ERROR -GRANT PROCESS ON * TO user@localhost; -disconnect con1; -connection default; - - -# -# Bug#9504 Stored procedures: execute privilege doesn't make 'use database' -# okay. -# - -# Prepare. - ---disable_warnings -DROP DATABASE IF EXISTS mysqltest1; -DROP DATABASE IF EXISTS mysqltest2; -DROP DATABASE IF EXISTS mysqltest3; -DROP DATABASE IF EXISTS mysqltest4; ---enable_warnings - -CREATE DATABASE mysqltest1; -CREATE DATABASE mysqltest2; -CREATE DATABASE mysqltest3; -CREATE DATABASE mysqltest4; - -CREATE PROCEDURE mysqltest1.p_def() SQL SECURITY DEFINER - SELECT 1; - -CREATE PROCEDURE mysqltest2.p_inv() SQL SECURITY INVOKER - SELECT 1; - -CREATE FUNCTION mysqltest3.f_def() RETURNS INT SQL SECURITY DEFINER - RETURN 1; - -CREATE FUNCTION mysqltest4.f_inv() RETURNS INT SQL SECURITY INVOKER - RETURN 1; - -GRANT EXECUTE ON PROCEDURE mysqltest1.p_def TO mysqltest_1@localhost; -GRANT EXECUTE ON PROCEDURE mysqltest2.p_inv TO mysqltest_1@localhost; -GRANT EXECUTE ON FUNCTION mysqltest3.f_def TO mysqltest_1@localhost; -GRANT EXECUTE ON FUNCTION mysqltest4.f_inv TO mysqltest_1@localhost; - -GRANT ALL PRIVILEGES ON test.* TO mysqltest_1@localhost; - -# Test. - ---connect (bug9504_con1,localhost,mysqltest_1,,) ---echo ---echo ---> connection: bug9504_con1 - -# - Check that we can switch to the db; - -use mysqltest1; - -use mysqltest2; - -use mysqltest3; - -use mysqltest4; - -# - Check that we can call stored routines; - -use test; - -CALL mysqltest1.p_def(); - -CALL mysqltest2.p_inv(); - -SELECT mysqltest3.f_def(); - -SELECT mysqltest4.f_inv(); - -# Cleanup. - ---connection default ---echo ---echo ---> connection: default - ---disconnect bug9504_con1 - -DROP DATABASE mysqltest1; -DROP DATABASE mysqltest2; -DROP DATABASE mysqltest3; -DROP DATABASE mysqltest4; - -DROP USER mysqltest_1@localhost; - - -# -# Bug#27337 Privileges are not restored properly. -# -# Actually, the patch for this bugs fixes two problems. So, here are two test -# cases. - -# Test case 1: privileges are not restored properly after calling a stored -# routine defined with SQL SECURITY INVOKER clause. - -# Prepare. - ---disable_warnings -DROP DATABASE IF EXISTS mysqltest1; -DROP DATABASE IF EXISTS mysqltest2; ---enable_warnings - -CREATE DATABASE mysqltest1; -CREATE DATABASE mysqltest2; - -GRANT ALL PRIVILEGES ON mysqltest1.* TO mysqltest_1@localhost; -GRANT SELECT ON mysqltest2.* TO mysqltest_1@localhost; - -CREATE PROCEDURE mysqltest1.p1() SQL SECURITY INVOKER - SELECT 1; - -# Test. - ---connect (bug27337_con1,localhost,mysqltest_1,,mysqltest2) ---echo ---echo ---> connection: bug27337_con1 - ---error ER_TABLEACCESS_DENIED_ERROR -CREATE TABLE t1(c INT); - -CALL mysqltest1.p1(); - ---error ER_TABLEACCESS_DENIED_ERROR -CREATE TABLE t1(c INT); - ---disconnect bug27337_con1 - ---connect (bug27337_con2,localhost,mysqltest_1,,mysqltest2) ---echo ---echo ---> connection: bug27337_con2 - ---error ER_TABLEACCESS_DENIED_ERROR -CREATE TABLE t1(c INT); - -SHOW TABLES; - -# Cleanup. - ---connection default ---echo ---echo ---> connection: default - ---disconnect bug27337_con2 - -DROP DATABASE mysqltest1; -DROP DATABASE mysqltest2; - -DROP USER mysqltest_1@localhost; - -# Test case 2: privileges are not checked properly for prepared statements. - -# Prepare. - ---disable_warnings -DROP DATABASE IF EXISTS mysqltest1; -DROP DATABASE IF EXISTS mysqltest2; ---enable_warnings - -CREATE DATABASE mysqltest1; -CREATE DATABASE mysqltest2; - -CREATE TABLE mysqltest1.t1(c INT); -CREATE TABLE mysqltest2.t2(c INT); - -GRANT SELECT ON mysqltest1.t1 TO mysqltest_1@localhost; -GRANT SELECT ON mysqltest2.t2 TO mysqltest_2@localhost; - -# Test. - ---connect (bug27337_con1,localhost,mysqltest_1,,mysqltest1) ---echo ---echo ---> connection: bug27337_con1 - -SHOW TABLES FROM mysqltest1; - -PREPARE stmt1 FROM 'SHOW TABLES FROM mysqltest1'; - -EXECUTE stmt1; - ---connect (bug27337_con2,localhost,mysqltest_2,,mysqltest2) ---echo ---echo ---> connection: bug27337_con2 - -SHOW COLUMNS FROM mysqltest2.t2; - -PREPARE stmt2 FROM 'SHOW COLUMNS FROM mysqltest2.t2'; - -EXECUTE stmt2; - ---connection default ---echo ---echo ---> connection: default - -REVOKE SELECT ON mysqltest1.t1 FROM mysqltest_1@localhost; -REVOKE SELECT ON mysqltest2.t2 FROM mysqltest_2@localhost; - ---connection bug27337_con1 ---echo ---echo ---> connection: bug27337_con1 - ---error ER_DBACCESS_DENIED_ERROR -SHOW TABLES FROM mysqltest1; - ---error ER_DBACCESS_DENIED_ERROR -EXECUTE stmt1; - ---connection bug27337_con2 ---echo ---echo ---> connection: bug27337_con2 - ---error ER_TABLEACCESS_DENIED_ERROR -SHOW COLUMNS FROM mysqltest2.t2; - ---error ER_TABLEACCESS_DENIED_ERROR -EXECUTE stmt2; - -# Cleanup. - ---connection default ---echo ---echo ---> connection: default - ---disconnect bug27337_con1 ---disconnect bug27337_con2 - -DROP DATABASE mysqltest1; -DROP DATABASE mysqltest2; - -DROP USER mysqltest_1@localhost; -DROP USER mysqltest_2@localhost; - -# -# Bug#27878 Unchecked privileges on a view referring to a table from another -# database. -# -USE test; -CREATE TABLE t1 (f1 int, f2 int); -INSERT INTO t1 VALUES(1,1), (2,2); -CREATE DATABASE db27878; -GRANT UPDATE(f1) ON t1 TO 'mysqltest_1'@'localhost'; -GRANT SELECT ON `test`.* TO 'mysqltest_1'@'localhost'; -GRANT ALL ON db27878.* TO 'mysqltest_1'@'localhost'; -USE db27878; -CREATE SQL SECURITY INVOKER VIEW db27878.v1 AS SELECT * FROM test.t1; -connect (user1,localhost,mysqltest_1,,test); -connection user1; -USE db27878; ---error 1356 -UPDATE v1 SET f2 = 4; -SELECT * FROM test.t1; -disconnect user1; -connection default; -REVOKE UPDATE (f1) ON `test`.`t1` FROM 'mysqltest_1'@'localhost'; -REVOKE SELECT ON `test`.* FROM 'mysqltest_1'@'localhost'; -REVOKE ALL ON db27878.* FROM 'mysqltest_1'@'localhost'; -DROP USER mysqltest_1@localhost; -DROP DATABASE db27878; -USE test; -DROP TABLE t1; - ---echo # ---echo # Bug#33275 Server crash when creating temporary table mysql.user ---echo # -CREATE TEMPORARY TABLE mysql.user (id INT); -FLUSH PRIVILEGES; -DROP TABLE mysql.user; - - -# -# Bug#33201 Crash occurs when granting update privilege on one column of a view -# -drop table if exists test; -drop function if exists test_function; -drop view if exists v1; -create table test (col1 varchar(30)); -delimiter |; -create function test_function() returns varchar(30) -begin - declare tmp varchar(30); - select col1 from test limit 1 into tmp; - return '1'; -end| -delimiter ;| -create view v1 as select test.* from test where test.col1=test_function(); -grant update (col1) on v1 to 'greg'@'localhost'; -drop user 'greg'@'localhost'; -drop view v1; -drop table test; -drop function test_function; - -# -# Bug#41456 SET PASSWORD hates CURRENT_USER() -# -SELECT CURRENT_USER(); -SET PASSWORD FOR CURRENT_USER() = PASSWORD("admin"); -SET PASSWORD FOR CURRENT_USER() = PASSWORD(""); - -# -# Bug#57952: privilege change is not taken into account by EXECUTE. -# - ---echo ---echo # Bug#57952 ---echo - ---disable_warnings -DROP DATABASE IF EXISTS mysqltest1; -DROP DATABASE IF EXISTS mysqltest2; ---enable_warnings - -CREATE DATABASE mysqltest1; -CREATE DATABASE mysqltest2; - -use mysqltest1; -CREATE TABLE t1(a INT, b INT); -INSERT INTO t1 VALUES (1, 1); - -CREATE TABLE t2(a INT); -INSERT INTO t2 VALUES (2); - -CREATE TABLE mysqltest2.t3(a INT); -INSERT INTO mysqltest2.t3 VALUES (4); - -CREATE USER testuser@localhost; -GRANT CREATE ROUTINE, EXECUTE ON mysqltest1.* TO testuser@localhost; -GRANT SELECT(b) ON t1 TO testuser@localhost; -GRANT SELECT ON t2 TO testuser@localhost; -GRANT SELECT ON mysqltest2.* TO testuser@localhost; - ---echo ---echo # Connection: bug57952_con1 (testuser@localhost, db: mysqltest1) ---connect (bug57952_con1,localhost,testuser,,mysqltest1) -PREPARE s1 FROM 'SELECT b FROM t1'; -PREPARE s2 FROM 'SELECT a FROM t2'; -PREPARE s3 FROM 'SHOW TABLES FROM mysqltest2'; - -CREATE PROCEDURE p1() SELECT b FROM t1; -CREATE PROCEDURE p2() SELECT a FROM t2; -CREATE PROCEDURE p3() SHOW TABLES FROM mysqltest2; - -CALL p1; -CALL p2; -CALL p3; - ---echo ---echo # Connection: default ---connection default -REVOKE SELECT ON t1 FROM testuser@localhost; -GRANT SELECT(a) ON t1 TO testuser@localhost; -REVOKE SELECT ON t2 FROM testuser@localhost; -REVOKE SELECT ON mysqltest2.* FROM testuser@localhost; - ---echo ---echo # Connection: bug57952_con1 (testuser@localhost, db: mysqltest1) ---connection bug57952_con1 ---echo # - Check column-level privileges... ---error ER_COLUMNACCESS_DENIED_ERROR -EXECUTE s1; - ---error ER_COLUMNACCESS_DENIED_ERROR -SELECT b FROM t1; - ---error ER_COLUMNACCESS_DENIED_ERROR -EXECUTE s1; - ---error ER_COLUMNACCESS_DENIED_ERROR -CALL p1; - ---echo # - Check table-level privileges... ---error ER_TABLEACCESS_DENIED_ERROR -SELECT a FROM t2; - ---error ER_TABLEACCESS_DENIED_ERROR -EXECUTE s2; - ---error ER_TABLEACCESS_DENIED_ERROR -CALL p2; - ---echo # - Check database-level privileges... ---error ER_DBACCESS_DENIED_ERROR -SHOW TABLES FROM mysqltest2; - ---error ER_DBACCESS_DENIED_ERROR -EXECUTE s3; - ---error ER_DBACCESS_DENIED_ERROR -CALL p3; - ---echo ---echo # Connection: default ---connection default ---disconnect bug57952_con1 -DROP DATABASE mysqltest1; -DROP DATABASE mysqltest2; -DROP USER testuser@localhost; -use test; ---echo - - ---echo # ---echo # Test for bug #36544 "DROP USER does not remove stored function ---echo # privileges". ---echo # -create database mysqltest1; -create function mysqltest1.f1() returns int return 0; -create procedure mysqltest1.p1() begin end; ---echo # ---echo # 1) Check that DROP USER properly removes privileges on both ---echo # stored procedures and functions. ---echo # -create user mysqluser1@localhost; -grant execute on function mysqltest1.f1 to mysqluser1@localhost; -grant execute on procedure mysqltest1.p1 to mysqluser1@localhost; - ---echo # Quick test that granted privileges are properly reflected ---echo # in privilege tables and in in-memory structures. -show grants for mysqluser1@localhost; -select db, routine_name, routine_type, proc_priv from mysql.procs_priv where user='mysqluser1' and host='localhost'; ---echo # ---echo # Create connection 'bug_36544_con1' as 'mysqluser1@localhost'. ---connect (bug36544_con1,localhost,mysqluser1,,) -call mysqltest1.p1(); -select mysqltest1.f1(); - ---echo # ---echo # Switch to connection 'default'. ---connection default -drop user mysqluser1@localhost; - ---echo # ---echo # Test that dropping of user is properly reflected in ---echo # both privilege tables and in in-memory structures. ---echo # ---echo # Switch to connection 'bug36544_con1'. ---connection bug36544_con1 ---echo # The connection cold be alive but should not be able to ---echo # access to any of the stored routines. ---error ER_PROCACCESS_DENIED_ERROR -call mysqltest1.p1(); ---error ER_PROCACCESS_DENIED_ERROR -select mysqltest1.f1(); ---disconnect bug36544_con1 - ---echo # ---echo # Switch to connection 'default'. ---connection default ---echo # ---echo # Now create user with the same name and check that he ---echo # has not inherited privileges. -create user mysqluser1@localhost; -show grants for mysqluser1@localhost; -select db, routine_name, routine_type, proc_priv from mysql.procs_priv where user='mysqluser1' and host='localhost'; ---echo # ---echo # Create connection 'bug_36544_con2' as 'mysqluser1@localhost'. ---connect (bug36544_con2,localhost,mysqluser1,,) ---echo # Newly created user should not be able to access any of the routines. ---error ER_PROCACCESS_DENIED_ERROR -call mysqltest1.p1(); ---error ER_PROCACCESS_DENIED_ERROR -select mysqltest1.f1(); ---echo # ---echo # Switch to connection 'default'. ---connection default - ---echo # ---echo # 2) Check that RENAME USER properly updates privileges on both ---echo # stored procedures and functions. ---echo # -grant execute on function mysqltest1.f1 to mysqluser1@localhost; -grant execute on procedure mysqltest1.p1 to mysqluser1@localhost; ---echo # ---echo # Create one more user to make in-memory hashes non-trivial. ---echo # User names 'mysqluser11' and 'mysqluser10' were selected ---echo # to trigger bug discovered during code inspection. -create user mysqluser11@localhost; -grant execute on function mysqltest1.f1 to mysqluser11@localhost; -grant execute on procedure mysqltest1.p1 to mysqluser11@localhost; ---echo # Also create a couple of tables to test for another bug ---echo # discovered during code inspection (again table names were ---echo # chosen especially to trigger the bug). -create table mysqltest1.t11 (i int); -create table mysqltest1.t22 (i int); -grant select on mysqltest1.t22 to mysqluser1@localhost; -grant select on mysqltest1.t11 to mysqluser1@localhost; - ---echo # Quick test that granted privileges are properly reflected ---echo # in privilege tables and in in-memory structures. -show grants for mysqluser1@localhost; -select db, routine_name, routine_type, proc_priv from mysql.procs_priv where user='mysqluser1' and host='localhost'; -select db, table_name, table_priv from mysql.tables_priv where user='mysqluser1' and host='localhost'; ---echo # ---echo # Switch to connection 'bug36544_con2'. ---connection bug36544_con2 -call mysqltest1.p1(); -select mysqltest1.f1(); -select * from mysqltest1.t11; -select * from mysqltest1.t22; - ---echo # ---echo # Switch to connection 'default'. ---connection default -rename user mysqluser1@localhost to mysqluser10@localhost; - ---echo # ---echo # Test that there are no privileges left for mysqluser1. ---echo # ---echo # Switch to connection 'bug36544_con2'. ---connection bug36544_con2 ---echo # The connection cold be alive but should not be able to ---echo # access to any of the stored routines or tables. ---error ER_PROCACCESS_DENIED_ERROR -call mysqltest1.p1(); ---error ER_PROCACCESS_DENIED_ERROR -select mysqltest1.f1(); ---error ER_TABLEACCESS_DENIED_ERROR -select * from mysqltest1.t11; ---error ER_TABLEACCESS_DENIED_ERROR -select * from mysqltest1.t22; ---disconnect bug36544_con2 - ---echo # ---echo # Switch to connection 'default'. ---connection default ---echo # ---echo # Now create user with the old name and check that he ---echo # has not inherited privileges. -create user mysqluser1@localhost; -show grants for mysqluser1@localhost; -select db, routine_name, routine_type, proc_priv from mysql.procs_priv where user='mysqluser1' and host='localhost'; -select db, table_name, table_priv from mysql.tables_priv where user='mysqluser1' and host='localhost'; ---echo # ---echo # Create connection 'bug_36544_con3' as 'mysqluser1@localhost'. ---connect (bug36544_con3,localhost,mysqluser1,,) ---echo # Newly created user should not be able to access to any of the ---echo # stored routines or tables. ---error ER_PROCACCESS_DENIED_ERROR -call mysqltest1.p1(); ---error ER_PROCACCESS_DENIED_ERROR -select mysqltest1.f1(); ---error ER_TABLEACCESS_DENIED_ERROR -select * from mysqltest1.t11; ---error ER_TABLEACCESS_DENIED_ERROR -select * from mysqltest1.t22; ---disconnect bug36544_con3 - ---echo # ---echo # Switch to connection 'default'. ---connection default ---echo # ---echo # Now check that privileges became associated with a new user ---echo # name - mysqluser10. ---echo # -show grants for mysqluser10@localhost; -select db, routine_name, routine_type, proc_priv from mysql.procs_priv where user='mysqluser10' and host='localhost'; -select db, table_name, table_priv from mysql.tables_priv where user='mysqluser10' and host='localhost'; ---echo # ---echo # Create connection 'bug_36544_con4' as 'mysqluser10@localhost'. ---connect (bug36544_con4,localhost,mysqluser10,,) -call mysqltest1.p1(); -select mysqltest1.f1(); -select * from mysqltest1.t11; -select * from mysqltest1.t22; ---disconnect bug36544_con4 - ---echo # ---echo # Switch to connection 'default'. ---connection default ---echo # ---echo # Clean-up. -drop user mysqluser1@localhost; -drop user mysqluser10@localhost; -drop user mysqluser11@localhost; -drop database mysqltest1; - - ---echo End of 5.0 tests -set names utf8; ---error ER_WRONG_STRING_LENGTH -grant select on test.* to очень_длинный_юзер890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890@localhost; -set names default; - -# -# Bug#20901 CREATE privilege is enough to insert into a table -# - -create database mysqltest; -use mysqltest; - -grant create on mysqltest.* to mysqltest@localhost; -create table t1 (i INT); - -connect (user1,localhost,mysqltest,,mysqltest); -connection user1; -# show we don't have INSERT ---error ER_TABLEACCESS_DENIED_ERROR -insert into t1 values (1); -# show we have CREATE -create table t2 (i INT); -create table t4 (i INT); - -connection default; -grant select, insert on mysqltest.t2 to mysqltest@localhost; -grant insert on mysqltest.t4 to mysqltest@localhost; -# to specify ACLs for non-existent objects, must explictly |CREATE -grant create, insert on mysqltest.t5 to mysqltest@localhost; -grant create, insert on mysqltest.t6 to mysqltest@localhost; -flush privileges; - -connection user1; -insert into t2 values (1); - - -# CREATE IF NOT EXISTS...SELECT, t1 exists, no INSERT, must fail ---error ER_TABLEACCESS_DENIED_ERROR -create table if not exists t1 select * from t2; - -# CREATE IF NOT EXISTS...SELECT, no t3 yet, no INSERT, must fail ---error ER_TABLEACCESS_DENIED_ERROR -create table if not exists t3 select * from t2; - -# CREATE IF NOT EXISTS...SELECT, t4 exists, have INSERT, must succeed -create table if not exists t4 select * from t2; - -# CREATE IF NOT EXISTS...SELECT, no t5 yet, have INSERT, must succeed -create table if not exists t5 select * from t2; - - -# CREATE...SELECT, no t6 yet, have INSERT, must succeed -create table t6 select * from t2; - -# CREATE...SELECT, no t7 yet, no INSERT, must fail ---error ER_TABLEACCESS_DENIED_ERROR -create table t7 select * from t2; - -# CREATE...SELECT, t4 exists, have INSERT, must still fail (exists) ---error 1050 -create table t4 select * from t2; - -# CREATE...SELECT, t1 exists, no INSERT, must fail ---error ER_TABLEACCESS_DENIED_ERROR -create table t1 select * from t2; - - -connection default; -drop table t1,t2,t4,t5,t6; - -revoke create on mysqltest.* from mysqltest@localhost; -revoke select, insert on mysqltest.t2 from mysqltest@localhost; -revoke insert on mysqltest.t4 from mysqltest@localhost; -revoke create, insert on mysqltest.t5 from mysqltest@localhost; -revoke create, insert on mysqltest.t6 from mysqltest@localhost; -drop user mysqltest@localhost; - -disconnect user1; -drop database mysqltest; -use test; - - -# -# Bug#16470 crash on grant if old grant tables -# - -call mtr.add_suppression("Can't open and lock privilege tables"); - ---echo FLUSH PRIVILEGES without procs_priv table. -RENAME TABLE mysql.procs_priv TO mysql.procs_gone; -FLUSH PRIVILEGES; ---echo Assigning privileges without procs_priv table. -CREATE DATABASE mysqltest1; -CREATE PROCEDURE mysqltest1.test() SQL SECURITY DEFINER - SELECT 1; -CREATE FUNCTION mysqltest1.test() RETURNS INT RETURN 1; ---error ER_NO_SUCH_TABLE -GRANT EXECUTE ON FUNCTION mysqltest1.test TO mysqltest_1@localhost; -GRANT ALL PRIVILEGES ON test.* TO mysqltest_1@localhost; -CALL mysqltest1.test(); -DROP DATABASE mysqltest1; -RENAME TABLE mysql.procs_gone TO mysql.procs_priv; -DROP USER mysqltest_1@localhost; -FLUSH PRIVILEGES; - - -# -# Bug#33464 DROP FUNCTION caused a crash. -# -CREATE DATABASE dbbug33464; -CREATE USER 'userbug33464'@'localhost'; - -GRANT CREATE ROUTINE ON dbbug33464.* TO 'userbug33464'@'localhost'; - ---replace_result $MASTER_MYPORT MYSQL_PORT $MASTER_MYSOCK MYSQL_SOCK -connect (connbug33464, localhost, userbug33464, , dbbug33464); ---source suite/funcs_1/include/show_connection.inc - -delimiter //; -CREATE PROCEDURE sp3(v1 char(20)) -BEGIN - SELECT * from dbbug33464.t6 where t6.f2= 'xyz'; -END// -delimiter ;// - -delimiter //; -CREATE FUNCTION fn1() returns char(50) SQL SECURITY INVOKER -BEGIN - return 1; -END// -delimiter ;// - -delimiter //; -CREATE FUNCTION fn2() returns char(50) SQL SECURITY DEFINER -BEGIN - return 2; -END// -delimiter ;// - -disconnect connbug33464; - -# cleanup -connection default; -USE dbbug33464; ---source suite/funcs_1/include/show_connection.inc - -SELECT fn1(); -SELECT fn2(); - ---error 0, ER_CANNOT_USER -DROP USER 'userbug33464'@'localhost'; - -DROP FUNCTION fn1; -DROP FUNCTION fn2; -DROP PROCEDURE sp3; - ---error 0, ER_CANNOT_USER -DROP USER 'userbug33464'@'localhost'; - -USE test; -DROP DATABASE dbbug33464; - - -SET @@global.log_bin_trust_function_creators= @old_log_bin_trust_function_creators; - -# -# Bug#44658 Create procedure makes server crash when user does not have ALL privilege -# -CREATE USER user1; -CREATE USER user2; -GRANT CREATE ON db1.* TO 'user1'@'localhost'; -GRANT CREATE ROUTINE ON db1.* TO 'user1'@'localhost'; -GRANT CREATE ON db1.* TO 'user2'@'%'; -GRANT CREATE ROUTINE ON db1.* TO 'user2'@'%'; -FLUSH PRIVILEGES; -SHOW GRANTS FOR 'user1'@'localhost'; -connect (con1,localhost,user1,,); ---echo ** Connect as user1 and create a procedure. ---echo ** The creation will imply implicitly assigned ---echo ** EXECUTE and ALTER ROUTINE privileges to ---echo ** the current user user1@localhost. -SELECT @@GLOBAL.sql_mode; -SELECT @@SESSION.sql_mode; -CREATE DATABASE db1; -DELIMITER ||; -CREATE PROCEDURE db1.proc1(p1 INT) - BEGIN - SET @x = 0; - REPEAT SET @x = @x + 1; UNTIL @x > p1 END REPEAT; - END ;|| -DELIMITER ;|| - -connect (con2,localhost,user2,,); ---echo ** Connect as user2 and create a procedure. ---echo ** Implicitly assignment of privileges will ---echo ** fail because the user2@localhost is an ---echo ** unknown user. -DELIMITER ||; -CREATE PROCEDURE db1.proc2(p1 INT) - BEGIN - SET @x = 0; - REPEAT SET @x = @x + 1; UNTIL @x > p1 END REPEAT; - END ;|| -DELIMITER ;|| - -connection default; -SHOW GRANTS FOR 'user1'@'localhost'; -SHOW GRANTS FOR 'user2'; -disconnect con1; -disconnect con2; -DROP PROCEDURE db1.proc1; -DROP PROCEDURE db1.proc2; -REVOKE ALL ON db1.* FROM 'user1'@'localhost'; -REVOKE ALL ON db1.* FROM 'user2'@'%'; -DROP USER 'user1'; -DROP USER 'user1'@'localhost'; -DROP USER 'user2'; -DROP DATABASE db1; - - ---echo # ---echo # Bug #25863 No database selected error, but documentation ---echo # says * for global allowed ---echo # - -connect(conn1,localhost,root,,*NO-ONE*); - ---error ER_NO_DB_ERROR -GRANT ALL ON * TO mysqltest_1; - -GRANT ALL ON *.* TO mysqltest_1; -SHOW GRANTS FOR mysqltest_1; -DROP USER mysqltest_1; - -USE test; - -GRANT ALL ON * TO mysqltest_1; -SHOW GRANTS FOR mysqltest_1; -DROP USER mysqltest_1; - -GRANT ALL ON *.* TO mysqltest_1; -SHOW GRANTS FOR mysqltest_1; -DROP USER mysqltest_1; - -connection default; -disconnect conn1; - - -# -# Bug #53371: COM_FIELD_LIST can be abused to bypass table level grants. -# - -CREATE DATABASE db1; -CREATE DATABASE db2; -GRANT SELECT ON db1.* to 'testbug'@localhost; -USE db2; -CREATE TABLE t1 (a INT); -USE test; -connect (con1,localhost,testbug,,db1); ---error ER_NO_SUCH_TABLE -SELECT * FROM `../db2/tb2`; ---error ER_TABLEACCESS_DENIED_ERROR -SELECT * FROM `../db2`.tb2; ---error ER_WRONG_TABLE_NAME -SELECT * FROM `#mysql50#/../db2/tb2`; -connection default; -disconnect con1; -DROP USER 'testbug'@localhost; -DROP TABLE db2.t1; -DROP DATABASE db1; -DROP DATABASE db2; - ---echo # ---echo # Bug #36742 ---echo # -grant usage on Foo.* to myuser@Localhost identified by 'foo'; -grant select on Foo.* to myuser@localhost; -select host,user from mysql.user where User='myuser'; -revoke select on Foo.* from myuser@localhost; -delete from mysql.user where User='myuser'; -flush privileges; - ---echo ######################################################################### ---echo # ---echo # Bug#38347: ALTER ROUTINE privilege allows SHOW CREATE TABLE. ---echo # ---echo ######################################################################### - ---echo ---echo # -- ---echo # -- Prepare the environment. ---echo # -- - -DELETE FROM mysql.user WHERE User LIKE 'mysqltest_%'; -DELETE FROM mysql.db WHERE User LIKE 'mysqltest_%'; -DELETE FROM mysql.tables_priv WHERE User LIKE 'mysqltest_%'; -DELETE FROM mysql.columns_priv WHERE User LIKE 'mysqltest_%'; -FLUSH PRIVILEGES; - ---disable_warnings -DROP DATABASE IF EXISTS mysqltest_db1; ---enable_warnings - -CREATE DATABASE mysqltest_db1; - -CREATE TABLE mysqltest_db1.t1(a INT); - ---echo ---echo # -- ---echo # -- Check that global privileges don't allow SHOW CREATE TABLE. ---echo # -- - -GRANT EVENT ON mysqltest_db1.* TO mysqltest_u1@localhost; -GRANT CREATE TEMPORARY TABLES ON mysqltest_db1.* TO mysqltest_u1@localhost; -GRANT LOCK TABLES ON mysqltest_db1.* TO mysqltest_u1@localhost; -GRANT ALTER ROUTINE ON mysqltest_db1.* TO mysqltest_u1@localhost; -GRANT CREATE ROUTINE ON mysqltest_db1.* TO mysqltest_u1@localhost; -GRANT EXECUTE ON mysqltest_db1.* TO mysqltest_u1@localhost; - -GRANT FILE ON *.* TO mysqltest_u1@localhost; -GRANT CREATE USER ON *.* TO mysqltest_u1@localhost; -GRANT PROCESS ON *.* TO mysqltest_u1@localhost; -GRANT RELOAD ON *.* TO mysqltest_u1@localhost; -GRANT REPLICATION CLIENT ON *.* TO mysqltest_u1@localhost; -GRANT REPLICATION SLAVE ON *.* TO mysqltest_u1@localhost; -GRANT SHOW DATABASES ON *.* TO mysqltest_u1@localhost; -GRANT SHUTDOWN ON *.* TO mysqltest_u1@localhost; -GRANT USAGE ON *.* TO mysqltest_u1@localhost; - ---echo -SHOW GRANTS FOR mysqltest_u1@localhost; - ---echo ---echo # connection: con1 (mysqltest_u1@mysqltest_db1) ---connect (con1,localhost,mysqltest_u1,,mysqltest_db1) ---connection con1 - ---echo ---error ER_TABLEACCESS_DENIED_ERROR -SHOW CREATE TABLE t1; - ---echo ---echo # connection: default ---connection default - ---disconnect con1 - ---echo -REVOKE ALL PRIVILEGES, GRANT OPTION FROM mysqltest_u1@localhost; -SHOW GRANTS FOR mysqltest_u1@localhost; - ---echo ---echo # -- ---echo # -- Check that global SELECT allows SHOW CREATE TABLE. ---echo # -- - ---echo -GRANT SELECT ON mysqltest_db1.* TO mysqltest_u1@localhost; - ---source include/bug38347.inc - ---echo ---echo # -- ---echo # -- Check that global INSERT allows SHOW CREATE TABLE. ---echo # -- - ---echo -GRANT INSERT ON mysqltest_db1.* TO mysqltest_u1@localhost; - ---source include/bug38347.inc - ---echo ---echo # -- ---echo # -- Check that global UPDATE allows SHOW CREATE TABLE. ---echo # -- - ---echo -GRANT UPDATE ON mysqltest_db1.* TO mysqltest_u1@localhost; - ---source include/bug38347.inc - ---echo ---echo # -- ---echo # -- Check that global DELETE allows SHOW CREATE TABLE. ---echo # -- - ---echo -GRANT DELETE ON mysqltest_db1.* TO mysqltest_u1@localhost; - ---source include/bug38347.inc - ---echo ---echo # -- ---echo # -- Check that global CREATE allows SHOW CREATE TABLE. ---echo # -- - ---echo -GRANT CREATE ON mysqltest_db1.* TO mysqltest_u1@localhost; - ---source include/bug38347.inc - ---echo ---echo # -- ---echo # -- Check that global DROP allows SHOW CREATE TABLE. ---echo # -- - ---echo -GRANT DROP ON mysqltest_db1.* TO mysqltest_u1@localhost; - ---source include/bug38347.inc - ---echo ---echo # -- ---echo # -- Check that global ALTER allows SHOW CREATE TABLE. ---echo # -- - ---echo -GRANT ALTER ON mysqltest_db1.* TO mysqltest_u1@localhost; - ---source include/bug38347.inc - ---echo ---echo # -- ---echo # -- Check that global INDEX allows SHOW CREATE TABLE. ---echo # -- - ---echo -GRANT INDEX ON mysqltest_db1.* TO mysqltest_u1@localhost; - ---source include/bug38347.inc - ---echo ---echo # -- ---echo # -- Check that global REFERENCES allows SHOW CREATE TABLE. ---echo # -- - ---echo -GRANT REFERENCES ON mysqltest_db1.* TO mysqltest_u1@localhost; - ---source include/bug38347.inc - ---echo ---echo # -- ---echo # -- Check that global GRANT OPTION allows SHOW CREATE TABLE. ---echo # -- - ---echo -GRANT GRANT OPTION ON mysqltest_db1.* TO mysqltest_u1@localhost; - ---source include/bug38347.inc - ---echo ---echo # -- ---echo # -- Check that global CREATE VIEW allows SHOW CREATE TABLE. ---echo # -- - ---echo -GRANT CREATE VIEW ON mysqltest_db1.* TO mysqltest_u1@localhost; - ---source include/bug38347.inc - ---echo ---echo # -- ---echo # -- Check that global SHOW VIEW allows SHOW CREATE TABLE. ---echo # -- - ---echo -GRANT SHOW VIEW ON mysqltest_db1.* TO mysqltest_u1@localhost; - ---source include/bug38347.inc - ---echo ---echo # -- ---echo # -- Check that table-level SELECT allows SHOW CREATE TABLE. ---echo # -- - ---echo -GRANT SELECT ON mysqltest_db1.t1 TO mysqltest_u1@localhost; - ---source include/bug38347.inc - ---echo ---echo # -- ---echo # -- Check that table-level INSERT allows SHOW CREATE TABLE. ---echo # -- - ---echo -GRANT INSERT ON mysqltest_db1.t1 TO mysqltest_u1@localhost; - ---source include/bug38347.inc - ---echo ---echo # -- ---echo # -- Check that table-level UPDATE allows SHOW CREATE TABLE. ---echo # -- - ---echo -GRANT UPDATE ON mysqltest_db1.t1 TO mysqltest_u1@localhost; - ---source include/bug38347.inc - ---echo ---echo # -- ---echo # -- Check that table-level DELETE allows SHOW CREATE TABLE. ---echo # -- - ---echo -GRANT DELETE ON mysqltest_db1.t1 TO mysqltest_u1@localhost; - ---source include/bug38347.inc - ---echo ---echo # -- ---echo # -- Check that table-level CREATE allows SHOW CREATE TABLE. ---echo # -- - ---echo -GRANT CREATE ON mysqltest_db1.t1 TO mysqltest_u1@localhost; - ---source include/bug38347.inc - ---echo ---echo # -- ---echo # -- Check that table-level DROP allows SHOW CREATE TABLE. ---echo # -- - ---echo -GRANT DROP ON mysqltest_db1.t1 TO mysqltest_u1@localhost; - ---source include/bug38347.inc - ---echo ---echo # -- ---echo # -- Check that table-level ALTER allows SHOW CREATE TABLE. ---echo # -- - ---echo -GRANT ALTER ON mysqltest_db1.t1 TO mysqltest_u1@localhost; - ---source include/bug38347.inc - ---echo ---echo # -- ---echo # -- Check that table-level INDEX allows SHOW CREATE TABLE. ---echo # -- - ---echo -GRANT INDEX ON mysqltest_db1.t1 TO mysqltest_u1@localhost; - ---source include/bug38347.inc - ---echo ---echo # -- ---echo # -- Check that table-level REFERENCES allows SHOW CREATE TABLE. ---echo # -- - ---echo -GRANT REFERENCES ON mysqltest_db1.t1 TO mysqltest_u1@localhost; - ---source include/bug38347.inc - ---echo ---echo # -- ---echo # -- Check that table-level GRANT OPTION allows SHOW CREATE TABLE. ---echo # -- - ---echo -GRANT GRANT OPTION ON mysqltest_db1.t1 TO mysqltest_u1@localhost; - ---source include/bug38347.inc - ---echo ---echo # -- ---echo # -- Check that table-level CREATE VIEW allows SHOW CREATE TABLE. ---echo # -- - ---echo -GRANT CREATE VIEW ON mysqltest_db1.t1 TO mysqltest_u1@localhost; - ---source include/bug38347.inc - ---echo ---echo # -- ---echo # -- Check that table-level SHOW VIEW allows SHOW CREATE TABLE. ---echo # -- - ---echo -GRANT SHOW VIEW ON mysqltest_db1.t1 TO mysqltest_u1@localhost; - ---source include/bug38347.inc - ---echo ---echo # -- ---echo # -- Cleanup. ---echo # -- - ---echo -DROP DATABASE mysqltest_db1; - -DROP USER mysqltest_u1@localhost; - ---echo ---echo # End of Bug#38347. ---echo - - ---echo # ---echo # BUG#11759114 - '51401: GRANT TREATS NONEXISTENT FUNCTIONS/PRIVILEGES ---echo # DIFFERENTLY'. ---echo # ---disable_warnings -drop database if exists mysqltest_db1; ---enable_warnings -create database mysqltest_db1; -create user mysqltest_u1; ---echo # Both GRANT statements below should fail with the same error. ---error ER_SP_DOES_NOT_EXIST -grant execute on function mysqltest_db1.f1 to mysqltest_u1; ---error ER_SP_DOES_NOT_EXIST -grant execute on procedure mysqltest_db1.p1 to mysqltest_u1; ---echo # Let us show that GRANT behaviour for routines is consistent ---echo # with GRANT behaviour for tables. Attempt to grant privilege ---echo # on non-existent table also results in an error. ---error ER_NO_SUCH_TABLE -grant select on mysqltest_db1.t1 to mysqltest_u1; -show grants for mysqltest_u1; -drop database mysqltest_db1; -drop user mysqltest_u1; - - ---echo # ---echo # Bug#12766319 - 61865: RENAME USER DOES NOT WORK CORRECTLY - ---echo # REQUIRES FLUSH PRIVILEGES ---echo # - -CREATE USER foo@'127.0.0.1'; -GRANT ALL ON *.* TO foo@'127.0.0.1'; - ---echo # First attempt, should connect successfully -connect (conn1, '127.0.0.1', foo,,test); -SELECT user(), current_user(); - ---echo # Rename the user -RENAME USER foo@'127.0.0.1' to foo@'127.0.0.0/255.0.0.0'; - ---echo # Second attempt, should connect successfully as its valid mask ---echo # This was failing without fix -connect (conn2, '127.0.0.1', foo,,test); -SELECT user(), current_user(); - ---echo # Rename the user back to original -RENAME USER foo@'127.0.0.0/255.0.0.0' to foo@'127.0.0.1'; - ---echo # Third attempt, should connect successfully -connect (conn3, '127.0.0.1', foo,,test); -SELECT user(), current_user(); - ---echo # Clean-up -connection default; -disconnect conn1; -disconnect conn2; -disconnect conn3; -DROP USER foo@'127.0.0.1'; - ---echo # End of Bug#12766319 - -# -# Bug#27230925: HANDLE_FATAL_SIGNAL (SIG=11) IN SHOW_ROUTINE_GRANTS -# -create user foo@localhost; -create database foodb; -grant create routine on foodb.* to foo@localhost; -connect con1,localhost,foo; -create procedure fooproc() select 'i am fooproc'; -show grants; -disconnect con1; -connection default; -rename table mysql.procs_priv to mysql.procs_priv1; -flush privileges; -show grants for foo@localhost; -rename table mysql.procs_priv1 to mysql.procs_priv; -show grants for foo@localhost; -flush privileges; -show grants for foo@localhost; -drop user foo@localhost; -drop procedure fooproc; -drop database foodb; - - ---echo # ---echo # Bug#11756966 - 48958: STORED PROCEDURES CAN BE LEVERAGED TO BYPASS ---echo # DATABASE SECURITY ---echo # - ---disable_warnings -DROP DATABASE IF EXISTS secret; -DROP DATABASE IF EXISTS no_such_db; ---enable_warnings - -CREATE DATABASE secret; -GRANT USAGE ON *.* TO untrusted@localhost; - ---echo # Connection con1 -connect (con1, localhost, untrusted); -SHOW GRANTS; -SHOW DATABASES; - ---echo # Both statements below should fail with the same error. ---echo # They used to give different errors, thereby ---echo # hinting that the secret database exists. ---error ER_DBACCESS_DENIED_ERROR -CREATE PROCEDURE no_such_db.foo() BEGIN END; ---error ER_DBACCESS_DENIED_ERROR -CREATE PROCEDURE secret.peek_at_secret() BEGIN END; - ---echo # Connection default ---connection default -disconnect con1; -DROP USER untrusted@localhost; -DROP DATABASE secret; - -# Wait till we reached the initial number of concurrent sessions ---source include/wait_until_count_sessions.inc diff --git a/mysql-test/r/lowercase_fs_off.test b/mysql-test/r/lowercase_fs_off.test deleted file mode 100644 index f4df5e8188d..00000000000 --- a/mysql-test/r/lowercase_fs_off.test +++ /dev/null @@ -1,124 +0,0 @@ -# -# Specific tests for case sensitive file systems -# i.e. lower_case_filesystem=OFF -# --- source include/have_case_sensitive_file_system.inc --- source include/not_embedded.inc - -connect (master,localhost,root,,); -connection master; -create database d1; -grant all on d1.* to 'sample'@'localhost' identified by 'password'; -flush privileges; - -connect (sample,localhost,sample,password,d1); -connection sample; -select database(); ---error ER_DBACCESS_DENIED_ERROR -create database d2; ---error ER_DBACCESS_DENIED_ERROR -create database D1; -disconnect sample; ---source include/wait_until_disconnected.inc - -connection master; -drop user 'sample'@'localhost'; -drop database if exists d1; -disconnect master; ---source include/wait_until_disconnected.inc -connection default; - -# End of 4.1 tests - -# -# Bug#41049 does syntax "grant" case insensitive? -# -CREATE DATABASE d1; -USE d1; -CREATE TABLE T1(f1 INT); -CREATE TABLE t1(f1 INT); -GRANT SELECT ON T1 to user_1@localhost; - -connect (con1,localhost,user_1,,d1); ---error ER_TABLEACCESS_DENIED_ERROR -select * from t1; -select * from T1; -connection default; -GRANT SELECT ON t1 to user_1@localhost; -connection con1; -select * from information_schema.table_privileges; -connection default; -disconnect con1; - -REVOKE ALL PRIVILEGES, GRANT OPTION FROM user_1@localhost; -DROP USER user_1@localhost; -DROP DATABASE d1; -USE test; - -CREATE DATABASE db1; -USE db1; -CREATE PROCEDURE p1() BEGIN END; -CREATE FUNCTION f1(i INT) RETURNS INT RETURN i+1; - -GRANT USAGE ON db1.* to user_1@localhost; -GRANT EXECUTE ON PROCEDURE db1.P1 to user_1@localhost; -GRANT EXECUTE ON FUNCTION db1.f1 to user_1@localhost; -GRANT UPDATE ON db1.* to USER_1@localhost; - -connect (con1,localhost,user_1,,db1); -call p1(); -call P1(); -select f1(1); -connect (con2,localhost,USER_1,,db1); ---error ER_PROCACCESS_DENIED_ERROR -call p1(); ---error ER_PROCACCESS_DENIED_ERROR -call P1(); ---error ER_PROCACCESS_DENIED_ERROR -select f1(1); - -connection default; -disconnect con1; -disconnect con2; - -REVOKE ALL PRIVILEGES, GRANT OPTION FROM user_1@localhost; -REVOKE ALL PRIVILEGES, GRANT OPTION FROM USER_1@localhost; -DROP FUNCTION f1; -DROP PROCEDURE p1; -DROP USER user_1@localhost; -DROP USER USER_1@localhost; -DROP DATABASE db1; -use test; - -# End of 5.0 tests - - ---echo # ---echo # Extra test coverage for Bug#56595 RENAME TABLE causes assert on OS X ---echo # - -CREATE TABLE t1(a INT); -CREATE TRIGGER t1_bi BEFORE INSERT ON t1 FOR EACH ROW SET new.a= 1; -RENAME TABLE t1 TO T1; -ALTER TABLE T1 RENAME t1; -DROP TABLE t1; - -# -# MDEV-13912 mysql_upgrade: case (in)sensitivity for stored procedures -# -create database TEST; -create procedure TEST.pr() begin end; -create procedure test.pr() begin end; ---exec $MYSQL_UPGRADE --force 2>&1 -drop procedure test.pr; -drop database TEST; - -# End of 5.5 tests - -# -# MDEV-9014 SHOW TRIGGERS not case sensitive -# -create table t1 (a int); -create trigger t1_bi before insert on t1 for each row set new.a= 1; -show triggers like '%T1%'; -drop table t1; diff --git a/mysql-test/r/mysql.result b/mysql-test/r/mysql.result index 06ef7e95bc9..02ca052cfc8 100644 --- a/mysql-test/r/mysql.result +++ b/mysql-test/r/mysql.result @@ -600,3 +600,18 @@ a 2 drop table "a1\""b1"; set sql_mode=default; +create table t1 (a text); +select count(*) from t1; +count(*) +41 +truncate table t1; +select count(*) from t1; +count(*) +41 +truncate table t1; +select count(*) from t1; +count(*) +0 +truncate table t1; +### FIXME: update libmariadb +drop table t1; diff --git a/mysql-test/r/row-checksum-old.result b/mysql-test/r/row-checksum-old.result index 87cd1cc89ed..d374013f61c 100644 --- a/mysql-test/r/row-checksum-old.result +++ b/mysql-test/r/row-checksum-old.result @@ -83,3 +83,19 @@ checksum table t1 extended; Table Checksum test.t1 452555338 drop table t1; +# +# MDEV-17085: CHECKSUM TABLE EXTENDED does not work correctly +# +CREATE TABLE t1 ( c1 int NOT NULL, c2 int NOT NULL, c4 varchar(20), c5 varchar(20), c6 varchar(20), c7 varchar(20), c8 varchar(20), c9 varchar(20), c10 varchar(20), c11 varchar(20), c12 varchar(20), c13 varchar(20), c14 varchar(20), c15 varchar(20), c16 varchar(20), c19 int NOT NULL, c20 int NOT NULL, c21 varchar(20), c22 VARCHAR(20), c23 varchar(20)); +insert into t1 values (5,0,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,0,"dog",NULL,NULL); +# Important is that checksum is different from following +CHECKSUM TABLE t1 EXTENDED; +Table Checksum +test.t1 2514025256 +UPDATE t1 SET c21='cat' WHERE c1=5; +# Important is that checksum is different from above +CHECKSUM TABLE t1 EXTENDED; +Table Checksum +test.t1 2326430205 +drop table t1; +# End of 5.5 tests diff --git a/mysql-test/r/row-checksum.result b/mysql-test/r/row-checksum.result index f2e687f8b6e..4625e09c060 100644 --- a/mysql-test/r/row-checksum.result +++ b/mysql-test/r/row-checksum.result @@ -83,3 +83,19 @@ checksum table t1 extended; Table Checksum test.t1 229851577 drop table t1; +# +# MDEV-17085: CHECKSUM TABLE EXTENDED does not work correctly +# +CREATE TABLE t1 ( c1 int NOT NULL, c2 int NOT NULL, c4 varchar(20), c5 varchar(20), c6 varchar(20), c7 varchar(20), c8 varchar(20), c9 varchar(20), c10 varchar(20), c11 varchar(20), c12 varchar(20), c13 varchar(20), c14 varchar(20), c15 varchar(20), c16 varchar(20), c19 int NOT NULL, c20 int NOT NULL, c21 varchar(20), c22 VARCHAR(20), c23 varchar(20)); +insert into t1 values (5,0,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,0,"dog",NULL,NULL); +# Important is that checksum is different from following +CHECKSUM TABLE t1 EXTENDED; +Table Checksum +test.t1 2514025256 +UPDATE t1 SET c21='cat' WHERE c1=5; +# Important is that checksum is different from above +CHECKSUM TABLE t1 EXTENDED; +Table Checksum +test.t1 2326430205 +drop table t1; +# End of 5.5 tests diff --git a/mysql-test/r/sp-security.test b/mysql-test/r/sp-security.test deleted file mode 100644 index 53dc4f8c7ac..00000000000 --- a/mysql-test/r/sp-security.test +++ /dev/null @@ -1,1069 +0,0 @@ -# -# Testing SQL SECURITY of stored procedures -# - -# Can't test with embedded server that doesn't support grants --- source include/not_embedded.inc - -# Save the initial number of concurrent sessions ---source include/count_sessions.inc - -connect (con1root,localhost,root,,); - -connection con1root; -use test; - -# Create user user1 with no particular access rights -grant usage on *.* to user1@localhost; -flush privileges; - ---disable_warnings -drop table if exists t1; -drop database if exists db1_secret; ---enable_warnings -# Create our secret database -create database db1_secret; - -# Can create a procedure in other db -create procedure db1_secret.dummy() begin end; -drop procedure db1_secret.dummy; - -use db1_secret; - -create table t1 ( u varchar(64), i int ); -insert into t1 values('test', 0); - -# A test procedure and function -create procedure stamp(i int) - insert into db1_secret.t1 values (user(), i); ---replace_column 5 '0000-00-00 00:00:00' 6 '0000-00-00 00:00:00' -show procedure status like 'stamp'; - -delimiter |; -create function db() returns varchar(64) -begin - declare v varchar(64); - - select u into v from t1 limit 1; - - return v; -end| -delimiter ;| ---replace_column 5 '0000-00-00 00:00:00' 6 '0000-00-00 00:00:00' -show function status like 'db'; - -# root can, of course -call stamp(1); -select * from t1; -select db(); - -grant execute on procedure db1_secret.stamp to user1@'%'; -grant execute on function db1_secret.db to user1@'%'; -grant execute on procedure db1_secret.stamp to ''@'%'; -grant execute on function db1_secret.db to ''@'%'; - -connect (con2user1,localhost,user1,,); -connect (con3anon,localhost,anon,,); - - -# -# User1 can -# -connection con2user1; - -# This should work... -call db1_secret.stamp(2); -select db1_secret.db(); - -# ...but not this ---error ER_TABLEACCESS_DENIED_ERROR -select * from db1_secret.t1; - -# ...and not this ---error ER_DBACCESS_DENIED_ERROR -create procedure db1_secret.dummy() begin end; ---error ER_PROCACCESS_DENIED_ERROR -drop procedure db1_secret.dummy; ---error ER_PROCACCESS_DENIED_ERROR -drop procedure db1_secret.stamp; ---error ER_PROCACCESS_DENIED_ERROR -drop function db1_secret.db; - - -# -# Anonymous can -# -connection con3anon; - -# This should work... -call db1_secret.stamp(3); -select db1_secret.db(); - -# ...but not this ---error ER_TABLEACCESS_DENIED_ERROR -select * from db1_secret.t1; - -# ...and not this ---error ER_DBACCESS_DENIED_ERROR -create procedure db1_secret.dummy() begin end; ---error ER_PROCACCESS_DENIED_ERROR -drop procedure db1_secret.dummy; ---error ER_PROCACCESS_DENIED_ERROR -drop procedure db1_secret.stamp; ---error ER_PROCACCESS_DENIED_ERROR -drop function db1_secret.db; - - -# -# Check it out -# -connection con1root; -select * from t1; - -# -# Change to invoker's rights -# -alter procedure stamp sql security invoker; ---replace_column 5 '0000-00-00 00:00:00' 6 '0000-00-00 00:00:00' -show procedure status like 'stamp'; - -alter function db sql security invoker; ---replace_column 5 '0000-00-00 00:00:00' 6 '0000-00-00 00:00:00' -show function status like 'db'; - -# root still can -call stamp(4); -select * from t1; -select db(); - -# -# User1 cannot -# -connection con2user1; - -# This should not work ---error ER_TABLEACCESS_DENIED_ERROR -call db1_secret.stamp(5); ---error ER_TABLEACCESS_DENIED_ERROR -select db1_secret.db(); - -# -# Anonymous cannot -# -connection con3anon; - -# This should not work ---error ER_TABLEACCESS_DENIED_ERROR -call db1_secret.stamp(6); ---error ER_TABLEACCESS_DENIED_ERROR -select db1_secret.db(); - -# -# Bug#2777 Stored procedure doesn't observe definer's rights -# - -connection con1root; ---disable_warnings -drop database if exists db2; ---enable_warnings -create database db2; - -use db2; - -create table t2 (s1 int); -insert into t2 values (0); - -grant usage on db2.* to user1@localhost; -grant select on db2.* to user1@localhost; -grant usage on db2.* to user2@localhost; -grant select,insert,update,delete,create routine on db2.* to user2@localhost; -grant create routine on db2.* to user1@localhost; -flush privileges; - -connection con2user1; -use db2; - -create procedure p () insert into t2 values (1); - -# Check that this doesn't work. ---error ER_TABLEACCESS_DENIED_ERROR -call p(); - -connect (con4user2,localhost,user2,,); - -connection con4user2; -use db2; - -# This should not work, since p is executed with definer's (user1's) rights. ---error ER_PROCACCESS_DENIED_ERROR -call p(); -select * from t2; - -create procedure q () insert into t2 values (2); - -call q(); -select * from t2; - -connection con1root; -grant usage on procedure db2.q to user2@localhost with grant option; - -connection con4user2; -grant execute on procedure db2.q to user1@localhost; - -connection con2user1; -use db2; - -# This should work -call q(); -select * from t2; - -# -# Bug#6030 Stored procedure has no appropriate DROP privilege -# (or ALTER for that matter) - -# still connection con2user1 in db2 - -# This should work: -alter procedure p modifies sql data; -drop procedure p; - -# This should NOT work ---error ER_PROCACCESS_DENIED_ERROR -alter procedure q modifies sql data; ---error ER_PROCACCESS_DENIED_ERROR -drop procedure q; - -connection con1root; -use db2; -# But root always can -alter procedure q modifies sql data; -drop procedure q; - - -# Clean up -#Still connection con1root; -disconnect con2user1; -disconnect con3anon; -disconnect con4user2; -use test; -select type,db,name from mysql.proc where db like 'db%'; -drop database db1_secret; -drop database db2; -# Make sure the routines are gone -select type,db,name from mysql.proc where db like 'db%'; -# Get rid of the users -delete from mysql.user where user='user1' or user='user2'; -delete from mysql.user where user='' and host='%'; -# And any routine privileges -delete from mysql.procs_priv where user='user1' or user='user2'; -# Delete the grants to user ''@'%' that was created above -delete from mysql.procs_priv where user='' and host='%'; -delete from mysql.db where user='user2'; -flush privileges; -# -# Test the new security acls -# -grant usage on *.* to usera@localhost; -grant usage on *.* to userb@localhost; -grant usage on *.* to userc@localhost; -create database sptest; -create table t1 ( u varchar(64), i int ); -create procedure sptest.p1(i int) insert into test.t1 values (user(), i); -grant insert on t1 to usera@localhost; -grant execute on procedure sptest.p1 to usera@localhost; -show grants for usera@localhost; -grant execute on procedure sptest.p1 to userc@localhost with grant option; -show grants for userc@localhost; - -connect (con2usera,localhost,usera,,); -connect (con3userb,localhost,userb,,); -connect (con4userc,localhost,userc,,); - -connection con2usera; -call sptest.p1(1); ---error ER_PROCACCESS_DENIED_ERROR -grant execute on procedure sptest.p1 to userb@localhost; ---error ER_PROCACCESS_DENIED_ERROR -drop procedure sptest.p1; - -connection con3userb; ---error ER_PROCACCESS_DENIED_ERROR -call sptest.p1(2); ---error ER_PROCACCESS_DENIED_ERROR -grant execute on procedure sptest.p1 to userb@localhost; ---error ER_PROCACCESS_DENIED_ERROR -drop procedure sptest.p1; - -connection con4userc; -call sptest.p1(3); -grant execute on procedure sptest.p1 to userb@localhost; ---error ER_PROCACCESS_DENIED_ERROR -drop procedure sptest.p1; - -connection con3userb; -call sptest.p1(4); ---error ER_PROCACCESS_DENIED_ERROR -grant execute on procedure sptest.p1 to userb@localhost; ---error ER_PROCACCESS_DENIED_ERROR -drop procedure sptest.p1; - -connection con1root; -select * from t1; - -grant all privileges on procedure sptest.p1 to userc@localhost; -show grants for userc@localhost; -show grants for userb@localhost; - -connection con4userc; -revoke all privileges on procedure sptest.p1 from userb@localhost; - -connection con1root; -show grants for userb@localhost; - -#cleanup -disconnect con4userc; -disconnect con3userb; -disconnect con2usera; -use test; -drop database sptest; -delete from mysql.user where user='usera' or user='userb' or user='userc'; -delete from mysql.procs_priv where user='usera' or user='userb' or user='userc'; -delete from mysql.tables_priv where user='usera'; -flush privileges; -drop table t1; - -# -# Bug#9503 reseting correct parameters of thread after error in SP function -# -connect (root,localhost,root,,test); -connection root; - ---disable_warnings -drop function if exists bug_9503; ---enable_warnings -delimiter //; -create database mysqltest// -use mysqltest// -create table t1 (s1 int)// -grant select on t1 to user1@localhost// -create function bug_9503 () returns int sql security invoker begin declare v int; -select min(s1) into v from t1; return v; end// -delimiter ;// - -connect (user1,localhost,user1,,test); -connection user1; -use mysqltest; --- error ER_PROCACCESS_DENIED_ERROR -select bug_9503(); - -connection root; -grant execute on function bug_9503 to user1@localhost; - -connection user1; -do 1; -use test; - -disconnect user1; -connection root; -REVOKE ALL PRIVILEGES, GRANT OPTION FROM user1@localhost; -drop function bug_9503; -use test; -drop database mysqltest; -connection default; -disconnect root; - -# -# correct value from current_user() in function run from "security definer" -# (Bug#7291 Stored procedures: wrong CURRENT_USER value) -# -connection con1root; -use test; - -select current_user(); -select user(); -create procedure bug7291_0 () sql security invoker select current_user(), user(); -create procedure bug7291_1 () sql security definer call bug7291_0(); -create procedure bug7291_2 () sql security invoker call bug7291_0(); -grant execute on procedure bug7291_0 to user1@localhost; -grant execute on procedure bug7291_1 to user1@localhost; -grant execute on procedure bug7291_2 to user1@localhost; - -connect (user1,localhost,user1,,); -connection user1; - -call bug7291_2(); -call bug7291_1(); - -connection con1root; -drop procedure bug7291_1; -drop procedure bug7291_2; -drop procedure bug7291_0; -disconnect user1; -REVOKE ALL PRIVILEGES, GRANT OPTION FROM user1@localhost; -drop user user1@localhost; - -# -# Bug#12318 Wrong error message when accessing an inaccessible stored -# procedure in another database when the current database is -# information_schema. -# - ---disable_warnings -drop database if exists mysqltest_1; ---enable_warnings - -create database mysqltest_1; -delimiter //; -create procedure mysqltest_1.p1() -begin - select 1 from dual; -end// -delimiter ;// - -grant usage on *.* to mysqltest_1@localhost; - -connect (n1,localhost,mysqltest_1,,information_schema,$MASTER_MYPORT,$MASTER_MYSOCK); -connection n1; ---error ER_PROCACCESS_DENIED_ERROR -call mysqltest_1.p1(); -disconnect n1; -# Test also without a current database -connect (n2,localhost,mysqltest_1,,*NO-ONE*,$MASTER_MYPORT,$MASTER_MYSOCK); -connection n2; ---error ER_PROCACCESS_DENIED_ERROR -call mysqltest_1.p1(); -disconnect n2; - -connection default; - -drop procedure mysqltest_1.p1; -drop database mysqltest_1; - -revoke usage on *.* from mysqltest_1@localhost; -drop user mysqltest_1@localhost; - -# -# Bug#12812 create view calling a function works without execute right -# on function -delimiter |; ---disable_warnings -drop function if exists bug12812| ---enable_warnings -create function bug12812() returns char(2) -begin - return 'ok'; -end; -create user user_bug12812@localhost IDENTIFIED BY 'ABC'| ---replace_result $MASTER_MYPORT MYSQL_PORT $MASTER_MYSOCK MYSQL_SOCK -connect (test_user_12812,localhost,user_bug12812,ABC,test)| ---error ER_PROCACCESS_DENIED_ERROR -SELECT test.bug12812()| ---error ER_PROCACCESS_DENIED_ERROR -CREATE VIEW v1 AS SELECT test.bug12812()| -# Cleanup -connection default| -disconnect test_user_12812| -DROP USER user_bug12812@localhost| -drop function bug12812| -delimiter ;| - - -# -# Bug#14834 Server denies to execute Stored Procedure -# -# The problem here was with '_' in the database name. -# -create database db_bug14834; - -create user user1_bug14834@localhost identified by ''; -# The exact name of the database (no wildcard) -grant all on `db\_bug14834`.* to user1_bug14834@localhost; - -create user user2_bug14834@localhost identified by ''; -# The exact name of the database (no wildcard) -grant all on `db\_bug14834`.* to user2_bug14834@localhost; - -create user user3_bug14834@localhost identified by ''; -# Wildcards in the database name -grant all on `db__ug14834`.* to user3_bug14834@localhost; - -connect (user1_bug14834,localhost,user1_bug14834,,db_bug14834); -# Create the procedure and check that we can call it -create procedure p_bug14834() select user(), current_user(); -call p_bug14834(); - -connect (user2_bug14834,localhost,user2_bug14834,,db_bug14834); -# This didn't work before -call p_bug14834(); - -connect (user3_bug14834,localhost,user3_bug14834,,db_bug14834); -# Should also work -call p_bug14834(); - -# Cleanup -connection default; -disconnect user1_bug14834; -disconnect user2_bug14834; -disconnect user3_bug14834; -drop user user1_bug14834@localhost; -drop user user2_bug14834@localhost; -drop user user3_bug14834@localhost; -drop database db_bug14834; - - -# -# Bug#14533 'desc tbl' in stored procedure causes error -# ER_TABLEACCESS_DENIED_ERROR -# -create database db_bug14533; -use db_bug14533; -create table t1 (id int); -create user user_bug14533@localhost identified by ''; - -create procedure bug14533_1() - sql security definer - desc db_bug14533.t1; - -create procedure bug14533_2() - sql security definer - select * from db_bug14533.t1; - -grant execute on procedure db_bug14533.bug14533_1 to user_bug14533@localhost; -grant execute on procedure db_bug14533.bug14533_2 to user_bug14533@localhost; - -connect (user_bug14533,localhost,user_bug14533,,test); - -# These should work -call db_bug14533.bug14533_1(); -call db_bug14533.bug14533_2(); - -# For reference, these should not work ---error ER_TABLEACCESS_DENIED_ERROR -desc db_bug14533.t1; ---error ER_TABLEACCESS_DENIED_ERROR -select * from db_bug14533.t1; - -# Cleanup -connection default; -disconnect user_bug14533; -drop user user_bug14533@localhost; -drop database db_bug14533; - - -# -# WL#2897 Complete definer support in the stored routines. -# -# The following cases are tested: -# 1. check that if DEFINER-clause is not explicitly specified, stored routines -# are created with CURRENT_USER privileges; -# 2. check that if DEFINER-clause specifies non-current user, SUPER privilege -# is required to create a stored routine; -# 3. check that if DEFINER-clause specifies non-existent user, a warning is -# emitted. -# 4. check that SHOW CREATE PROCEDURE | FUNCTION works correctly; -# -# The following cases are tested in other test suites: -# - check that mysqldump dumps new attribute correctly; -# - check that slave replicates CREATE-statements with explicitly specified -# DEFINER correctly. -# - -# Setup the environment. - ---echo ---echo ---> connection: root ---connection con1root - ---disable_warnings -DROP DATABASE IF EXISTS mysqltest; ---enable_warnings - -CREATE DATABASE mysqltest; - -CREATE USER mysqltest_1@localhost; -GRANT ALL PRIVILEGES ON mysqltest.* TO mysqltest_1@localhost; - -CREATE USER mysqltest_2@localhost; -GRANT SUPER ON *.* TO mysqltest_2@localhost; -GRANT ALL PRIVILEGES ON mysqltest.* TO mysqltest_2@localhost; - ---connect (mysqltest_2_con,localhost,mysqltest_2,,mysqltest) ---connect (mysqltest_1_con,localhost,mysqltest_1,,mysqltest) - -# test case (1). - ---echo ---echo ---> connection: mysqltest_2_con ---connection mysqltest_2_con - -USE mysqltest; - -CREATE PROCEDURE wl2897_p1() SELECT 1; - -CREATE FUNCTION wl2897_f1() RETURNS INT RETURN 1; - -# test case (2). - ---echo ---echo ---> connection: mysqltest_1_con ---connection mysqltest_1_con - -USE mysqltest; - ---error ER_SPECIFIC_ACCESS_DENIED_ERROR -CREATE DEFINER=root@localhost PROCEDURE wl2897_p2() SELECT 2; - ---error ER_SPECIFIC_ACCESS_DENIED_ERROR -CREATE DEFINER=root@localhost FUNCTION wl2897_f2() RETURNS INT RETURN 2; - -# test case (3). - ---echo ---echo ---> connection: mysqltest_2_con ---connection mysqltest_2_con - -use mysqltest; - -CREATE DEFINER='a @ b @ c'@localhost PROCEDURE wl2897_p3() SELECT 3; - -CREATE DEFINER='a @ b @ c'@localhost FUNCTION wl2897_f3() RETURNS INT RETURN 3; - -# test case (4). - ---echo ---echo ---> connection: con1root ---connection con1root - -USE mysqltest; - -SHOW CREATE PROCEDURE wl2897_p1; -SHOW CREATE PROCEDURE wl2897_p3; - -SHOW CREATE FUNCTION wl2897_f1; -SHOW CREATE FUNCTION wl2897_f3; - -# Cleanup. - -DROP USER mysqltest_1@localhost; -DROP USER mysqltest_2@localhost; - -DROP DATABASE mysqltest; - ---disconnect mysqltest_1_con ---disconnect mysqltest_2_con - - -# -# Bug#13198 SP executes if definer does not exist -# - -# Prepare environment. - ---echo ---echo ---> connection: root ---connection con1root - ---disable_warnings -DROP DATABASE IF EXISTS mysqltest; ---enable_warnings - -CREATE DATABASE mysqltest; - -CREATE USER mysqltest_1@localhost; -GRANT ALL PRIVILEGES ON mysqltest.* TO mysqltest_1@localhost; - -CREATE USER mysqltest_2@localhost; -GRANT ALL PRIVILEGES ON mysqltest.* TO mysqltest_2@localhost; - ---connect (mysqltest_1_con,localhost,mysqltest_1,,mysqltest) ---connect (mysqltest_2_con,localhost,mysqltest_2,,mysqltest) - -# Create a procedure/function under u1. - ---echo ---echo ---> connection: mysqltest_1_con ---connection mysqltest_1_con - -USE mysqltest; - -CREATE PROCEDURE bug13198_p1() - SELECT 1; - -CREATE FUNCTION bug13198_f1() RETURNS INT - RETURN 1; - -CALL bug13198_p1(); - -SELECT bug13198_f1(); - -# Check that u2 can call the procedure/function. - ---echo ---echo ---> connection: mysqltest_2_con ---connection mysqltest_2_con - -USE mysqltest; - -CALL bug13198_p1(); - -SELECT bug13198_f1(); - -# Drop user u1 (definer of the object); - ---echo ---echo ---> connection: root ---connection con1root - ---disconnect mysqltest_1_con - -DROP USER mysqltest_1@localhost; - -# Check that u2 can not call the procedure/function. - ---echo ---echo ---> connection: mysqltest_2_con ---connection mysqltest_2_con - -USE mysqltest; - ---error ER_NO_SUCH_USER -CALL bug13198_p1(); - ---error ER_NO_SUCH_USER -SELECT bug13198_f1(); - -# Cleanup. - ---echo ---echo ---> connection: root ---connection con1root - ---disconnect mysqltest_2_con - -DROP USER mysqltest_2@localhost; - -DROP DATABASE mysqltest; - -# -# Bug#19857 When a user with CREATE ROUTINE priv creates a routine, -# it results in NULL p/w -# - -# Can't test with embedded server that doesn't support grants - -GRANT USAGE ON *.* TO user19857@localhost IDENTIFIED BY 'meow'; -GRANT SELECT, INSERT, UPDATE, DELETE, CREATE ROUTINE, ALTER ROUTINE ON test.* TO -user19857@localhost; -SELECT Host,User,Password FROM mysql.user WHERE User='user19857'; - ---connect (mysqltest_2_con,localhost,user19857,meow,test) ---echo ---echo ---> connection: mysqltest_2_con ---connection mysqltest_2_con - -USE test; - -DELIMITER //; - CREATE PROCEDURE sp19857() DETERMINISTIC - BEGIN - DECLARE a INT; - SET a=1; - SELECT a; - END // -DELIMITER ;// - -SHOW CREATE PROCEDURE test.sp19857; - ---disconnect mysqltest_2_con ---connect (mysqltest_2_con,localhost,user19857,meow,test) ---connection mysqltest_2_con - -DROP PROCEDURE IF EXISTS test.sp19857; - ---echo ---echo ---> connection: root ---connection con1root - ---disconnect mysqltest_2_con - -SELECT Host,User,Password FROM mysql.user WHERE User='user19857'; - -DROP USER user19857@localhost; - ---disconnect con1root ---connection default -use test; - -# -# Bug#18630 Arguments of suid routine calculated in wrong security context -# -# Arguments of suid routines were calculated in definer's security -# context instead of caller's context thus creating security hole. -# ---disable_warnings -DROP TABLE IF EXISTS t1; -DROP VIEW IF EXISTS v1; -DROP FUNCTION IF EXISTS f_suid; -DROP PROCEDURE IF EXISTS p_suid; -DROP FUNCTION IF EXISTS f_evil; ---enable_warnings -DELETE FROM mysql.user WHERE user LIKE 'mysqltest\_%'; -DELETE FROM mysql.db WHERE user LIKE 'mysqltest\_%'; -DELETE FROM mysql.tables_priv WHERE user LIKE 'mysqltest\_%'; -DELETE FROM mysql.columns_priv WHERE user LIKE 'mysqltest\_%'; -FLUSH PRIVILEGES; - -CREATE TABLE t1 (i INT); -CREATE FUNCTION f_suid(i INT) RETURNS INT SQL SECURITY DEFINER RETURN 0; -CREATE PROCEDURE p_suid(IN i INT) SQL SECURITY DEFINER SET @c:= 0; - -CREATE USER mysqltest_u1@localhost; -# Thanks to this grant statement privileges of anonymous users on -# 'test' database are not applicable for mysqltest_u1@localhost. -GRANT EXECUTE ON test.* TO mysqltest_u1@localhost; - -delimiter |; -CREATE DEFINER=mysqltest_u1@localhost FUNCTION f_evil () RETURNS INT - SQL SECURITY INVOKER -BEGIN - SET @a:= CURRENT_USER(); - SET @b:= (SELECT COUNT(*) FROM t1); - RETURN @b; -END| -delimiter ;| - -CREATE SQL SECURITY INVOKER VIEW v1 AS SELECT f_evil(); - -connect (conn1, localhost, mysqltest_u1,,); - ---error ER_TABLEACCESS_DENIED_ERROR -SELECT COUNT(*) FROM t1; - ---error ER_TABLEACCESS_DENIED_ERROR -SELECT f_evil(); -SELECT @a, @b; - ---error ER_TABLEACCESS_DENIED_ERROR -SELECT f_suid(f_evil()); -SELECT @a, @b; - ---error ER_TABLEACCESS_DENIED_ERROR -CALL p_suid(f_evil()); -SELECT @a, @b; - ---error ER_TABLEACCESS_DENIED_ERROR -SELECT * FROM v1; -SELECT @a, @b; - -disconnect conn1; -connection default; - -DROP VIEW v1; -DROP FUNCTION f_evil; -DROP USER mysqltest_u1@localhost; -DROP PROCEDURE p_suid; -DROP FUNCTION f_suid; -DROP TABLE t1; - ---echo # ---echo # Bug #48872 : Privileges for stored functions ignored if function name ---echo # is mixed case ---echo # - -CREATE DATABASE B48872; -USE B48872; -CREATE TABLE `TestTab` (id INT); -INSERT INTO `TestTab` VALUES (1),(2); -CREATE FUNCTION `f_Test`() RETURNS INT RETURN 123; -CREATE FUNCTION `f_Test_denied`() RETURNS INT RETURN 123; -CREATE USER 'tester'; -CREATE USER 'Tester'; -GRANT SELECT ON TABLE `TestTab` TO 'tester'; -GRANT EXECUTE ON FUNCTION `f_Test` TO 'tester'; -GRANT EXECUTE ON FUNCTION `f_Test_denied` TO 'Tester'; - -SELECT f_Test(); -SELECT * FROM TestTab; - -CONNECT (con_tester,localhost,tester,,B48872); -CONNECT (con_tester_denied,localhost,Tester,,B48872); -CONNECTION con_tester; - -SELECT * FROM TestTab; -SELECT `f_Test`(); -SELECT `F_TEST`(); -SELECT f_Test(); -SELECT F_TEST(); - -CONNECTION con_tester_denied; - ---disable_result_log ---error ER_TABLEACCESS_DENIED_ERROR -SELECT * FROM TestTab; ---error ER_PROCACCESS_DENIED_ERROR -SELECT `f_Test`(); ---error ER_PROCACCESS_DENIED_ERROR -SELECT `F_TEST`(); ---error ER_PROCACCESS_DENIED_ERROR -SELECT f_Test(); ---error ER_PROCACCESS_DENIED_ERROR -SELECT F_TEST(); ---enable_result_log -SELECT `f_Test_denied`(); -SELECT `F_TEST_DENIED`(); - -CONNECTION default; -DISCONNECT con_tester; -DISCONNECT con_tester_denied; -DROP TABLE `TestTab`; -DROP FUNCTION `f_Test`; -DROP FUNCTION `f_Test_denied`; - -USE test; -DROP USER 'tester'; -DROP USER 'Tester'; -DROP DATABASE B48872; - ---echo End of 5.0 tests. - - ---echo # ---echo # Test for bug#57061 "User without privilege on routine can discover ---echo # its existence." ---echo # ---disable_warnings -drop database if exists mysqltest_db; ---enable_warnings -create database mysqltest_db; ---echo # Create user with no privileges on mysqltest_db database. -create user bug57061_user@localhost; -create function mysqltest_db.f1() returns int return 0; -create procedure mysqltest_db.p1() begin end; ---echo # Connect as user 'bug57061_user@localhost' -connect (conn1, localhost, bug57061_user,,); ---echo # Attempt to drop routine on which user doesn't have privileges ---echo # should result in the same 'access denied' type of error whether ---echo # routine exists or not. ---error ER_PROCACCESS_DENIED_ERROR -drop function if exists mysqltest_db.f_does_not_exist; ---error ER_PROCACCESS_DENIED_ERROR -drop procedure if exists mysqltest_db.p_does_not_exist; ---error ER_PROCACCESS_DENIED_ERROR -drop function if exists mysqltest_db.f1; ---error ER_PROCACCESS_DENIED_ERROR -drop procedure if exists mysqltest_db.p1; ---echo # Connection 'default'. -connection default; -disconnect conn1; -drop user bug57061_user@localhost; -drop database mysqltest_db; - - ---echo # ---echo # Bug#11882603 SELECT_ACL ON ANY COLUMN IN MYSQL.PROC ALLOWS TO SEE ---echo # DEFINITION OF ANY ROUTINE. ---echo # - ---disable_warnings -DROP DATABASE IF EXISTS db1; ---enable_warnings - -CREATE DATABASE db1; -CREATE PROCEDURE db1.p1() SELECT 1; -CREATE USER user2@localhost IDENTIFIED BY ''; -GRANT SELECT(db) ON mysql.proc TO user2@localhost; - ---echo # Connection con2 as user2 -connect (con2, localhost, user2); ---echo # The statement below before disclosed info from body_utf8 column. ---error ER_SP_DOES_NOT_EXIST -SHOW CREATE PROCEDURE db1.p1; - ---echo # Check that SHOW works with SELECT grant on whole table ---echo # Connection default -connection default; -GRANT SELECT ON mysql.proc TO user2@localhost; - ---echo # Connection con2 -connection con2; ---echo # This should work -SHOW CREATE PROCEDURE db1.p1; - ---echo # Connection default -connection default; -disconnect con2; -DROP USER user2@localhost; -DROP DATABASE db1; - -# -# Bug#27407480: AUTOMATIC_SP_PRIVILEGES REQUIRES NEED THE INSERT PRIVILEGES FOR MYSQL.USER TABLE -# -create user foo@local_ost; -# -# Create a user with an authentification plugin 'foobar'. -# Instead of using a normal "CREATE USER <user> IDENTIFIED VIA <plugin>" -# we do CREATE (without VIA) followed by UPDATE and FLUSH. -# This is to avoid installing a real plugin and thus avoid the test dependency. -# We won't login under this user in the below test, so this is fine. -# -create user foo@`local\_ost`; -update mysql.user set plugin='foobar' where host='local\\_ost'; -flush privileges; -create database foodb; -grant create routine on foodb.* to foo@local_ost; -connect con1,localhost,foo; -select user(), current_user(); -show grants; -create procedure fooproc() select 'i am fooproc'; -show grants; -disconnect con1; -connection default; -drop user foo@local_ost; -drop user foo@`local\_ost`; -drop procedure fooproc; -drop database foodb; - ---echo # ---echo # Test for bug#12602983 - User without privilege on routine can discover ---echo # its existence by executing "select non_existing_func();" or by ---echo # "call non_existing_proc()"; ---echo # ---disable_warnings -drop database if exists mysqltest_db; ---enable_warnings -create database mysqltest_db; -create function mysqltest_db.f1() returns int return 0; -create procedure mysqltest_db.p1() begin end; - ---echo # Create user with no privileges on mysqltest_db database. -create user bug12602983_user@localhost; - ---echo # Connect as user 'bug12602983_user@localhost' -connect (conn1, localhost, bug12602983_user,,); - ---echo # Attempt to execute routine on which user doesn't have privileges ---echo # should result in the same 'access denied' error whether ---echo # routine exists or not. ---error ER_PROCACCESS_DENIED_ERROR -select mysqltest_db.f_does_not_exist(); ---error ER_PROCACCESS_DENIED_ERROR -call mysqltest_db.p_does_not_exist(); - ---error ER_PROCACCESS_DENIED_ERROR -select mysqltest_db.f1(); ---error ER_PROCACCESS_DENIED_ERROR -call mysqltest_db.p1(); - ---error ER_PROCACCESS_DENIED_ERROR -create view bug12602983_v1 as select mysqltest_db.f_does_not_exist(); ---error ER_PROCACCESS_DENIED_ERROR -create view bug12602983_v1 as select mysqltest_db.f1(); - ---echo # Connection 'default'. -connection default; -disconnect conn1; -drop user bug12602983_user@localhost; -drop database mysqltest_db; - -# Wait till all disconnects are completed ---source include/wait_until_count_sessions.inc diff --git a/mysql-test/r/subselect2.result b/mysql-test/r/subselect2.result index b8295416e93..9de9d34a2f9 100644 --- a/mysql-test/r/subselect2.result +++ b/mysql-test/r/subselect2.result @@ -394,3 +394,25 @@ select null in (select a from t1 where a < out3.a union select a from t2 where (select a from t3) +1 < out3.a+1) from t3 out3; ERROR 21000: Subquery returns more than 1 row drop table t1, t2, t3; +CREATE TABLE t1( +q11 int, q12 int, q13 int, q14 int, q15 int, q16 int, q17 int, q18 int, q19 int, +q21 int, q22 int, q23 int, q24 int, q25 int, q26 int, q27 int, q28 int, q29 int, +f1 int +); +CREATE TABLE t2(f2 int, f21 int, f3 timestamp, f4 int, f5 int, f6 int); +INSERT INTO t1 (f1) VALUES (1),(1),(2),(2); +INSERT INTO t2 VALUES (1,1,"2004-02-29 11:11:11",0,0,0), (2,2,"2004-02-29 11:11:11",0,0,0); +SELECT f1, +(SELECT t.f21 from t2 t where max( +q11+q12+q13+q14+q15+q16+q17+q18+q19+ +q21+q22+q23+q24+q25+q26+q27+q28+q29) = t.f2 UNION +SELECT t.f3 FROM t2 AS t WHERE t1.f1=t.f2 AND t.f3=MAX(t1.f1) UNION +SELECT 1 LIMIT 1) AS test +FROM t1 GROUP BY f1; +f1 test +1 1 +2 1 +Warnings: +Warning 1292 Incorrect datetime value: '1' +Warning 1292 Incorrect datetime value: '2' +DROP TABLE t1,t2; diff --git a/mysql-test/r/subselect_mat.result b/mysql-test/r/subselect_mat.result index bc223158eb6..993d7f0f003 100644 --- a/mysql-test/r/subselect_mat.result +++ b/mysql-test/r/subselect_mat.result @@ -2865,6 +2865,22 @@ SELECT * FROM t2 WHERE f IN ( SELECT LEFT('foo',0) FROM t1 ORDER BY 1 ); f DROP TABLE t1, t2; # +# MDEV-18255: Server crashes in Bitmap<64u>::intersect +# +create table t1 (v1 varchar(1)) engine=myisam ; +create table t2 (v1 varchar(1)) engine=myisam ; +explain +select 1 from t1 where exists +(select 1 from t1 where t1.v1 in (select t2.v1 from t2 having t2.v1 < 'j')) ; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE +2 SUBQUERY NULL NULL NULL NULL NULL NULL NULL no matching row in const table +3 MATERIALIZED NULL NULL NULL NULL NULL NULL NULL no matching row in const table +select 1 from t1 where exists +(select 1 from t1 where t1.v1 in (select t2.v1 from t2 having t2.v1 < 'j')) ; +1 +drop table t1,t2; +# # MDEV-9489: Assertion `0' failed in Protocol::end_statement() on # UNION ALL # diff --git a/mysql-test/r/type_float.test b/mysql-test/r/type_float.test deleted file mode 100644 index 5dfb4a75bb3..00000000000 --- a/mysql-test/r/type_float.test +++ /dev/null @@ -1,417 +0,0 @@ -# Description -# ----------- -# Numeric floating point. - ---disable_warnings -drop table if exists t1,t2; ---enable_warnings - -SELECT 10,10.0,10.,.1e+2,100.0e-1; -SELECT 6e-16, -6e-16, --6e-16, -6e-16+1.000000; -SELECT 1e1,1.e1,1.0e1,1e+1,1.e+1,1.0e+1,1e-1,1.e-1,1.0e-1; -SELECT 0.001e+1,0.001e-1, -0.001e+01,-0.001e-01; -SELECT 123.23E+02,-123.23E-02,"123.23E+02"+0.0,"-123.23E-02"+0.0; -SELECT 2147483647E+02,21474836.47E+06; - -create table t1 (f1 float(24),f2 float(52)); -# We mask out Privileges column because it differs for embedded server ---replace_column 8 # -show full columns from t1; -insert into t1 values(10,10),(1e+5,1e+5),(1234567890,1234567890),(1e+10,1e+10),(1e+15,1e+15),(1e+20,1e+20),(1e+50,1e+50),(1e+150,1e+150); -insert into t1 values(-10,-10),(1e-5,1e-5),(1e-10,1e-10),(1e-15,1e-15),(1e-20,1e-20),(1e-50,1e-50),(1e-150,1e-150); -select * from t1; -drop table t1; - -create table t1 (datum double); -insert into t1 values (0.5),(1.0),(1.5),(2.0),(2.5); -select * from t1; -select * from t1 where datum < 1.5; -select * from t1 where datum > 1.5; -select * from t1 where datum = 1.5; -drop table t1; - -create table t1 (a decimal(7,3) not null, key (a)); -insert into t1 values ("0"),("-0.00"),("-0.01"),("-0.002"),("1"); -select a from t1 order by a; -select min(a) from t1; -drop table t1; - -# -# BUG#3612, BUG#4393, BUG#4356, BUG#4394 -# - -create table t1 (c1 double, c2 varchar(20)); -insert t1 values (121,"16"); -select c1 + c1 * (c2 / 100) as col from t1; -create table t2 select c1 + c1 * (c2 / 100) as col1, round(c1, 5) as col2, round(c1, 35) as col3, sqrt(c1*1e-15) col4 from t1; -# Floats are a bit different in PS ---disable_ps_protocol -select * from t2; ---enable_ps_protocol -show create table t2; -drop table t1,t2; - -# Bug #1022: When a table contains a 'float' field, -# and one of the functions MAX, MIN, or AVG is used on that field, -# the system crashes. - -create table t1 (a float); -insert into t1 values (1); -select max(a),min(a),avg(a) from t1; -drop table t1; - -# -# FLOAT/DOUBLE/DECIMAL handling -# - -create table t1 (f float, f2 float(24), f3 float(6,2), d double, d2 float(53), d3 double(10,3), de decimal, de2 decimal(6), de3 decimal(5,2), n numeric, n2 numeric(8), n3 numeric(7,6)); -# We mask out Privileges column because it differs for embedded server ---replace_column 8 # -show full columns from t1; -drop table t1; - -create table t1 (a decimal(7,3) not null, key (a)); -insert into t1 values ("0"),("-0.00"),("-0.01"),("-0.002"),("1"); -select a from t1 order by a; -select min(a) from t1; -drop table t1; - ---error 1425 -create table t1 (a float(200,100), b double(200,100)); - -# -# float in a char(1) field -# -create table t1 (c20 char); -insert into t1 values (5000.0); -insert into t1 values (0.5e4); -drop table t1; - -# Errors - ---error 1063 -create table t1 (f float(54)); # Should give an error ---disable_warnings -drop table if exists t1; ---enable_warnings - -# Don't allow 'double unsigned' to be set to a negative value (Bug #7700) -create table t1 (d1 double, d2 double unsigned); -insert into t1 set d1 = -1.0; -update t1 set d2 = d1; -select * from t1; -drop table t1; - -# Ensure that maximum values as the result of number of decimals -# being specified in table schema are enforced (Bug #7361) -create table t1 (f float(4,3)); -insert into t1 values (-11.0),(-11),("-11"),(11.0),(11),("11"); -select * from t1; -drop table if exists t1; -create table t1 (f double(4,3)); -insert into t1 values (-11.0),(-11),("-11"),(11.0),(11),("11"); -select * from t1; -drop table if exists t1; - -# Check conversion of floats to character field (Bug #7774) -create table t1 (c char(20)); -insert into t1 values (5e-28); -select * from t1; -drop table t1; -create table t1 (c char(6)); -insert into t1 values (2e5),(2e6),(2e-4),(2e-5); -select * from t1; -drop table t1; - -# -# Test of comparison of integer with float-in-range (Bug #7840) -# This is needed because some ODBC applications (like Foxpro) uses -# floats for everything. -# - -CREATE TABLE t1 ( - reckey int unsigned NOT NULL, - recdesc varchar(50) NOT NULL, - PRIMARY KEY (reckey) -) ENGINE=MyISAM DEFAULT CHARSET=latin1; - -INSERT INTO t1 VALUES (108, 'Has 108 as key'); -INSERT INTO t1 VALUES (109, 'Has 109 as key'); -select * from t1 where reckey=108; -select * from t1 where reckey=1.08E2; -select * from t1 where reckey=109; -select * from t1 where reckey=1.09E2; -drop table t1; - -# -# Bug #13372 (decimal union) -# -create table t1 (d double(10,1)); -create table t2 (d double(10,9)); -insert into t1 values ("100000000.0"); -insert into t2 values ("1.23456780"); -create table t3 select * from t2 union select * from t1; -select * from t3; -show create table t3; -drop table t1, t2, t3; - - -# -# Bug #9855 (inconsistent column type for create select -# -create table t1 select 105213674794682365.00 + 0.0 x; -show warnings; -desc t1; -drop table t1; - -create table t1 select 0.0 x; -desc t1; -create table t2 select 105213674794682365.00 y; -desc t2; -create table t3 select x+y a from t1,t2; -show warnings; -desc t3; -drop table t1,t2,t3; - -# -# Bug #22129: A small double precision number becomes zero -# -# check if underflows are detected correctly -select 1e-308, 1.00000001e-300, 100000000e-300; - -# check if overflows are detected correctly -select 10e307; - -# -# Bug #19690: ORDER BY eliminates rows from the result -# -create table t1(a int, b double(8, 2)); -insert into t1 values -(1, 28.50), (1, 121.85), (1, 157.23), (1, 1351.00), (1, -1965.35), (1, 81.75), -(1, 217.08), (1, 7.94), (4, 96.07), (4, 6404.65), (4, -6500.72), (2, 100.00), -(5, 5.00), (5, -2104.80), (5, 2033.80), (5, 0.07), (5, 65.93), -(3, -4986.24), (3, 5.00), (3, 4857.34), (3, 123.74), (3, 0.16), -(6, -1695.31), (6, 1003.77), (6, 499.72), (6, 191.82); -explain select sum(b) s from t1 group by a; -select sum(b) s from t1 group by a; -select sum(b) s from t1 group by a having s <> 0; -select sum(b) s from t1 group by a having s <> 0 order by s; -select sum(b) s from t1 group by a having s <=> 0; -select sum(b) s from t1 group by a having s <=> 0 order by s; -alter table t1 add key (a, b); -explain select sum(b) s from t1 group by a; -select sum(b) s from t1 group by a; -select sum(b) s from t1 group by a having s <> 0; -select sum(b) s from t1 group by a having s <> 0 order by s; -select sum(b) s from t1 group by a having s <=> 0; -select sum(b) s from t1 group by a having s <=> 0 order by s; -drop table t1; - ---echo End of 4.1 tests - -# -# bug #12694 (float(m,d) specifications) -# - ---error 1427 -create table t1 (s1 float(0,2)); ---error 1427 -create table t1 (s1 float(1,2)); - -# -# MySQL Bugs: #11589: mysqltest --ps-protocol, strange output, float/double/real with zerofill -# - -CREATE TABLE t1 ( - f1 real zerofill, - f2 double zerofill, - f3 float zerofill); -INSERT INTO t1 VALUES ( 0.314152e+1, 0.314152e+1, 0.314152e+1); - -let $my_stmt= select f1, f2, f3 FROM t1; -eval PREPARE stmt1 FROM '$my_stmt'; -select f1, f2, f3 FROM t1; -eval $my_stmt; -EXECUTE stmt1; - -DROP TABLE t1; -# Bug #28121 "INSERT or UPDATE into DOUBLE(200,0) field being truncated to 31 digits" -# - -create table t1 (f1 double(200, 0)); -insert into t1 values (1e199), (-1e199); -insert into t1 values (1e200), (-1e200); -insert into t1 values (2e200), (-2e200); -select f1 + 0e0 from t1; -drop table t1; - -create table t1 (f1 float(30, 0)); -insert into t1 values (1e29), (-1e29); -insert into t1 values (1e30), (-1e30); -insert into t1 values (2e30), (-2e30); -select f1 + 0e0 from t1; -drop table t1; - -# -# Bug #12860 "Difference in zero padding of exponent between Unix and Windows" -# - -create table t1 (c char(6)); -insert into t1 values (2e6),(2e-5); -select * from t1; -drop table t1; - -# -# Bug #21497 "DOUBLE truncated to unusable value" -# - -CREATE TABLE d1 (d DOUBLE); -INSERT INTO d1 VALUES (1.7976931348623157E+308); -SELECT * FROM d1; ---error ER_ILLEGAL_VALUE_FOR_TYPE -INSERT INTO d1 VALUES (1.79769313486232e+308); -SELECT * FROM d1; -DROP TABLE d1; - -# -# Bug #26788 "mysqld (debug) aborts when inserting specific numbers into char -# fields" -# - -create table t1 (a char(20)); -insert into t1 values (1.225e-05); -select a+0 from t1; -drop table t1; - -# -# Bug #27483: Casting 'scientific notation type' to 'unsigned bigint' fails on -# windows. -# - -create table t1(d double, u bigint unsigned); - -insert into t1(d) values (9.22337203685479e18), - (1.84e19); - -update t1 set u = d; -select u from t1; - -drop table t1; - -# -# Bug #21205: Different number of digits for float/doble/real in --ps-protocol -# - -CREATE TABLE t1 (f1 DOUBLE); -INSERT INTO t1 VALUES(-1.79769313486231e+308); -SELECT f1 FROM t1; -DROP TABLE t1; - ---echo # ---echo # Bug#12406055 BUFFER OVERFLOW OF VARIABLE 'BUFF' IN STRING::SET_REAL ---echo # - ---echo # Ignoring output from misc. float operations ---disable_result_log - -let $nine_65= -99999999999999999999999999999999999999999999999999999999999999999; - -select format(-1.7976931348623157E+307,256) as foo; -select least(-1.1111111111111111111111111, - - group_concat(1.7976931348623157E+308)) as foo; -eval select concat((truncate((-1.7976931348623157E+307),(0x1e))), - ($nine_65)) into @a; ---enable_result_log - ---echo End of 5.0 tests - ---echo # ---echo # Bug#12368853 FORMAT() CRASHES WITH LARGE NUMBERS AFTER TRUNCATE... ---echo # - -select format(truncate('1.7976931348623157E+308',-12),1,'fr_BE') as foo; - - ---echo # ---echo # MDEV-17249 MAKETIME(-1e50,0,0) returns a wrong result ---echo # - -SELECT LEFT('a',EXP(50)); -SELECT LEFT('a', COALESCE(1e30)); - -CREATE TABLE t1 (a FLOAT); -INSERT INTO t1 VALUES (1e30); -SELECT LEFT('a',a), LEFT('a',1e30) FROM t1; -DROP TABLE t1; - -PREPARE stmt FROM 'SELECT LEFT(111,?)'; -SET @a=1e30; -EXECUTE stmt USING @a; -DEALLOCATE PREPARE stmt; - -CREATE TABLE t1 (a INT); -INSERT INTO t1 VALUES (1),(2),(3); -SELECT LEFT('a',(SELECT 1e30 FROM t1 LIMIT 1)); -DROP TABLE t1; - -CREATE TABLE t1 (a DOUBLE); -INSERT INTO t1 VALUES (1e30),(0); -SELECT LEFT('a', SUM(a)) FROM t1; -SELECT LEFT('a', AVG(a)) FROM t1; -DROP TABLE t1; - - ---echo # ---echo # Bug #13500371 63704: CONVERSION OF '1.' TO A NUMBER GIVES ERROR 1265 ---echo # (WARN_DATA_TRUNCATED) ---echo # - -CREATE TABLE t1 (f FLOAT); -INSERT INTO t1 VALUES ('1.'); -INSERT INTO t1 VALUES ('2.0.'); -INSERT INTO t1 VALUES ('.'); -SELECT * FROM t1 ORDER BY f; -DROP TABLE t1; - - ---echo # ---echo # Start of 10.0 tests ---echo # - ---echo # ---echo # MDEV-6950 Bad results with joins comparing DATE/DATETIME and INT/DECIMAL/DOUBLE/ENUM/VARCHAR columns ---echo # -CREATE TABLE t1 (a DATETIME PRIMARY KEY); -INSERT INTO t1 VALUES ('1999-01-01 00:00:00'); -CREATE TABLE t2 (a DOUBLE); -INSERT INTO t2 VALUES (19990101000000); -INSERT INTO t2 VALUES (990101000000); -SELECT t1.* FROM t1,t2 WHERE t1.a=t2.a; -SELECT t1.* FROM t1 LEFT JOIN t2 ON t1.a=t2.a; -ALTER TABLE t2 ADD PRIMARY KEY(a); -SELECT t1.* FROM t1,t2 WHERE t1.a=t2.a; -SELECT t1.* FROM t1 LEFT JOIN t2 ON t1.a=t2.a; ---echo # t2 should NOT be eliminated -EXPLAIN SELECT t1.* FROM t1 LEFT JOIN t2 ON t1.a=t2.a; -DROP TABLE t1,t2; - ---echo # ---echo # MDEV-6971 Bad results with joins comparing TIME and DOUBLE/DECIMAL columns ---echo # -CREATE TABLE t1 (a TIME(6) PRIMARY KEY); -INSERT INTO t1 VALUES ('10:20:30'); -CREATE TABLE t2 (a DOUBLE); -INSERT INTO t2 VALUES (102030),(102030.000000001); -SELECT t1.* FROM t1 JOIN t2 USING(a); -SELECT t1.* FROM t1 LEFT JOIN t2 USING(a); -ALTER TABLE t2 ADD PRIMARY KEY(a); -SELECT t1.* FROM t1 JOIN t2 USING(a); -SELECT t1.* FROM t1 LEFT JOIN t2 USING(a); ---echo # t2 should NOT be elimitated -EXPLAIN SELECT t1.* FROM t1 LEFT JOIN t2 USING(a); -DROP TABLE t1,t2; - ---echo # ---echo # End of 10.0 tests ---echo # diff --git a/mysql-test/suite/innodb/r/alter_foreign_crash.result b/mysql-test/suite/innodb/r/alter_foreign_crash.result index 66ffb5f5411..34577ecf0fd 100644 --- a/mysql-test/suite/innodb/r/alter_foreign_crash.result +++ b/mysql-test/suite/innodb/r/alter_foreign_crash.result @@ -21,6 +21,6 @@ Tables_in_bug parent alter table parent row_format=dynamic; Warnings: -Warning 1088 InnoDB: Could not add foreign key constraints. +Warning 1088 failed to load FOREIGN KEY constraints drop table parent; drop database bug; diff --git a/mysql-test/suite/innodb/r/foreign_key.result b/mysql-test/suite/innodb/r/foreign_key.result index 7195f3e7c3f..c4c7fd6990e 100644 --- a/mysql-test/suite/innodb/r/foreign_key.result +++ b/mysql-test/suite/innodb/r/foreign_key.result @@ -206,6 +206,39 @@ connection default; ERROR 70100: Query execution was interrupted disconnect fk; DROP TABLE t3,t1; +# +# MDEV-18222 InnoDB: Failing assertion: heap->magic_n == MEM_BLOCK_MAGIC_N +# or ASAN heap-use-after-free in dict_foreign_remove_from_cache upon CHANGE COLUMN +# +CREATE TABLE t1 (a INT, UNIQUE(a), KEY(a)) ENGINE=InnoDB; +ALTER TABLE t1 ADD FOREIGN KEY (a) REFERENCES t1 (a); +SET SESSION FOREIGN_KEY_CHECKS = OFF; +ALTER TABLE t1 CHANGE COLUMN a a TIME NOT NULL; +ALTER TABLE t1 ADD pk INT NOT NULL AUTO_INCREMENT PRIMARY KEY; +ALTER TABLE t1 CHANGE COLUMN a b TIME; +SET SESSION FOREIGN_KEY_CHECKS = ON; +DROP TABLE t1; +# +# MDEV-18256 InnoDB: Failing assertion: heap->magic_n == MEM_BLOCK_MAGIC_N +# upon DROP FOREIGN KEY +# +CREATE TABLE t1 (a INT PRIMARY KEY) ENGINE=InnoDB; +CREATE TABLE t2 (b INT PRIMARY KEY, FOREIGN KEY fk1 (b) REFERENCES t1 (a)) +ENGINE=InnoDB; +ALTER TABLE t2 DROP FOREIGN KEY fk1, DROP FOREIGN KEY fk1; +DROP TABLE t2, t1; +CREATE TABLE t1 (f VARCHAR(256)) ENGINE=InnoDB; +SET SESSION FOREIGN_KEY_CHECKS = OFF; +ALTER TABLE t1 ADD FOREIGN KEY (f) REFERENCES non_existing_table (x); +SET SESSION FOREIGN_KEY_CHECKS = ON; +ALTER TABLE t1 ADD FULLTEXT INDEX ft1 (f); +Warnings: +Warning 124 InnoDB rebuilding table to add column FTS_DOC_ID +Warning 1088 failed to load FOREIGN KEY constraints +ALTER TABLE t1 ADD FULLTEXT INDEX ft2 (f); +Warnings: +Warning 1088 failed to load FOREIGN KEY constraints +DROP TABLE t1; # Start of 10.2 tests # # MDEV-13246 Stale rows despite ON DELETE CASCADE constraint diff --git a/mysql-test/suite/innodb/t/foreign_key.test b/mysql-test/suite/innodb/t/foreign_key.test index 6e8658c4e3e..773fa71761b 100644 --- a/mysql-test/suite/innodb/t/foreign_key.test +++ b/mysql-test/suite/innodb/t/foreign_key.test @@ -191,6 +191,37 @@ disconnect fk; DROP TABLE t3,t1; +--echo # +--echo # MDEV-18222 InnoDB: Failing assertion: heap->magic_n == MEM_BLOCK_MAGIC_N +--echo # or ASAN heap-use-after-free in dict_foreign_remove_from_cache upon CHANGE COLUMN +--echo # +CREATE TABLE t1 (a INT, UNIQUE(a), KEY(a)) ENGINE=InnoDB; +ALTER TABLE t1 ADD FOREIGN KEY (a) REFERENCES t1 (a); +SET SESSION FOREIGN_KEY_CHECKS = OFF; +ALTER TABLE t1 CHANGE COLUMN a a TIME NOT NULL; +ALTER TABLE t1 ADD pk INT NOT NULL AUTO_INCREMENT PRIMARY KEY; +ALTER TABLE t1 CHANGE COLUMN a b TIME; +SET SESSION FOREIGN_KEY_CHECKS = ON; +DROP TABLE t1; + +--echo # +--echo # MDEV-18256 InnoDB: Failing assertion: heap->magic_n == MEM_BLOCK_MAGIC_N +--echo # upon DROP FOREIGN KEY +--echo # +CREATE TABLE t1 (a INT PRIMARY KEY) ENGINE=InnoDB; +CREATE TABLE t2 (b INT PRIMARY KEY, FOREIGN KEY fk1 (b) REFERENCES t1 (a)) +ENGINE=InnoDB; +ALTER TABLE t2 DROP FOREIGN KEY fk1, DROP FOREIGN KEY fk1; +DROP TABLE t2, t1; + +CREATE TABLE t1 (f VARCHAR(256)) ENGINE=InnoDB; +SET SESSION FOREIGN_KEY_CHECKS = OFF; +ALTER TABLE t1 ADD FOREIGN KEY (f) REFERENCES non_existing_table (x); +SET SESSION FOREIGN_KEY_CHECKS = ON; +ALTER TABLE t1 ADD FULLTEXT INDEX ft1 (f); +ALTER TABLE t1 ADD FULLTEXT INDEX ft2 (f); +DROP TABLE t1; + --echo # Start of 10.2 tests --echo # diff --git a/mysql-test/suite/perfschema/r/dml_setup_instruments.result b/mysql-test/suite/perfschema/r/dml_setup_instruments.result index 4c123663597..10d576a0583 100644 --- a/mysql-test/suite/perfschema/r/dml_setup_instruments.result +++ b/mysql-test/suite/perfschema/r/dml_setup_instruments.result @@ -16,7 +16,9 @@ wait/synch/mutex/sql/LOCK_audit_mask YES YES wait/synch/mutex/sql/LOCK_binlog_state YES YES select * from performance_schema.setup_instruments where name like 'Wait/Synch/Rwlock/sql/%' - and name not in ('wait/synch/rwlock/sql/CRYPTO_dynlock_value::lock') + and name not in ( +'wait/synch/rwlock/sql/CRYPTO_dynlock_value::lock', +'wait/synch/rwlock/sql/LOCK_named_pipe_full_access_group') order by name limit 10; NAME ENABLED TIMED wait/synch/rwlock/sql/LOCK_dboptions YES YES diff --git a/mysql-test/suite/perfschema/t/dml_setup_instruments.test b/mysql-test/suite/perfschema/t/dml_setup_instruments.test index 6b4fe89a1cf..098d6bd031d 100644 --- a/mysql-test/suite/perfschema/t/dml_setup_instruments.test +++ b/mysql-test/suite/perfschema/t/dml_setup_instruments.test @@ -22,10 +22,13 @@ select * from performance_schema.setup_instruments order by name limit 10; # CRYPTO_dynlock_value::lock is dependent on the build (SSL) +# LOCK_named_pipe_full_access_group is dependent on the build (Windows) select * from performance_schema.setup_instruments where name like 'Wait/Synch/Rwlock/sql/%' - and name not in ('wait/synch/rwlock/sql/CRYPTO_dynlock_value::lock') + and name not in ( + 'wait/synch/rwlock/sql/CRYPTO_dynlock_value::lock', + 'wait/synch/rwlock/sql/LOCK_named_pipe_full_access_group') order by name limit 10; # COND_handler_count is dependent on the build (Windows only) diff --git a/mysql-test/suite/rpl/r/rpl_set_statement.test b/mysql-test/suite/rpl/r/rpl_set_statement.test deleted file mode 100644 index e69de29bb2d..00000000000 --- a/mysql-test/suite/rpl/r/rpl_set_statement.test +++ /dev/null diff --git a/mysql-test/suite/sys_vars/r/sysvars_innodb,32bit,xtradb.rdiff-disabled b/mysql-test/suite/sys_vars/r/sysvars_innodb,32bit,xtradb.rdiff-disabled index 73dd57ed1fb..2019c4dc616 100644 --- a/mysql-test/suite/sys_vars/r/sysvars_innodb,32bit,xtradb.rdiff-disabled +++ b/mysql-test/suite/sys_vars/r/sysvars_innodb,32bit,xtradb.rdiff-disabled @@ -1214,8 +1214,8 @@ COMMAND_LINE_ARGUMENT OPTIONAL VARIABLE_NAME INNODB_VERSION SESSION_VALUE NULL --GLOBAL_VALUE 5.6.42 -+GLOBAL_VALUE 5.6.41-84.1 +-GLOBAL_VALUE 5.6.43 ++GLOBAL_VALUE 5.6.42-84.2 GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE NULL VARIABLE_SCOPE GLOBAL diff --git a/mysql-test/suite/sys_vars/r/sysvars_innodb,xtradb.rdiff-disabled b/mysql-test/suite/sys_vars/r/sysvars_innodb,xtradb.rdiff-disabled index 44269b2c74a..998d95e523f 100644 --- a/mysql-test/suite/sys_vars/r/sysvars_innodb,xtradb.rdiff-disabled +++ b/mysql-test/suite/sys_vars/r/sysvars_innodb,xtradb.rdiff-disabled @@ -684,8 +684,8 @@ COMMAND_LINE_ARGUMENT OPTIONAL VARIABLE_NAME INNODB_VERSION SESSION_VALUE NULL --GLOBAL_VALUE 5.6.42 -+GLOBAL_VALUE 5.6.41-84.1 +-GLOBAL_VALUE 5.6.43 ++GLOBAL_VALUE 5.6.42-84.2 GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE NULL VARIABLE_SCOPE GLOBAL diff --git a/mysql-test/t/mysql.test b/mysql-test/t/mysql.test index e3219c21517..a90095d06f5 100644 --- a/mysql-test/t/mysql.test +++ b/mysql-test/t/mysql.test @@ -680,3 +680,26 @@ show create table "a1\""b1"; select * from "a1\""b1"; drop table "a1\""b1"; set sql_mode=default; + +# +# mysql --local-infile +# +--let $ldli = load data local infile '$MYSQLTEST_VARDIR/tmp/bug.sql' into table test.t1; +create table t1 (a text); +--exec $MYSQL -e "$ldli" +select count(*) from t1; truncate table t1; +--exec $MYSQL --enable-local-infile -e "$ldli" +select count(*) from t1; truncate table t1; +--error 1 +--exec $MYSQL --disable-local-infile -e "$ldli" +select count(*) from t1; truncate table t1; +--echo ### FIXME: update libmariadb +#--error 1 +#--exec $MYSQL -e "/*q*/$ldli" +#select count(*) from t1; truncate table t1; +#--exec $MYSQL --enable-local-infile -e "/*q*/$ldli" +#select count(*) from t1; truncate table t1; +# --error 1 +# --exec $MYSQL --disable-local-infile -e "/*q*/$ldli" +#select count(*) from t1; truncate table t1; +drop table t1; diff --git a/mysql-test/t/row-checksum.test b/mysql-test/t/row-checksum.test index 82efcf3ef93..5acfda45f75 100644 --- a/mysql-test/t/row-checksum.test +++ b/mysql-test/t/row-checksum.test @@ -60,3 +60,20 @@ checksum table t1; checksum table t1 quick; checksum table t1 extended; drop table t1; + +--echo # +--echo # MDEV-17085: CHECKSUM TABLE EXTENDED does not work correctly +--echo # + +CREATE TABLE t1 ( c1 int NOT NULL, c2 int NOT NULL, c4 varchar(20), c5 varchar(20), c6 varchar(20), c7 varchar(20), c8 varchar(20), c9 varchar(20), c10 varchar(20), c11 varchar(20), c12 varchar(20), c13 varchar(20), c14 varchar(20), c15 varchar(20), c16 varchar(20), c19 int NOT NULL, c20 int NOT NULL, c21 varchar(20), c22 VARCHAR(20), c23 varchar(20)); + +insert into t1 values (5,0,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,0,"dog",NULL,NULL); +--echo # Important is that checksum is different from following +CHECKSUM TABLE t1 EXTENDED; +UPDATE t1 SET c21='cat' WHERE c1=5; +--echo # Important is that checksum is different from above +CHECKSUM TABLE t1 EXTENDED; + +drop table t1; + +--echo # End of 5.5 tests diff --git a/mysql-test/t/subselect2.test b/mysql-test/t/subselect2.test index c106d40b095..5f7e5f80626 100644 --- a/mysql-test/t/subselect2.test +++ b/mysql-test/t/subselect2.test @@ -411,3 +411,23 @@ insert into t3 select a from t1; select null in (select a from t1 where a < out3.a union select a from t2 where (select a from t3) +1 < out3.a+1) from t3 out3; drop table t1, t2, t3; + +# +# Bug #28499924: INCORRECT BEHAVIOR WITH UNION IN SUBQUERY +# +CREATE TABLE t1( + q11 int, q12 int, q13 int, q14 int, q15 int, q16 int, q17 int, q18 int, q19 int, + q21 int, q22 int, q23 int, q24 int, q25 int, q26 int, q27 int, q28 int, q29 int, + f1 int +); +CREATE TABLE t2(f2 int, f21 int, f3 timestamp, f4 int, f5 int, f6 int); +INSERT INTO t1 (f1) VALUES (1),(1),(2),(2); +INSERT INTO t2 VALUES (1,1,"2004-02-29 11:11:11",0,0,0), (2,2,"2004-02-29 11:11:11",0,0,0); +SELECT f1, + (SELECT t.f21 from t2 t where max( + q11+q12+q13+q14+q15+q16+q17+q18+q19+ + q21+q22+q23+q24+q25+q26+q27+q28+q29) = t.f2 UNION + SELECT t.f3 FROM t2 AS t WHERE t1.f1=t.f2 AND t.f3=MAX(t1.f1) UNION + SELECT 1 LIMIT 1) AS test + FROM t1 GROUP BY f1; +DROP TABLE t1,t2; diff --git a/mysql-test/t/subselect_mat.test b/mysql-test/t/subselect_mat.test index bf5de741ea0..f554d86c5a9 100644 --- a/mysql-test/t/subselect_mat.test +++ b/mysql-test/t/subselect_mat.test @@ -269,6 +269,19 @@ SELECT * FROM t2 WHERE f IN ( SELECT LEFT('foo',0) FROM t1 ORDER BY 1 ); DROP TABLE t1, t2; --echo # +--echo # MDEV-18255: Server crashes in Bitmap<64u>::intersect +--echo # +create table t1 (v1 varchar(1)) engine=myisam ; +create table t2 (v1 varchar(1)) engine=myisam ; + +explain +select 1 from t1 where exists + (select 1 from t1 where t1.v1 in (select t2.v1 from t2 having t2.v1 < 'j')) ; +select 1 from t1 where exists + (select 1 from t1 where t1.v1 in (select t2.v1 from t2 having t2.v1 < 'j')) ; +drop table t1,t2; + +--echo # --echo # MDEV-9489: Assertion `0' failed in Protocol::end_statement() on --echo # UNION ALL --echo # diff --git a/mysys/my_file.c b/mysys/my_file.c index a23ab487d00..23226595b2e 100644 --- a/mysys/my_file.c +++ b/mysys/my_file.c @@ -52,10 +52,9 @@ static uint set_max_open_files(uint max_file_limit) DBUG_PRINT("info", ("rlim_cur: %u rlim_max: %u", (uint) rlimit.rlim_cur, (uint) rlimit.rlim_max)); - if ((ulonglong) rlimit.rlim_cur == (ulonglong) RLIM_INFINITY) - rlimit.rlim_cur = max_file_limit; - if (rlimit.rlim_cur >= max_file_limit) - DBUG_RETURN(rlimit.rlim_cur); /* purecov: inspected */ + if ((ulonglong) rlimit.rlim_cur == (ulonglong) RLIM_INFINITY || + rlimit.rlim_cur >= max_file_limit) + DBUG_RETURN(max_file_limit); rlimit.rlim_cur= rlimit.rlim_max= max_file_limit; if (setrlimit(RLIMIT_NOFILE, &rlimit)) max_file_limit= old_cur; /* Use original value */ diff --git a/scripts/mysql_install_db.sh b/scripts/mysql_install_db.sh index 959923f3407..681b73dfc9f 100644 --- a/scripts/mysql_install_db.sh +++ b/scripts/mysql_install_db.sh @@ -40,6 +40,9 @@ install_params="" auth_root_authentication_method=normal auth_root_socket_user='root' +dirname0=`dirname $0 2>/dev/null` +dirname0=`dirname $dirname0 2>/dev/null` + usage() { cat <<EOF @@ -242,11 +245,6 @@ cannot_find_file() echo "If you don't want to do a full install, you can use the --srcdir" echo "option to only install the mysql database and privilege tables" echo - echo "If you compiled from source, you need to either run 'make install' to" - echo "copy the software into the correct location ready for operation." - echo "If you don't want to do a full install, you can use the --srcdir" - echo "option to only install the mysql database and privilege tables" - echo echo "If you are using a binary release, you must either be at the top" echo "level of the extracted archive, or pass the --basedir option" echo "pointing to that location." @@ -287,6 +285,9 @@ then cannot_find_file my_print_defaults $basedir/bin $basedir/extra exit 1 fi +elif test -n "$dirname0" -a -x "$dirname0/@bindir@/my_print_defaults" +then + print_defaults="$dirname0/@bindir@/my_print_defaults" else print_defaults="@bindir@/my_print_defaults" fi @@ -342,6 +343,16 @@ then exit 1 fi plugindir=`find_in_dirs --dir auth_socket.so $basedir/lib*/plugin $basedir/lib*/mysql/plugin` +# relative from where the script was run for a relocatable install +elif test -n "$dirname0" -a -x "$dirname0/@INSTALL_SBINDIR@/mysqld" +then + basedir="$dirname0" + bindir="$basedir/@INSTALL_SBINDIR@" + resolveip="$bindir/resolveip" + mysqld="$basedir/@INSTALL_SBINDIR@/mysqld" + srcpkgdatadir="$basedir/@INSTALL_MYSQLSHAREDIR@" + buildpkgdatadir="$basedir/@INSTALL_MYSQLSHAREDIR@" + plugindir="$basedir/@INSTALL_PLUGINDIR@" else basedir="@prefix@" bindir="@bindir@" diff --git a/sql-common/client.c b/sql-common/client.c index 3cc4b918772..5ac03a59708 100644 --- a/sql-common/client.c +++ b/sql-common/client.c @@ -111,6 +111,12 @@ my_bool net_flush(NET *net); #include <my_context.h> #include <mysql_async.h> +typedef enum { + ALWAYS_ACCEPT, /* heuristics is disabled, use CLIENT_LOCAL_FILES */ + WAIT_FOR_QUERY, /* heuristics is enabled, not sending files */ + ACCEPT_FILE_REQUEST /* heuristics is enabled, ready to send a file */ +} auto_local_infile_state; + #define native_password_plugin_name "mysql_native_password" #define old_password_plugin_name "mysql_old_password" @@ -1635,8 +1641,10 @@ mysql_init(MYSQL *mysql) --enable-local-infile */ -#if defined(ENABLED_LOCAL_INFILE) && !defined(MYSQL_SERVER) +#if ENABLED_LOCAL_INFILE && !defined(MYSQL_SERVER) mysql->options.client_flag|= CLIENT_LOCAL_FILES; + mysql->auto_local_infile= ENABLED_LOCAL_INFILE == LOCAL_INFILE_MODE_AUTO + ? WAIT_FOR_QUERY : ALWAYS_ACCEPT; #endif #ifdef HAVE_SMEM @@ -4003,8 +4011,14 @@ static my_bool cli_read_query_result(MYSQL *mysql) ulong field_count; MYSQL_DATA *fields; ulong length; +#ifdef MYSQL_CLIENT + my_bool can_local_infile= mysql->auto_local_infile != WAIT_FOR_QUERY; +#endif DBUG_ENTER("cli_read_query_result"); + if (mysql->auto_local_infile == ACCEPT_FILE_REQUEST) + mysql->auto_local_infile= WAIT_FOR_QUERY; + if ((length = cli_safe_read(mysql)) == packet_error) DBUG_RETURN(1); free_old_query(mysql); /* Free old result */ @@ -4041,7 +4055,8 @@ get_info: { int error; - if (!(mysql->options.client_flag & CLIENT_LOCAL_FILES)) + if (!(mysql->options.client_flag & CLIENT_LOCAL_FILES) || + !can_local_infile) { set_mysql_error(mysql, CR_MALFORMED_PACKET, unknown_sqlstate); DBUG_RETURN(1); @@ -4079,6 +4094,13 @@ int STDCALL mysql_send_query(MYSQL* mysql, const char* query, ulong length) { DBUG_ENTER("mysql_send_query"); + if (mysql->options.client_flag & CLIENT_LOCAL_FILES && + mysql->auto_local_infile == WAIT_FOR_QUERY && + (*query == 'l' || *query == 'L')) + { + if (strncasecmp(query, STRING_WITH_LEN("load")) == 0) + mysql->auto_local_infile= ACCEPT_FILE_REQUEST; + } DBUG_RETURN(simple_command(mysql, COM_QUERY, (uchar*) query, length, 1)); } @@ -4292,10 +4314,12 @@ mysql_options(MYSQL *mysql,enum mysql_option option, const void *arg) mysql->options.protocol=MYSQL_PROTOCOL_PIPE; /* Force named pipe */ break; case MYSQL_OPT_LOCAL_INFILE: /* Allow LOAD DATA LOCAL ?*/ - if (!arg || MY_TEST(*(uint*) arg)) + if (!arg || *(uint*) arg) mysql->options.client_flag|= CLIENT_LOCAL_FILES; else mysql->options.client_flag&= ~CLIENT_LOCAL_FILES; + mysql->auto_local_infile= arg && *(uint*)arg == LOCAL_INFILE_MODE_AUTO + ? WAIT_FOR_QUERY : ALWAYS_ACCEPT; break; case MYSQL_INIT_COMMAND: add_init_command(&mysql->options,arg); diff --git a/sql/CMakeLists.txt b/sql/CMakeLists.txt index c1f1df818ed..1b52c26ce22 100644 --- a/sql/CMakeLists.txt +++ b/sql/CMakeLists.txt @@ -472,7 +472,7 @@ IF(WIN32) COMPONENT Server ) SET_TARGET_PROPERTIES(mysql_install_db PROPERTIES COMPILE_FLAGS -DINSTALL_PLUGINDIR=${INSTALL_PLUGINDIR}) - TARGET_LINK_LIBRARIES(mysql_install_db mysys) + TARGET_LINK_LIBRARIES(mysql_install_db mysys shlwapi) ADD_LIBRARY(winservice STATIC winservice.c) TARGET_LINK_LIBRARIES(winservice shell32) diff --git a/sql/log.cc b/sql/log.cc index 053c0f16c6c..4d62c9783cd 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -1,5 +1,5 @@ -/* Copyright (c) 2000, 2016, Oracle and/or its affiliates. - Copyright (c) 2009, 2017, MariaDB Corporation. +/* Copyright (c) 2000, 2018, Oracle and/or its affiliates. + Copyright (c) 2009, 2019, MariaDB Corporation 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 @@ -3919,7 +3919,7 @@ int MYSQL_BIN_LOG::find_log_pos(LOG_INFO *linfo, const char *log_name, // if the log entry matches, null string matching anything if (!log_name || (log_name_len == fname_len && - !memcmp(full_fname, full_log_name, log_name_len))) + !strncmp(full_fname, full_log_name, log_name_len))) { DBUG_PRINT("info", ("Found log file entry")); linfo->index_file_start_offset= offset; diff --git a/sql/mysql_install_db.cc b/sql/mysql_install_db.cc index 17e83126bc9..73281161335 100644 --- a/sql/mysql_install_db.cc +++ b/sql/mysql_install_db.cc @@ -27,6 +27,8 @@ #include <shellapi.h> #include <accctrl.h> #include <aclapi.h> +struct IUnknown; +#include <shlwapi.h> #define USAGETEXT \ "mysql_install_db.exe Ver 1.00 for Windows\n" \ @@ -556,20 +558,78 @@ static int create_db_instance() DWORD cwd_len= MAX_PATH; char cmdline[3*MAX_PATH]; FILE *in; + bool cleanup_datadir= true; + DWORD last_error; verbose("Running bootstrap"); GetCurrentDirectory(cwd_len, cwd); - CreateDirectory(opt_datadir, NULL); /*ignore error, it might already exist */ + + /* Create datadir and datadir/mysql, if they do not already exist. */ + + if (!CreateDirectory(opt_datadir, NULL) && (GetLastError() != ERROR_ALREADY_EXISTS)) + { + last_error = GetLastError(); + switch(last_error) + { + case ERROR_ACCESS_DENIED: + die("Can't create data directory '%s' (access denied)\n", + opt_datadir); + break; + case ERROR_PATH_NOT_FOUND: + die("Can't create data directory '%s' " + "(one or more intermediate directories do not exist)\n", + opt_datadir); + break; + default: + die("Can't create data directory '%s', last error %u\n", + opt_datadir, last_error); + break; + } + } if (!SetCurrentDirectory(opt_datadir)) { - die("Cannot set current directory to '%s'\n",opt_datadir); - return -1; + last_error = GetLastError(); + switch (last_error) + { + case ERROR_DIRECTORY: + die("Can't set current directory to '%s', the path is not a valid directory \n", + opt_datadir); + break; + default: + die("Can' set current directory to '%s', last error %u\n", + opt_datadir, last_error); + break; + } + } + + if (PathIsDirectoryEmpty(opt_datadir)) + { + cleanup_datadir= false; } - CreateDirectory("mysql",NULL); - CreateDirectory("test", NULL); + if (!CreateDirectory("mysql",NULL)) + { + last_error = GetLastError(); + DWORD attributes; + switch(last_error) + { + case ERROR_ACCESS_DENIED: + die("Can't create subdirectory 'mysql' in '%s' (access denied)\n",opt_datadir); + break; + case ERROR_ALREADY_EXISTS: + attributes = GetFileAttributes("mysql"); + + if (attributes == INVALID_FILE_ATTRIBUTES) + die("GetFileAttributes() failed for existing file '%s\\mysql', last error %u", + opt_datadir, GetLastError()); + else if (!(attributes & FILE_ATTRIBUTE_DIRECTORY)) + die("File '%s\\mysql' exists, but it is not a directory", opt_datadir); + + break; + } + } /* Set data directory permissions for both current user and @@ -675,7 +735,7 @@ static int create_db_instance() } end: - if (ret) + if (ret && cleanup_datadir) { SetCurrentDirectory(cwd); clean_directory(opt_datadir); diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 6d1a15baece..869d990ed6e 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -3857,7 +3857,8 @@ bool st_select_lex::optimize_unflattened_subqueries(bool const_only) inner_join->select_options|= SELECT_DESCRIBE; } res= inner_join->optimize(); - sl->update_used_tables(); + if (!inner_join->cleaned) + sl->update_used_tables(); sl->update_correlated_cache(); is_correlated_unit|= sl->is_correlated; inner_join->select_options= save_options; diff --git a/sql/sql_repl.cc b/sql/sql_repl.cc index 35cdc98e0f4..3bc1a019f40 100644 --- a/sql/sql_repl.cc +++ b/sql/sql_repl.cc @@ -1,5 +1,5 @@ -/* Copyright (c) 2000, 2017, Oracle and/or its affiliates. - Copyright (c) 2008, 2017, MariaDB Corporation +/* Copyright (c) 2000, 2018, Oracle and/or its affiliates. + Copyright (c) 2008, 2019, MariaDB Corporation 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 @@ -543,7 +543,7 @@ bool log_in_use(const char* log_name) if ((linfo = tmp->current_linfo)) { mysql_mutex_lock(&linfo->lock); - result = !memcmp(log_name, linfo->log_file_name, log_name_len); + result = !strncmp(log_name, linfo->log_file_name, log_name_len); mysql_mutex_unlock(&linfo->lock); if (result) break; diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 19100aafd51..5329bc81ec7 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -5767,7 +5767,8 @@ static bool is_candidate_key(KEY *key) KEY_PART_INFO *key_part; KEY_PART_INFO *key_part_end= key->key_part + key->user_defined_key_parts; - if (!(key->flags & HA_NOSAME) || (key->flags & HA_NULL_PART_KEY)) + if (!(key->flags & HA_NOSAME) || (key->flags & HA_NULL_PART_KEY) || + (key->flags & HA_KEY_HAS_PART_KEY_SEG)) return false; for (key_part= key->key_part; key_part < key_part_end; key_part++) @@ -6298,9 +6299,7 @@ static int compare_uint(const uint *s, const uint *t) @retval false success */ -static bool fill_alter_inplace_info(THD *thd, - TABLE *table, - bool varchar, +static bool fill_alter_inplace_info(THD *thd, TABLE *table, bool varchar, Alter_inplace_info *ha_alter_info) { Field **f_ptr, *field, *old_field; @@ -6308,7 +6307,6 @@ static bool fill_alter_inplace_info(THD *thd, Create_field *new_field; KEY_PART_INFO *key_part, *new_part; KEY_PART_INFO *end; - uint candidate_key_count= 0; Alter_info *alter_info= ha_alter_info->alter_info; DBUG_ENTER("fill_alter_inplace_info"); @@ -6639,8 +6637,13 @@ static bool fill_alter_inplace_info(THD *thd, Primary key index for the new table */ const KEY* const new_pk= (ha_alter_info->key_count > 0 && - is_candidate_key(ha_alter_info->key_info_buffer)) ? + (!my_strcasecmp(system_charset_info, + ha_alter_info->key_info_buffer->name, + primary_key_name) || + is_candidate_key(ha_alter_info->key_info_buffer))) ? ha_alter_info->key_info_buffer : NULL; + const KEY *const old_pk= table->s->primary_key == MAX_KEY ? NULL : + table->key_info + table->s->primary_key; DBUG_PRINT("info", ("index count old: %d new: %d", table->s->keys, ha_alter_info->key_count)); @@ -6740,8 +6743,7 @@ static bool fill_alter_inplace_info(THD *thd, (i) Old table doesn't have primary key, new table has it and vice-versa (ii) Primary key changed to another existing index */ - if ((new_key == new_pk) != - ((uint) (table_key - table->key_info) == table->s->primary_key)) + if ((new_key == new_pk) != (table_key == old_pk)) goto index_changed; /* Check that key comment is not changed. */ @@ -6802,22 +6804,6 @@ static bool fill_alter_inplace_info(THD *thd, /* Now let us calculate flags for storage engine API. */ - /* Count all existing candidate keys. */ - for (table_key= table->key_info; table_key < table_key_end; table_key++) - { - /* - Check if key is a candidate key, This key is either already primary key - or could be promoted to primary key if the original primary key is - dropped. - In MySQL one is allowed to create primary key with partial fields (i.e. - primary key which is not considered candidate). For simplicity we count - such key as a candidate key here. - */ - if (((uint) (table_key - table->key_info) == table->s->primary_key) || - is_candidate_key(table_key)) - candidate_key_count++; - } - /* Figure out what kind of indexes we are dropping. */ KEY **dropped_key; KEY **dropped_key_end= ha_alter_info->index_drop_buffer + @@ -6830,21 +6816,10 @@ static bool fill_alter_inplace_info(THD *thd, if (table_key->flags & HA_NOSAME) { - /* - Unique key. Check for PRIMARY KEY. Also see comment about primary - and candidate keys above. - */ - if ((uint) (table_key - table->key_info) == table->s->primary_key) - { + if (table_key == old_pk) ha_alter_info->handler_flags|= Alter_inplace_info::DROP_PK_INDEX; - candidate_key_count--; - } else - { ha_alter_info->handler_flags|= Alter_inplace_info::DROP_UNIQUE_INDEX; - if (is_candidate_key(table_key)) - candidate_key_count--; - } } else ha_alter_info->handler_flags|= Alter_inplace_info::DROP_INDEX; @@ -6857,23 +6832,10 @@ static bool fill_alter_inplace_info(THD *thd, if (new_key->flags & HA_NOSAME) { - bool is_pk= !my_strcasecmp(system_charset_info, new_key->name, primary_key_name); - - if ((!(new_key->flags & HA_KEY_HAS_PART_KEY_SEG) && - !(new_key->flags & HA_NULL_PART_KEY)) || - is_pk) - { - /* Candidate key or primary key! */ - if (candidate_key_count == 0 || is_pk) - ha_alter_info->handler_flags|= Alter_inplace_info::ADD_PK_INDEX; - else - ha_alter_info->handler_flags|= Alter_inplace_info::ADD_UNIQUE_INDEX; - candidate_key_count++; - } + if (new_key == new_pk) + ha_alter_info->handler_flags|= Alter_inplace_info::ADD_PK_INDEX; else - { ha_alter_info->handler_flags|= Alter_inplace_info::ADD_UNIQUE_INDEX; - } } else ha_alter_info->handler_flags|= Alter_inplace_info::ADD_INDEX; @@ -10384,7 +10346,10 @@ bool mysql_checksum_table(THD *thd, TABLE_LIST *tables, { /* calculating table's checksum */ ha_checksum crc= 0; - uchar null_mask=256 - (1 << t->s->last_null_bit_pos); + DBUG_ASSERT(t->s->last_null_bit_pos < 8); + uchar null_mask= (t->s->last_null_bit_pos ? + (256 - (1 << t->s->last_null_bit_pos)): + 0); t->use_all_columns(); diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 10c2204d193..480c2e9bacb 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -16441,19 +16441,21 @@ subselect_end: lex->current_select = lex->current_select->return_after_parsing(); lex->nest_level--; lex->current_select->n_child_sum_items += child->n_sum_items; - /* - A subselect can add fields to an outer select. Reserve space for - them. - */ - lex->current_select->select_n_where_fields+= - child->select_n_where_fields; /* - Aggregate functions in having clause may add fields to an outer - select. Count them also. + A subquery (and all the subsequent query blocks in a UNION) can + add columns to an outer query block. Reserve space for them. + Aggregate functions in having clause can also add fields to an + outer select. */ - lex->current_select->select_n_having_items+= - child->select_n_having_items; + for (SELECT_LEX *temp= child->master_unit()->first_select(); + temp != NULL; temp= temp->next_select()) + { + lex->current_select->select_n_where_fields+= + temp->select_n_where_fields; + lex->current_select->select_n_having_items+= + temp->select_n_having_items; + } } ; diff --git a/sql/wsrep_mysqld_c.h b/sql/wsrep_mysqld_c.h index 15ca0ae2a6d..235a871c113 100644 --- a/sql/wsrep_mysqld_c.h +++ b/sql/wsrep_mysqld_c.h @@ -21,6 +21,10 @@ enum enum_wsrep_certification_rules { WSREP_CERTIFICATION_RULES_OPTIMIZED }; -extern ulong wsrep_certification_rules; +/* This is intentionally declared as a weak global symbol, so that +the same ha_innodb.so can be used with the embedded server +(which does not link to the definition of this variable) +and with the regular server built WITH_WSREP. */ +extern ulong wsrep_certification_rules __attribute__((weak)); #endif /* WSREP_MYSQLD_C_H */ diff --git a/storage/connect/mysql-test/connect/r/jdbc_postgresql.result b/storage/connect/mysql-test/connect/r/jdbc_postgresql.result index 07cc3c465ea..bec1dc8725b 100644 --- a/storage/connect/mysql-test/connect/r/jdbc_postgresql.result +++ b/storage/connect/mysql-test/connect/r/jdbc_postgresql.result @@ -1,4 +1,4 @@ -SET GLOBAL connect_class_path='C:/MariaDB-10.2/MariaDB/storage/connect/mysql-test/connect/std_data/JavaWrappers.jar;C:/Jconnectors/postgresql-42.2.1.jar'; +SET GLOBAL connect_class_path='C:/MariaDB-10.0/MariaDB/storage/connect/mysql-test/connect/std_data/JavaWrappers.jar;C:/Jconnectors/postgresql-42.2.1.jar'; CREATE TABLE t2 ( command varchar(128) not null, number int(5) not null flag=1, diff --git a/storage/connect/mysql-test/connect/r/part_table.result b/storage/connect/mysql-test/connect/r/part_table.result index f3a556ae784..ee17a1d32b9 100644 --- a/storage/connect/mysql-test/connect/r/part_table.result +++ b/storage/connect/mysql-test/connect/r/part_table.result @@ -23,7 +23,7 @@ id msg CREATE TABLE xt3 ( id INT KEY NOT NULL, msg VARCHAR(32)) -ENGINE=CONNECT TABLE_TYPE=CSV AVG_ROW_LENGTH=10; +ENGINE=CONNECT TABLE_TYPE=CSV AVG_ROW_LENGTH=6; Warnings: Warning 1105 No file name. Table will use xt3.csv INSERT INTO xt3 VALUES(60,'sixty'),(81,'eighty one'),(72,'seventy two'); @@ -92,7 +92,7 @@ id msg EXPLAIN PARTITIONS SELECT * FROM t1 WHERE id = 81; id select_type table partitions type possible_keys key key_len ref rows Extra -1 SIMPLE t1 3 ALL NULL NULL NULL NULL 4 Using where +1 SIMPLE t1 3 ALL NULL NULL NULL NULL 6 Using where DELETE FROM t1; Warnings: Note 1105 xt1: 4 affected rows diff --git a/storage/connect/mysql-test/connect/t/part_table.test b/storage/connect/mysql-test/connect/t/part_table.test index 5edd5766bd6..0fb2a11f0f9 100644 --- a/storage/connect/mysql-test/connect/t/part_table.test +++ b/storage/connect/mysql-test/connect/t/part_table.test @@ -22,7 +22,7 @@ SELECT * FROM xt2; CREATE TABLE xt3 ( id INT KEY NOT NULL, msg VARCHAR(32)) -ENGINE=CONNECT TABLE_TYPE=CSV AVG_ROW_LENGTH=10; +ENGINE=CONNECT TABLE_TYPE=CSV AVG_ROW_LENGTH=6; INSERT INTO xt3 VALUES(60,'sixty'),(81,'eighty one'),(72,'seventy two'); SELECT * FROM xt3; diff --git a/storage/connect/tabjson.cpp b/storage/connect/tabjson.cpp index d20e793ff88..c0d36efcf42 100644 --- a/storage/connect/tabjson.cpp +++ b/storage/connect/tabjson.cpp @@ -1,6 +1,6 @@ /************* tabjson C++ Program Source Code File (.CPP) *************/ -/* PROGRAM NAME: tabjson Version 1.5 */ -/* (C) Copyright to the author Olivier BERTRAND 2014 - 2017 */ +/* PROGRAM NAME: tabjson Version 1.6 */ +/* (C) Copyright to the author Olivier BERTRAND 2014 - 2018 */ /* This program are the JSON class DB execution routines. */ /***********************************************************************/ @@ -173,6 +173,7 @@ JSONDISC::JSONDISC(PGLOBAL g, uint *lg) int JSONDISC::GetColumns(PGLOBAL g, PCSZ db, PCSZ dsn, PTOS topt) { + char filename[_MAX_PATH]; bool mgo = (GetTypeID(topt->type) == TAB_MONGO); PCSZ level = GetStringTableOption(g, topt, "Level", NULL); @@ -209,6 +210,12 @@ int JSONDISC::GetColumns(PGLOBAL g, PCSZ db, PCSZ dsn, PTOS topt) return 0; } // endif Fn + if (tdp->Fn) { + // We used the file name relative to recorded datapath + PlugSetPath(filename, tdp->Fn, tdp->GetPath()); + tdp->Fn = PlugDup(g, filename); + } // endif Fn + if (trace(1)) htrc("File %s objname=%s pretty=%d lvl=%d\n", tdp->Fn, tdp->Objname, tdp->Pretty, lvl); @@ -342,7 +349,7 @@ int JSONDISC::GetColumns(PGLOBAL g, PCSZ db, PCSZ dsn, PTOS topt) strncpy(colname, jpp->GetKey(), 64); fmt[bf] = 0; - if (Find(g, jpp->GetVal(), MY_MIN(lvl, 0))) + if (Find(g, jpp->GetVal(), colname, MY_MIN(lvl, 0))) goto err; } // endfor jpp @@ -385,7 +392,7 @@ err: return 0; } // end of GetColumns -bool JSONDISC::Find(PGLOBAL g, PJVAL jvp, int j) +bool JSONDISC::Find(PGLOBAL g, PJVAL jvp, PCSZ key, int j) { char *p, *pc = colname + strlen(colname); int ars; @@ -413,12 +420,14 @@ bool JSONDISC::Find(PGLOBAL g, PJVAL jvp, int j) job = (PJOB)jsp; for (PJPR jrp = job->GetFirst(); jrp; jrp = jrp->GetNext()) { - if (*jrp->GetKey() != '$') { - strncat(strncat(fmt, sep, 128), jrp->GetKey(), 128); - strncat(strncat(colname, "_", 64), jrp->GetKey(), 64); + PCSZ k = jrp->GetKey(); + + if (*k != '$') { + strncat(strncat(fmt, sep, 128), k, 128); + strncat(strncat(colname, "_", 64), k, 64); } // endif Key - if (Find(g, jrp->GetVal(), j + 1)) + if (Find(g, jrp->GetVal(), k, j + 1)) return true; *p = *pc = 0; @@ -428,13 +437,13 @@ bool JSONDISC::Find(PGLOBAL g, PJVAL jvp, int j) case TYPE_JAR: jar = (PJAR)jsp; - if (all || (tdp->Xcol && !stricmp(tdp->Xcol, colname))) + if (all || (tdp->Xcol && !stricmp(tdp->Xcol, key))) ars = jar->GetSize(false); else ars = MY_MIN(jar->GetSize(false), 1); for (int k = 0; k < ars; k++) { - if (!tdp->Xcol || stricmp(tdp->Xcol, colname)) { + if (!tdp->Xcol || stricmp(tdp->Xcol, key)) { sprintf(buf, "%d", k); if (tdp->Uri) @@ -448,7 +457,7 @@ bool JSONDISC::Find(PGLOBAL g, PJVAL jvp, int j) } else strncat(fmt, (tdp->Uri ? sep : "[*]"), 128); - if (Find(g, jar->GetValue(k), j)) + if (Find(g, jar->GetValue(k), "", j)) return true; *p = *pc = 0; @@ -522,7 +531,9 @@ void JSONDISC::AddColumn(PGLOBAL g) n++; } // endif jcp - pjcp = jcp; + if (jcp) + pjcp = jcp; + } // end of AddColumn @@ -549,7 +560,7 @@ JSONDEF::JSONDEF(void) /***********************************************************************/ /* DefineAM: define specific AM block values. */ /***********************************************************************/ -bool JSONDEF::DefineAM(PGLOBAL g, LPCSTR, int poff) +bool JSONDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff) { Schema = GetStringCatInfo(g, "DBname", Schema); Jmode = (JMODE)GetIntCatInfo("Jmode", MODE_OBJECT); @@ -561,7 +572,8 @@ bool JSONDEF::DefineAM(PGLOBAL g, LPCSTR, int poff) Sep = *GetStringCatInfo(g, "Separator", "."); Accept = GetBoolCatInfo("Accept", false); - if (Uri = GetStringCatInfo(g, "Connect", NULL)) { + // Don't use url as uri when called from REST OEM module + if (stricmp(am, "REST") && (Uri = GetStringCatInfo(g, "Connect", NULL))) { #if defined(JAVA_SUPPORT) || defined(CMGO_SUPPORT) Collname = GetStringCatInfo(g, "Name", (Catfunc & (FNC_TABLE | FNC_COL)) ? NULL : Name); @@ -2340,7 +2352,7 @@ void TDBJSON::CloseDB(PGLOBAL g) TDBJCL::TDBJCL(PJDEF tdp) : TDBCAT(tdp) { Topt = tdp->GetTopt(); - Db = tdp->Schema; + Db = tdp->Schema; Dsn = tdp->Uri; } // end of TDBJCL constructor diff --git a/storage/connect/tabjson.h b/storage/connect/tabjson.h index fcbfe4ed1ec..8721a2a5ab7 100644 --- a/storage/connect/tabjson.h +++ b/storage/connect/tabjson.h @@ -52,7 +52,7 @@ public: // Functions int GetColumns(PGLOBAL g, PCSZ db, PCSZ dsn, PTOS topt); - bool Find(PGLOBAL g, PJVAL jvp, int j); + bool Find(PGLOBAL g, PJVAL jvp, PCSZ key, int j); void AddColumn(PGLOBAL g); // Members diff --git a/storage/connect/tabxml.cpp b/storage/connect/tabxml.cpp index fa4854bb618..d808bd5ecd4 100644 --- a/storage/connect/tabxml.cpp +++ b/storage/connect/tabxml.cpp @@ -163,8 +163,11 @@ PQRYRES XMLColumns(PGLOBAL g, char *db, char *tab, PTOS topt, bool info) return NULL; tdp->Tabname = tab; + tdp->Tabname = (char*)GetStringTableOption(g, topt, "Tabname", tab); + tdp->Rowname = (char*)GetStringTableOption(g, topt, "Rownode", NULL); tdp->Zipped = GetBooleanTableOption(g, topt, "Zipped", false); tdp->Entry = GetStringTableOption(g, topt, "Entry", NULL); + tdp->Skip = GetBooleanTableOption(g, topt, "Skipnull", false); if (!(op = GetStringTableOption(g, topt, "Xmlsup", NULL))) #if defined(__WIN__) @@ -280,7 +283,9 @@ PQRYRES XMLColumns(PGLOBAL g, char *db, char *tab, PTOS topt, bool info) if (!vp->atp) node = vp->nl->GetItem(g, vp->k++, tdp->Usedom ? node : NULL); - strncat(fmt, colname, XLEN(fmt)); + if (!j) + strncat(fmt, colname, XLEN(fmt)); + strncat(fmt, "/", XLEN(fmt)); strncat(xcol->Name, "_", XLEN(xcol->Name)); j++; @@ -302,6 +307,7 @@ PQRYRES XMLColumns(PGLOBAL g, char *db, char *tab, PTOS topt, bool info) case RC_INFO: PushWarning(g, txmp); case RC_OK: + xcol->Cbn = !strlen(buf); break; default: goto err; @@ -327,9 +333,9 @@ PQRYRES XMLColumns(PGLOBAL g, char *db, char *tab, PTOS topt, bool info) xcp->Len = MY_MAX(xcp->Len, xcol->Len); xcp->Scale = MY_MAX(xcp->Scale, xcol->Scale); - xcp->Cbn |= xcol->Cbn; + xcp->Cbn |= (xcol->Cbn || !xcol->Len); xcp->Found = true; - } else { + } else if(xcol->Len || !tdp->Skip) { // New column xcp = new(g) XMCOL(g, xcol, fmt, i); length[0] = MY_MAX(length[0], strlen(xcol->Name)); @@ -344,7 +350,8 @@ PQRYRES XMLColumns(PGLOBAL g, char *db, char *tab, PTOS topt, bool info) n++; } // endif xcp - pxcp = xcp; + if (xcp) + pxcp = xcp; if (vp->atp) vp->atp = vp->atp->GetNext(g); @@ -445,6 +452,7 @@ XMLDEF::XMLDEF(void) Usedom = false; Zipped = false; Mulentries = false; + Skip = false; } // end of XMLDEF constructor /***********************************************************************/ @@ -814,127 +822,141 @@ bool TDBXML::Initialize(PGLOBAL g) } // endif Bufdone #if !defined(UNIX) - if (!Root) try { + if (!Root) try { #else - if (!Root) { + if (!Root) { #endif - char tabpath[64], filename[_MAX_PATH]; - - // We used the file name relative to recorded datapath - PlugSetPath(filename, Xfile, GetPath()); - - // Load or re-use the table file - rc = LoadTableFile(g, filename); - - if (rc == RC_OK) { - // Get root node - if (!(Root = Docp->GetRoot(g))) { - // This should never happen as load should have failed - strcpy(g->Message, MSG(EMPTY_DOC)); - goto error; - } // endif Root - - // If tabname is not an Xpath, - // construct one that will find it anywhere - if (!strchr(Tabname, '/')) - strcat(strcpy(tabpath, "//"), Tabname); - else - strcpy(tabpath, Tabname); - - // Evaluate table xpath - if ((TabNode = Root->SelectSingleNode(g, tabpath))) { - if (TabNode->GetType() != XML_ELEMENT_NODE) { - sprintf(g->Message, MSG(BAD_NODE_TYPE), TabNode->GetType()); - goto error; - } // endif Type - - } else if (Mode == MODE_INSERT && XmlDB) { - // We are adding a new table to a multi-table file - - // If XmlDB is not an Xpath, - // construct one that will find it anywhere - if (!strchr(XmlDB, '/')) - strcat(strcpy(tabpath, "//"), XmlDB); - else - strcpy(tabpath, XmlDB); - - if (!(DBnode = Root->SelectSingleNode(g, tabpath))) { - // DB node does not exist yet; we cannot create it - // because we don't know where it should be placed - sprintf(g->Message, MSG(MISSING_NODE), XmlDB, Xfile); - goto error; - } // endif DBnode - - if (!(TabNode = DBnode->AddChildNode(g, Tabname))) { - sprintf(g->Message, MSG(FAIL_ADD_NODE), Tabname); - goto error; - } // endif TabNode - - DBnode->AddText(g, "\n"); - } else - TabNode = Root; // Try this ? - - } else if (rc == RC_NF || rc == RC_EF) { - // The XML file does not exist or is void - if (Mode == MODE_INSERT) { - // New Document - char buf[64]; - - // Create the XML node - if (Docp->NewDoc(g, "1.0")) { - strcpy(g->Message, MSG(NEW_DOC_FAILED)); - goto error; - } // endif NewDoc - - // Now we can link the Xblock - To_Xb = Docp->LinkXblock(g, Mode, rc, filename); - - // Add a CONNECT comment node - strcpy(buf, " Created by the MariaDB CONNECT Storage Engine"); - Docp->AddComment(g, buf); - - if (XmlDB) { - // This is a multi-table file - DBnode = Root = Docp->NewRoot(g, XmlDB); - DBnode->AddText(g, "\n"); - TabNode = DBnode->AddChildNode(g, Tabname); - DBnode->AddText(g, "\n"); - } else - TabNode = Root = Docp->NewRoot(g, Tabname); - - if (TabNode == NULL || Root == NULL) { - strcpy(g->Message, MSG(XML_INIT_ERROR)); - goto error; - } else if (SetTabNode(g)) - goto error; - - } else { - sprintf(g->Message, MSG(FILE_UNFOUND), Xfile); - - if (Mode == MODE_READ) { - PushWarning(g, this); - Void = true; - } // endif Mode - - goto error; - } // endif Mode - - } else if (rc == RC_INFO) { - // Loading failed - sprintf(g->Message, MSG(LOADING_FAILED), Xfile); - goto error; - } else // (rc == RC_FX) - goto error; - - // Get row node list - if (Rowname) - Nlist = TabNode->SelectNodes(g, Rowname); - else - Nlist = TabNode->GetChildElements(g); - - Docp->SetNofree(true); // For libxml2 + char tabpath[64], filename[_MAX_PATH]; + + // We used the file name relative to recorded datapath + PlugSetPath(filename, Xfile, GetPath()); + + // Load or re-use the table file + rc = LoadTableFile(g, filename); + + if (rc == RC_OK) { + // Get root node + if (!(Root = Docp->GetRoot(g))) { + // This should never happen as load should have failed + strcpy(g->Message, MSG(EMPTY_DOC)); + goto error; + } // endif Root + + // If tabname is not an Xpath, + // construct one that will find it anywhere + if (!strchr(Tabname, '/')) + strcat(strcpy(tabpath, "//"), Tabname); + else + strcpy(tabpath, Tabname); + + // Evaluate table xpath + if ((TabNode = Root->SelectSingleNode(g, tabpath))) { + if (TabNode->GetType() != XML_ELEMENT_NODE) { + sprintf(g->Message, MSG(BAD_NODE_TYPE), TabNode->GetType()); + goto error; + } // endif Type + + } else if (Mode == MODE_INSERT && XmlDB) { + // We are adding a new table to a multi-table file + + // If XmlDB is not an Xpath, + // construct one that will find it anywhere + if (!strchr(XmlDB, '/')) + strcat(strcpy(tabpath, "//"), XmlDB); + else + strcpy(tabpath, XmlDB); + + if (!(DBnode = Root->SelectSingleNode(g, tabpath))) { + // DB node does not exist yet; we cannot create it + // because we don't know where it should be placed + sprintf(g->Message, MSG(MISSING_NODE), XmlDB, Xfile); + goto error; + } // endif DBnode + + if (!(TabNode = DBnode->AddChildNode(g, Tabname))) { + sprintf(g->Message, MSG(FAIL_ADD_NODE), Tabname); + goto error; + } // endif TabNode + + DBnode->AddText(g, "\n"); + } else { + TabNode = Root; // Try this ? + Tabname = TabNode->GetName(g); + } // endif's + + } else if (rc == RC_NF || rc == RC_EF) { + // The XML file does not exist or is void + if (Mode == MODE_INSERT) { + // New Document + char buf[64]; + + // Create the XML node + if (Docp->NewDoc(g, "1.0")) { + strcpy(g->Message, MSG(NEW_DOC_FAILED)); + goto error; + } // endif NewDoc + + // Now we can link the Xblock + To_Xb = Docp->LinkXblock(g, Mode, rc, filename); + + // Add a CONNECT comment node + strcpy(buf, " Created by the MariaDB CONNECT Storage Engine"); + Docp->AddComment(g, buf); + + if (XmlDB) { + // This is a multi-table file + DBnode = Root = Docp->NewRoot(g, XmlDB); + DBnode->AddText(g, "\n"); + TabNode = DBnode->AddChildNode(g, Tabname); + DBnode->AddText(g, "\n"); + } else + TabNode = Root = Docp->NewRoot(g, Tabname); + + if (TabNode == NULL || Root == NULL) { + strcpy(g->Message, MSG(XML_INIT_ERROR)); + goto error; + } else if (SetTabNode(g)) + goto error; + + } else { + sprintf(g->Message, MSG(FILE_UNFOUND), Xfile); + + if (Mode == MODE_READ) { + PushWarning(g, this); + Void = true; + } // endif Mode + + goto error; + } // endif Mode + + } else if (rc == RC_INFO) { + // Loading failed + sprintf(g->Message, MSG(LOADING_FAILED), Xfile); + goto error; + } else // (rc == RC_FX) + goto error; + + if (!Rowname) { + for (PXNODE n = TabNode->GetChild(g); n; n = n->GetNext(g)) + if (n->GetType() == XML_ELEMENT_NODE) { + Rowname = n->GetName(g); + break; + } // endif Type + + if (!Rowname) + Rowname = TabNode->GetName(g); + } // endif Rowname + + // Get row node list + if (strcmp(Rowname, Tabname)) + Nlist = TabNode->SelectNodes(g, Rowname); + else + Nrow = 1; + + + Docp->SetNofree(true); // For libxml2 #if defined(__WIN__) - } catch(_com_error e) { + } catch (_com_error e) { // We come here if a DOM command threw an error char buf[128]; @@ -1221,10 +1243,14 @@ int TDBXML::ReadDB(PGLOBAL g) htrc("TDBXML ReadDB: Irow=%d RowNode=%p\n", Irow, RowNode); // Get the new row node - if ((RowNode = Nlist->GetItem(g, Irow, RowNode)) == NULL) { - sprintf(g->Message, MSG(MISSING_ROWNODE), Irow); - return RC_FX; - } // endif RowNode + if (Nlist) { + if ((RowNode = Nlist->GetItem(g, Irow, RowNode)) == NULL) { + sprintf(g->Message, MSG(MISSING_ROWNODE), Irow); + return RC_FX; + } // endif RowNode + + } else + RowNode = TabNode; if (Colname && Coltype == 2) Clist = RowNode->SelectNodes(g, Colname, Clist); @@ -1279,6 +1305,7 @@ int TDBXML::WriteDB(PGLOBAL g) /***********************************************************************/ int TDBXML::DeleteDB(PGLOBAL g, int irc) { + // TODO: Handle null Nlist if (irc == RC_FX) { // Delete all rows for (Irow = 0; Irow < Nrow; Irow++) diff --git a/storage/connect/tabxml.h b/storage/connect/tabxml.h index 102767e965a..fb3913f08ea 100644 --- a/storage/connect/tabxml.h +++ b/storage/connect/tabxml.h @@ -52,6 +52,7 @@ class DllExport XMLDEF : public TABDEF { /* Logical table description */ bool Usedom; /* True: DOM, False: libxml2 */ bool Zipped; /* True: Zipped XML file(s) */ bool Mulentries; /* True: multiple entries in zip file*/ + bool Skip; /* Skip null columns */ }; // end of XMLDEF #if defined(INCLUDE_TDBXML) diff --git a/storage/innobase/buf/buf0buf.cc b/storage/innobase/buf/buf0buf.cc index e97a36efa56..6f00ba7d6d4 100644 --- a/storage/innobase/buf/buf0buf.cc +++ b/storage/innobase/buf/buf0buf.cc @@ -2,7 +2,7 @@ Copyright (c) 1995, 2018, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2008, Google Inc. -Copyright (c) 2013, 2018, MariaDB Corporation. +Copyright (c) 2013, 2019, MariaDB Corporation. Portions of this file contain modifications contributed and copyrighted by Google, Inc. Those modifications are gratefully acknowledged and are described @@ -1013,7 +1013,10 @@ buf_page_is_corrupted( /* Check whether the checksum fields have correct values */ - if (srv_checksum_algorithm == SRV_CHECKSUM_ALGORITHM_NONE) { + const srv_checksum_algorithm_t curr_algo = + static_cast<srv_checksum_algorithm_t>(srv_checksum_algorithm); + + if (curr_algo == SRV_CHECKSUM_ALGORITHM_NONE) { return(false); } @@ -1054,9 +1057,6 @@ buf_page_is_corrupted( return(false); } - const srv_checksum_algorithm_t curr_algo = - static_cast<srv_checksum_algorithm_t>(srv_checksum_algorithm); - switch (curr_algo) { case SRV_CHECKSUM_ALGORITHM_STRICT_CRC32: return !buf_page_is_checksum_valid_crc32( @@ -1101,9 +1101,7 @@ buf_page_is_corrupted( != mach_read_from_4(read_buf + FIL_PAGE_LSN) && checksum_field2 != BUF_NO_CHECKSUM_MAGIC) { - if (srv_checksum_algorithm - == SRV_CHECKSUM_ALGORITHM_CRC32) { - + if (curr_algo == SRV_CHECKSUM_ALGORITHM_CRC32) { DBUG_EXECUTE_IF( "page_intermittent_checksum_mismatch", { static int page_counter; @@ -1112,7 +1110,6 @@ buf_page_is_corrupted( } }); - crc32 = buf_page_check_crc32(read_buf, checksum_field2); crc32_inited = true; @@ -1123,7 +1120,7 @@ buf_page_is_corrupted( return true; } } else { - ut_ad(srv_checksum_algorithm + ut_ad(curr_algo == SRV_CHECKSUM_ALGORITHM_INNODB); if (checksum_field2 @@ -1141,9 +1138,7 @@ buf_page_is_corrupted( if (checksum_field1 == 0 || checksum_field1 == BUF_NO_CHECKSUM_MAGIC) { - } else if (srv_checksum_algorithm - == SRV_CHECKSUM_ALGORITHM_CRC32) { - + } else if (curr_algo == SRV_CHECKSUM_ALGORITHM_CRC32) { if (!crc32_inited) { crc32 = buf_page_check_crc32( read_buf, checksum_field2); @@ -1156,8 +1151,7 @@ buf_page_is_corrupted( return true; } } else { - ut_ad(srv_checksum_algorithm - == SRV_CHECKSUM_ALGORITHM_INNODB); + ut_ad(curr_algo == SRV_CHECKSUM_ALGORITHM_INNODB); if (checksum_field1 != buf_calc_page_new_checksum(read_buf)) { diff --git a/storage/innobase/handler/handler0alter.cc b/storage/innobase/handler/handler0alter.cc index 13d78d636d8..886b841b9c4 100644 --- a/storage/innobase/handler/handler0alter.cc +++ b/storage/innobase/handler/handler0alter.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 2005, 2018, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2013, 2018, MariaDB Corporation. +Copyright (c) 2013, 2019, MariaDB Corporation. 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 @@ -5852,12 +5852,14 @@ check_if_ok_to_rename: continue; } + dict_foreign_t* foreign; + for (dict_foreign_set::iterator it = m_prebuilt->table->foreign_set.begin(); it != m_prebuilt->table->foreign_set.end(); ++it) { - dict_foreign_t* foreign = *it; + foreign = *it; const char* fid = strchr(foreign->id, '/'); DBUG_ASSERT(fid); @@ -5868,7 +5870,6 @@ check_if_ok_to_rename: if (!my_strcasecmp(system_charset_info, fid, drop->name)) { - drop_fk[n_drop_fk++] = foreign; goto found_fk; } } @@ -5877,13 +5878,20 @@ check_if_ok_to_rename: drop->type_name(), drop->name); goto err_exit; found_fk: + for (ulint i = n_drop_fk; i--; ) { + if (drop_fk[i] == foreign) { + goto dup_fk; + } + } + drop_fk[n_drop_fk++] = foreign; +dup_fk: continue; } DBUG_ASSERT(n_drop_fk > 0); DBUG_ASSERT(n_drop_fk - == ha_alter_info->alter_info->drop_list.elements); + <= ha_alter_info->alter_info->drop_list.elements); } else { drop_fk = NULL; } @@ -7031,7 +7039,7 @@ err_exit: rename_foreign: trx->op_info = "renaming column in SYS_FOREIGN_COLS"; - std::list<dict_foreign_t*> fk_evict; + std::set<dict_foreign_t*> fk_evict; bool foreign_modified; for (dict_foreign_set::const_iterator it = user_table->foreign_set.begin(); @@ -7071,7 +7079,7 @@ rename_foreign: } if (foreign_modified) { - fk_evict.push_back(foreign); + fk_evict.insert(foreign); } } @@ -7113,7 +7121,7 @@ rename_foreign: } if (foreign_modified) { - fk_evict.push_back(foreign); + fk_evict.insert(foreign); } } @@ -7760,6 +7768,8 @@ commit_try_rebuild( DBUG_ASSERT(!(ha_alter_info->handler_flags & Alter_inplace_info::DROP_FOREIGN_KEY) || ctx->num_to_drop_fk > 0); + DBUG_ASSERT(ctx->num_to_drop_fk + <= ha_alter_info->alter_info->drop_list.elements); for (dict_index_t* index = dict_table_get_first_index(rebuilt_table); index; @@ -8007,7 +8017,7 @@ commit_try_norebuild( & Alter_inplace_info::DROP_FOREIGN_KEY) || ctx->num_to_drop_fk > 0); DBUG_ASSERT(ctx->num_to_drop_fk - == ha_alter_info->alter_info->drop_list.elements + <= ha_alter_info->alter_info->drop_list.elements || ctx->num_to_drop_vcol == ha_alter_info->alter_info->drop_list.elements); @@ -8437,7 +8447,6 @@ ha_innobase::commit_inplace_alter_table( Alter_inplace_info* ha_alter_info, bool commit) { - dberr_t error; ha_innobase_inplace_ctx*ctx0; struct mtr_buf_copy_t logs; @@ -8525,7 +8534,7 @@ ha_innobase::commit_inplace_alter_table( transactions collected during crash recovery could be holding InnoDB locks only, not MySQL locks. */ - error = row_merge_lock_table( + dberr_t error = row_merge_lock_table( m_prebuilt->trx, ctx->old_table, LOCK_X); if (error != DB_SUCCESS) { @@ -8708,9 +8717,9 @@ ha_innobase::commit_inplace_alter_table( file operations that will be performed in commit_cache_rebuild(), and if none, generate the redo log for these operations. */ - error = fil_mtr_rename_log(ctx->old_table, - ctx->new_table, - ctx->tmp_name, &mtr); + dberr_t error = fil_mtr_rename_log( + ctx->old_table, ctx->new_table, ctx->tmp_name, + &mtr); if (error != DB_SUCCESS) { /* Out of memory or a problem will occur when renaming files. */ @@ -8846,41 +8855,34 @@ ha_innobase::commit_inplace_alter_table( /* Rename the tablespace files. */ commit_cache_rebuild(ctx); - error = innobase_update_foreign_cache(ctx, m_user_thd); - if (error != DB_SUCCESS) { - goto foreign_fail; - } - } else { - error = innobase_update_foreign_cache(ctx, m_user_thd); - - if (error != DB_SUCCESS) { + if (innobase_update_foreign_cache(ctx, m_user_thd) + != DB_SUCCESS + && m_prebuilt->trx->check_foreigns) { foreign_fail: - /* The data dictionary cache - should be corrupted now. The - best solution should be to - kill and restart the server, - but the *.frm file has not - been replaced yet. */ push_warning_printf( m_user_thd, Sql_condition::WARN_LEVEL_WARN, ER_ALTER_INFO, - "InnoDB: Could not add foreign" - " key constraints."); - } else { - if (!commit_cache_norebuild( - ctx, table, trx)) { - ut_a(!m_prebuilt->trx->check_foreigns); - } + "failed to load FOREIGN KEY" + " constraints"); + } + } else { + bool fk_fail = innobase_update_foreign_cache( + ctx, m_user_thd) != DB_SUCCESS; + + if (!commit_cache_norebuild(ctx, table, trx)) { + fk_fail = true; + ut_ad(!m_prebuilt->trx->check_foreigns); + } - innobase_rename_or_enlarge_columns_cache( - ha_alter_info, table, - ctx->new_table); + innobase_rename_or_enlarge_columns_cache( + ha_alter_info, table, ctx->new_table); #ifdef MYSQL_RENAME_INDEX - rename_indexes_in_cache(ctx, ha_alter_info); + rename_indexes_in_cache(ctx, ha_alter_info); #endif + if (fk_fail && m_prebuilt->trx->check_foreigns) { + goto foreign_fail; } - } dict_mem_table_free_foreign_vcol_set(ctx->new_table); @@ -9087,7 +9089,7 @@ foreign_fail: before this is completed, some orphan tables with ctx->tmp_name may be recovered. */ trx_start_for_ddl(trx, TRX_DICT_OP_TABLE); - error = row_merge_drop_table(trx, ctx->old_table); + dberr_t error = row_merge_drop_table(trx, ctx->old_table); if (error != DB_SUCCESS) { ib::error() << "Inplace alter table " << ctx->old_table->name diff --git a/storage/innobase/row/row0ins.cc b/storage/innobase/row/row0ins.cc index 1d71b1e0616..2dc81665a72 100644 --- a/storage/innobase/row/row0ins.cc +++ b/storage/innobase/row/row0ins.cc @@ -46,6 +46,7 @@ Created 4/20/1996 Heikki Tuuri #include "fts0types.h" #ifdef WITH_WSREP +#include <mysql/service_wsrep.h> #include "../../../wsrep/wsrep_api.h" #include "wsrep_mysqld_c.h" #endif /* WITH_WSREP */ @@ -1765,6 +1766,9 @@ row_ins_check_foreign_constraint( if (check_ref) { err = DB_SUCCESS; #ifdef WITH_WSREP + if (!wsrep_on(trx->mysql_thd)) { + goto end_scan; + } enum wsrep_key_type key_type; if (upd_node != NULL) { key_type = WSREP_KEY_SHARED; @@ -1781,7 +1785,7 @@ row_ins_check_foreign_constraint( } err = wsrep_append_foreign_key( - thr_get_trx(thr), + trx, foreign, rec, check_index, diff --git a/storage/innobase/row/row0mysql.cc b/storage/innobase/row/row0mysql.cc index 55eadefeb29..1e2c22c1c2f 100644 --- a/storage/innobase/row/row0mysql.cc +++ b/storage/innobase/row/row0mysql.cc @@ -4451,9 +4451,6 @@ row_rename_table_for_mysql( " = TO_BINARY(:old_table_name);\n" "END;\n" , FALSE, trx); - if (err != DB_SUCCESS) { - goto end; - } } else if (n_constraints_to_drop > 0) { /* Drop some constraints of tmp tables. */ diff --git a/storage/tokudb/PerconaFT/COPYING.APACHEv2 b/storage/tokudb/PerconaFT/COPYING.APACHEv2 new file mode 100644 index 00000000000..ecbfc770fa9 --- /dev/null +++ b/storage/tokudb/PerconaFT/COPYING.APACHEv2 @@ -0,0 +1,174 @@ +Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. diff --git a/storage/tokudb/PerconaFT/README.md b/storage/tokudb/PerconaFT/README.md index ffb646b67af..26333df877e 100644 --- a/storage/tokudb/PerconaFT/README.md +++ b/storage/tokudb/PerconaFT/README.md @@ -104,11 +104,14 @@ All source code and test contributions must be provided under a [BSD 2-Clause][b License ------- +Portions of the PerconaFT library (the 'locktree' and 'omt') are available under the Apache version 2 license. PerconaFT is available under the GPL version 2, and AGPL version 3. -See [COPYING.AGPLv3][agpllicense], +See [COPYING.APACHEv2][apachelicense], +[COPYING.AGPLv3][agpllicense], [COPYING.GPLv2][gpllicense], and [PATENTS][patents]. +[apachelicense]: http://github.com/Percona/PerconaFT/blob/master/COPYING.APACHEv2 [agpllicense]: http://github.com/Percona/PerconaFT/blob/master/COPYING.AGPLv3 [gpllicense]: http://github.com/Percona/PerconaFT/blob/master/COPYING.GPLv2 [patents]: http://github.com/Percona/PerconaFT/blob/master/PATENTS diff --git a/storage/tokudb/PerconaFT/ft/txn/txn_manager.h b/storage/tokudb/PerconaFT/ft/txn/txn_manager.h index 7cdc52c4f43..25fa6032112 100644 --- a/storage/tokudb/PerconaFT/ft/txn/txn_manager.h +++ b/storage/tokudb/PerconaFT/ft/txn/txn_manager.h @@ -46,11 +46,11 @@ Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved. void set_test_txn_sync_callback(void (*) (pthread_t, void*), void*); #define toku_test_txn_sync_callback(a) ((test_txn_sync_callback)? test_txn_sync_callback( a,test_txn_sync_callback_extra) : (void) 0) -#if TOKU_DEBUG_TXN_SYNC +#if defined(TOKU_DEBUG_TXN_SYNC) #define toku_debug_txn_sync(a) toku_test_txn_sync_callback(a) #else #define toku_debug_txn_sync(a) ((void) 0) -#endif +#endif // defined(TOKU_DEBUG_TXN_SYNC) typedef struct txn_manager *TXN_MANAGER; diff --git a/storage/tokudb/PerconaFT/locktree/concurrent_tree.cc b/storage/tokudb/PerconaFT/locktree/concurrent_tree.cc index 9347267db49..e07f32c98fb 100644 --- a/storage/tokudb/PerconaFT/locktree/concurrent_tree.cc +++ b/storage/tokudb/PerconaFT/locktree/concurrent_tree.cc @@ -32,6 +32,20 @@ Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved. You should have received a copy of the GNU Affero General Public License along with PerconaFT. If not, see <http://www.gnu.org/licenses/>. + +---------------------------------------- + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. ======= */ #ident "Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved." diff --git a/storage/tokudb/PerconaFT/locktree/concurrent_tree.h b/storage/tokudb/PerconaFT/locktree/concurrent_tree.h index 1eb339b7317..66a7ff176bb 100644 --- a/storage/tokudb/PerconaFT/locktree/concurrent_tree.h +++ b/storage/tokudb/PerconaFT/locktree/concurrent_tree.h @@ -32,6 +32,20 @@ Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved. You should have received a copy of the GNU Affero General Public License along with PerconaFT. If not, see <http://www.gnu.org/licenses/>. + +---------------------------------------- + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. ======= */ #ident "Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved." diff --git a/storage/tokudb/PerconaFT/locktree/keyrange.cc b/storage/tokudb/PerconaFT/locktree/keyrange.cc index 8c2a69d4703..2b4b3bbd4fd 100644 --- a/storage/tokudb/PerconaFT/locktree/keyrange.cc +++ b/storage/tokudb/PerconaFT/locktree/keyrange.cc @@ -32,6 +32,19 @@ Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved. You should have received a copy of the GNU Affero General Public License along with PerconaFT. If not, see <http://www.gnu.org/licenses/>. + +---------------------------------------- + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and ======= */ #ident "Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved." diff --git a/storage/tokudb/PerconaFT/locktree/keyrange.h b/storage/tokudb/PerconaFT/locktree/keyrange.h index 079ac3d7a80..a454287cbc8 100644 --- a/storage/tokudb/PerconaFT/locktree/keyrange.h +++ b/storage/tokudb/PerconaFT/locktree/keyrange.h @@ -32,6 +32,19 @@ Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved. You should have received a copy of the GNU Affero General Public License along with PerconaFT. If not, see <http://www.gnu.org/licenses/>. + +---------------------------------------- + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and ======= */ #ident "Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved." diff --git a/storage/tokudb/PerconaFT/locktree/lock_request.cc b/storage/tokudb/PerconaFT/locktree/lock_request.cc index c0829e3f4e1..51898d4ccb1 100644 --- a/storage/tokudb/PerconaFT/locktree/lock_request.cc +++ b/storage/tokudb/PerconaFT/locktree/lock_request.cc @@ -32,6 +32,19 @@ Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved. You should have received a copy of the GNU Affero General Public License along with PerconaFT. If not, see <http://www.gnu.org/licenses/>. + +---------------------------------------- + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and ======= */ #ident "Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved." diff --git a/storage/tokudb/PerconaFT/locktree/lock_request.h b/storage/tokudb/PerconaFT/locktree/lock_request.h index 9e82b31541e..455433cb90c 100644 --- a/storage/tokudb/PerconaFT/locktree/lock_request.h +++ b/storage/tokudb/PerconaFT/locktree/lock_request.h @@ -32,6 +32,19 @@ Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved. You should have received a copy of the GNU Affero General Public License along with PerconaFT. If not, see <http://www.gnu.org/licenses/>. + +---------------------------------------- + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and ======= */ #ident "Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved." diff --git a/storage/tokudb/PerconaFT/locktree/locktree.cc b/storage/tokudb/PerconaFT/locktree/locktree.cc index 069aae26f66..8ba3f0f00ae 100644 --- a/storage/tokudb/PerconaFT/locktree/locktree.cc +++ b/storage/tokudb/PerconaFT/locktree/locktree.cc @@ -32,6 +32,19 @@ Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved. You should have received a copy of the GNU Affero General Public License along with PerconaFT. If not, see <http://www.gnu.org/licenses/>. + +---------------------------------------- + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and ======= */ #ident "Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved." diff --git a/storage/tokudb/PerconaFT/locktree/locktree.h b/storage/tokudb/PerconaFT/locktree/locktree.h index 1ba7a51b124..7006b6fb01d 100644 --- a/storage/tokudb/PerconaFT/locktree/locktree.h +++ b/storage/tokudb/PerconaFT/locktree/locktree.h @@ -32,6 +32,19 @@ Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved. You should have received a copy of the GNU Affero General Public License along with PerconaFT. If not, see <http://www.gnu.org/licenses/>. + +---------------------------------------- + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and ======= */ #ident "Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved." diff --git a/storage/tokudb/PerconaFT/locktree/manager.cc b/storage/tokudb/PerconaFT/locktree/manager.cc index 6bb5c77bf32..21f8dc6cf01 100644 --- a/storage/tokudb/PerconaFT/locktree/manager.cc +++ b/storage/tokudb/PerconaFT/locktree/manager.cc @@ -32,6 +32,19 @@ Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved. You should have received a copy of the GNU Affero General Public License along with PerconaFT. If not, see <http://www.gnu.org/licenses/>. + +---------------------------------------- + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and ======= */ #ident "Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved." diff --git a/storage/tokudb/PerconaFT/locktree/range_buffer.cc b/storage/tokudb/PerconaFT/locktree/range_buffer.cc index 3ddfd0faf97..d1f14fc4a52 100644 --- a/storage/tokudb/PerconaFT/locktree/range_buffer.cc +++ b/storage/tokudb/PerconaFT/locktree/range_buffer.cc @@ -32,6 +32,19 @@ Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved. You should have received a copy of the GNU Affero General Public License along with PerconaFT. If not, see <http://www.gnu.org/licenses/>. + +---------------------------------------- + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and ======= */ #ident "Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved." diff --git a/storage/tokudb/PerconaFT/locktree/range_buffer.h b/storage/tokudb/PerconaFT/locktree/range_buffer.h index b0e36968e73..811b0f85e69 100644 --- a/storage/tokudb/PerconaFT/locktree/range_buffer.h +++ b/storage/tokudb/PerconaFT/locktree/range_buffer.h @@ -32,6 +32,19 @@ Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved. You should have received a copy of the GNU Affero General Public License along with PerconaFT. If not, see <http://www.gnu.org/licenses/>. + +---------------------------------------- + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and ======= */ #ident "Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved." diff --git a/storage/tokudb/PerconaFT/locktree/treenode.cc b/storage/tokudb/PerconaFT/locktree/treenode.cc index cc3a4969643..0247242f975 100644 --- a/storage/tokudb/PerconaFT/locktree/treenode.cc +++ b/storage/tokudb/PerconaFT/locktree/treenode.cc @@ -32,6 +32,19 @@ Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved. You should have received a copy of the GNU Affero General Public License along with PerconaFT. If not, see <http://www.gnu.org/licenses/>. + +---------------------------------------- + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and ======= */ #ident "Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved." diff --git a/storage/tokudb/PerconaFT/locktree/treenode.h b/storage/tokudb/PerconaFT/locktree/treenode.h index 08aad2b6636..981e8b5a9cf 100644 --- a/storage/tokudb/PerconaFT/locktree/treenode.h +++ b/storage/tokudb/PerconaFT/locktree/treenode.h @@ -32,6 +32,19 @@ Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved. You should have received a copy of the GNU Affero General Public License along with PerconaFT. If not, see <http://www.gnu.org/licenses/>. + +---------------------------------------- + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and ======= */ #ident "Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved." diff --git a/storage/tokudb/PerconaFT/locktree/txnid_set.cc b/storage/tokudb/PerconaFT/locktree/txnid_set.cc index 82b59453156..bd4e9723155 100644 --- a/storage/tokudb/PerconaFT/locktree/txnid_set.cc +++ b/storage/tokudb/PerconaFT/locktree/txnid_set.cc @@ -32,6 +32,19 @@ Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved. You should have received a copy of the GNU Affero General Public License along with PerconaFT. If not, see <http://www.gnu.org/licenses/>. + +---------------------------------------- + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and ======= */ #ident "Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved." diff --git a/storage/tokudb/PerconaFT/locktree/txnid_set.h b/storage/tokudb/PerconaFT/locktree/txnid_set.h index 109d7f798e4..81fd45b6dde 100644 --- a/storage/tokudb/PerconaFT/locktree/txnid_set.h +++ b/storage/tokudb/PerconaFT/locktree/txnid_set.h @@ -32,6 +32,19 @@ Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved. You should have received a copy of the GNU Affero General Public License along with PerconaFT. If not, see <http://www.gnu.org/licenses/>. + +---------------------------------------- + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and ======= */ #ident "Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved." diff --git a/storage/tokudb/PerconaFT/locktree/wfg.cc b/storage/tokudb/PerconaFT/locktree/wfg.cc index 9a234f50060..26b7a3b5295 100644 --- a/storage/tokudb/PerconaFT/locktree/wfg.cc +++ b/storage/tokudb/PerconaFT/locktree/wfg.cc @@ -32,6 +32,19 @@ Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved. You should have received a copy of the GNU Affero General Public License along with PerconaFT. If not, see <http://www.gnu.org/licenses/>. + +---------------------------------------- + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and ======= */ #ident "Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved." diff --git a/storage/tokudb/PerconaFT/locktree/wfg.h b/storage/tokudb/PerconaFT/locktree/wfg.h index c56886e1362..5c1599592e6 100644 --- a/storage/tokudb/PerconaFT/locktree/wfg.h +++ b/storage/tokudb/PerconaFT/locktree/wfg.h @@ -32,6 +32,19 @@ Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved. You should have received a copy of the GNU Affero General Public License along with PerconaFT. If not, see <http://www.gnu.org/licenses/>. + +---------------------------------------- + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and ======= */ #ident "Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved." diff --git a/storage/tokudb/PerconaFT/portability/toku_instr_mysql.cc b/storage/tokudb/PerconaFT/portability/toku_instr_mysql.cc index d742555f878..786a6ef0546 100644 --- a/storage/tokudb/PerconaFT/portability/toku_instr_mysql.cc +++ b/storage/tokudb/PerconaFT/portability/toku_instr_mysql.cc @@ -184,9 +184,9 @@ void toku_instr_file_io_end(toku_io_instrumentation &io_instr, ssize_t count) { void toku_instr_mutex_init(const toku_instr_key &key, toku_mutex_t &mutex) { mutex.psi_mutex = PSI_MUTEX_CALL(init_mutex)(key.id(), &mutex.pmutex); -#if TOKU_PTHREAD_DEBUG +#if defined(TOKU_PTHREAD_DEBUG) mutex.instr_key_id = key.id(); -#endif +#endif // defined(TOKU_PTHREAD_DEBUG) } void toku_instr_mutex_destroy(PSI_mutex *&mutex_instr) { @@ -242,9 +242,9 @@ void toku_instr_mutex_unlock(PSI_mutex *mutex_instr) { void toku_instr_cond_init(const toku_instr_key &key, toku_cond_t &cond) { cond.psi_cond = PSI_COND_CALL(init_cond)(key.id(), &cond.pcond); -#if TOKU_PTHREAD_DEBUG +#if defined(TOKU_PTHREAD_DEBUG) cond.instr_key_id = key.id(); -#endif +#endif // // defined(TOKU_PTHREAD_DEBUG) } void toku_instr_cond_destroy(PSI_cond *&cond_instr) { @@ -295,9 +295,9 @@ void toku_instr_cond_broadcast(const toku_cond_t &cond) { void toku_instr_rwlock_init(const toku_instr_key &key, toku_pthread_rwlock_t &rwlock) { rwlock.psi_rwlock = PSI_RWLOCK_CALL(init_rwlock)(key.id(), &rwlock.rwlock); -#if TOKU_PTHREAD_DEBUG +#if defined(TOKU_PTHREAD_DEBUG) rwlock.instr_key_id = key.id(); -#endif +#endif // defined(TOKU_PTHREAD_DEBUG) } void toku_instr_rwlock_destroy(PSI_rwlock *&rwlock_instr) { diff --git a/storage/tokudb/PerconaFT/portability/toku_instr_mysql.h b/storage/tokudb/PerconaFT/portability/toku_instr_mysql.h index d6b0ed35ce9..beb833a163c 100644 --- a/storage/tokudb/PerconaFT/portability/toku_instr_mysql.h +++ b/storage/tokudb/PerconaFT/portability/toku_instr_mysql.h @@ -12,8 +12,15 @@ // undefine them here to avoid compilation errors. #undef __STDC_FORMAT_MACROS #undef __STDC_LIMIT_MACROS -#include <mysql/psi/mysql_file.h> // PSI_file -#include <mysql/psi/mysql_thread.h> // PSI_mutex +#include "mysql/psi/mysql_file.h" // PSI_file +#include "mysql/psi/mysql_thread.h" // PSI_mutex +#include "mysql/psi/mysql_stage.h" // PSI_stage + +#if (MYSQL_VERSION_ID >= 80000) && ( MYSQL_VERSION_ID <= 100000) +#include "mysql/psi/mysql_cond.h" +#include "mysql/psi/mysql_mutex.h" +#include "mysql/psi/mysql_rwlock.h" +#endif // (MYSQL_VERSION_ID >= nn) #ifndef HAVE_PSI_MUTEX_INTERFACE #error HAVE_PSI_MUTEX_INTERFACE required diff --git a/storage/tokudb/PerconaFT/portability/toku_pthread.h b/storage/tokudb/PerconaFT/portability/toku_pthread.h index a0dfcc246a7..d05c6fabf53 100644 --- a/storage/tokudb/PerconaFT/portability/toku_pthread.h +++ b/storage/tokudb/PerconaFT/portability/toku_pthread.h @@ -64,23 +64,23 @@ struct toku_mutex_t { pthread_mutex_t pmutex; struct PSI_mutex *psi_mutex; /* The performance schema instrumentation hook */ -#if TOKU_PTHREAD_DEBUG +#if defined(TOKU_PTHREAD_DEBUG) pthread_t owner; // = pthread_self(); // for debugging bool locked; bool valid; pfs_key_t instr_key_id; -#endif +#endif // defined(TOKU_PTHREAD_DEBUG) }; struct toku_cond_t { pthread_cond_t pcond; struct PSI_cond *psi_cond; -#if TOKU_PTHREAD_DEBUG +#if defined(TOKU_PTHREAD_DEBUG) pfs_key_t instr_key_id; -#endif +#endif // defined(TOKU_PTHREAD_DEBUG) }; -#ifdef TOKU_PTHREAD_DEBUG +#if defined(TOKU_PTHREAD_DEBUG) #define TOKU_COND_INITIALIZER \ { \ .pcond = PTHREAD_COND_INITIALIZER, .psi_cond = nullptr, \ @@ -89,14 +89,14 @@ struct toku_cond_t { #else #define TOKU_COND_INITIALIZER \ { .pcond = PTHREAD_COND_INITIALIZER, .psi_cond = nullptr } -#endif +#endif // defined(TOKU_PTHREAD_DEBUG) struct toku_pthread_rwlock_t { pthread_rwlock_t rwlock; struct PSI_rwlock *psi_rwlock; -#if TOKU_PTHREAD_DEBUG +#if defined(TOKU_PTHREAD_DEBUG) pfs_key_t instr_key_id; -#endif +#endif // defined(TOKU_PTHREAD_DEBUG) }; typedef struct toku_mutex_aligned { @@ -117,7 +117,7 @@ typedef struct toku_mutex_aligned { #define ZERO_MUTEX_INITIALIZER \ {} -#if TOKU_PTHREAD_DEBUG +#if defined(TOKU_PTHREAD_DEBUG) #define TOKU_MUTEX_INITIALIZER \ { \ .pmutex = PTHREAD_MUTEX_INITIALIZER, .psi_mutex = nullptr, .owner = 0, \ @@ -126,12 +126,12 @@ typedef struct toku_mutex_aligned { #else #define TOKU_MUTEX_INITIALIZER \ { .pmutex = PTHREAD_MUTEX_INITIALIZER, .psi_mutex = nullptr } -#endif +#endif // defined(TOKU_PTHREAD_DEBUG) // Darwin doesn't provide adaptive mutexes #if defined(__APPLE__) #define TOKU_MUTEX_ADAPTIVE PTHREAD_MUTEX_DEFAULT -#if TOKU_PTHREAD_DEBUG +#if defined(TOKU_PTHREAD_DEBUG) #define TOKU_ADAPTIVE_MUTEX_INITIALIZER \ { \ .pmutex = PTHREAD_MUTEX_INITIALIZER, .psi_mutex = nullptr, .owner = 0, \ @@ -140,10 +140,10 @@ typedef struct toku_mutex_aligned { #else #define TOKU_ADAPTIVE_MUTEX_INITIALIZER \ { .pmutex = PTHREAD_MUTEX_INITIALIZER, .psi_mutex = nullptr } -#endif +#endif // defined(TOKU_PTHREAD_DEBUG) #else // __FreeBSD__, __linux__, at least #define TOKU_MUTEX_ADAPTIVE PTHREAD_MUTEX_ADAPTIVE_NP -#if TOKU_PTHREAD_DEBUG +#if defined(TOKU_PTHREAD_DEBUG) #define TOKU_ADAPTIVE_MUTEX_INITIALIZER \ { \ .pmutex = PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP, .psi_mutex = nullptr, \ @@ -152,8 +152,8 @@ typedef struct toku_mutex_aligned { #else #define TOKU_ADAPTIVE_MUTEX_INITIALIZER \ { .pmutex = PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP, .psi_mutex = nullptr } -#endif -#endif +#endif // defined(TOKU_PTHREAD_DEBUG) +#endif // defined(__APPLE__) // Different OSes implement mutexes as different amounts of nested structs. // C++ will fill out all missing values with zeroes if you provide at least one @@ -198,7 +198,7 @@ toku_mutexattr_destroy(toku_pthread_mutexattr_t *attr) { assert_zero(r); } -#if TOKU_PTHREAD_DEBUG +#if defined(TOKU_PTHREAD_DEBUG) static inline void toku_mutex_assert_locked(const toku_mutex_t *mutex) { invariant(mutex->locked); invariant(mutex->owner == pthread_self()); @@ -207,7 +207,7 @@ static inline void toku_mutex_assert_locked(const toku_mutex_t *mutex) { static inline void toku_mutex_assert_locked(const toku_mutex_t *mutex __attribute__((unused))) { } -#endif +#endif // defined(TOKU_PTHREAD_DEBUG) // asserting that a mutex is unlocked only makes sense // if the calling thread can guaruntee that no other threads @@ -217,7 +217,7 @@ toku_mutex_assert_locked(const toku_mutex_t *mutex __attribute__((unused))) { // when a node is locked the caller knows that no other threads // can be trying to lock its childrens' mutexes. the children // are in one of two fixed states: locked or unlocked. -#if TOKU_PTHREAD_DEBUG +#if defined(TOKU_PTHREAD_DEBUG) static inline void toku_mutex_assert_unlocked(toku_mutex_t *mutex) { invariant(mutex->owner == 0); @@ -226,7 +226,7 @@ toku_mutex_assert_unlocked(toku_mutex_t *mutex) { #else static inline void toku_mutex_assert_unlocked(toku_mutex_t *mutex __attribute__((unused))) {} -#endif +#endif // defined(TOKU_PTHREAD_DEBUG) #define toku_mutex_lock(M) \ toku_mutex_lock_with_source_location(M, __FILE__, __LINE__) @@ -241,13 +241,13 @@ static inline void toku_cond_init(toku_cond_t *cond, toku_mutex_trylock_with_source_location(M, __FILE__, __LINE__) inline void toku_mutex_unlock(toku_mutex_t *mutex) { -#if TOKU_PTHREAD_DEBUG +#if defined(TOKU_PTHREAD_DEBUG) invariant(mutex->owner == pthread_self()); invariant(mutex->valid); invariant(mutex->locked); mutex->locked = false; mutex->owner = 0; -#endif +#endif // defined(TOKU_PTHREAD_DEBUG) toku_instr_mutex_unlock(mutex->psi_mutex); int r = pthread_mutex_unlock(&mutex->pmutex); assert_zero(r); @@ -264,13 +264,13 @@ inline void toku_mutex_lock_with_source_location(toku_mutex_t *mutex, toku_instr_mutex_lock_end(mutex_instr, r); assert_zero(r); -#if TOKU_PTHREAD_DEBUG +#if defined(TOKU_PTHREAD_DEBUG) invariant(mutex->valid); invariant(!mutex->locked); invariant(mutex->owner == 0); mutex->locked = true; mutex->owner = pthread_self(); -#endif +#endif // defined(TOKU_PTHREAD_DEBUG) } inline int toku_mutex_trylock_with_source_location(toku_mutex_t *mutex, @@ -283,7 +283,7 @@ inline int toku_mutex_trylock_with_source_location(toku_mutex_t *mutex, const int r = pthread_mutex_lock(&mutex->pmutex); toku_instr_mutex_lock_end(mutex_instr, r); -#if TOKU_PTHREAD_DEBUG +#if defined(TOKU_PTHREAD_DEBUG) if (r == 0) { invariant(mutex->valid); invariant(!mutex->locked); @@ -291,7 +291,7 @@ inline int toku_mutex_trylock_with_source_location(toku_mutex_t *mutex, mutex->locked = true; mutex->owner = pthread_self(); } -#endif +#endif // defined(TOKU_PTHREAD_DEBUG) return r; } @@ -320,11 +320,11 @@ inline void toku_cond_wait_with_source_location(toku_cond_t *cond, const char *src_file, uint src_line) { -#if TOKU_PTHREAD_DEBUG +#if defined(TOKU_PTHREAD_DEBUG) invariant(mutex->locked); mutex->locked = false; mutex->owner = 0; -#endif +#endif // defined(TOKU_PTHREAD_DEBUG) /* Instrumentation start */ toku_cond_instrumentation cond_instr; @@ -342,11 +342,11 @@ inline void toku_cond_wait_with_source_location(toku_cond_t *cond, toku_instr_cond_wait_end(cond_instr, r); assert_zero(r); -#if TOKU_PTHREAD_DEBUG +#if defined(TOKU_PTHREAD_DEBUG) invariant(!mutex->locked); mutex->locked = true; mutex->owner = pthread_self(); -#endif +#endif // defined(TOKU_PTHREAD_DEBUG) } inline int toku_cond_timedwait_with_source_location(toku_cond_t *cond, @@ -354,11 +354,11 @@ inline int toku_cond_timedwait_with_source_location(toku_cond_t *cond, toku_timespec_t *wakeup_at, const char *src_file, uint src_line) { -#if TOKU_PTHREAD_DEBUG +#if defined(TOKU_PTHREAD_DEBUG) invariant(mutex->locked); mutex->locked = false; mutex->owner = 0; -#endif +#endif // defined(TOKU_PTHREAD_DEBUG) /* Instrumentation start */ toku_cond_instrumentation cond_instr; @@ -376,11 +376,11 @@ inline int toku_cond_timedwait_with_source_location(toku_cond_t *cond, /* Instrumentation end */ toku_instr_cond_wait_end(cond_instr, r); -#if TOKU_PTHREAD_DEBUG +#if defined(TOKU_PTHREAD_DEBUG) invariant(!mutex->locked); mutex->locked = true; mutex->owner = pthread_self(); -#endif +#endif // defined(TOKU_PTHREAD_DEBUG) return r; } @@ -399,26 +399,26 @@ inline void toku_cond_broadcast(toku_cond_t *cond) { inline void toku_mutex_init(const toku_instr_key &key, toku_mutex_t *mutex, const toku_pthread_mutexattr_t *attr) { -#if TOKU_PTHREAD_DEBUG +#if defined(TOKU_PTHREAD_DEBUG) mutex->valid = true; -#endif +#endif // defined(TOKU_PTHREAD_DEBUG) toku_instr_mutex_init(key, *mutex); const int r = pthread_mutex_init(&mutex->pmutex, attr); assert_zero(r); -#if TOKU_PTHREAD_DEBUG +#if defined(TOKU_PTHREAD_DEBUG) mutex->locked = false; invariant(mutex->valid); mutex->valid = true; mutex->owner = 0; -#endif +#endif // defined(TOKU_PTHREAD_DEBUG) } inline void toku_mutex_destroy(toku_mutex_t *mutex) { -#if TOKU_PTHREAD_DEBUG +#if defined(TOKU_PTHREAD_DEBUG) invariant(mutex->valid); mutex->valid = false; invariant(!mutex->locked); -#endif +#endif // defined(TOKU_PTHREAD_DEBUG) toku_instr_mutex_destroy(mutex->psi_mutex); int r = pthread_mutex_destroy(&mutex->pmutex); assert_zero(r); diff --git a/storage/tokudb/PerconaFT/util/growable_array.h b/storage/tokudb/PerconaFT/util/growable_array.h index e8873ae4abd..ad60ea6395b 100644 --- a/storage/tokudb/PerconaFT/util/growable_array.h +++ b/storage/tokudb/PerconaFT/util/growable_array.h @@ -32,6 +32,19 @@ Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved. You should have received a copy of the GNU Affero General Public License along with PerconaFT. If not, see <http://www.gnu.org/licenses/>. + +---------------------------------------- + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and ======= */ #ident "Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved." diff --git a/storage/tokudb/PerconaFT/util/omt.cc b/storage/tokudb/PerconaFT/util/omt.cc index 1fae0712c77..846c4df7f54 100644 --- a/storage/tokudb/PerconaFT/util/omt.cc +++ b/storage/tokudb/PerconaFT/util/omt.cc @@ -32,1105 +32,1356 @@ Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved. You should have received a copy of the GNU Affero General Public License along with PerconaFT. If not, see <http://www.gnu.org/licenses/>. + +---------------------------------------- + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and ======= */ -#ident "Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved." +#ident \ + "Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved." -#include <string.h> #include <db.h> +#include <string.h> #include <portability/memory.h> namespace toku { -template<typename omtdata_t, typename omtdataout_t, bool supports_marks> -void omt<omtdata_t, omtdataout_t, supports_marks>::create(void) { - this->create_internal(2); - if (supports_marks) { - this->convert_to_tree(); + template <typename omtdata_t, typename omtdataout_t, bool supports_marks> + void omt<omtdata_t, omtdataout_t, supports_marks>::create(void) { + this->create_internal(2); + if (supports_marks) { + this->convert_to_tree(); + } } -} -template<typename omtdata_t, typename omtdataout_t, bool supports_marks> -void omt<omtdata_t, omtdataout_t, supports_marks>::create_no_array(void) { - if (!supports_marks) { - this->create_internal_no_array(0); - } else { - this->is_array = false; - this->capacity = 0; - this->d.t.nodes = nullptr; - this->d.t.root.set_to_null(); - this->d.t.free_idx = 0; - } -} - -template<typename omtdata_t, typename omtdataout_t, bool supports_marks> -void omt<omtdata_t, omtdataout_t, supports_marks>::create_from_sorted_array(const omtdata_t *const values, const uint32_t numvalues) { - this->create_internal(numvalues); - memcpy(this->d.a.values, values, numvalues * (sizeof values[0])); - this->d.a.num_values = numvalues; - if (supports_marks) { - this->convert_to_tree(); - } -} - -template<typename omtdata_t, typename omtdataout_t, bool supports_marks> -void omt<omtdata_t, omtdataout_t, supports_marks>::create_steal_sorted_array(omtdata_t **const values, const uint32_t numvalues, const uint32_t new_capacity) { - paranoid_invariant_notnull(values); - this->create_internal_no_array(new_capacity); - this->d.a.num_values = numvalues; - this->d.a.values = *values; - *values = nullptr; - if (supports_marks) { - this->convert_to_tree(); - } -} - -template<typename omtdata_t, typename omtdataout_t, bool supports_marks> -int omt<omtdata_t, omtdataout_t, supports_marks>::split_at(omt *const newomt, const uint32_t idx) { - barf_if_marked(*this); - paranoid_invariant_notnull(newomt); - if (idx > this->size()) { return EINVAL; } - this->convert_to_array(); - const uint32_t newsize = this->size() - idx; - newomt->create_from_sorted_array(&this->d.a.values[this->d.a.start_idx + idx], newsize); - this->d.a.num_values = idx; - this->maybe_resize_array(idx); - if (supports_marks) { - this->convert_to_tree(); - } - return 0; -} - -template<typename omtdata_t, typename omtdataout_t, bool supports_marks> -void omt<omtdata_t, omtdataout_t, supports_marks>::merge(omt *const leftomt, omt *const rightomt) { - barf_if_marked(*this); - paranoid_invariant_notnull(leftomt); - paranoid_invariant_notnull(rightomt); - const uint32_t leftsize = leftomt->size(); - const uint32_t rightsize = rightomt->size(); - const uint32_t newsize = leftsize + rightsize; - - if (leftomt->is_array) { - if (leftomt->capacity - (leftomt->d.a.start_idx + leftomt->d.a.num_values) >= rightsize) { - this->create_steal_sorted_array(&leftomt->d.a.values, leftomt->d.a.num_values, leftomt->capacity); - this->d.a.start_idx = leftomt->d.a.start_idx; + template <typename omtdata_t, typename omtdataout_t, bool supports_marks> + void omt<omtdata_t, omtdataout_t, supports_marks>::create_no_array(void) { + if (!supports_marks) { + this->create_internal_no_array(0); + } else { + this->is_array = false; + this->capacity = 0; + this->d.t.nodes = nullptr; + this->d.t.root.set_to_null(); + this->d.t.free_idx = 0; + } + } + + template <typename omtdata_t, typename omtdataout_t, bool supports_marks> + void omt<omtdata_t, omtdataout_t, supports_marks>::create_from_sorted_array( + const omtdata_t *const values, + const uint32_t numvalues) { + this->create_internal(numvalues); + memcpy(this->d.a.values, values, numvalues * (sizeof values[0])); + this->d.a.num_values = numvalues; + if (supports_marks) { + this->convert_to_tree(); + } + } + + template <typename omtdata_t, typename omtdataout_t, bool supports_marks> + void + omt<omtdata_t, omtdataout_t, supports_marks>::create_steal_sorted_array( + omtdata_t **const values, + const uint32_t numvalues, + const uint32_t new_capacity) { + paranoid_invariant_notnull(values); + this->create_internal_no_array(new_capacity); + this->d.a.num_values = numvalues; + this->d.a.values = *values; + *values = nullptr; + if (supports_marks) { + this->convert_to_tree(); + } + } + + template <typename omtdata_t, typename omtdataout_t, bool supports_marks> + int omt<omtdata_t, omtdataout_t, supports_marks>::split_at( + omt *const newomt, + const uint32_t idx) { + barf_if_marked(*this); + paranoid_invariant_notnull(newomt); + if (idx > this->size()) { + return EINVAL; + } + this->convert_to_array(); + const uint32_t newsize = this->size() - idx; + newomt->create_from_sorted_array( + &this->d.a.values[this->d.a.start_idx + idx], newsize); + this->d.a.num_values = idx; + this->maybe_resize_array(idx); + if (supports_marks) { + this->convert_to_tree(); + } + return 0; + } + + template <typename omtdata_t, typename omtdataout_t, bool supports_marks> + void omt<omtdata_t, omtdataout_t, supports_marks>::merge( + omt *const leftomt, + omt *const rightomt) { + barf_if_marked(*this); + paranoid_invariant_notnull(leftomt); + paranoid_invariant_notnull(rightomt); + const uint32_t leftsize = leftomt->size(); + const uint32_t rightsize = rightomt->size(); + const uint32_t newsize = leftsize + rightsize; + + if (leftomt->is_array) { + if (leftomt->capacity - + (leftomt->d.a.start_idx + leftomt->d.a.num_values) >= + rightsize) { + this->create_steal_sorted_array(&leftomt->d.a.values, + leftomt->d.a.num_values, + leftomt->capacity); + this->d.a.start_idx = leftomt->d.a.start_idx; + } else { + this->create_internal(newsize); + memcpy(&this->d.a.values[0], + &leftomt->d.a.values[leftomt->d.a.start_idx], + leftomt->d.a.num_values * (sizeof this->d.a.values[0])); + } } else { this->create_internal(newsize); + leftomt->fill_array_with_subtree_values(&this->d.a.values[0], + leftomt->d.t.root); + } + leftomt->destroy(); + this->d.a.num_values = leftsize; + + if (rightomt->is_array) { + memcpy( + &this->d.a.values[this->d.a.start_idx + this->d.a.num_values], + &rightomt->d.a.values[rightomt->d.a.start_idx], + rightomt->d.a.num_values * (sizeof this->d.a.values[0])); + } else { + rightomt->fill_array_with_subtree_values( + &this->d.a.values[this->d.a.start_idx + this->d.a.num_values], + rightomt->d.t.root); + } + rightomt->destroy(); + this->d.a.num_values += rightsize; + paranoid_invariant(this->size() == newsize); + if (supports_marks) { + this->convert_to_tree(); + } + } + + template <typename omtdata_t, typename omtdataout_t, bool supports_marks> + void omt<omtdata_t, omtdataout_t, supports_marks>::clone(const omt &src) { + barf_if_marked(*this); + this->create_internal(src.size()); + if (src.is_array) { memcpy(&this->d.a.values[0], - &leftomt->d.a.values[leftomt->d.a.start_idx], - leftomt->d.a.num_values * (sizeof this->d.a.values[0])); - } - } else { - this->create_internal(newsize); - leftomt->fill_array_with_subtree_values(&this->d.a.values[0], leftomt->d.t.root); - } - leftomt->destroy(); - this->d.a.num_values = leftsize; - - if (rightomt->is_array) { - memcpy(&this->d.a.values[this->d.a.start_idx + this->d.a.num_values], - &rightomt->d.a.values[rightomt->d.a.start_idx], - rightomt->d.a.num_values * (sizeof this->d.a.values[0])); - } else { - rightomt->fill_array_with_subtree_values(&this->d.a.values[this->d.a.start_idx + this->d.a.num_values], - rightomt->d.t.root); - } - rightomt->destroy(); - this->d.a.num_values += rightsize; - paranoid_invariant(this->size() == newsize); - if (supports_marks) { - this->convert_to_tree(); - } -} - -template<typename omtdata_t, typename omtdataout_t, bool supports_marks> -void omt<omtdata_t, omtdataout_t, supports_marks>::clone(const omt &src) { - barf_if_marked(*this); - this->create_internal(src.size()); - if (src.is_array) { - memcpy(&this->d.a.values[0], &src.d.a.values[src.d.a.start_idx], src.d.a.num_values * (sizeof this->d.a.values[0])); - } else { - src.fill_array_with_subtree_values(&this->d.a.values[0], src.d.t.root); - } - this->d.a.num_values = src.size(); - if (supports_marks) { - this->convert_to_tree(); - } -} - -template<typename omtdata_t, typename omtdataout_t, bool supports_marks> -void omt<omtdata_t, omtdataout_t, supports_marks>::clear(void) { - if (this->is_array) { - this->d.a.start_idx = 0; - this->d.a.num_values = 0; - } else { - this->d.t.root.set_to_null(); - this->d.t.free_idx = 0; - } -} - -template<typename omtdata_t, typename omtdataout_t, bool supports_marks> -void omt<omtdata_t, omtdataout_t, supports_marks>::destroy(void) { - this->clear(); - this->capacity = 0; - if (this->is_array) { - if (this->d.a.values != nullptr) { - toku_free(this->d.a.values); + &src.d.a.values[src.d.a.start_idx], + src.d.a.num_values * (sizeof this->d.a.values[0])); + } else { + src.fill_array_with_subtree_values(&this->d.a.values[0], + src.d.t.root); } - this->d.a.values = nullptr; - } else { - if (this->d.t.nodes != nullptr) { - toku_free(this->d.t.nodes); + this->d.a.num_values = src.size(); + if (supports_marks) { + this->convert_to_tree(); + } + } + + template <typename omtdata_t, typename omtdataout_t, bool supports_marks> + void omt<omtdata_t, omtdataout_t, supports_marks>::clear(void) { + if (this->is_array) { + this->d.a.start_idx = 0; + this->d.a.num_values = 0; + } else { + this->d.t.root.set_to_null(); + this->d.t.free_idx = 0; + } + } + + template <typename omtdata_t, typename omtdataout_t, bool supports_marks> + void omt<omtdata_t, omtdataout_t, supports_marks>::destroy(void) { + this->clear(); + this->capacity = 0; + if (this->is_array) { + if (this->d.a.values != nullptr) { + toku_free(this->d.a.values); + } + this->d.a.values = nullptr; + } else { + if (this->d.t.nodes != nullptr) { + toku_free(this->d.t.nodes); + } + this->d.t.nodes = nullptr; } - this->d.t.nodes = nullptr; } -} -template<typename omtdata_t, typename omtdataout_t, bool supports_marks> -uint32_t omt<omtdata_t, omtdataout_t, supports_marks>::size(void) const { - if (this->is_array) { - return this->d.a.num_values; - } else { - return this->nweight(this->d.t.root); + template <typename omtdata_t, typename omtdataout_t, bool supports_marks> + uint32_t omt<omtdata_t, omtdataout_t, supports_marks>::size(void) const { + if (this->is_array) { + return this->d.a.num_values; + } else { + return this->nweight(this->d.t.root); + } } -} + template <typename omtdata_t, typename omtdataout_t, bool supports_marks> + template <typename omtcmp_t, int (*h)(const omtdata_t &, const omtcmp_t &)> + int omt<omtdata_t, omtdataout_t, supports_marks>::insert( + const omtdata_t &value, + const omtcmp_t &v, + uint32_t *const idx) { + int r; + uint32_t insert_idx; -template<typename omtdata_t, typename omtdataout_t, bool supports_marks> -template<typename omtcmp_t, int (*h)(const omtdata_t &, const omtcmp_t &)> -int omt<omtdata_t, omtdataout_t, supports_marks>::insert(const omtdata_t &value, const omtcmp_t &v, uint32_t *const idx) { - int r; - uint32_t insert_idx; + r = this->find_zero<omtcmp_t, h>(v, nullptr, &insert_idx); + if (r == 0) { + if (idx) + *idx = insert_idx; + return DB_KEYEXIST; + } + if (r != DB_NOTFOUND) + return r; - r = this->find_zero<omtcmp_t, h>(v, nullptr, &insert_idx); - if (r==0) { - if (idx) *idx = insert_idx; - return DB_KEYEXIST; + if ((r = this->insert_at(value, insert_idx))) + return r; + if (idx) + *idx = insert_idx; + + return 0; } - if (r != DB_NOTFOUND) return r; - if ((r = this->insert_at(value, insert_idx))) return r; - if (idx) *idx = insert_idx; + // The following 3 functions implement a static if for us. + template <typename omtdata_t, typename omtdataout_t> + static void barf_if_marked( + const omt<omtdata_t, omtdataout_t, false> &UU(omt)) {} - return 0; -} + template <typename omtdata_t, typename omtdataout_t> + static void barf_if_marked(const omt<omtdata_t, omtdataout_t, true> &omt) { + invariant(!omt.has_marks()); + } -// The following 3 functions implement a static if for us. -template<typename omtdata_t, typename omtdataout_t> -static void barf_if_marked(const omt<omtdata_t, omtdataout_t, false> &UU(omt)) { -} + template <typename omtdata_t, typename omtdataout_t, bool supports_marks> + bool omt<omtdata_t, omtdataout_t, supports_marks>::has_marks(void) const { + static_assert(supports_marks, "Does not support marks"); + if (this->d.t.root.is_null()) { + return false; + } + const omt_node &node = this->d.t.nodes[this->d.t.root.get_index()]; + return node.get_marks_below() || node.get_marked(); + } -template<typename omtdata_t, typename omtdataout_t> -static void barf_if_marked(const omt<omtdata_t, omtdataout_t, true> &omt) { - invariant(!omt.has_marks()); -} - -template<typename omtdata_t, typename omtdataout_t, bool supports_marks> -bool omt<omtdata_t, omtdataout_t, supports_marks>::has_marks(void) const { - static_assert(supports_marks, "Does not support marks"); - if (this->d.t.root.is_null()) { - return false; - } - const omt_node &node = this->d.t.nodes[this->d.t.root.get_index()]; - return node.get_marks_below() || node.get_marked(); -} - -template<typename omtdata_t, typename omtdataout_t, bool supports_marks> -int omt<omtdata_t, omtdataout_t, supports_marks>::insert_at(const omtdata_t &value, const uint32_t idx) { - barf_if_marked(*this); - if (idx > this->size()) { return EINVAL; } - - this->maybe_resize_or_convert(this->size() + 1); - if (this->is_array && idx != this->d.a.num_values && - (idx != 0 || this->d.a.start_idx == 0)) { - this->convert_to_tree(); - } - if (this->is_array) { - if (idx == this->d.a.num_values) { - this->d.a.values[this->d.a.start_idx + this->d.a.num_values] = value; - } - else { - this->d.a.values[--this->d.a.start_idx] = value; - } - this->d.a.num_values++; - } - else { - subtree *rebalance_subtree = nullptr; - this->insert_internal(&this->d.t.root, value, idx, &rebalance_subtree); - if (rebalance_subtree != nullptr) { - this->rebalance(rebalance_subtree); - } - } - return 0; -} - -template<typename omtdata_t, typename omtdataout_t, bool supports_marks> -int omt<omtdata_t, omtdataout_t, supports_marks>::set_at(const omtdata_t &value, const uint32_t idx) { - barf_if_marked(*this); - if (idx >= this->size()) { return EINVAL; } - - if (this->is_array) { - this->set_at_internal_array(value, idx); - } else { - this->set_at_internal(this->d.t.root, value, idx); - } - return 0; -} - -template<typename omtdata_t, typename omtdataout_t, bool supports_marks> -int omt<omtdata_t, omtdataout_t, supports_marks>::delete_at(const uint32_t idx) { - barf_if_marked(*this); - if (idx >= this->size()) { return EINVAL; } - - this->maybe_resize_or_convert(this->size() - 1); - if (this->is_array && idx != 0 && idx != this->d.a.num_values - 1) { - this->convert_to_tree(); - } - if (this->is_array) { - //Testing for 0 does not rule out it being the last entry. - //Test explicitly for num_values-1 - if (idx != this->d.a.num_values - 1) { - this->d.a.start_idx++; - } - this->d.a.num_values--; - } else { - subtree *rebalance_subtree = nullptr; - this->delete_internal(&this->d.t.root, idx, nullptr, &rebalance_subtree); - if (rebalance_subtree != nullptr) { - this->rebalance(rebalance_subtree); - } - } - return 0; -} - -template<typename omtdata_t, typename omtdataout_t, bool supports_marks> -template<typename iterate_extra_t, - int (*f)(const omtdata_t &, const uint32_t, iterate_extra_t *const)> -int omt<omtdata_t, omtdataout_t, supports_marks>::iterate(iterate_extra_t *const iterate_extra) const { - return this->iterate_on_range<iterate_extra_t, f>(0, this->size(), iterate_extra); -} - -template<typename omtdata_t, typename omtdataout_t, bool supports_marks> -template<typename iterate_extra_t, - int (*f)(const omtdata_t &, const uint32_t, iterate_extra_t *const)> -int omt<omtdata_t, omtdataout_t, supports_marks>::iterate_on_range(const uint32_t left, const uint32_t right, iterate_extra_t *const iterate_extra) const { - if (right > this->size()) { return EINVAL; } - if (left == right) { return 0; } - if (this->is_array) { - return this->iterate_internal_array<iterate_extra_t, f>(left, right, iterate_extra); - } - return this->iterate_internal<iterate_extra_t, f>(left, right, this->d.t.root, 0, iterate_extra); -} - -template<typename omtdata_t, typename omtdataout_t, bool supports_marks> -template<typename iterate_extra_t, - int (*f)(const omtdata_t &, const uint32_t, iterate_extra_t *const)> -int omt<omtdata_t, omtdataout_t, supports_marks>::iterate_and_mark_range(const uint32_t left, const uint32_t right, iterate_extra_t *const iterate_extra) { - static_assert(supports_marks, "does not support marks"); - if (right > this->size()) { return EINVAL; } - if (left == right) { return 0; } - paranoid_invariant(!this->is_array); - return this->iterate_and_mark_range_internal<iterate_extra_t, f>(left, right, this->d.t.root, 0, iterate_extra); -} - -//TODO: We can optimize this if we steal 3 bits. 1 bit: this node is marked. 1 bit: left subtree has marks. 1 bit: right subtree has marks. -template<typename omtdata_t, typename omtdataout_t, bool supports_marks> -template<typename iterate_extra_t, - int (*f)(const omtdata_t &, const uint32_t, iterate_extra_t *const)> -int omt<omtdata_t, omtdataout_t, supports_marks>::iterate_over_marked(iterate_extra_t *const iterate_extra) const { - static_assert(supports_marks, "does not support marks"); - paranoid_invariant(!this->is_array); - return this->iterate_over_marked_internal<iterate_extra_t, f>(this->d.t.root, 0, iterate_extra); -} - -template<typename omtdata_t, typename omtdataout_t, bool supports_marks> -void omt<omtdata_t, omtdataout_t, supports_marks>::unmark(const subtree &subtree, const uint32_t index, GrowableArray<node_idx> *const indexes) { - if (subtree.is_null()) { return; } - omt_node &n = this->d.t.nodes[subtree.get_index()]; - const uint32_t index_root = index + this->nweight(n.left); - - const bool below = n.get_marks_below(); - if (below) { - this->unmark(n.left, index, indexes); - } - if (n.get_marked()) { - indexes->push(index_root); - } - n.clear_stolen_bits(); - if (below) { - this->unmark(n.right, index_root + 1, indexes); - } -} - -template<typename omtdata_t, typename omtdataout_t, bool supports_marks> -void omt<omtdata_t, omtdataout_t, supports_marks>::delete_all_marked(void) { - static_assert(supports_marks, "does not support marks"); - if (!this->has_marks()) { - return; - } - paranoid_invariant(!this->is_array); - GrowableArray<node_idx> marked_indexes; - marked_indexes.init(); - - // Remove all marks. - // We need to delete all the stolen bits before calling delete_at to prevent barfing. - this->unmark(this->d.t.root, 0, &marked_indexes); - - for (uint32_t i = 0; i < marked_indexes.get_size(); i++) { - // Delete from left to right, shift by number already deleted. - // Alternative is delete from right to left. - int r = this->delete_at(marked_indexes.fetch_unchecked(i) - i); - lazy_assert_zero(r); - } - marked_indexes.deinit(); - barf_if_marked(*this); -} - -template<typename omtdata_t, typename omtdataout_t, bool supports_marks> -uint32_t omt<omtdata_t, omtdataout_t, supports_marks>::verify_marks_consistent_internal(const subtree &subtree, const bool UU(allow_marks)) const { - if (subtree.is_null()) { + template <typename omtdata_t, typename omtdataout_t, bool supports_marks> + int omt<omtdata_t, omtdataout_t, supports_marks>::insert_at( + const omtdata_t &value, + const uint32_t idx) { + barf_if_marked(*this); + if (idx > this->size()) { + return EINVAL; + } + + this->maybe_resize_or_convert(this->size() + 1); + if (this->is_array && idx != this->d.a.num_values && + (idx != 0 || this->d.a.start_idx == 0)) { + this->convert_to_tree(); + } + if (this->is_array) { + if (idx == this->d.a.num_values) { + this->d.a.values[this->d.a.start_idx + this->d.a.num_values] = + value; + } else { + this->d.a.values[--this->d.a.start_idx] = value; + } + this->d.a.num_values++; + } else { + subtree *rebalance_subtree = nullptr; + this->insert_internal( + &this->d.t.root, value, idx, &rebalance_subtree); + if (rebalance_subtree != nullptr) { + this->rebalance(rebalance_subtree); + } + } return 0; } - const omt_node &node = this->d.t.nodes[subtree.get_index()]; - uint32_t num_marks = verify_marks_consistent_internal(node.left, node.get_marks_below()); - num_marks += verify_marks_consistent_internal(node.right, node.get_marks_below()); - if (node.get_marks_below()) { - paranoid_invariant(allow_marks); - paranoid_invariant(num_marks > 0); - } else { - // redundant with invariant below, but nice to have explicitly - paranoid_invariant(num_marks == 0); - } - if (node.get_marked()) { - paranoid_invariant(allow_marks); - ++num_marks; - } - return num_marks; -} - -template<typename omtdata_t, typename omtdataout_t, bool supports_marks> -void omt<omtdata_t, omtdataout_t, supports_marks>::verify_marks_consistent(void) const { - static_assert(supports_marks, "does not support marks"); - paranoid_invariant(!this->is_array); - this->verify_marks_consistent_internal(this->d.t.root, true); -} - -template<typename omtdata_t, typename omtdataout_t, bool supports_marks> -template<typename iterate_extra_t, - int (*f)(omtdata_t *, const uint32_t, iterate_extra_t *const)> -void omt<omtdata_t, omtdataout_t, supports_marks>::iterate_ptr(iterate_extra_t *const iterate_extra) { - if (this->is_array) { - this->iterate_ptr_internal_array<iterate_extra_t, f>(0, this->size(), iterate_extra); - } else { - this->iterate_ptr_internal<iterate_extra_t, f>(0, this->size(), this->d.t.root, 0, iterate_extra); - } -} - -template<typename omtdata_t, typename omtdataout_t, bool supports_marks> -int omt<omtdata_t, omtdataout_t, supports_marks>::fetch(const uint32_t idx, omtdataout_t *const value) const { - if (idx >= this->size()) { return EINVAL; } - if (this->is_array) { - this->fetch_internal_array(idx, value); - } else { - this->fetch_internal(this->d.t.root, idx, value); - } - return 0; -} - -template<typename omtdata_t, typename omtdataout_t, bool supports_marks> -template<typename omtcmp_t, - int (*h)(const omtdata_t &, const omtcmp_t &)> -int omt<omtdata_t, omtdataout_t, supports_marks>::find_zero(const omtcmp_t &extra, omtdataout_t *const value, uint32_t *const idxp) const { - uint32_t tmp_index; - uint32_t *const child_idxp = (idxp != nullptr) ? idxp : &tmp_index; - int r; - if (this->is_array) { - r = this->find_internal_zero_array<omtcmp_t, h>(extra, value, child_idxp); - } - else { - r = this->find_internal_zero<omtcmp_t, h>(this->d.t.root, extra, value, child_idxp); - } - return r; -} - -template<typename omtdata_t, typename omtdataout_t, bool supports_marks> -template<typename omtcmp_t, - int (*h)(const omtdata_t &, const omtcmp_t &)> -int omt<omtdata_t, omtdataout_t, supports_marks>::find(const omtcmp_t &extra, int direction, omtdataout_t *const value, uint32_t *const idxp) const { - uint32_t tmp_index; - uint32_t *const child_idxp = (idxp != nullptr) ? idxp : &tmp_index; - paranoid_invariant(direction != 0); - if (direction < 0) { + + template <typename omtdata_t, typename omtdataout_t, bool supports_marks> + int omt<omtdata_t, omtdataout_t, supports_marks>::set_at( + const omtdata_t &value, + const uint32_t idx) { + barf_if_marked(*this); + if (idx >= this->size()) { + return EINVAL; + } + if (this->is_array) { - return this->find_internal_minus_array<omtcmp_t, h>(extra, value, child_idxp); + this->set_at_internal_array(value, idx); } else { - return this->find_internal_minus<omtcmp_t, h>(this->d.t.root, extra, value, child_idxp); + this->set_at_internal(this->d.t.root, value, idx); + } + return 0; + } + + template <typename omtdata_t, typename omtdataout_t, bool supports_marks> + int omt<omtdata_t, omtdataout_t, supports_marks>::delete_at( + const uint32_t idx) { + barf_if_marked(*this); + if (idx >= this->size()) { + return EINVAL; + } + + this->maybe_resize_or_convert(this->size() - 1); + if (this->is_array && idx != 0 && idx != this->d.a.num_values - 1) { + this->convert_to_tree(); } - } else { if (this->is_array) { - return this->find_internal_plus_array<omtcmp_t, h>(extra, value, child_idxp); + // Testing for 0 does not rule out it being the last entry. + // Test explicitly for num_values-1 + if (idx != this->d.a.num_values - 1) { + this->d.a.start_idx++; + } + this->d.a.num_values--; } else { - return this->find_internal_plus<omtcmp_t, h>(this->d.t.root, extra, value, child_idxp); + subtree *rebalance_subtree = nullptr; + this->delete_internal( + &this->d.t.root, idx, nullptr, &rebalance_subtree); + if (rebalance_subtree != nullptr) { + this->rebalance(rebalance_subtree); + } } + return 0; } -} -template<typename omtdata_t, typename omtdataout_t, bool supports_marks> -size_t omt<omtdata_t, omtdataout_t, supports_marks>::memory_size(void) { - if (this->is_array) { - return (sizeof *this) + this->capacity * (sizeof this->d.a.values[0]); + template <typename omtdata_t, typename omtdataout_t, bool supports_marks> + template < + typename iterate_extra_t, + int (*f)(const omtdata_t &, const uint32_t, iterate_extra_t *const)> + int omt<omtdata_t, omtdataout_t, supports_marks>::iterate( + iterate_extra_t *const iterate_extra) const { + return this->iterate_on_range<iterate_extra_t, f>( + 0, this->size(), iterate_extra); + } + + template <typename omtdata_t, typename omtdataout_t, bool supports_marks> + template < + typename iterate_extra_t, + int (*f)(const omtdata_t &, const uint32_t, iterate_extra_t *const)> + int omt<omtdata_t, omtdataout_t, supports_marks>::iterate_on_range( + const uint32_t left, + const uint32_t right, + iterate_extra_t *const iterate_extra) const { + if (right > this->size()) { + return EINVAL; + } + if (left == right) { + return 0; + } + if (this->is_array) { + return this->iterate_internal_array<iterate_extra_t, f>( + left, right, iterate_extra); + } + return this->iterate_internal<iterate_extra_t, f>( + left, right, this->d.t.root, 0, iterate_extra); + } + + template <typename omtdata_t, typename omtdataout_t, bool supports_marks> + template < + typename iterate_extra_t, + int (*f)(const omtdata_t &, const uint32_t, iterate_extra_t *const)> + int omt<omtdata_t, omtdataout_t, supports_marks>::iterate_and_mark_range( + const uint32_t left, + const uint32_t right, + iterate_extra_t *const iterate_extra) { + static_assert(supports_marks, "does not support marks"); + if (right > this->size()) { + return EINVAL; + } + if (left == right) { + return 0; + } + paranoid_invariant(!this->is_array); + return this->iterate_and_mark_range_internal<iterate_extra_t, f>( + left, right, this->d.t.root, 0, iterate_extra); + } + + // TODO: We can optimize this if we steal 3 bits. 1 bit: this node is + // marked. 1 bit: left subtree has marks. 1 bit: right subtree has marks. + template <typename omtdata_t, typename omtdataout_t, bool supports_marks> + template < + typename iterate_extra_t, + int (*f)(const omtdata_t &, const uint32_t, iterate_extra_t *const)> + int omt<omtdata_t, omtdataout_t, supports_marks>::iterate_over_marked( + iterate_extra_t *const iterate_extra) const { + static_assert(supports_marks, "does not support marks"); + paranoid_invariant(!this->is_array); + return this->iterate_over_marked_internal<iterate_extra_t, f>( + this->d.t.root, 0, iterate_extra); + } + + template <typename omtdata_t, typename omtdataout_t, bool supports_marks> + void omt<omtdata_t, omtdataout_t, supports_marks>::unmark( + const subtree &st, + const uint32_t index, + GrowableArray<node_idx> *const indexes) { + if (st.is_null()) { + return; + } + omt_node &n = this->d.t.nodes[st.get_index()]; + const uint32_t index_root = index + this->nweight(n.left); + + const bool below = n.get_marks_below(); + if (below) { + this->unmark(n.left, index, indexes); + } + if (n.get_marked()) { + indexes->push(index_root); + } + n.clear_stolen_bits(); + if (below) { + this->unmark(n.right, index_root + 1, indexes); + } } - return (sizeof *this) + this->capacity * (sizeof this->d.t.nodes[0]); -} + template <typename omtdata_t, typename omtdataout_t, bool supports_marks> + void omt<omtdata_t, omtdataout_t, supports_marks>::delete_all_marked(void) { + static_assert(supports_marks, "does not support marks"); + if (!this->has_marks()) { + return; + } + paranoid_invariant(!this->is_array); + GrowableArray<node_idx> marked_indexes; + marked_indexes.init(); + + // Remove all marks. + // We need to delete all the stolen bits before calling delete_at to + // prevent barfing. + this->unmark(this->d.t.root, 0, &marked_indexes); + + for (uint32_t i = 0; i < marked_indexes.get_size(); i++) { + // Delete from left to right, shift by number already deleted. + // Alternative is delete from right to left. + int r = this->delete_at(marked_indexes.fetch_unchecked(i) - i); + lazy_assert_zero(r); + } + marked_indexes.deinit(); + barf_if_marked(*this); + } -template<typename omtdata_t, typename omtdataout_t, bool supports_marks> -void omt<omtdata_t, omtdataout_t, supports_marks>::create_internal_no_array(const uint32_t new_capacity) { - this->is_array = true; - this->d.a.start_idx = 0; - this->d.a.num_values = 0; - this->d.a.values = nullptr; - this->capacity = new_capacity; -} + template <typename omtdata_t, typename omtdataout_t, bool supports_marks> + uint32_t omt<omtdata_t, omtdataout_t, supports_marks>:: + verify_marks_consistent_internal(const subtree &st, + const bool UU(allow_marks)) const { + if (st.is_null()) { + return 0; + } + const omt_node &node = this->d.t.nodes[st.get_index()]; + uint32_t num_marks = + verify_marks_consistent_internal(node.left, node.get_marks_below()); + num_marks += verify_marks_consistent_internal(node.right, + node.get_marks_below()); + if (node.get_marks_below()) { + paranoid_invariant(allow_marks); + paranoid_invariant(num_marks > 0); + } else { + // redundant with invariant below, but nice to have explicitly + paranoid_invariant(num_marks == 0); + } + if (node.get_marked()) { + paranoid_invariant(allow_marks); + ++num_marks; + } + return num_marks; + } + + template <typename omtdata_t, typename omtdataout_t, bool supports_marks> + void omt<omtdata_t, omtdataout_t, supports_marks>::verify_marks_consistent( + void) const { + static_assert(supports_marks, "does not support marks"); + paranoid_invariant(!this->is_array); + this->verify_marks_consistent_internal(this->d.t.root, true); + } -template<typename omtdata_t, typename omtdataout_t, bool supports_marks> -void omt<omtdata_t, omtdataout_t, supports_marks>::create_internal(const uint32_t new_capacity) { - this->create_internal_no_array(new_capacity); - XMALLOC_N(this->capacity, this->d.a.values); -} + template <typename omtdata_t, typename omtdataout_t, bool supports_marks> + template <typename iterate_extra_t, + int (*f)(omtdata_t *, const uint32_t, iterate_extra_t *const)> + void omt<omtdata_t, omtdataout_t, supports_marks>::iterate_ptr( + iterate_extra_t *const iterate_extra) { + if (this->is_array) { + this->iterate_ptr_internal_array<iterate_extra_t, f>( + 0, this->size(), iterate_extra); + } else { + this->iterate_ptr_internal<iterate_extra_t, f>( + 0, this->size(), this->d.t.root, 0, iterate_extra); + } + } -template<typename omtdata_t, typename omtdataout_t, bool supports_marks> -uint32_t omt<omtdata_t, omtdataout_t, supports_marks>::nweight(const subtree &subtree) const { - if (subtree.is_null()) { + template <typename omtdata_t, typename omtdataout_t, bool supports_marks> + int omt<omtdata_t, omtdataout_t, supports_marks>::fetch( + const uint32_t idx, + omtdataout_t *const value) const { + if (idx >= this->size()) { + return EINVAL; + } + if (this->is_array) { + this->fetch_internal_array(idx, value); + } else { + this->fetch_internal(this->d.t.root, idx, value); + } return 0; - } else { - return this->d.t.nodes[subtree.get_index()].weight; - } -} - -template<typename omtdata_t, typename omtdataout_t, bool supports_marks> -typename omt<omtdata_t, omtdataout_t, supports_marks>::node_idx omt<omtdata_t, omtdataout_t, supports_marks>::node_malloc(void) { - paranoid_invariant(this->d.t.free_idx < this->capacity); - omt_node &n = this->d.t.nodes[this->d.t.free_idx]; - n.clear_stolen_bits(); - return this->d.t.free_idx++; -} - -template<typename omtdata_t, typename omtdataout_t, bool supports_marks> -void omt<omtdata_t, omtdataout_t, supports_marks>::node_free(const node_idx UU(idx)) { - paranoid_invariant(idx < this->capacity); -} - -template<typename omtdata_t, typename omtdataout_t, bool supports_marks> -void omt<omtdata_t, omtdataout_t, supports_marks>::maybe_resize_array(const uint32_t n) { - const uint32_t new_size = n<=2 ? 4 : 2*n; - const uint32_t room = this->capacity - this->d.a.start_idx; - - if (room < n || this->capacity / 2 >= new_size) { - omtdata_t *XMALLOC_N(new_size, tmp_values); - memcpy(tmp_values, &this->d.a.values[this->d.a.start_idx], - this->d.a.num_values * (sizeof tmp_values[0])); + } + + template <typename omtdata_t, typename omtdataout_t, bool supports_marks> + template <typename omtcmp_t, int (*h)(const omtdata_t &, const omtcmp_t &)> + int omt<omtdata_t, omtdataout_t, supports_marks>::find_zero( + const omtcmp_t &extra, + omtdataout_t *const value, + uint32_t *const idxp) const { + uint32_t tmp_index; + uint32_t *const child_idxp = (idxp != nullptr) ? idxp : &tmp_index; + int r; + if (this->is_array) { + r = this->find_internal_zero_array<omtcmp_t, h>( + extra, value, child_idxp); + } else { + r = this->find_internal_zero<omtcmp_t, h>( + this->d.t.root, extra, value, child_idxp); + } + return r; + } + + template <typename omtdata_t, typename omtdataout_t, bool supports_marks> + template <typename omtcmp_t, int (*h)(const omtdata_t &, const omtcmp_t &)> + int omt<omtdata_t, omtdataout_t, supports_marks>::find( + const omtcmp_t &extra, + int direction, + omtdataout_t *const value, + uint32_t *const idxp) const { + uint32_t tmp_index; + uint32_t *const child_idxp = (idxp != nullptr) ? idxp : &tmp_index; + paranoid_invariant(direction != 0); + if (direction < 0) { + if (this->is_array) { + return this->find_internal_minus_array<omtcmp_t, h>( + extra, value, child_idxp); + } else { + return this->find_internal_minus<omtcmp_t, h>( + this->d.t.root, extra, value, child_idxp); + } + } else { + if (this->is_array) { + return this->find_internal_plus_array<omtcmp_t, h>( + extra, value, child_idxp); + } else { + return this->find_internal_plus<omtcmp_t, h>( + this->d.t.root, extra, value, child_idxp); + } + } + } + + template <typename omtdata_t, typename omtdataout_t, bool supports_marks> + size_t omt<omtdata_t, omtdataout_t, supports_marks>::memory_size(void) { + if (this->is_array) { + return (sizeof *this) + + this->capacity * (sizeof this->d.a.values[0]); + } + return (sizeof *this) + this->capacity * (sizeof this->d.t.nodes[0]); + } + + template <typename omtdata_t, typename omtdataout_t, bool supports_marks> + void omt<omtdata_t, omtdataout_t, supports_marks>::create_internal_no_array( + const uint32_t new_capacity) { + this->is_array = true; this->d.a.start_idx = 0; - this->capacity = new_size; - toku_free(this->d.a.values); - this->d.a.values = tmp_values; - } -} - -template<typename omtdata_t, typename omtdataout_t, bool supports_marks> -void omt<omtdata_t, omtdataout_t, supports_marks>::fill_array_with_subtree_values(omtdata_t *const array, const subtree &subtree) const { - if (subtree.is_null()) return; - const omt_node &tree = this->d.t.nodes[subtree.get_index()]; - this->fill_array_with_subtree_values(&array[0], tree.left); - array[this->nweight(tree.left)] = tree.value; - this->fill_array_with_subtree_values(&array[this->nweight(tree.left) + 1], tree.right); -} - -template<typename omtdata_t, typename omtdataout_t, bool supports_marks> -void omt<omtdata_t, omtdataout_t, supports_marks>::convert_to_array(void) { - if (!this->is_array) { - const uint32_t num_values = this->size(); - uint32_t new_size = 2*num_values; - new_size = new_size < 4 ? 4 : new_size; - - omtdata_t *XMALLOC_N(new_size, tmp_values); - this->fill_array_with_subtree_values(tmp_values, this->d.t.root); - toku_free(this->d.t.nodes); - this->is_array = true; - this->capacity = new_size; - this->d.a.num_values = num_values; - this->d.a.values = tmp_values; - this->d.a.start_idx = 0; - } -} - -template<typename omtdata_t, typename omtdataout_t, bool supports_marks> -void omt<omtdata_t, omtdataout_t, supports_marks>::rebuild_from_sorted_array(subtree *const subtree, const omtdata_t *const values, const uint32_t numvalues) { - if (numvalues==0) { - subtree->set_to_null(); - } else { - const uint32_t halfway = numvalues/2; - const node_idx newidx = this->node_malloc(); - omt_node *const newnode = &this->d.t.nodes[newidx]; - newnode->weight = numvalues; - newnode->value = values[halfway]; - subtree->set_index(newidx); - // update everything before the recursive calls so the second call can be a tail call. - this->rebuild_from_sorted_array(&newnode->left, &values[0], halfway); - this->rebuild_from_sorted_array(&newnode->right, &values[halfway+1], numvalues - (halfway+1)); - } -} - -template<typename omtdata_t, typename omtdataout_t, bool supports_marks> -void omt<omtdata_t, omtdataout_t, supports_marks>::convert_to_tree(void) { - if (this->is_array) { - const uint32_t num_nodes = this->size(); - uint32_t new_size = num_nodes*2; - new_size = new_size < 4 ? 4 : new_size; - - omt_node *XMALLOC_N(new_size, new_nodes); - omtdata_t *const values = this->d.a.values; - omtdata_t *const tmp_values = &values[this->d.a.start_idx]; - this->is_array = false; - this->d.t.nodes = new_nodes; - this->capacity = new_size; - this->d.t.free_idx = 0; - this->d.t.root.set_to_null(); - this->rebuild_from_sorted_array(&this->d.t.root, tmp_values, num_nodes); - toku_free(values); - } -} - -template<typename omtdata_t, typename omtdataout_t, bool supports_marks> -void omt<omtdata_t, omtdataout_t, supports_marks>::maybe_resize_or_convert(const uint32_t n) { - if (this->is_array) { - this->maybe_resize_array(n); - } else { - const uint32_t new_size = n<=2 ? 4 : 2*n; - const uint32_t num_nodes = this->nweight(this->d.t.root); - if ((this->capacity/2 >= new_size) || - (this->d.t.free_idx >= this->capacity && num_nodes < n) || - (this->capacity<n)) { - this->convert_to_array(); - // if we had a free list, the "supports_marks" version could - // just resize, as it is now, we have to convert to and back - // from an array. - if (supports_marks) { - this->convert_to_tree(); + this->d.a.num_values = 0; + this->d.a.values = nullptr; + this->capacity = new_capacity; + } + + template <typename omtdata_t, typename omtdataout_t, bool supports_marks> + void omt<omtdata_t, omtdataout_t, supports_marks>::create_internal( + const uint32_t new_capacity) { + this->create_internal_no_array(new_capacity); + XMALLOC_N(this->capacity, this->d.a.values); + } + + template <typename omtdata_t, typename omtdataout_t, bool supports_marks> + uint32_t omt<omtdata_t, omtdataout_t, supports_marks>::nweight( + const subtree &st) const { + if (st.is_null()) { + return 0; + } else { + return this->d.t.nodes[st.get_index()].weight; + } + } + + template <typename omtdata_t, typename omtdataout_t, bool supports_marks> + typename omt<omtdata_t, omtdataout_t, supports_marks>::node_idx + omt<omtdata_t, omtdataout_t, supports_marks>::node_malloc(void) { + paranoid_invariant(this->d.t.free_idx < this->capacity); + omt_node &n = this->d.t.nodes[this->d.t.free_idx]; + n.clear_stolen_bits(); + return this->d.t.free_idx++; + } + + template <typename omtdata_t, typename omtdataout_t, bool supports_marks> + void omt<omtdata_t, omtdataout_t, supports_marks>::node_free( + const node_idx UU(idx)) { + paranoid_invariant(idx < this->capacity); + } + + template <typename omtdata_t, typename omtdataout_t, bool supports_marks> + void omt<omtdata_t, omtdataout_t, supports_marks>::maybe_resize_array( + const uint32_t n) { + const uint32_t new_size = n <= 2 ? 4 : 2 * n; + const uint32_t room = this->capacity - this->d.a.start_idx; + + if (room < n || this->capacity / 2 >= new_size) { + omtdata_t *XMALLOC_N(new_size, tmp_values); + memcpy(tmp_values, + &this->d.a.values[this->d.a.start_idx], + this->d.a.num_values * (sizeof tmp_values[0])); + this->d.a.start_idx = 0; + this->capacity = new_size; + toku_free(this->d.a.values); + this->d.a.values = tmp_values; + } + } + + template <typename omtdata_t, typename omtdataout_t, bool supports_marks> + void omt<omtdata_t, omtdataout_t, supports_marks>:: + fill_array_with_subtree_values(omtdata_t *const array, + const subtree &st) const { + if (st.is_null()) + return; + const omt_node &tree = this->d.t.nodes[st.get_index()]; + this->fill_array_with_subtree_values(&array[0], tree.left); + array[this->nweight(tree.left)] = tree.value; + this->fill_array_with_subtree_values( + &array[this->nweight(tree.left) + 1], tree.right); + } + + template <typename omtdata_t, typename omtdataout_t, bool supports_marks> + void omt<omtdata_t, omtdataout_t, supports_marks>::convert_to_array(void) { + if (!this->is_array) { + const uint32_t num_values = this->size(); + uint32_t new_size = 2 * num_values; + new_size = new_size < 4 ? 4 : new_size; + + omtdata_t *XMALLOC_N(new_size, tmp_values); + this->fill_array_with_subtree_values(tmp_values, this->d.t.root); + toku_free(this->d.t.nodes); + this->is_array = true; + this->capacity = new_size; + this->d.a.num_values = num_values; + this->d.a.values = tmp_values; + this->d.a.start_idx = 0; + } + } + + template <typename omtdata_t, typename omtdataout_t, bool supports_marks> + void + omt<omtdata_t, omtdataout_t, supports_marks>::rebuild_from_sorted_array( + subtree *const st, + const omtdata_t *const values, + const uint32_t numvalues) { + if (numvalues == 0) { + st->set_to_null(); + } else { + const uint32_t halfway = numvalues / 2; + const node_idx newidx = this->node_malloc(); + omt_node *const newnode = &this->d.t.nodes[newidx]; + newnode->weight = numvalues; + newnode->value = values[halfway]; + st->set_index(newidx); + // update everything before the recursive calls so the second call + // can be a tail call. + this->rebuild_from_sorted_array( + &newnode->left, &values[0], halfway); + this->rebuild_from_sorted_array(&newnode->right, + &values[halfway + 1], + numvalues - (halfway + 1)); + } + } + + template <typename omtdata_t, typename omtdataout_t, bool supports_marks> + void omt<omtdata_t, omtdataout_t, supports_marks>::convert_to_tree(void) { + if (this->is_array) { + const uint32_t num_nodes = this->size(); + uint32_t new_size = num_nodes * 2; + new_size = new_size < 4 ? 4 : new_size; + + omt_node *XMALLOC_N(new_size, new_nodes); + omtdata_t *const values = this->d.a.values; + omtdata_t *const tmp_values = &values[this->d.a.start_idx]; + this->is_array = false; + this->d.t.nodes = new_nodes; + this->capacity = new_size; + this->d.t.free_idx = 0; + this->d.t.root.set_to_null(); + this->rebuild_from_sorted_array( + &this->d.t.root, tmp_values, num_nodes); + toku_free(values); + } + } + + template <typename omtdata_t, typename omtdataout_t, bool supports_marks> + void omt<omtdata_t, omtdataout_t, supports_marks>::maybe_resize_or_convert( + const uint32_t n) { + if (this->is_array) { + this->maybe_resize_array(n); + } else { + const uint32_t new_size = n <= 2 ? 4 : 2 * n; + const uint32_t num_nodes = this->nweight(this->d.t.root); + if ((this->capacity / 2 >= new_size) || + (this->d.t.free_idx >= this->capacity && num_nodes < n) || + (this->capacity < n)) { + this->convert_to_array(); + // if we had a free list, the "supports_marks" version could + // just resize, as it is now, we have to convert to and back + // from an array. + if (supports_marks) { + this->convert_to_tree(); + } } } } -} - -template<typename omtdata_t, typename omtdataout_t, bool supports_marks> -bool omt<omtdata_t, omtdataout_t, supports_marks>::will_need_rebalance(const subtree &subtree, const int leftmod, const int rightmod) const { - if (subtree.is_null()) { return false; } - const omt_node &n = this->d.t.nodes[subtree.get_index()]; - // one of the 1's is for the root. - // the other is to take ceil(n/2) - const uint32_t weight_left = this->nweight(n.left) + leftmod; - const uint32_t weight_right = this->nweight(n.right) + rightmod; - return ((1+weight_left < (1+1+weight_right)/2) - || - (1+weight_right < (1+1+weight_left)/2)); -} - -template<typename omtdata_t, typename omtdataout_t, bool supports_marks> -void omt<omtdata_t, omtdataout_t, supports_marks>::insert_internal(subtree *const subtreep, const omtdata_t &value, const uint32_t idx, subtree **const rebalance_subtree) { - if (subtreep->is_null()) { - paranoid_invariant_zero(idx); - const node_idx newidx = this->node_malloc(); - omt_node *const newnode = &this->d.t.nodes[newidx]; - newnode->weight = 1; - newnode->left.set_to_null(); - newnode->right.set_to_null(); - newnode->value = value; - subtreep->set_index(newidx); - } else { + + template <typename omtdata_t, typename omtdataout_t, bool supports_marks> + bool omt<omtdata_t, omtdataout_t, supports_marks>::will_need_rebalance( + const subtree &st, + const int leftmod, + const int rightmod) const { + if (st.is_null()) { + return false; + } + const omt_node &n = this->d.t.nodes[st.get_index()]; + // one of the 1's is for the root. + // the other is to take ceil(n/2) + const uint32_t weight_left = this->nweight(n.left) + leftmod; + const uint32_t weight_right = this->nweight(n.right) + rightmod; + return ((1 + weight_left < (1 + 1 + weight_right) / 2) || + (1 + weight_right < (1 + 1 + weight_left) / 2)); + } + + template <typename omtdata_t, typename omtdataout_t, bool supports_marks> + void omt<omtdata_t, omtdataout_t, supports_marks>::insert_internal( + subtree *const subtreep, + const omtdata_t &value, + const uint32_t idx, + subtree **const rebalance_subtree) { + if (subtreep->is_null()) { + paranoid_invariant_zero(idx); + const node_idx newidx = this->node_malloc(); + omt_node *const newnode = &this->d.t.nodes[newidx]; + newnode->weight = 1; + newnode->left.set_to_null(); + newnode->right.set_to_null(); + newnode->value = value; + subtreep->set_index(newidx); + } else { + omt_node &n = this->d.t.nodes[subtreep->get_index()]; + n.weight++; + if (idx <= this->nweight(n.left)) { + if (*rebalance_subtree == nullptr && + this->will_need_rebalance(*subtreep, 1, 0)) { + *rebalance_subtree = subtreep; + } + this->insert_internal(&n.left, value, idx, rebalance_subtree); + } else { + if (*rebalance_subtree == nullptr && + this->will_need_rebalance(*subtreep, 0, 1)) { + *rebalance_subtree = subtreep; + } + const uint32_t sub_index = idx - this->nweight(n.left) - 1; + this->insert_internal( + &n.right, value, sub_index, rebalance_subtree); + } + } + } + + template <typename omtdata_t, typename omtdataout_t, bool supports_marks> + void omt<omtdata_t, omtdataout_t, supports_marks>::set_at_internal_array( + const omtdata_t &value, + const uint32_t idx) { + this->d.a.values[this->d.a.start_idx + idx] = value; + } + + template <typename omtdata_t, typename omtdataout_t, bool supports_marks> + void omt<omtdata_t, omtdataout_t, supports_marks>::set_at_internal( + const subtree &st, + const omtdata_t &value, + const uint32_t idx) { + paranoid_invariant(!st.is_null()); + omt_node &n = this->d.t.nodes[st.get_index()]; + const uint32_t leftweight = this->nweight(n.left); + if (idx < leftweight) { + this->set_at_internal(n.left, value, idx); + } else if (idx == leftweight) { + n.value = value; + } else { + this->set_at_internal(n.right, value, idx - leftweight - 1); + } + } + + template <typename omtdata_t, typename omtdataout_t, bool supports_marks> + void omt<omtdata_t, omtdataout_t, supports_marks>::delete_internal( + subtree *const subtreep, + const uint32_t idx, + omt_node *const copyn, + subtree **const rebalance_subtree) { + paranoid_invariant_notnull(subtreep); + paranoid_invariant_notnull(rebalance_subtree); + paranoid_invariant(!subtreep->is_null()); omt_node &n = this->d.t.nodes[subtreep->get_index()]; - n.weight++; - if (idx <= this->nweight(n.left)) { - if (*rebalance_subtree == nullptr && this->will_need_rebalance(*subtreep, 1, 0)) { + const uint32_t leftweight = this->nweight(n.left); + if (idx < leftweight) { + n.weight--; + if (*rebalance_subtree == nullptr && + this->will_need_rebalance(*subtreep, -1, 0)) { *rebalance_subtree = subtreep; } - this->insert_internal(&n.left, value, idx, rebalance_subtree); + this->delete_internal(&n.left, idx, copyn, rebalance_subtree); + } else if (idx == leftweight) { + if (n.left.is_null()) { + const uint32_t oldidx = subtreep->get_index(); + *subtreep = n.right; + if (copyn != nullptr) { + copyn->value = n.value; + } + this->node_free(oldidx); + } else if (n.right.is_null()) { + const uint32_t oldidx = subtreep->get_index(); + *subtreep = n.left; + if (copyn != nullptr) { + copyn->value = n.value; + } + this->node_free(oldidx); + } else { + if (*rebalance_subtree == nullptr && + this->will_need_rebalance(*subtreep, 0, -1)) { + *rebalance_subtree = subtreep; + } + // don't need to copy up value, it's only used by this + // next call, and when that gets to the bottom there + // won't be any more recursion + n.weight--; + this->delete_internal(&n.right, 0, &n, rebalance_subtree); + } } else { - if (*rebalance_subtree == nullptr && this->will_need_rebalance(*subtreep, 0, 1)) { + n.weight--; + if (*rebalance_subtree == nullptr && + this->will_need_rebalance(*subtreep, 0, -1)) { *rebalance_subtree = subtreep; } - const uint32_t sub_index = idx - this->nweight(n.left) - 1; - this->insert_internal(&n.right, value, sub_index, rebalance_subtree); - } - } -} - -template<typename omtdata_t, typename omtdataout_t, bool supports_marks> -void omt<omtdata_t, omtdataout_t, supports_marks>::set_at_internal_array(const omtdata_t &value, const uint32_t idx) { - this->d.a.values[this->d.a.start_idx + idx] = value; -} - -template<typename omtdata_t, typename omtdataout_t, bool supports_marks> -void omt<omtdata_t, omtdataout_t, supports_marks>::set_at_internal(const subtree &subtree, const omtdata_t &value, const uint32_t idx) { - paranoid_invariant(!subtree.is_null()); - omt_node &n = this->d.t.nodes[subtree.get_index()]; - const uint32_t leftweight = this->nweight(n.left); - if (idx < leftweight) { - this->set_at_internal(n.left, value, idx); - } else if (idx == leftweight) { - n.value = value; - } else { - this->set_at_internal(n.right, value, idx - leftweight - 1); - } -} - -template<typename omtdata_t, typename omtdataout_t, bool supports_marks> -void omt<omtdata_t, omtdataout_t, supports_marks>::delete_internal(subtree *const subtreep, const uint32_t idx, omt_node *const copyn, subtree **const rebalance_subtree) { - paranoid_invariant_notnull(subtreep); - paranoid_invariant_notnull(rebalance_subtree); - paranoid_invariant(!subtreep->is_null()); - omt_node &n = this->d.t.nodes[subtreep->get_index()]; - const uint32_t leftweight = this->nweight(n.left); - if (idx < leftweight) { - n.weight--; - if (*rebalance_subtree == nullptr && this->will_need_rebalance(*subtreep, -1, 0)) { - *rebalance_subtree = subtreep; - } - this->delete_internal(&n.left, idx, copyn, rebalance_subtree); - } else if (idx == leftweight) { - if (n.left.is_null()) { - const uint32_t oldidx = subtreep->get_index(); - *subtreep = n.right; - if (copyn != nullptr) { - copyn->value = n.value; + this->delete_internal( + &n.right, idx - leftweight - 1, copyn, rebalance_subtree); + } + } + + template <typename omtdata_t, typename omtdataout_t, bool supports_marks> + template < + typename iterate_extra_t, + int (*f)(const omtdata_t &, const uint32_t, iterate_extra_t *const)> + int omt<omtdata_t, omtdataout_t, supports_marks>::iterate_internal_array( + const uint32_t left, + const uint32_t right, + iterate_extra_t *const iterate_extra) const { + int r; + for (uint32_t i = left; i < right; ++i) { + r = f(this->d.a.values[this->d.a.start_idx + i], i, iterate_extra); + if (r != 0) { + return r; } - this->node_free(oldidx); - } else if (n.right.is_null()) { - const uint32_t oldidx = subtreep->get_index(); - *subtreep = n.left; - if (copyn != nullptr) { - copyn->value = n.value; + } + return 0; + } + + template <typename omtdata_t, typename omtdataout_t, bool supports_marks> + template <typename iterate_extra_t, + int (*f)(omtdata_t *, const uint32_t, iterate_extra_t *const)> + void omt<omtdata_t, omtdataout_t, supports_marks>::iterate_ptr_internal( + const uint32_t left, + const uint32_t right, + const subtree &st, + const uint32_t idx, + iterate_extra_t *const iterate_extra) { + if (!st.is_null()) { + omt_node &n = this->d.t.nodes[st.get_index()]; + const uint32_t idx_root = idx + this->nweight(n.left); + if (left < idx_root) { + this->iterate_ptr_internal<iterate_extra_t, f>( + left, right, n.left, idx, iterate_extra); } - this->node_free(oldidx); - } else { - if (*rebalance_subtree == nullptr && this->will_need_rebalance(*subtreep, 0, -1)) { - *rebalance_subtree = subtreep; + if (left <= idx_root && idx_root < right) { + int r = f(&n.value, idx_root, iterate_extra); + lazy_assert_zero(r); + } + if (idx_root + 1 < right) { + this->iterate_ptr_internal<iterate_extra_t, f>( + left, right, n.right, idx_root + 1, iterate_extra); } - // don't need to copy up value, it's only used by this - // next call, and when that gets to the bottom there - // won't be any more recursion - n.weight--; - this->delete_internal(&n.right, 0, &n, rebalance_subtree); - } - } else { - n.weight--; - if (*rebalance_subtree == nullptr && this->will_need_rebalance(*subtreep, 0, -1)) { - *rebalance_subtree = subtreep; - } - this->delete_internal(&n.right, idx - leftweight - 1, copyn, rebalance_subtree); - } -} - -template<typename omtdata_t, typename omtdataout_t, bool supports_marks> -template<typename iterate_extra_t, - int (*f)(const omtdata_t &, const uint32_t, iterate_extra_t *const)> -int omt<omtdata_t, omtdataout_t, supports_marks>::iterate_internal_array(const uint32_t left, const uint32_t right, - iterate_extra_t *const iterate_extra) const { - int r; - for (uint32_t i = left; i < right; ++i) { - r = f(this->d.a.values[this->d.a.start_idx + i], i, iterate_extra); - if (r != 0) { - return r; } } - return 0; -} -template<typename omtdata_t, typename omtdataout_t, bool supports_marks> -template<typename iterate_extra_t, - int (*f)(omtdata_t *, const uint32_t, iterate_extra_t *const)> -void omt<omtdata_t, omtdataout_t, supports_marks>::iterate_ptr_internal(const uint32_t left, const uint32_t right, - const subtree &subtree, const uint32_t idx, - iterate_extra_t *const iterate_extra) { - if (!subtree.is_null()) { - omt_node &n = this->d.t.nodes[subtree.get_index()]; + template <typename omtdata_t, typename omtdataout_t, bool supports_marks> + template <typename iterate_extra_t, + int (*f)(omtdata_t *, const uint32_t, iterate_extra_t *const)> + void + omt<omtdata_t, omtdataout_t, supports_marks>::iterate_ptr_internal_array( + const uint32_t left, + const uint32_t right, + iterate_extra_t *const iterate_extra) { + for (uint32_t i = left; i < right; ++i) { + int r = + f(&this->d.a.values[this->d.a.start_idx + i], i, iterate_extra); + lazy_assert_zero(r); + } + } + + template <typename omtdata_t, typename omtdataout_t, bool supports_marks> + template < + typename iterate_extra_t, + int (*f)(const omtdata_t &, const uint32_t, iterate_extra_t *const)> + int omt<omtdata_t, omtdataout_t, supports_marks>::iterate_internal( + const uint32_t left, + const uint32_t right, + const subtree &st, + const uint32_t idx, + iterate_extra_t *const iterate_extra) const { + if (st.is_null()) { + return 0; + } + int r; + const omt_node &n = this->d.t.nodes[st.get_index()]; const uint32_t idx_root = idx + this->nweight(n.left); if (left < idx_root) { - this->iterate_ptr_internal<iterate_extra_t, f>(left, right, n.left, idx, iterate_extra); + r = this->iterate_internal<iterate_extra_t, f>( + left, right, n.left, idx, iterate_extra); + if (r != 0) { + return r; + } } if (left <= idx_root && idx_root < right) { - int r = f(&n.value, idx_root, iterate_extra); - lazy_assert_zero(r); + r = f(n.value, idx_root, iterate_extra); + if (r != 0) { + return r; + } } if (idx_root + 1 < right) { - this->iterate_ptr_internal<iterate_extra_t, f>(left, right, n.right, idx_root + 1, iterate_extra); - } - } -} - -template<typename omtdata_t, typename omtdataout_t, bool supports_marks> -template<typename iterate_extra_t, - int (*f)(omtdata_t *, const uint32_t, iterate_extra_t *const)> -void omt<omtdata_t, omtdataout_t, supports_marks>::iterate_ptr_internal_array(const uint32_t left, const uint32_t right, - iterate_extra_t *const iterate_extra) { - for (uint32_t i = left; i < right; ++i) { - int r = f(&this->d.a.values[this->d.a.start_idx + i], i, iterate_extra); - lazy_assert_zero(r); - } -} - -template<typename omtdata_t, typename omtdataout_t, bool supports_marks> -template<typename iterate_extra_t, - int (*f)(const omtdata_t &, const uint32_t, iterate_extra_t *const)> -int omt<omtdata_t, omtdataout_t, supports_marks>::iterate_internal(const uint32_t left, const uint32_t right, - const subtree &subtree, const uint32_t idx, - iterate_extra_t *const iterate_extra) const { - if (subtree.is_null()) { return 0; } - int r; - const omt_node &n = this->d.t.nodes[subtree.get_index()]; - const uint32_t idx_root = idx + this->nweight(n.left); - if (left < idx_root) { - r = this->iterate_internal<iterate_extra_t, f>(left, right, n.left, idx, iterate_extra); - if (r != 0) { return r; } - } - if (left <= idx_root && idx_root < right) { - r = f(n.value, idx_root, iterate_extra); - if (r != 0) { return r; } - } - if (idx_root + 1 < right) { - return this->iterate_internal<iterate_extra_t, f>(left, right, n.right, idx_root + 1, iterate_extra); - } - return 0; -} - -template<typename omtdata_t, typename omtdataout_t, bool supports_marks> -template<typename iterate_extra_t, - int (*f)(const omtdata_t &, const uint32_t, iterate_extra_t *const)> -int omt<omtdata_t, omtdataout_t, supports_marks>::iterate_and_mark_range_internal(const uint32_t left, const uint32_t right, - const subtree &subtree, const uint32_t idx, - iterate_extra_t *const iterate_extra) { - paranoid_invariant(!subtree.is_null()); - int r; - omt_node &n = this->d.t.nodes[subtree.get_index()]; - const uint32_t idx_root = idx + this->nweight(n.left); - if (left < idx_root && !n.left.is_null()) { - n.set_marks_below_bit(); - r = this->iterate_and_mark_range_internal<iterate_extra_t, f>(left, right, n.left, idx, iterate_extra); - if (r != 0) { return r; } - } - if (left <= idx_root && idx_root < right) { - n.set_marked_bit(); - r = f(n.value, idx_root, iterate_extra); - if (r != 0) { return r; } - } - if (idx_root + 1 < right && !n.right.is_null()) { - n.set_marks_below_bit(); - return this->iterate_and_mark_range_internal<iterate_extra_t, f>(left, right, n.right, idx_root + 1, iterate_extra); - } - return 0; -} - -template<typename omtdata_t, typename omtdataout_t, bool supports_marks> -template<typename iterate_extra_t, - int (*f)(const omtdata_t &, const uint32_t, iterate_extra_t *const)> -int omt<omtdata_t, omtdataout_t, supports_marks>::iterate_over_marked_internal(const subtree &subtree, const uint32_t idx, - iterate_extra_t *const iterate_extra) const { - if (subtree.is_null()) { return 0; } - int r; - const omt_node &n = this->d.t.nodes[subtree.get_index()]; - const uint32_t idx_root = idx + this->nweight(n.left); - if (n.get_marks_below()) { - r = this->iterate_over_marked_internal<iterate_extra_t, f>(n.left, idx, iterate_extra); - if (r != 0) { return r; } - } - if (n.get_marked()) { - r = f(n.value, idx_root, iterate_extra); - if (r != 0) { return r; } - } - if (n.get_marks_below()) { - return this->iterate_over_marked_internal<iterate_extra_t, f>(n.right, idx_root + 1, iterate_extra); - } - return 0; -} - -template<typename omtdata_t, typename omtdataout_t, bool supports_marks> -void omt<omtdata_t, omtdataout_t, supports_marks>::fetch_internal_array(const uint32_t i, omtdataout_t *const value) const { - if (value != nullptr) { - copyout(value, &this->d.a.values[this->d.a.start_idx + i]); - } -} - -template<typename omtdata_t, typename omtdataout_t, bool supports_marks> -void omt<omtdata_t, omtdataout_t, supports_marks>::fetch_internal(const subtree &subtree, const uint32_t i, omtdataout_t *const value) const { - omt_node &n = this->d.t.nodes[subtree.get_index()]; - const uint32_t leftweight = this->nweight(n.left); - if (i < leftweight) { - this->fetch_internal(n.left, i, value); - } else if (i == leftweight) { - if (value != nullptr) { - copyout(value, &n); - } - } else { - this->fetch_internal(n.right, i - leftweight - 1, value); - } -} - -template<typename omtdata_t, typename omtdataout_t, bool supports_marks> -void omt<omtdata_t, omtdataout_t, supports_marks>::fill_array_with_subtree_idxs(node_idx *const array, const subtree &subtree) const { - if (!subtree.is_null()) { - const omt_node &tree = this->d.t.nodes[subtree.get_index()]; - this->fill_array_with_subtree_idxs(&array[0], tree.left); - array[this->nweight(tree.left)] = subtree.get_index(); - this->fill_array_with_subtree_idxs(&array[this->nweight(tree.left) + 1], tree.right); - } -} - -template<typename omtdata_t, typename omtdataout_t, bool supports_marks> -void omt<omtdata_t, omtdataout_t, supports_marks>::rebuild_subtree_from_idxs(subtree *const subtree, const node_idx *const idxs, const uint32_t numvalues) { - if (numvalues==0) { - subtree->set_to_null(); - } else { - uint32_t halfway = numvalues/2; - subtree->set_index(idxs[halfway]); - //node_idx newidx = idxs[halfway]; - omt_node &newnode = this->d.t.nodes[subtree->get_index()]; - newnode.weight = numvalues; - // value is already in there. - this->rebuild_subtree_from_idxs(&newnode.left, &idxs[0], halfway); - this->rebuild_subtree_from_idxs(&newnode.right, &idxs[halfway+1], numvalues-(halfway+1)); - //n_idx = newidx; - } -} - -template<typename omtdata_t, typename omtdataout_t, bool supports_marks> -void omt<omtdata_t, omtdataout_t, supports_marks>::rebalance(subtree *const subtree) { - node_idx idx = subtree->get_index(); - if (idx==this->d.t.root.get_index()) { - //Try to convert to an array. - //If this fails, (malloc) nothing will have changed. - //In the failure case we continue on to the standard rebalance - //algorithm. - this->convert_to_array(); - if (supports_marks) { - this->convert_to_tree(); + return this->iterate_internal<iterate_extra_t, f>( + left, right, n.right, idx_root + 1, iterate_extra); } - } else { - const omt_node &n = this->d.t.nodes[idx]; - node_idx *tmp_array; - size_t mem_needed = n.weight * (sizeof tmp_array[0]); - size_t mem_free = (this->capacity - this->d.t.free_idx) * (sizeof this->d.t.nodes[0]); - bool malloced; - if (mem_needed<=mem_free) { - //There is sufficient free space at the end of the nodes array - //to hold enough node indexes to rebalance. - malloced = false; - tmp_array = reinterpret_cast<node_idx *>(&this->d.t.nodes[this->d.t.free_idx]); - } - else { - malloced = true; - XMALLOC_N(n.weight, tmp_array); - } - this->fill_array_with_subtree_idxs(tmp_array, *subtree); - this->rebuild_subtree_from_idxs(subtree, tmp_array, n.weight); - if (malloced) toku_free(tmp_array); - } -} - -template<typename omtdata_t, typename omtdataout_t, bool supports_marks> -void omt<omtdata_t, omtdataout_t, supports_marks>::copyout(omtdata_t *const out, const omt_node *const n) { - *out = n->value; -} - -template<typename omtdata_t, typename omtdataout_t, bool supports_marks> -void omt<omtdata_t, omtdataout_t, supports_marks>::copyout(omtdata_t **const out, omt_node *const n) { - *out = &n->value; -} - -template<typename omtdata_t, typename omtdataout_t, bool supports_marks> -void omt<omtdata_t, omtdataout_t, supports_marks>::copyout(omtdata_t *const out, const omtdata_t *const stored_value_ptr) { - *out = *stored_value_ptr; -} - -template<typename omtdata_t, typename omtdataout_t, bool supports_marks> -void omt<omtdata_t, omtdataout_t, supports_marks>::copyout(omtdata_t **const out, omtdata_t *const stored_value_ptr) { - *out = stored_value_ptr; -} - -template<typename omtdata_t, typename omtdataout_t, bool supports_marks> -template<typename omtcmp_t, - int (*h)(const omtdata_t &, const omtcmp_t &)> -int omt<omtdata_t, omtdataout_t, supports_marks>::find_internal_zero_array(const omtcmp_t &extra, omtdataout_t *const value, uint32_t *const idxp) const { - paranoid_invariant_notnull(idxp); - uint32_t min = this->d.a.start_idx; - uint32_t limit = this->d.a.start_idx + this->d.a.num_values; - uint32_t best_pos = subtree::NODE_NULL; - uint32_t best_zero = subtree::NODE_NULL; - - while (min!=limit) { - uint32_t mid = (min + limit) / 2; - int hv = h(this->d.a.values[mid], extra); - if (hv<0) { - min = mid+1; - } - else if (hv>0) { - best_pos = mid; - limit = mid; - } - else { - best_zero = mid; - limit = mid; - } - } - if (best_zero!=subtree::NODE_NULL) { - //Found a zero - if (value != nullptr) { - copyout(value, &this->d.a.values[best_zero]); + return 0; + } + + template <typename omtdata_t, typename omtdataout_t, bool supports_marks> + template < + typename iterate_extra_t, + int (*f)(const omtdata_t &, const uint32_t, iterate_extra_t *const)> + int omt<omtdata_t, omtdataout_t, supports_marks>:: + iterate_and_mark_range_internal(const uint32_t left, + const uint32_t right, + const subtree &st, + const uint32_t idx, + iterate_extra_t *const iterate_extra) { + paranoid_invariant(!st.is_null()); + int r; + omt_node &n = this->d.t.nodes[st.get_index()]; + const uint32_t idx_root = idx + this->nweight(n.left); + if (left < idx_root && !n.left.is_null()) { + n.set_marks_below_bit(); + r = this->iterate_and_mark_range_internal<iterate_extra_t, f>( + left, right, n.left, idx, iterate_extra); + if (r != 0) { + return r; + } + } + if (left <= idx_root && idx_root < right) { + n.set_marked_bit(); + r = f(n.value, idx_root, iterate_extra); + if (r != 0) { + return r; + } + } + if (idx_root + 1 < right && !n.right.is_null()) { + n.set_marks_below_bit(); + return this->iterate_and_mark_range_internal<iterate_extra_t, f>( + left, right, n.right, idx_root + 1, iterate_extra); } - *idxp = best_zero - this->d.a.start_idx; return 0; } - if (best_pos!=subtree::NODE_NULL) *idxp = best_pos - this->d.a.start_idx; - else *idxp = this->d.a.num_values; - return DB_NOTFOUND; -} - -template<typename omtdata_t, typename omtdataout_t, bool supports_marks> -template<typename omtcmp_t, - int (*h)(const omtdata_t &, const omtcmp_t &)> -int omt<omtdata_t, omtdataout_t, supports_marks>::find_internal_zero(const subtree &subtree, const omtcmp_t &extra, omtdataout_t *const value, uint32_t *const idxp) const { - paranoid_invariant_notnull(idxp); - if (subtree.is_null()) { - *idxp = 0; - return DB_NOTFOUND; + + template <typename omtdata_t, typename omtdataout_t, bool supports_marks> + template < + typename iterate_extra_t, + int (*f)(const omtdata_t &, const uint32_t, iterate_extra_t *const)> + int + omt<omtdata_t, omtdataout_t, supports_marks>::iterate_over_marked_internal( + const subtree &st, + const uint32_t idx, + iterate_extra_t *const iterate_extra) const { + if (st.is_null()) { + return 0; + } + int r; + const omt_node &n = this->d.t.nodes[st.get_index()]; + const uint32_t idx_root = idx + this->nweight(n.left); + if (n.get_marks_below()) { + r = this->iterate_over_marked_internal<iterate_extra_t, f>( + n.left, idx, iterate_extra); + if (r != 0) { + return r; + } + } + if (n.get_marked()) { + r = f(n.value, idx_root, iterate_extra); + if (r != 0) { + return r; + } + } + if (n.get_marks_below()) { + return this->iterate_over_marked_internal<iterate_extra_t, f>( + n.right, idx_root + 1, iterate_extra); + } + return 0; } - omt_node &n = this->d.t.nodes[subtree.get_index()]; - int hv = h(n.value, extra); - if (hv<0) { - int r = this->find_internal_zero<omtcmp_t, h>(n.right, extra, value, idxp); - *idxp += this->nweight(n.left)+1; - return r; - } else if (hv>0) { - return this->find_internal_zero<omtcmp_t, h>(n.left, extra, value, idxp); - } else { - int r = this->find_internal_zero<omtcmp_t, h>(n.left, extra, value, idxp); - if (r==DB_NOTFOUND) { - *idxp = this->nweight(n.left); + + template <typename omtdata_t, typename omtdataout_t, bool supports_marks> + void omt<omtdata_t, omtdataout_t, supports_marks>::fetch_internal_array( + const uint32_t i, + omtdataout_t *const value) const { + if (value != nullptr) { + copyout(value, &this->d.a.values[this->d.a.start_idx + i]); + } + } + + template <typename omtdata_t, typename omtdataout_t, bool supports_marks> + void omt<omtdata_t, omtdataout_t, supports_marks>::fetch_internal( + const subtree &st, + const uint32_t i, + omtdataout_t *const value) const { + omt_node &n = this->d.t.nodes[st.get_index()]; + const uint32_t leftweight = this->nweight(n.left); + if (i < leftweight) { + this->fetch_internal(n.left, i, value); + } else if (i == leftweight) { if (value != nullptr) { copyout(value, &n); } - r = 0; + } else { + this->fetch_internal(n.right, i - leftweight - 1, value); } - return r; } -} -template<typename omtdata_t, typename omtdataout_t, bool supports_marks> -template<typename omtcmp_t, - int (*h)(const omtdata_t &, const omtcmp_t &)> -int omt<omtdata_t, omtdataout_t, supports_marks>::find_internal_plus_array(const omtcmp_t &extra, omtdataout_t *const value, uint32_t *const idxp) const { - paranoid_invariant_notnull(idxp); - uint32_t min = this->d.a.start_idx; - uint32_t limit = this->d.a.start_idx + this->d.a.num_values; - uint32_t best = subtree::NODE_NULL; + template <typename omtdata_t, typename omtdataout_t, bool supports_marks> + void + omt<omtdata_t, omtdataout_t, supports_marks>::fill_array_with_subtree_idxs( + node_idx *const array, + const subtree &st) const { + if (!st.is_null()) { + const omt_node &tree = this->d.t.nodes[st.get_index()]; + this->fill_array_with_subtree_idxs(&array[0], tree.left); + array[this->nweight(tree.left)] = st.get_index(); + this->fill_array_with_subtree_idxs( + &array[this->nweight(tree.left) + 1], tree.right); + } + } - while (min != limit) { - const uint32_t mid = (min + limit) / 2; - const int hv = h(this->d.a.values[mid], extra); - if (hv > 0) { - best = mid; - limit = mid; + template <typename omtdata_t, typename omtdataout_t, bool supports_marks> + void + omt<omtdata_t, omtdataout_t, supports_marks>::rebuild_subtree_from_idxs( + subtree *const st, + const node_idx *const idxs, + const uint32_t numvalues) { + if (numvalues == 0) { + st->set_to_null(); } else { - min = mid + 1; + uint32_t halfway = numvalues / 2; + st->set_index(idxs[halfway]); + // node_idx newidx = idxs[halfway]; + omt_node &newnode = this->d.t.nodes[st->get_index()]; + newnode.weight = numvalues; + // value is already in there. + this->rebuild_subtree_from_idxs(&newnode.left, &idxs[0], halfway); + this->rebuild_subtree_from_idxs( + &newnode.right, &idxs[halfway + 1], numvalues - (halfway + 1)); + // n_idx = newidx; } } - if (best == subtree::NODE_NULL) { return DB_NOTFOUND; } - if (value != nullptr) { - copyout(value, &this->d.a.values[best]); - } - *idxp = best - this->d.a.start_idx; - return 0; -} -template<typename omtdata_t, typename omtdataout_t, bool supports_marks> -template<typename omtcmp_t, - int (*h)(const omtdata_t &, const omtcmp_t &)> -int omt<omtdata_t, omtdataout_t, supports_marks>::find_internal_plus(const subtree &subtree, const omtcmp_t &extra, omtdataout_t *const value, uint32_t *const idxp) const { - paranoid_invariant_notnull(idxp); - if (subtree.is_null()) { - return DB_NOTFOUND; + template <typename omtdata_t, typename omtdataout_t, bool supports_marks> + void omt<omtdata_t, omtdataout_t, supports_marks>::rebalance( + subtree *const st) { + node_idx idx = st->get_index(); + if (idx == this->d.t.root.get_index()) { + // Try to convert to an array. + // If this fails, (malloc) nothing will have changed. + // In the failure case we continue on to the standard rebalance + // algorithm. + this->convert_to_array(); + if (supports_marks) { + this->convert_to_tree(); + } + } else { + const omt_node &n = this->d.t.nodes[idx]; + node_idx *tmp_array; + size_t mem_needed = n.weight * (sizeof tmp_array[0]); + size_t mem_free = (this->capacity - this->d.t.free_idx) * + (sizeof this->d.t.nodes[0]); + bool malloced; + if (mem_needed <= mem_free) { + // There is sufficient free space at the end of the nodes array + // to hold enough node indexes to rebalance. + malloced = false; + tmp_array = reinterpret_cast<node_idx *>( + &this->d.t.nodes[this->d.t.free_idx]); + } else { + malloced = true; + XMALLOC_N(n.weight, tmp_array); + } + this->fill_array_with_subtree_idxs(tmp_array, *st); + this->rebuild_subtree_from_idxs(st, tmp_array, n.weight); + if (malloced) + toku_free(tmp_array); + } } - omt_node *const n = &this->d.t.nodes[subtree.get_index()]; - int hv = h(n->value, extra); - int r; - if (hv > 0) { - r = this->find_internal_plus<omtcmp_t, h>(n->left, extra, value, idxp); - if (r == DB_NOTFOUND) { - *idxp = this->nweight(n->left); - if (value != nullptr) { - copyout(value, n); + + template <typename omtdata_t, typename omtdataout_t, bool supports_marks> + void omt<omtdata_t, omtdataout_t, supports_marks>::copyout( + omtdata_t *const out, + const omt_node *const n) { + *out = n->value; + } + + template <typename omtdata_t, typename omtdataout_t, bool supports_marks> + void omt<omtdata_t, omtdataout_t, supports_marks>::copyout( + omtdata_t **const out, + omt_node *const n) { + *out = &n->value; + } + + template <typename omtdata_t, typename omtdataout_t, bool supports_marks> + void omt<omtdata_t, omtdataout_t, supports_marks>::copyout( + omtdata_t *const out, + const omtdata_t *const stored_value_ptr) { + *out = *stored_value_ptr; + } + + template <typename omtdata_t, typename omtdataout_t, bool supports_marks> + void omt<omtdata_t, omtdataout_t, supports_marks>::copyout( + omtdata_t **const out, + omtdata_t *const stored_value_ptr) { + *out = stored_value_ptr; + } + + template <typename omtdata_t, typename omtdataout_t, bool supports_marks> + template <typename omtcmp_t, int (*h)(const omtdata_t &, const omtcmp_t &)> + int omt<omtdata_t, omtdataout_t, supports_marks>::find_internal_zero_array( + const omtcmp_t &extra, + omtdataout_t *const value, + uint32_t *const idxp) const { + paranoid_invariant_notnull(idxp); + uint32_t min = this->d.a.start_idx; + uint32_t limit = this->d.a.start_idx + this->d.a.num_values; + uint32_t best_pos = subtree::NODE_NULL; + uint32_t best_zero = subtree::NODE_NULL; + + while (min != limit) { + uint32_t mid = (min + limit) / 2; + int hv = h(this->d.a.values[mid], extra); + if (hv < 0) { + min = mid + 1; + } else if (hv > 0) { + best_pos = mid; + limit = mid; + } else { + best_zero = mid; + limit = mid; } - r = 0; } - } else { - r = this->find_internal_plus<omtcmp_t, h>(n->right, extra, value, idxp); - if (r == 0) { - *idxp += this->nweight(n->left) + 1; + if (best_zero != subtree::NODE_NULL) { + // Found a zero + if (value != nullptr) { + copyout(value, &this->d.a.values[best_zero]); + } + *idxp = best_zero - this->d.a.start_idx; + return 0; } + if (best_pos != subtree::NODE_NULL) + *idxp = best_pos - this->d.a.start_idx; + else + *idxp = this->d.a.num_values; + return DB_NOTFOUND; } - return r; -} - -template<typename omtdata_t, typename omtdataout_t, bool supports_marks> -template<typename omtcmp_t, - int (*h)(const omtdata_t &, const omtcmp_t &)> -int omt<omtdata_t, omtdataout_t, supports_marks>::find_internal_minus_array(const omtcmp_t &extra, omtdataout_t *const value, uint32_t *const idxp) const { - paranoid_invariant_notnull(idxp); - uint32_t min = this->d.a.start_idx; - uint32_t limit = this->d.a.start_idx + this->d.a.num_values; - uint32_t best = subtree::NODE_NULL; - while (min != limit) { - const uint32_t mid = (min + limit) / 2; - const int hv = h(this->d.a.values[mid], extra); + template <typename omtdata_t, typename omtdataout_t, bool supports_marks> + template <typename omtcmp_t, int (*h)(const omtdata_t &, const omtcmp_t &)> + int omt<omtdata_t, omtdataout_t, supports_marks>::find_internal_zero( + const subtree &st, + const omtcmp_t &extra, + omtdataout_t *const value, + uint32_t *const idxp) const { + paranoid_invariant_notnull(idxp); + if (st.is_null()) { + *idxp = 0; + return DB_NOTFOUND; + } + omt_node &n = this->d.t.nodes[st.get_index()]; + int hv = h(n.value, extra); if (hv < 0) { - best = mid; - min = mid + 1; + int r = this->find_internal_zero<omtcmp_t, h>( + n.right, extra, value, idxp); + *idxp += this->nweight(n.left) + 1; + return r; + } else if (hv > 0) { + return this->find_internal_zero<omtcmp_t, h>( + n.left, extra, value, idxp); } else { - limit = mid; + int r = this->find_internal_zero<omtcmp_t, h>( + n.left, extra, value, idxp); + if (r == DB_NOTFOUND) { + *idxp = this->nweight(n.left); + if (value != nullptr) { + copyout(value, &n); + } + r = 0; + } + return r; } } - if (best == subtree::NODE_NULL) { return DB_NOTFOUND; } - if (value != nullptr) { - copyout(value, &this->d.a.values[best]); - } - *idxp = best - this->d.a.start_idx; - return 0; -} -template<typename omtdata_t, typename omtdataout_t, bool supports_marks> -template<typename omtcmp_t, - int (*h)(const omtdata_t &, const omtcmp_t &)> -int omt<omtdata_t, omtdataout_t, supports_marks>::find_internal_minus(const subtree &subtree, const omtcmp_t &extra, omtdataout_t *const value, uint32_t *const idxp) const { - paranoid_invariant_notnull(idxp); - if (subtree.is_null()) { - return DB_NOTFOUND; + template <typename omtdata_t, typename omtdataout_t, bool supports_marks> + template <typename omtcmp_t, int (*h)(const omtdata_t &, const omtcmp_t &)> + int omt<omtdata_t, omtdataout_t, supports_marks>::find_internal_plus_array( + const omtcmp_t &extra, + omtdataout_t *const value, + uint32_t *const idxp) const { + paranoid_invariant_notnull(idxp); + uint32_t min = this->d.a.start_idx; + uint32_t limit = this->d.a.start_idx + this->d.a.num_values; + uint32_t best = subtree::NODE_NULL; + + while (min != limit) { + const uint32_t mid = (min + limit) / 2; + const int hv = h(this->d.a.values[mid], extra); + if (hv > 0) { + best = mid; + limit = mid; + } else { + min = mid + 1; + } + } + if (best == subtree::NODE_NULL) { + return DB_NOTFOUND; + } + if (value != nullptr) { + copyout(value, &this->d.a.values[best]); + } + *idxp = best - this->d.a.start_idx; + return 0; } - omt_node *const n = &this->d.t.nodes[subtree.get_index()]; - int hv = h(n->value, extra); - if (hv < 0) { - int r = this->find_internal_minus<omtcmp_t, h>(n->right, extra, value, idxp); - if (r == 0) { - *idxp += this->nweight(n->left) + 1; - } else if (r == DB_NOTFOUND) { - *idxp = this->nweight(n->left); - if (value != nullptr) { - copyout(value, n); + + template <typename omtdata_t, typename omtdataout_t, bool supports_marks> + template <typename omtcmp_t, int (*h)(const omtdata_t &, const omtcmp_t &)> + int omt<omtdata_t, omtdataout_t, supports_marks>::find_internal_plus( + const subtree &st, + const omtcmp_t &extra, + omtdataout_t *const value, + uint32_t *const idxp) const { + paranoid_invariant_notnull(idxp); + if (st.is_null()) { + return DB_NOTFOUND; + } + omt_node *const n = &this->d.t.nodes[st.get_index()]; + int hv = h(n->value, extra); + int r; + if (hv > 0) { + r = this->find_internal_plus<omtcmp_t, h>( + n->left, extra, value, idxp); + if (r == DB_NOTFOUND) { + *idxp = this->nweight(n->left); + if (value != nullptr) { + copyout(value, n); + } + r = 0; + } + } else { + r = this->find_internal_plus<omtcmp_t, h>( + n->right, extra, value, idxp); + if (r == 0) { + *idxp += this->nweight(n->left) + 1; } - r = 0; } return r; - } else { - return this->find_internal_minus<omtcmp_t, h>(n->left, extra, value, idxp); } -} -} // namespace toku + + template <typename omtdata_t, typename omtdataout_t, bool supports_marks> + template <typename omtcmp_t, int (*h)(const omtdata_t &, const omtcmp_t &)> + int omt<omtdata_t, omtdataout_t, supports_marks>::find_internal_minus_array( + const omtcmp_t &extra, + omtdataout_t *const value, + uint32_t *const idxp) const { + paranoid_invariant_notnull(idxp); + uint32_t min = this->d.a.start_idx; + uint32_t limit = this->d.a.start_idx + this->d.a.num_values; + uint32_t best = subtree::NODE_NULL; + + while (min != limit) { + const uint32_t mid = (min + limit) / 2; + const int hv = h(this->d.a.values[mid], extra); + if (hv < 0) { + best = mid; + min = mid + 1; + } else { + limit = mid; + } + } + if (best == subtree::NODE_NULL) { + return DB_NOTFOUND; + } + if (value != nullptr) { + copyout(value, &this->d.a.values[best]); + } + *idxp = best - this->d.a.start_idx; + return 0; + } + + template <typename omtdata_t, typename omtdataout_t, bool supports_marks> + template <typename omtcmp_t, int (*h)(const omtdata_t &, const omtcmp_t &)> + int omt<omtdata_t, omtdataout_t, supports_marks>::find_internal_minus( + const subtree &st, + const omtcmp_t &extra, + omtdataout_t *const value, + uint32_t *const idxp) const { + paranoid_invariant_notnull(idxp); + if (st.is_null()) { + return DB_NOTFOUND; + } + omt_node *const n = &this->d.t.nodes[st.get_index()]; + int hv = h(n->value, extra); + if (hv < 0) { + int r = this->find_internal_minus<omtcmp_t, h>( + n->right, extra, value, idxp); + if (r == 0) { + *idxp += this->nweight(n->left) + 1; + } else if (r == DB_NOTFOUND) { + *idxp = this->nweight(n->left); + if (value != nullptr) { + copyout(value, n); + } + r = 0; + } + return r; + } else { + return this->find_internal_minus<omtcmp_t, h>( + n->left, extra, value, idxp); + } + } +} // namespace toku diff --git a/storage/tokudb/PerconaFT/util/omt.h b/storage/tokudb/PerconaFT/util/omt.h index 36946401381..dc26b2d5718 100644 --- a/storage/tokudb/PerconaFT/util/omt.h +++ b/storage/tokudb/PerconaFT/util/omt.h @@ -32,6 +32,19 @@ Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved. You should have received a copy of the GNU Affero General Public License along with PerconaFT. If not, see <http://www.gnu.org/licenses/>. + +---------------------------------------- + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and ======= */ #ident "Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved." diff --git a/storage/tokudb/ha_tokudb.cc b/storage/tokudb/ha_tokudb.cc index 1f626727e7b..60e32f92285 100644 --- a/storage/tokudb/ha_tokudb.cc +++ b/storage/tokudb/ha_tokudb.cc @@ -7240,6 +7240,16 @@ int ha_tokudb::create( tokudb_trx_data *trx = NULL; THD* thd = ha_thd(); + String database_name, table_name, dictionary_name; + tokudb_split_dname(name, database_name, table_name, dictionary_name); + if (database_name.is_empty() || table_name.is_empty()) { + push_warning_printf(thd, + Sql_condition::WARN_LEVEL_WARN, + ER_TABLE_NAME, + "TokuDB: Table Name or Database Name is empty"); + DBUG_RETURN(ER_TABLE_NAME); + } + memset(&kc_info, 0, sizeof(kc_info)); #if 100000 <= MYSQL_VERSION_ID && MYSQL_VERSION_ID <= 100999 diff --git a/storage/tokudb/hatoku_hton.cc b/storage/tokudb/hatoku_hton.cc index 217cc5f0136..cbb6bb57657 100644 --- a/storage/tokudb/hatoku_hton.cc +++ b/storage/tokudb/hatoku_hton.cc @@ -571,10 +571,10 @@ static int tokudb_init_func(void *p) { db_env->set_update(db_env, tokudb_update_fun); - db_env_set_direct_io(tokudb::sysvars::directio == TRUE); + db_env_set_direct_io(tokudb::sysvars::directio); db_env_set_compress_buffers_before_eviction( - tokudb::sysvars::compress_buffers_before_eviction == TRUE); + tokudb::sysvars::compress_buffers_before_eviction); db_env->change_fsync_log_period(db_env, tokudb::sysvars::fsync_log_period); diff --git a/storage/tokudb/hatoku_hton.h b/storage/tokudb/hatoku_hton.h index e632a9afe88..816a66aa440 100644 --- a/storage/tokudb/hatoku_hton.h +++ b/storage/tokudb/hatoku_hton.h @@ -190,7 +190,6 @@ inline bool tokudb_killed_thd_callback(void* extra, return thd_kill_level(thd) != 0; } -extern HASH tokudb_open_tables; extern const char* tokudb_hton_name; extern int tokudb_hton_initialized; extern tokudb::thread::rwlock_t tokudb_hton_initialized_lock; diff --git a/storage/tokudb/mysql-test/tokudb_bugs/r/PS-4979.result b/storage/tokudb/mysql-test/tokudb_bugs/r/PS-4979.result new file mode 100644 index 00000000000..5bf7a270fe5 --- /dev/null +++ b/storage/tokudb/mysql-test/tokudb_bugs/r/PS-4979.result @@ -0,0 +1,2 @@ +CREATE TABLE `#mysql50#q.q`(f1 INT KEY) ENGINE=TOKUDB; +ERROR 42000: Incorrect table name '#mysql50#q.q' diff --git a/storage/tokudb/mysql-test/tokudb_bugs/t/PS-4979.test b/storage/tokudb/mysql-test/tokudb_bugs/t/PS-4979.test new file mode 100644 index 00000000000..cb902f6e52a --- /dev/null +++ b/storage/tokudb/mysql-test/tokudb_bugs/t/PS-4979.test @@ -0,0 +1,13 @@ +--source include/have_tokudb.inc +# PS-4979 : Dropping TokuDB table with non-alphanumeric characters could lead +# to a crash +# +# `#mysql50#q.q` is an invalid table name, but the server side doesn't detect it +# and complain. Instead it passes in an empty table name to the engine. The +# engine expects a table name in the form of a relative path like +# "./databasename/tablename". InnoDB detects this in parsing the table name +# during the creation and returns an error. +# MariaDB server detect above error. + +--error ER_WRONG_TABLE_NAME +CREATE TABLE `#mysql50#q.q`(f1 INT KEY) ENGINE=TOKUDB; diff --git a/storage/tokudb/tokudb_background.cc b/storage/tokudb/tokudb_background.cc index 13e0e9321cc..19f03dbca65 100644 --- a/storage/tokudb/tokudb_background.cc +++ b/storage/tokudb/tokudb_background.cc @@ -182,14 +182,14 @@ void* job_manager_t::real_thread_func() { if (res == tokudb::thread::semaphore_t::E_INTERRUPTED || _shutdown) { break; } else if (res == tokudb::thread::semaphore_t::E_SIGNALLED) { -#if TOKUDB_DEBUG +#if defined(TOKUDB_DEBUG) if (TOKUDB_UNLIKELY( tokudb::sysvars::debug_pause_background_job_manager)) { _sem.signal(); tokudb::time::sleep_microsec(250000); continue; } -#endif // TOKUDB_DEBUG +#endif // defined(TOKUDB_DEBUG) mutex_t_lock(_mutex); assert_debug(_background_jobs.size() > 0); diff --git a/storage/tokudb/tokudb_sysvars.cc b/storage/tokudb/tokudb_sysvars.cc index 7771204dc11..88449242d36 100644 --- a/storage/tokudb/tokudb_sysvars.cc +++ b/storage/tokudb/tokudb_sysvars.cc @@ -661,13 +661,13 @@ static MYSQL_THDVAR_ULONGLONG( ~0ULL, 1); -static MYSQL_THDVAR_STR( - last_lock_timeout, - PLUGIN_VAR_MEMALLOC, - "last lock timeout", - NULL, - NULL, - NULL); +static MYSQL_THDVAR_STR(last_lock_timeout, + PLUGIN_VAR_MEMALLOC | PLUGIN_VAR_NOCMDOPT | + PLUGIN_VAR_READONLY, + "last lock timeout", + NULL, + NULL, + NULL); static MYSQL_THDVAR_BOOL( load_save_space, diff --git a/storage/tokudb/tokudb_sysvars.h b/storage/tokudb/tokudb_sysvars.h index 2454f8fefd2..23199baa7be 100644 --- a/storage/tokudb/tokudb_sysvars.h +++ b/storage/tokudb/tokudb_sysvars.h @@ -113,10 +113,10 @@ extern my_bool gdb_on_fatal; extern my_bool check_jemalloc; -#if TOKUDB_DEBUG +#if defined(TOKUDB_DEBUG) // used to control background job manager extern my_bool debug_pause_background_job_manager; -#endif // TOKUDB_DEBUG +#endif // defined(TOKUDB_DEBUG) // session/thread my_bool alter_print_error(THD* thd); diff --git a/storage/xtradb/buf/buf0buf.cc b/storage/xtradb/buf/buf0buf.cc index 44ad78b1f9a..b03aafb6fc7 100644 --- a/storage/xtradb/buf/buf0buf.cc +++ b/storage/xtradb/buf/buf0buf.cc @@ -2,7 +2,7 @@ Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2008, Google Inc. -Copyright (c) 2013, 2018, MariaDB Corporation. +Copyright (c) 2013, 2019, MariaDB Corporation. Portions of this file contain modifications contributed and copyrighted by Google, Inc. Those modifications are gratefully acknowledged and are described @@ -924,7 +924,10 @@ buf_page_is_corrupted( /* Check whether the checksum fields have correct values */ - if (srv_checksum_algorithm == SRV_CHECKSUM_ALGORITHM_NONE) { + const srv_checksum_algorithm_t curr_algo = + static_cast<srv_checksum_algorithm_t>(srv_checksum_algorithm); + + if (curr_algo == SRV_CHECKSUM_ALGORITHM_NONE) { return(false); } @@ -956,9 +959,6 @@ buf_page_is_corrupted( return(false); } - const srv_checksum_algorithm_t curr_algo = - static_cast<srv_checksum_algorithm_t>(srv_checksum_algorithm); - switch (curr_algo) { case SRV_CHECKSUM_ALGORITHM_STRICT_CRC32: return !buf_page_is_checksum_valid_crc32( @@ -987,9 +987,7 @@ buf_page_is_corrupted( for writing checksums because we assume that the chance of it matching is higher. */ - if (srv_checksum_algorithm - == SRV_CHECKSUM_ALGORITHM_CRC32) { - + if (curr_algo == SRV_CHECKSUM_ALGORITHM_CRC32) { crc32 = buf_calc_page_crc32(read_buf); crc32_inited = true; @@ -999,7 +997,7 @@ buf_page_is_corrupted( return true; } } else { - ut_ad(srv_checksum_algorithm + ut_ad(curr_algo == SRV_CHECKSUM_ALGORITHM_INNODB); if (checksum_field2 @@ -1028,8 +1026,7 @@ buf_page_is_corrupted( for writing checksums because we assume that the chance of it matching is higher. */ - if (srv_checksum_algorithm - == SRV_CHECKSUM_ALGORITHM_CRC32) { + if (curr_algo == SRV_CHECKSUM_ALGORITHM_CRC32) { if (!crc32_inited) { crc32 = buf_calc_page_crc32(read_buf); @@ -1042,7 +1039,7 @@ buf_page_is_corrupted( return true; } } else { - ut_ad(srv_checksum_algorithm + ut_ad(curr_algo == SRV_CHECKSUM_ALGORITHM_INNODB); if (checksum_field1 diff --git a/storage/xtradb/handler/handler0alter.cc b/storage/xtradb/handler/handler0alter.cc index 2a5a7af1467..b36010b822a 100644 --- a/storage/xtradb/handler/handler0alter.cc +++ b/storage/xtradb/handler/handler0alter.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 2005, 2018, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2013, 2018, MariaDB Corporation. +Copyright (c) 2017, 2019, MariaDB Corporation. 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 @@ -3811,12 +3811,14 @@ check_if_ok_to_rename: continue; } + dict_foreign_t* foreign; + for (dict_foreign_set::iterator it = prebuilt->table->foreign_set.begin(); it != prebuilt->table->foreign_set.end(); ++it) { - dict_foreign_t* foreign = *it; + foreign = *it; const char* fid = strchr(foreign->id, '/'); DBUG_ASSERT(fid); @@ -3827,7 +3829,6 @@ check_if_ok_to_rename: if (!my_strcasecmp(system_charset_info, fid, drop->name)) { - drop_fk[n_drop_fk++] = foreign; goto found_fk; } } @@ -3836,12 +3837,19 @@ check_if_ok_to_rename: drop->type_name(), drop->name); goto err_exit; found_fk: + for (ulint i = n_drop_fk; i--; ) { + if (drop_fk[i] == foreign) { + goto dup_fk; + } + } + drop_fk[n_drop_fk++] = foreign; +dup_fk: continue; } DBUG_ASSERT(n_drop_fk > 0); DBUG_ASSERT(n_drop_fk - == ha_alter_info->alter_info->drop_list.elements); + <= ha_alter_info->alter_info->drop_list.elements); } else { drop_fk = NULL; } @@ -4712,7 +4720,7 @@ err_exit: rename_foreign: trx->op_info = "renaming column in SYS_FOREIGN_COLS"; - std::list<dict_foreign_t*> fk_evict; + std::set<dict_foreign_t*> fk_evict; bool foreign_modified; for (dict_foreign_set::const_iterator it = user_table->foreign_set.begin(); @@ -4752,7 +4760,7 @@ rename_foreign: } if (foreign_modified) { - fk_evict.push_back(foreign); + fk_evict.insert(foreign); } } @@ -4794,7 +4802,7 @@ rename_foreign: } if (foreign_modified) { - fk_evict.push_back(foreign); + fk_evict.insert(foreign); } } @@ -5190,7 +5198,7 @@ commit_try_rebuild( & Alter_inplace_info::DROP_FOREIGN_KEY) || ctx->num_to_drop_fk > 0); DBUG_ASSERT(ctx->num_to_drop_fk - == ha_alter_info->alter_info->drop_list.elements); + <= ha_alter_info->alter_info->drop_list.elements); for (dict_index_t* index = dict_table_get_first_index(rebuilt_table); index; @@ -5444,7 +5452,7 @@ commit_try_norebuild( & Alter_inplace_info::DROP_FOREIGN_KEY) || ctx->num_to_drop_fk > 0); DBUG_ASSERT(ctx->num_to_drop_fk - == ha_alter_info->alter_info->drop_list.elements); + <= ha_alter_info->alter_info->drop_list.elements); for (ulint i = 0; i < ctx->num_to_add_index; i++) { dict_index_t* index = ctx->add_index[i]; @@ -5765,7 +5773,6 @@ ha_innobase::commit_inplace_alter_table( Alter_inplace_info* ha_alter_info, bool commit) { - dberr_t error; ha_innobase_inplace_ctx* ctx0 = static_cast<ha_innobase_inplace_ctx*> (ha_alter_info->handler_ctx); @@ -5845,7 +5852,7 @@ ha_innobase::commit_inplace_alter_table( transactions collected during crash recovery could be holding InnoDB locks only, not MySQL locks. */ - error = row_merge_lock_table( + dberr_t error = row_merge_lock_table( prebuilt->trx, ctx->old_table, LOCK_X); if (error != DB_SUCCESS) { @@ -6030,9 +6037,9 @@ rollback_trx: file operations that will be performed in commit_cache_rebuild(), and if none, generate the redo log for these operations. */ - error = fil_mtr_rename_log(ctx->old_table, - ctx->new_table, - ctx->tmp_name, &mtr); + dberr_t error = fil_mtr_rename_log( + ctx->old_table, ctx->new_table, ctx->tmp_name, + &mtr); if (error != DB_SUCCESS) { /* Out of memory or a problem will occur when renaming files. */ @@ -6157,39 +6164,30 @@ rollback_trx: /* Rename the tablespace files. */ commit_cache_rebuild(ctx); - error = innobase_update_foreign_cache(ctx, user_thd); - if (error != DB_SUCCESS) { - goto foreign_fail; + if (innobase_update_foreign_cache(ctx, user_thd) + != DB_SUCCESS + && prebuilt->trx->check_foreigns) { +foreign_fail: + push_warning_printf( + user_thd, + Sql_condition::WARN_LEVEL_WARN, + ER_ALTER_INFO, + "failed to load FOREIGN KEY" + " constraints"); } } else { - error = innobase_update_foreign_cache(ctx, user_thd); + bool fk_fail = innobase_update_foreign_cache( + ctx, user_thd) != DB_SUCCESS; - if (error != DB_SUCCESS) { -foreign_fail: - /* The data dictionary cache - should be corrupted now. The - best solution should be to - kill and restart the server, - but the *.frm file has not - been replaced yet. */ - my_error(ER_CANNOT_ADD_FOREIGN, - MYF(0)); - sql_print_error( - "InnoDB: dict_load_foreigns()" - " returned %u for %s", - (unsigned) error, - thd_query_string(user_thd) - ->str); - ut_ad(0); - } else { - if (!commit_cache_norebuild( - ctx, table, trx)) { - ut_a(!prebuilt->trx->check_foreigns); - } + if (!commit_cache_norebuild(ctx, table, trx)) { + fk_fail = true; + ut_ad(!prebuilt->trx->check_foreigns); + } - innobase_rename_columns_cache( - ha_alter_info, table, - ctx->new_table); + innobase_rename_columns_cache(ha_alter_info, table, + ctx->new_table); + if (fk_fail && prebuilt->trx->check_foreigns) { + goto foreign_fail; } } DBUG_INJECT_CRASH("ib_commit_inplace_crash", diff --git a/storage/xtradb/include/univ.i b/storage/xtradb/include/univ.i index 7da0dfe4728..6d1520bc6a3 100644 --- a/storage/xtradb/include/univ.i +++ b/storage/xtradb/include/univ.i @@ -45,10 +45,10 @@ Created 1/20/1994 Heikki Tuuri #define INNODB_VERSION_MAJOR 5 #define INNODB_VERSION_MINOR 6 -#define INNODB_VERSION_BUGFIX 41 +#define INNODB_VERSION_BUGFIX 42 #ifndef PERCONA_INNODB_VERSION -#define PERCONA_INNODB_VERSION 84.1 +#define PERCONA_INNODB_VERSION 84.2 #endif /* Enable UNIV_LOG_ARCHIVE in XtraDB */ diff --git a/storage/xtradb/log/log0online.cc b/storage/xtradb/log/log0online.cc index 42e92ea6f0e..bc1667e1c20 100644 --- a/storage/xtradb/log/log0online.cc +++ b/storage/xtradb/log/log0online.cc @@ -1864,6 +1864,8 @@ log_online_purge_changed_page_bitmaps( for (i = 0; i < bitmap_files.count; i++) { + char full_bmp_file_name[2 * FN_REFLEN + 2]; + /* We consider the end LSN of the current bitmap, derived from the start LSN of the subsequent bitmap file, to determine whether to remove the current bitmap. Note that bitmap_files @@ -1879,8 +1881,45 @@ log_online_purge_changed_page_bitmaps( break; } + + /* In some non-trivial cases the sequence of .xdb files may + have gaps. For instance: + ib_modified_log_1_0.xdb + ib_modified_log_2_<mmm>.xdb + ib_modified_log_4_<nnn>.xdb + Adding this check as a safety precaution. */ + if (bitmap_files.files[i].name[0] == '\0') + continue; + + /* If redo log tracking is enabled, reuse 'bmp_file_home' + from 'log_bmp_sys'. Otherwise, compose the full '.xdb' file + path from 'srv_data_home', adding a path separator if + necessary. */ + if (log_bmp_sys != NULL) { + ut_snprintf(full_bmp_file_name, + sizeof(full_bmp_file_name), + "%s%s", log_bmp_sys->bmp_file_home, + bitmap_files.files[i].name); + } + else { + char separator[2] = {0, 0}; + const size_t srv_data_home_len = + strlen(srv_data_home); + + ut_a(srv_data_home_len < FN_REFLEN); + if (srv_data_home_len != 0 && + srv_data_home[srv_data_home_len - 1] != + SRV_PATH_SEPARATOR) { + separator[0] = SRV_PATH_SEPARATOR; + } + ut_snprintf(full_bmp_file_name, + sizeof(full_bmp_file_name), "%s%s%s", + srv_data_home, separator, + bitmap_files.files[i].name); + } + if (!os_file_delete_if_exists(innodb_file_bmp_key, - bitmap_files.files[i].name)) { + full_bmp_file_name)) { os_file_get_last_error(TRUE); result = TRUE; diff --git a/storage/xtradb/row/row0ins.cc b/storage/xtradb/row/row0ins.cc index b14d43e4f42..476c18680f3 100644 --- a/storage/xtradb/row/row0ins.cc +++ b/storage/xtradb/row/row0ins.cc @@ -56,6 +56,7 @@ Created 4/20/1996 Heikki Tuuri #include "m_string.h" #ifdef WITH_WSREP +#include <mysql/service_wsrep.h> #include "../../../wsrep/wsrep_api.h" #include "wsrep_mysqld_c.h" #endif /* WITH_WSREP */ @@ -1657,6 +1658,9 @@ run_again: if (check_ref) { err = DB_SUCCESS; #ifdef WITH_WSREP + if (!wsrep_on(trx->mysql_thd)) { + goto end_scan; + } enum wsrep_key_type key_type; if (upd_node != NULL) { key_type = WSREP_KEY_SHARED; @@ -1673,7 +1677,7 @@ run_again: } err = wsrep_append_foreign_key( - thr_get_trx(thr), + trx, foreign, rec, check_index, diff --git a/storage/xtradb/row/row0mysql.cc b/storage/xtradb/row/row0mysql.cc index 6c11dd78d7a..93a4db98e7b 100644 --- a/storage/xtradb/row/row0mysql.cc +++ b/storage/xtradb/row/row0mysql.cc @@ -5132,18 +5132,6 @@ row_rename_table_for_mysql( goto funct_exit; } - /* Wait for background fts sync to finish */ - for (retry = 1; dict_fts_index_syncing(table); ++retry) { - DICT_BG_YIELD(trx); - if (retry % 100 == 0) { - ib_logf(IB_LOG_LEVEL_INFO, - "Unable to rename table %s to new name" - " %s because FTS sync is running on table." - " Retrying\n", - old_name, new_name); - } - } - /* We use the private SQL parser of Innobase to generate the query graphs needed in updating the dictionary data from system tables. */ diff --git a/support-files/mysql.server.sh b/support-files/mysql.server.sh index e2054a8fb98..09f26d52129 100644 --- a/support-files/mysql.server.sh +++ b/support-files/mysql.server.sh @@ -185,7 +185,11 @@ fi user='@MYSQLD_USER@' su_kill() { - su - $user -s /bin/sh -c "kill $*" >/dev/null 2>&1 + if test "$USER" = "$user"; then + kill $* >/dev/null 2>&1 + else + su - $user -s /bin/sh -c "kill $*" >/dev/null 2>&1 + fi } # diff --git a/unittest/mysys/thr_template.c b/unittest/mysys/thr_template.c index de68aca6d36..38b8d2903a5 100644 --- a/unittest/mysys/thr_template.c +++ b/unittest/mysys/thr_template.c @@ -34,7 +34,7 @@ void test_concurrently(const char *test, pthread_handler handler, int n, int m) bad= 0; diag("Testing %s with %d threads, %d iterations... ", test, n, m); - for (i= n; i; i--) + for (i= 0; i < n; i++) { if (pthread_create(&threads[i], 0, handler, &m) != 0) { @@ -43,7 +43,7 @@ void test_concurrently(const char *test, pthread_handler handler, int n, int m) } } - for (i= n; i; i--) + for (i= 0; i < n; i++) pthread_join(threads[i], 0); now= my_interval_timer() - now; diff --git a/win/packaging/heidisql.cmake b/win/packaging/heidisql.cmake index 569ae4d8ed5..897678f2025 100644 --- a/win/packaging/heidisql.cmake +++ b/win/packaging/heidisql.cmake @@ -1,4 +1,4 @@ -SET(HEIDISQL_BASE_NAME "HeidiSQL_9.4_Portable") +SET(HEIDISQL_BASE_NAME "HeidiSQL_9.5_Portable") SET(HEIDISQL_ZIP "${HEIDISQL_BASE_NAME}.zip") SET(HEIDISQL_URL "http://www.heidisql.com/downloads/releases/${HEIDISQL_ZIP}") SET(HEIDISQL_DOWNLOAD_DIR ${THIRD_PARTY_DOWNLOAD_LOCATION}/${HEIDISQL_BASE_NAME}) |