diff options
author | unknown <joerg@trift2.> | 2007-11-14 16:11:52 +0100 |
---|---|---|
committer | unknown <joerg@trift2.> | 2007-11-14 16:11:52 +0100 |
commit | d1d6920db95611c656ba63117b7e3ab924902705 (patch) | |
tree | 59a760a5c50ffb7c3cbe0b554f709d71909e132d | |
parent | 37e64bd3c06d50b4d7b7ba58f18172c2c6f76f5e (diff) | |
parent | b3a71e34487b69846553111448fa2b32c86176a9 (diff) | |
download | mariadb-git-d1d6920db95611c656ba63117b7e3ab924902705.tar.gz |
Merge trift2.:/MySQL/M51/mysql-5.1
into trift2.:/MySQL/M51/push-5.1
include/my_sys.h:
Auto merged
sql/CMakeLists.txt:
Manual merge: Keep the workaround for the cmake 2.4.6 bug, enclose it in "if".
55 files changed, 1280 insertions, 121 deletions
diff --git a/config/ac-macros/plugins.m4 b/config/ac-macros/plugins.m4 index 48754563992..8dfb698709f 100644 --- a/config/ac-macros/plugins.m4 +++ b/config/ac-macros/plugins.m4 @@ -360,6 +360,17 @@ AC_DEFUN([__MYSQL_EMIT_CHECK_PLUGIN],[ AC_MSG_ERROR([cannot disable mandatory plugin]) fi [mysql_plugin_]$2=yes + ],[ + case "$with_mysqld_ldflags " in + *"-all-static "*) + # No need to build shared plugins when mysqld is linked with + # -all-static as it won't be able to load them. + if test "X[$mysql_plugin_]$2" != Xyes -a \ + "X[$with_plugin_]$2" != Xyes; then + [with_plugin_]$2=no + fi + ;; + esac ]) if test "X[$with_plugin_]$2" = Xno; then AC_MSG_RESULT([no]) diff --git a/configure.in b/configure.in index 980519dc535..161a70dae5f 100644 --- a/configure.in +++ b/configure.in @@ -1750,7 +1750,18 @@ then LDFLAGS="$LDFLAGS -rdynamic" AC_MSG_RESULT("-rdynamic") else - AC_MSG_RESULT("none") + case "$SYSTEM_TYPE$with_mysqld_ldflags " in + *freebsd*"-all-static "*|*dragonfly*"-all-static "*) + AC_MSG_RESULT("none") + ;; + *freebsd*|*dragonfly*) + MYSQLD_EXTRA_LDFLAGS="$MYSQLD_EXTRA_LDFLAGS -export-dynamic" + AC_MSG_RESULT("-export-dynamic") + ;; + *) + AC_MSG_RESULT("none") + ;; + esac fi dnl Checks for typedefs, structures, and compiler characteristics. diff --git a/libmysqld/lib_sql.cc b/libmysqld/lib_sql.cc index 13847c324e1..4963d7fc978 100644 --- a/libmysqld/lib_sql.cc +++ b/libmysqld/lib_sql.cc @@ -93,6 +93,7 @@ emb_advanced_command(MYSQL *mysql, enum enum_server_command command, thd->current_stmt= stmt; thd->store_globals(); // Fix if more than one connect + lex_start(thd); /* We have to call free_old_query before we start to fill mysql->fields for new query. In the case of embedded server we collect field data @@ -580,6 +581,7 @@ void *create_embedded_thd(int client_flag) fprintf(stderr,"store_globals failed.\n"); goto err; } + lex_start(thd); /* TODO - add init_connect command execution */ diff --git a/mysql-test/include/gis_keys.inc b/mysql-test/include/gis_keys.inc index 295e0c48234..c75311f062a 100644 --- a/mysql-test/include/gis_keys.inc +++ b/mysql-test/include/gis_keys.inc @@ -13,20 +13,20 @@ CREATE TABLE t2 (p POINT, INDEX(p)); INSERT INTO t1 VALUES (POINTFROMTEXT('POINT(1 2)')); INSERT INTO t2 VALUES (POINTFROMTEXT('POINT(1 2)')); --- no index, returns 1 as expected +# no index, returns 1 as expected SELECT COUNT(*) FROM t1 WHERE p=POINTFROMTEXT('POINT(1 2)'); --- with index, returns 1 as expected --- EXPLAIN shows that the index is not used though --- due to the "most rows covered anyway, so a scan is more effective" rule +# with index, returns 1 as expected +# EXPLAIN shows that the index is not used though +# due to the "most rows covered anyway, so a scan is more effective" rule EXPLAIN SELECT COUNT(*) FROM t2 WHERE p=POINTFROMTEXT('POINT(1 2)'); SELECT COUNT(*) FROM t2 WHERE p=POINTFROMTEXT('POINT(1 2)'); --- adding another row to the table so that --- the "most rows covered" rule doesn't kick in anymore --- now EXPLAIN shows the index used on the table --- and we're getting the wrong result again +# adding another row to the table so that +# the "most rows covered" rule doesn't kick in anymore +# now EXPLAIN shows the index used on the table +# and we're getting the wrong result again INSERT INTO t1 VALUES (POINTFROMTEXT('POINT(1 2)')); INSERT INTO t2 VALUES (POINTFROMTEXT('POINT(1 2)')); EXPLAIN diff --git a/mysql-test/include/mix1.inc b/mysql-test/include/mix1.inc index d55b404621d..7998baa6ccf 100644 --- a/mysql-test/include/mix1.inc +++ b/mysql-test/include/mix1.inc @@ -1212,7 +1212,7 @@ CREATE TABLE t1 (a INT PRIMARY KEY, b VARCHAR(256)) ENGINE = $engine_type; INSERT INTO t1 VALUES (1,2); ---#echo 1. test for locking: +--echo # 1. test for locking: BEGIN; --enable_info diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl index c3312dce3ac..f6ea5550007 100755 --- a/mysql-test/mysql-test-run.pl +++ b/mysql-test/mysql-test-run.pl @@ -3754,7 +3754,9 @@ sub mysqld_arguments ($$$$) { # When mysqld is run by a root user(euid is 0), it will fail # to start unless we specify what user to run as. If not running # as root it will be ignored, see BUG#30630 - if (!(grep(/^--user/, @$extra_opt, @opt_extra_mysqld_opt))) { + my $euid= $>; + if (!$glob_win32 and $euid == 0 and + grep(/^--user/, @$extra_opt, @opt_extra_mysqld_opt) == 0) { mtr_add_arg($args, "%s--user=root"); } diff --git a/mysql-test/r/ctype_ucs.result b/mysql-test/r/ctype_ucs.result index a0a8455b496..59b1bfa183d 100644 --- a/mysql-test/r/ctype_ucs.result +++ b/mysql-test/r/ctype_ucs.result @@ -811,6 +811,12 @@ quote(name) ???????? ???????????????? drop table bug20536; +CREATE TABLE t1(a TEXT CHARSET ucs2 COLLATE ucs2_unicode_ci); +INSERT INTO t1 VALUES('abcd'); +SELECT * FROM t1 WHERE MATCH(a) AGAINST ('+abcd' IN BOOLEAN MODE); +a +abcd +DROP TABLE t1; End of 4.1 tests CREATE TABLE t1 (a varchar(64) character set ucs2, b decimal(10,3)); INSERT INTO t1 VALUES ("1.1", 0), ("2.1", 0); diff --git a/mysql-test/r/federated_server.result b/mysql-test/r/federated_server.result index 0905aabb075..32717b4f0e3 100644 --- a/mysql-test/r/federated_server.result +++ b/mysql-test/r/federated_server.result @@ -253,6 +253,14 @@ drop user guest_usage@localhost; drop user guest_select@localhost; drop table federated.t1; drop server 's1'; +create server 's1' foreign data wrapper 'mysql' options (port 3306); +alter server 's1' options +(host 'localhost', database '', user '', +password '', socket '', owner '', port 3306); +alter server 's1' options +(host 'localhost', database 'database1', user '', +password '', socket '', owner '', port 3306); +drop server 's1'; # End of 5.1 tests use test; create procedure p1 () @@ -262,7 +270,7 @@ DECLARE e INT DEFAULT 0; DECLARE i INT; DECLARE CONTINUE HANDLER FOR SQLEXCEPTION SET e = e + 1; SET i = sleep(5); -WHILE v < 20000 do +WHILE v < 10000 do CREATE SERVER s FOREIGN DATA WRAPPER mysql OPTIONS (USER 'Remote', HOST '192.168.1.106', DATABASE 'test'); diff --git a/mysql-test/r/fulltext.result b/mysql-test/r/fulltext.result index 96ebb9bf254..c3fa427127b 100644 --- a/mysql-test/r/fulltext.result +++ b/mysql-test/r/fulltext.result @@ -476,6 +476,12 @@ ALTER TABLE t1 DISABLE KEYS; SELECT * FROM t1 WHERE MATCH(a) AGAINST('test'); ERROR HY000: Can't find FULLTEXT index matching the column list DROP TABLE t1; +CREATE TABLE t1(a TEXT); +INSERT INTO t1 VALUES(' aaaaa aaaa'); +SELECT * FROM t1 WHERE MATCH(a) AGAINST ('"aaaa"' IN BOOLEAN MODE); +a + aaaaa aaaa +DROP TABLE t1; CREATE TABLE t1(a VARCHAR(20), FULLTEXT(a)); INSERT INTO t1 VALUES('Offside'),('City Of God'); SELECT a FROM t1 WHERE MATCH a AGAINST ('+city of*' IN BOOLEAN MODE); diff --git a/mysql-test/r/innodb_mysql.result b/mysql-test/r/innodb_mysql.result index 05db4436a65..3f9e9b404f0 100644 --- a/mysql-test/r/innodb_mysql.result +++ b/mysql-test/r/innodb_mysql.result @@ -1460,6 +1460,7 @@ SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED; CREATE TABLE t1 (a INT PRIMARY KEY, b VARCHAR(256)) ENGINE = InnoDB; INSERT INTO t1 VALUES (1,2); +# 1. test for locking: BEGIN; UPDATE t1 SET b = 12 WHERE a = 1; affected rows: 1 diff --git a/mysql-test/r/myisam.result b/mysql-test/r/myisam.result index 73661897ee1..3125660643c 100644 --- a/mysql-test/r/myisam.result +++ b/mysql-test/r/myisam.result @@ -1794,6 +1794,31 @@ SELECT a FROM t1 FORCE INDEX (inx) WHERE a=1; a 1 DROP TABLE t1; +CREATE TABLE t1 (c1 INT, c2 INT, UNIQUE INDEX (c1), INDEX (c2)) ENGINE=MYISAM; +SHOW TABLE STATUS LIKE 't1'; +Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment +t1 MyISAM 10 Fixed 0 # # # 1024 # # # # # # # +INSERT INTO t1 VALUES (1,1); +SHOW TABLE STATUS LIKE 't1'; +Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment +t1 MyISAM 10 Fixed 1 # # # 3072 # # # # # # # +ALTER TABLE t1 DISABLE KEYS; +SHOW TABLE STATUS LIKE 't1'; +Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment +t1 MyISAM 10 Fixed 1 # # # 3072 # # # # # # # +ALTER TABLE t1 ENABLE KEYS; +SHOW TABLE STATUS LIKE 't1'; +Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment +t1 MyISAM 10 Fixed 1 # # # 3072 # # # # # # # +ALTER TABLE t1 DISABLE KEYS; +SHOW TABLE STATUS LIKE 't1'; +Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment +t1 MyISAM 10 Fixed 1 # # # 3072 # # # # # # # +ALTER TABLE t1 ENABLE KEYS; +SHOW TABLE STATUS LIKE 't1'; +Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment +t1 MyISAM 10 Fixed 1 # # # 3072 # # # # # # # +DROP TABLE t1; End of 5.0 tests create table t1 (a int not null, key `a` (a) key_block_size=1024); show create table t1; diff --git a/mysql-test/r/partition.result b/mysql-test/r/partition.result index b8ca0a247d9..aa6a64ac76e 100644 --- a/mysql-test/r/partition.result +++ b/mysql-test/r/partition.result @@ -1,4 +1,32 @@ drop table if exists t1; +CREATE TABLE t1 ( +d DATE NOT NULL +) +PARTITION BY RANGE( YEAR(d) ) ( +PARTITION p0 VALUES LESS THAN (1960), +PARTITION p1 VALUES LESS THAN (1970), +PARTITION p2 VALUES LESS THAN (1980), +PARTITION p3 VALUES LESS THAN (1990) +); +ALTER TABLE t1 ADD PARTITION ( +PARTITION `p5` VALUES LESS THAN (2010) +COMMENT 'APSTART \' APEND' +); +SELECT * FROM t1 LIMIT 1; +d +DROP TABLE t1; +create table t1 (id int auto_increment, s1 int, primary key (id)); +insert into t1 values (null,1); +insert into t1 values (null,6); +select * from t1; +id s1 +1 1 +2 6 +alter table t1 partition by range (id) ( +partition p0 values less than (3), +partition p1 values less than maxvalue +); +drop table t1; create table t1 (a int) partition by key(a) partitions 0.2+e1; @@ -687,7 +715,7 @@ partition by range (a) alter table t1 add partition (partition p1 values in (2)); ERROR HY000: Only LIST PARTITIONING can use VALUES IN in partition definition alter table t1 add partition (partition p1); -ERROR HY000: RANGE PARTITIONING requires definition of VALUES LESS THAN for each partition +ERROR HY000: Syntax error: RANGE PARTITIONING requires definition of VALUES LESS THAN for each partition drop table t1; create table t1 (a int) partition by list (a) @@ -695,7 +723,7 @@ partition by list (a) alter table t1 add partition (partition p1 values less than (2)); ERROR HY000: Only RANGE PARTITIONING can use VALUES LESS THAN in partition definition alter table t1 add partition (partition p1); -ERROR HY000: LIST PARTITIONING requires definition of VALUES IN for each partition +ERROR HY000: Syntax error: LIST PARTITIONING requires definition of VALUES IN for each partition drop table t1; create table t1 (a int) partition by hash (a) diff --git a/mysql-test/r/partition_datatype.result b/mysql-test/r/partition_datatype.result new file mode 100644 index 00000000000..c6506178b03 --- /dev/null +++ b/mysql-test/r/partition_datatype.result @@ -0,0 +1,282 @@ +drop table if exists t1; +create table t1 (a tinyint not null) partition by key (a); +insert into t1 values (2); +select * from t1 where a = 2; +a +2 +drop table t1; +create table t1 (a smallint not null) partition by key (a); +insert into t1 values (2); +select * from t1 where a = 2; +a +2 +drop table t1; +create table t1 (a mediumint not null) partition by key (a); +insert into t1 values (2); +select * from t1 where a = 2; +a +2 +drop table t1; +create table t1 (a int not null) partition by key (a); +insert into t1 values (2); +select * from t1 where a = 2; +a +2 +drop table t1; +create table t1 (a bigint not null) partition by key (a); +insert into t1 values (2); +select * from t1 where a = 2; +a +2 +drop table t1; +create table t1 (a float not null) partition by key (a); +insert into t1 values (2.1); +select * from t1 where a = 2.1; +a +drop table t1; +create table t1 (a double not null) partition by key (a); +insert into t1 values (2.1); +select * from t1 where a = 2.1; +a +2.1 +drop table t1; +create table t1 (a decimal not null) partition by key (a); +insert into t1 values (2.1); +Warnings: +Note 1265 Data truncated for column 'a' at row 1 +select * from t1 where a = 2.1; +a +drop table t1; +create table t1 (a date not null) partition by key (a); +insert into t1 values ('2001-01-01'); +select * from t1 where a = '2001-01-01'; +a +2001-01-01 +drop table t1; +create table t1 (a datetime not null) partition by key (a); +insert into t1 values ('2001-01-01 01:02:03'); +select * from t1 where a = '2001-01-01 01:02:03'; +a +2001-01-01 01:02:03 +drop table t1; +create table t1 (a timestamp not null) partition by key (a); +insert into t1 values ('2001-01-01 01:02:03'); +select * from t1 where a = '2001-01-01 01:02:03'; +a +2001-01-01 01:02:03 +drop table t1; +create table t1 (a time not null) partition by key (a); +insert into t1 values ('01:02:03'); +select * from t1 where a = '01:02:03'; +a +01:02:03 +drop table t1; +create table t1 (a year not null) partition by key (a); +insert into t1 values ('2001'); +select * from t1 where a = '2001'; +a +2001 +drop table t1; +create table t1 (a varchar(10) character set utf8 not null) partition by key (a); +insert into t1 values ('abc'); +select * from t1 where a = 'abc'; +a +abc +drop table t1; +create table t1 (a varchar(300) character set utf8 not null) partition by key (a); +insert into t1 values ('abc'); +select * from t1 where a = 'abc'; +a +abc +drop table t1; +create table t1 (a varchar(10) character set latin1 not null) partition by key (a); +insert into t1 values ('abc'); +select * from t1 where a = 'abc'; +a +abc +drop table t1; +create table t1 (a varchar(300) character set latin1 not null) partition by key (a); +insert into t1 values ('abc'); +select * from t1 where a = 'abc'; +a +abc +drop table t1; +create table t1 (a char(10) character set utf8 not null) partition by key (a); +insert into t1 values ('abc'); +select * from t1 where a = 'abc'; +a +abc +drop table t1; +create table t1 (a char(10) character set latin1 not null) partition by key (a); +insert into t1 values ('abc'); +select * from t1 where a = 'abc'; +a +abc +drop table t1; +create table t1 (a enum('y','n') not null) partition by key (a); +insert into t1 values ('y'); +select * from t1 where a = 'y'; +a +y +drop table t1; +create table t1 (a set('y','n') not null) partition by key (a); +insert into t1 values ('y'); +select * from t1 where a = 'y'; +a +y +drop table t1; +create table t1 (a tinyint) partition by key (a); +insert into t1 values (2); +select * from t1 where a = 2; +a +2 +drop table t1; +create table t1 (a smallint) partition by key (a); +insert into t1 values (2); +select * from t1 where a = 2; +a +2 +drop table t1; +create table t1 (a mediumint) partition by key (a); +insert into t1 values (2); +select * from t1 where a = 2; +a +2 +drop table t1; +create table t1 (a int) partition by key (a); +insert into t1 values (2); +select * from t1 where a = 2; +a +2 +drop table t1; +create table t1 (a bigint) partition by key (a); +insert into t1 values (2); +select * from t1 where a = 2; +a +2 +drop table t1; +create table t1 (a float) partition by key (a); +insert into t1 values (2.1); +select * from t1 where a = 2.1; +a +drop table t1; +create table t1 (a double) partition by key (a); +insert into t1 values (2.1); +select * from t1 where a = 2.1; +a +2.1 +drop table t1; +create table t1 (a decimal) partition by key (a); +insert into t1 values (2.1); +Warnings: +Note 1265 Data truncated for column 'a' at row 1 +select * from t1 where a = 2.1; +a +drop table t1; +create table t1 (a date) partition by key (a); +insert into t1 values ('2001-01-01'); +select * from t1 where a = '2001-01-01'; +a +2001-01-01 +drop table t1; +create table t1 (a datetime) partition by key (a); +insert into t1 values ('2001-01-01 01:02:03'); +select * from t1 where a = '2001-01-01 01:02:03'; +a +2001-01-01 01:02:03 +drop table t1; +create table t1 (a timestamp null) partition by key (a); +insert into t1 values ('2001-01-01 01:02:03'); +select * from t1 where a = '2001-01-01 01:02:03'; +a +2001-01-01 01:02:03 +drop table t1; +create table t1 (a time) partition by key (a); +insert into t1 values ('01:02:03'); +select * from t1 where a = '01:02:03'; +a +01:02:03 +drop table t1; +create table t1 (a year) partition by key (a); +insert into t1 values ('2001'); +select * from t1 where a = '2001'; +a +2001 +drop table t1; +create table t1 (a varchar(10) character set utf8) partition by key (a); +insert into t1 values ('abc'); +select * from t1 where a = 'abc'; +a +abc +drop table t1; +create table t1 (a varchar(300) character set utf8) partition by key (a); +insert into t1 values ('abc'); +select * from t1 where a = 'abc'; +a +abc +drop table t1; +create table t1 (a varchar(10) character set latin1) partition by key (a); +insert into t1 values ('abc'); +select * from t1 where a = 'abc'; +a +abc +drop table t1; +create table t1 (a varchar(300) character set latin1) partition by key (a); +insert into t1 values ('abc'); +select * from t1 where a = 'abc'; +a +abc +drop table t1; +create table t1 (a char(10) character set utf8) partition by key (a); +insert into t1 values ('abc'); +select * from t1 where a = 'abc'; +a +abc +drop table t1; +create table t1 (a char(10) character set latin1) partition by key (a); +insert into t1 values ('abc'); +select * from t1 where a = 'abc'; +a +abc +drop table t1; +create table t1 (a enum('y','n')) partition by key (a); +insert into t1 values ('y'); +select * from t1 where a = 'y'; +a +y +drop table t1; +create table t1 (a set('y','n')) partition by key (a); +insert into t1 values ('y'); +select * from t1 where a = 'y'; +a +y +drop table t1; +create table t1 (a varchar(65531)) partition by key (a); +insert into t1 values ('bbbb'); +insert into t1 values ('aaaa'); +select * from t1 where a = 'aaa%'; +a +select * from t1 where a like 'aaa%'; +a +aaaa +drop table t1; +create table t1 (a varchar(65532)) partition by key (a); +insert into t1 values ('bbbb'); +insert into t1 values ('aaaa'); +select * from t1 where a = 'aaa%'; +a +select * from t1 where a like 'aaa%'; +a +aaaa +drop table t1; +create table t1 (a varchar(65533) not null) partition by key (a); +insert into t1 values ('aaaa'); +select * from t1 where a = 'aaa%'; +a +drop table t1; +create table t1 (a varchar(65533)) partition by key (a); +ERROR 42000: Row size too large. The maximum row size for the used table type, not counting BLOBs, is 65535. You have to change some columns to TEXT or BLOBs +create table t1 (a varchar(65534) not null) partition by key (a); +ERROR 42000: Row size too large. The maximum row size for the used table type, not counting BLOBs, is 65535. You have to change some columns to TEXT or BLOBs +create table t1 (a varchar(65535)) partition by key (a); +ERROR 42000: Row size too large. The maximum row size for the used table type, not counting BLOBs, is 65535. You have to change some columns to TEXT or BLOBs diff --git a/mysql-test/r/partition_error.result b/mysql-test/r/partition_error.result index 7952c8df609..46532cb32ab 100644 --- a/mysql-test/r/partition_error.result +++ b/mysql-test/r/partition_error.result @@ -1,4 +1,13 @@ drop table if exists t1; +CREATE TABLE t1 ( +a int +) +PARTITION BY RANGE (a) +( +PARTITION p0 VALUES LESS THAN (1), +PARTITION p1 VALU ES LESS THAN (2) +); +ERROR HY000: Syntax error: RANGE PARTITIONING requires definition of VALUES LESS THAN for each partition partition by list (a) partitions 3 (partition x1 values in (1,2,9,4) tablespace ts1, @@ -351,7 +360,7 @@ partition by range (a) partitions 2 (partition x1 values less than (4), partition x2); -ERROR HY000: RANGE PARTITIONING requires definition of VALUES LESS THAN for each partition +ERROR HY000: Syntax error: RANGE PARTITIONING requires definition of VALUES LESS THAN for each partition CREATE TABLE t1 ( a int not null, b int not null, @@ -531,7 +540,7 @@ partition by list (a) partitions 2 (partition x1 values in (4), partition x2); -ERROR HY000: LIST PARTITIONING requires definition of VALUES IN for each partition +ERROR HY000: Syntax error: LIST PARTITIONING requires definition of VALUES IN for each partition CREATE TABLE t1 ( a int not null, b int not null, @@ -551,7 +560,7 @@ partition by list (a) partitions 2 (partition x1 values in (4,6), partition x2); -ERROR HY000: LIST PARTITIONING requires definition of VALUES IN for each partition +ERROR HY000: Syntax error: LIST PARTITIONING requires definition of VALUES IN for each partition CREATE TABLE t1 ( a int not null, b int not null, diff --git a/mysql-test/r/partition_hash.result b/mysql-test/r/partition_hash.result index 9a82a36d902..72f036be099 100644 --- a/mysql-test/r/partition_hash.result +++ b/mysql-test/r/partition_hash.result @@ -183,3 +183,6 @@ c1 c2 c3 182 abc 2002-11-09 184 abc 2002-11-22 drop table t1; +CREATE TABLE t1 (c1 INT) ENGINE=MyISAM PARTITION BY HASH(c1) PARTITIONS 1; +INSERT DELAYED INTO t1 VALUES (1); +DROP TABLE t1; diff --git a/mysql-test/r/partition_mgm.result b/mysql-test/r/partition_mgm.result index 04ac603fea7..9ef220028b3 100644 --- a/mysql-test/r/partition_mgm.result +++ b/mysql-test/r/partition_mgm.result @@ -17,12 +17,6 @@ t1 CREATE TABLE `t1` ( `f_date` date DEFAULT NULL, `f_varchar` varchar(30) DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 /*!50100 PARTITION BY HASH (YEAR(f_date)) PARTITIONS 2 */ -hello/master-data/test/t1#P#p0.MYD -hello/master-data/test/t1#P#p0.MYI -hello/master-data/test/t1#P#p1.MYD -hello/master-data/test/t1#P#p1.MYI -hello/master-data/test/t1.frm -hello/master-data/test/t1.par ALTER TABLE t1 COALESCE PARTITION 1; SHOW CREATE TABLE t1; Table Create Table @@ -30,10 +24,6 @@ t1 CREATE TABLE `t1` ( `f_date` date DEFAULT NULL, `f_varchar` varchar(30) DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 /*!50100 PARTITION BY HASH (YEAR(f_date)) PARTITIONS 1 */ -hello/master-data/test/t1#P#p0.MYD -hello/master-data/test/t1#P#p0.MYI -hello/master-data/test/t1.frm -hello/master-data/test/t1.par drop table t1; create table t1 (a int) partition by list (a) diff --git a/mysql-test/r/partition_symlink.result b/mysql-test/r/partition_symlink.result new file mode 100644 index 00000000000..20e841d2e0e --- /dev/null +++ b/mysql-test/r/partition_symlink.result @@ -0,0 +1,83 @@ +DROP TABLE IF EXISTS t1; +DROP DATABASE IF EXISTS mysqltest2; +# Creating two non colliding tables mysqltest2.t1 and test.t1 +# test.t1 have partitions in mysqltest2-directory! +# user root: +CREATE USER mysqltest_1@localhost; +CREATE DATABASE mysqltest2; +USE mysqltest2; +CREATE TABLE t1 (a INT); +INSERT INTO t1 VALUES (0); +# user mysqltest_1: +USE test; +CREATE TABLE t1 (a INT) +PARTITION BY LIST (a) ( +PARTITION p0 VALUES IN (0) +DATA DIRECTORY 'MYSQLTEST_VARDIR/master-data/mysqltest2' + INDEX DIRECTORY 'MYSQLTEST_VARDIR/master-data/mysqltest2', +PARTITION p1 VALUES IN (1) +DATA DIRECTORY 'MYSQLTEST_VARDIR/master-data/test' + INDEX DIRECTORY 'MYSQLTEST_VARDIR/master-data/test', +PARTITION p2 VALUES IN (2) +); +# without the patch for bug#32091 this would create +# files mysqltest2/t1.MYD + .MYI and possible overwrite +# the mysqltest2.t1 table (depending on bug#32111) +ALTER TABLE t1 REMOVE PARTITIONING; +INSERT INTO t1 VALUES (1); +SELECT * FROM t1; +a +1 +# user root: +USE mysqltest2; +FLUSH TABLES; +# if the patch works, this should be different +# and before the patch they were the same! +SELECT * FROM t1; +a +0 +USE test; +SELECT * FROM t1; +a +1 +DROP TABLE t1; +DROP DATABASE mysqltest2; +# test that symlinks can not overwrite files when CREATE TABLE +# user root: +CREATE DATABASE mysqltest2; +USE mysqltest2; +CREATE TABLE t1 (a INT) +PARTITION BY LIST (a) ( +PARTITION p0 VALUES IN (0) +DATA DIRECTORY 'MYSQLTEST_VARDIR/master-data/mysqltest2' + INDEX DIRECTORY 'MYSQLTEST_VARDIR/master-data/mysqltest2', +PARTITION p1 VALUES IN (1) +DATA DIRECTORY 'MYSQLTEST_VARDIR/master-data/test' + INDEX DIRECTORY 'MYSQLTEST_VARDIR/master-data/test' + ); +# user mysqltest_1: +USE test; +CREATE TABLE t1 (a INT) +PARTITION BY LIST (a) ( +PARTITION p0 VALUES IN (0) +DATA DIRECTORY 'MYSQLTEST_VARDIR/master-data/mysqltest2' + INDEX DIRECTORY 'MYSQLTEST_VARDIR/master-data/mysqltest2', +PARTITION p1 VALUES IN (1) +DATA DIRECTORY 'MYSQLTEST_VARDIR/master-data/test' + INDEX DIRECTORY 'MYSQLTEST_VARDIR/master-data/test' + ); +Got one of the listed errors +CREATE TABLE t1 (a INT) +PARTITION BY LIST (a) ( +PARTITION p0 VALUES IN (0) +DATA DIRECTORY 'MYSQLTEST_VARDIR/master-data/test' + INDEX DIRECTORY 'MYSQLTEST_VARDIR/master-data/test', +PARTITION p1 VALUES IN (1) +DATA DIRECTORY 'MYSQLTEST_VARDIR/master-data/mysqltest2' + INDEX DIRECTORY 'MYSQLTEST_VARDIR/master-data/mysqltest2' + ); +Got one of the listed errors +# user root (cleanup): +DROP DATABASE mysqltest2; +USE test; +DROP USER mysqltest_1@localhost; diff --git a/mysql-test/r/symlink.result b/mysql-test/r/symlink.result index aba60f757c6..4eece9d5b5a 100644 --- a/mysql-test/r/symlink.result +++ b/mysql-test/r/symlink.result @@ -99,6 +99,12 @@ t1 CREATE TABLE `t1` ( `b` int(11) DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 drop table t1; +CREATE TABLE t1(a INT) +DATA DIRECTORY='TEST_DIR/master-data/mysql' +INDEX DIRECTORY='TEST_DIR/master-data/mysql'; +RENAME TABLE t1 TO user; +ERROR HY000: Can't create/write to file 'TEST_DIR/master-data/mysql/user.MYI' (Errcode: 17) +DROP TABLE t1; show create table t1; Table Create Table t1 CREATE TABLE `t1` ( diff --git a/mysql-test/t/ctype_ucs.test b/mysql-test/t/ctype_ucs.test index 5525a5beb6f..7827ff0d31e 100644 --- a/mysql-test/t/ctype_ucs.test +++ b/mysql-test/t/ctype_ucs.test @@ -547,6 +547,14 @@ select quote(name) from bug20536; drop table bug20536; +# +# BUG#31159 - fulltext search on ucs2 column crashes server +# +CREATE TABLE t1(a TEXT CHARSET ucs2 COLLATE ucs2_unicode_ci); +INSERT INTO t1 VALUES('abcd'); +SELECT * FROM t1 WHERE MATCH(a) AGAINST ('+abcd' IN BOOLEAN MODE); +DROP TABLE t1; + --echo End of 4.1 tests # diff --git a/mysql-test/t/federated_server.test b/mysql-test/t/federated_server.test index 87b67720104..444285ac045 100644 --- a/mysql-test/t/federated_server.test +++ b/mysql-test/t/federated_server.test @@ -2,7 +2,7 @@ # if federated can utilise the servers table # should work with embedded server after mysqltest is fixed -- source include/not_embedded.inc --- source include/federated.inc; +-- source include/federated.inc -- source include/big_test.inc connection slave; @@ -282,6 +282,18 @@ drop user guest_select@localhost; drop table federated.t1; drop server 's1'; +# +# Bug#30671 - ALTER SERVER causes the server to crash +# +create server 's1' foreign data wrapper 'mysql' options (port 3306); +alter server 's1' options + (host 'localhost', database '', user '', + password '', socket '', owner '', port 3306); +# The next statement would crash unpatched server +alter server 's1' options + (host 'localhost', database 'database1', user '', + password '', socket '', owner '', port 3306); +drop server 's1'; --echo # End of 5.1 tests diff --git a/mysql-test/t/fulltext.test b/mysql-test/t/fulltext.test index 1f8a3b82cfd..64f77b4f0b7 100644 --- a/mysql-test/t/fulltext.test +++ b/mysql-test/t/fulltext.test @@ -400,6 +400,14 @@ SELECT * FROM t1 WHERE MATCH(a) AGAINST('test'); DROP TABLE t1; # +# BUG#11392 - fulltext search bug +# +CREATE TABLE t1(a TEXT); +INSERT INTO t1 VALUES(' aaaaa aaaa'); +SELECT * FROM t1 WHERE MATCH(a) AGAINST ('"aaaa"' IN BOOLEAN MODE); +DROP TABLE t1; + +# # BUG#29445 - match ... against () never returns # CREATE TABLE t1(a VARCHAR(20), FULLTEXT(a)); diff --git a/mysql-test/t/myisam.test b/mysql-test/t/myisam.test index b06fd536f45..6f24d84f4c0 100644 --- a/mysql-test/t/myisam.test +++ b/mysql-test/t/myisam.test @@ -1146,6 +1146,32 @@ ALTER TABLE t1 ENABLE KEYS; SELECT a FROM t1 FORCE INDEX (inx) WHERE a=1; DROP TABLE t1; +# +# Bug#4692 - DISABLE/ENABLE KEYS waste a space +# +CREATE TABLE t1 (c1 INT, c2 INT, UNIQUE INDEX (c1), INDEX (c2)) ENGINE=MYISAM; +--replace_column 6 # 7 # 8 # 10 # 11 # 12 # 13 # 14 # 15 # 16 # +SHOW TABLE STATUS LIKE 't1'; +INSERT INTO t1 VALUES (1,1); +--replace_column 6 # 7 # 8 # 10 # 11 # 12 # 13 # 14 # 15 # 16 # +SHOW TABLE STATUS LIKE 't1'; +ALTER TABLE t1 DISABLE KEYS; +--replace_column 6 # 7 # 8 # 10 # 11 # 12 # 13 # 14 # 15 # 16 # +SHOW TABLE STATUS LIKE 't1'; +ALTER TABLE t1 ENABLE KEYS; +--replace_column 6 # 7 # 8 # 10 # 11 # 12 # 13 # 14 # 15 # 16 # +SHOW TABLE STATUS LIKE 't1'; +ALTER TABLE t1 DISABLE KEYS; +--replace_column 6 # 7 # 8 # 10 # 11 # 12 # 13 # 14 # 15 # 16 # +SHOW TABLE STATUS LIKE 't1'; +ALTER TABLE t1 ENABLE KEYS; +--replace_column 6 # 7 # 8 # 10 # 11 # 12 # 13 # 14 # 15 # 16 # +SHOW TABLE STATUS LIKE 't1'; +#--exec ls -log var/master-data/test/t1.MYI +#--exec myisamchk -dvv var/master-data/test/t1.MYI +#--exec myisamchk -iev var/master-data/test/t1.MYI +DROP TABLE t1; + --echo End of 5.0 tests @@ -1256,3 +1282,4 @@ CHECK TABLE t1; DROP TABLE t1; --echo End of 5.1 tests + diff --git a/mysql-test/t/partition.test b/mysql-test/t/partition.test index a1d01b9ae19..f986215ee89 100644 --- a/mysql-test/t/partition.test +++ b/mysql-test/t/partition.test @@ -15,6 +15,50 @@ drop table if exists t1; --enable_warnings # +# Bug #30695: An apostrophe ' in the comment of the ADD PARTITION causes the Server to crash. +# +# To verify the fix for crashing (on unix-type OS) +# uncomment the exec and error rows! + +CREATE TABLE t1 ( + d DATE NOT NULL +) +PARTITION BY RANGE( YEAR(d) ) ( + PARTITION p0 VALUES LESS THAN (1960), + PARTITION p1 VALUES LESS THAN (1970), + PARTITION p2 VALUES LESS THAN (1980), + PARTITION p3 VALUES LESS THAN (1990) +); + +ALTER TABLE t1 ADD PARTITION ( +PARTITION `p5` VALUES LESS THAN (2010) +COMMENT 'APSTART \' APEND' +); +#--exec sed 's/APSTART \\/APSTART /' var/master-data/test/t1.frm > tmpt1.frm && mv tmpt1.frm var/master-data/test/t1.frm +#--error 1064 +SELECT * FROM t1 LIMIT 1; + +DROP TABLE t1; + +# +# Bug 30878: crashing when alter an auto_increment non partitioned +# table to partitioned + +create table t1 (id int auto_increment, s1 int, primary key (id)); + +insert into t1 values (null,1); +insert into t1 values (null,6); + +select * from t1; + +alter table t1 partition by range (id) ( + partition p0 values less than (3), + partition p1 values less than maxvalue +); + +drop table t1; + +# # Bug 15890: Strange number of partitions accepted # -- error ER_PARSE_ERROR diff --git a/mysql-test/t/partition_datatype.test b/mysql-test/t/partition_datatype.test new file mode 100644 index 00000000000..61d3cb42c7b --- /dev/null +++ b/mysql-test/t/partition_datatype.test @@ -0,0 +1,213 @@ +# +# Simple test for the partition storage engine +# with most datatypes and null / not null +# as partition by key +# Created to verify the fix for Bug#31705 +# Partitions: crash if varchar length > 65530 +# +-- source include/have_partition.inc + +--disable_warnings +drop table if exists t1; +--enable_warnings + +# FIXME: disabled this test because of valgrind error +#create table t1 (a bit not null) partition by key (a); +#insert into t1 values (b'1'); +#select * from t1 where a = b'1'; +#drop table t1; +create table t1 (a tinyint not null) partition by key (a); +insert into t1 values (2); +select * from t1 where a = 2; +drop table t1; +create table t1 (a smallint not null) partition by key (a); +insert into t1 values (2); +select * from t1 where a = 2; +drop table t1; +create table t1 (a mediumint not null) partition by key (a); +insert into t1 values (2); +select * from t1 where a = 2; +drop table t1; +create table t1 (a int not null) partition by key (a); +insert into t1 values (2); +select * from t1 where a = 2; +drop table t1; +create table t1 (a bigint not null) partition by key (a); +insert into t1 values (2); +select * from t1 where a = 2; +drop table t1; +create table t1 (a float not null) partition by key (a); +insert into t1 values (2.1); +select * from t1 where a = 2.1; +drop table t1; +create table t1 (a double not null) partition by key (a); +insert into t1 values (2.1); +select * from t1 where a = 2.1; +drop table t1; +create table t1 (a decimal not null) partition by key (a); +insert into t1 values (2.1); +select * from t1 where a = 2.1; +drop table t1; +create table t1 (a date not null) partition by key (a); +insert into t1 values ('2001-01-01'); +select * from t1 where a = '2001-01-01'; +drop table t1; +create table t1 (a datetime not null) partition by key (a); +insert into t1 values ('2001-01-01 01:02:03'); +select * from t1 where a = '2001-01-01 01:02:03'; +drop table t1; +create table t1 (a timestamp not null) partition by key (a); +insert into t1 values ('2001-01-01 01:02:03'); +select * from t1 where a = '2001-01-01 01:02:03'; +drop table t1; +create table t1 (a time not null) partition by key (a); +insert into t1 values ('01:02:03'); +select * from t1 where a = '01:02:03'; +drop table t1; +create table t1 (a year not null) partition by key (a); +insert into t1 values ('2001'); +select * from t1 where a = '2001'; +drop table t1; +create table t1 (a varchar(10) character set utf8 not null) partition by key (a); +insert into t1 values ('abc'); +select * from t1 where a = 'abc'; +drop table t1; +create table t1 (a varchar(300) character set utf8 not null) partition by key (a); +insert into t1 values ('abc'); +select * from t1 where a = 'abc'; +drop table t1; +create table t1 (a varchar(10) character set latin1 not null) partition by key (a); +insert into t1 values ('abc'); +select * from t1 where a = 'abc'; +drop table t1; +create table t1 (a varchar(300) character set latin1 not null) partition by key (a); +insert into t1 values ('abc'); +select * from t1 where a = 'abc'; +drop table t1; +create table t1 (a char(10) character set utf8 not null) partition by key (a); +insert into t1 values ('abc'); +select * from t1 where a = 'abc'; +drop table t1; +create table t1 (a char(10) character set latin1 not null) partition by key (a); +insert into t1 values ('abc'); +select * from t1 where a = 'abc'; +drop table t1; +create table t1 (a enum('y','n') not null) partition by key (a); +insert into t1 values ('y'); +select * from t1 where a = 'y'; +drop table t1; +create table t1 (a set('y','n') not null) partition by key (a); +insert into t1 values ('y'); +select * from t1 where a = 'y'; +drop table t1; +# FIXME: disabled this test because of valgrind error +#create table t1 (a bit) partition by key (a); +#insert into t1 values (b'1'); +#select * from t1 where a = b'1'; +#drop table t1; +create table t1 (a tinyint) partition by key (a); +insert into t1 values (2); +select * from t1 where a = 2; +drop table t1; +create table t1 (a smallint) partition by key (a); +insert into t1 values (2); +select * from t1 where a = 2; +drop table t1; +create table t1 (a mediumint) partition by key (a); +insert into t1 values (2); +select * from t1 where a = 2; +drop table t1; +create table t1 (a int) partition by key (a); +insert into t1 values (2); +select * from t1 where a = 2; +drop table t1; +create table t1 (a bigint) partition by key (a); +insert into t1 values (2); +select * from t1 where a = 2; +drop table t1; +create table t1 (a float) partition by key (a); +insert into t1 values (2.1); +select * from t1 where a = 2.1; +drop table t1; +create table t1 (a double) partition by key (a); +insert into t1 values (2.1); +select * from t1 where a = 2.1; +drop table t1; +create table t1 (a decimal) partition by key (a); +insert into t1 values (2.1); +select * from t1 where a = 2.1; +drop table t1; +create table t1 (a date) partition by key (a); +insert into t1 values ('2001-01-01'); +select * from t1 where a = '2001-01-01'; +drop table t1; +create table t1 (a datetime) partition by key (a); +insert into t1 values ('2001-01-01 01:02:03'); +select * from t1 where a = '2001-01-01 01:02:03'; +drop table t1; +create table t1 (a timestamp null) partition by key (a); +insert into t1 values ('2001-01-01 01:02:03'); +select * from t1 where a = '2001-01-01 01:02:03'; +drop table t1; +create table t1 (a time) partition by key (a); +insert into t1 values ('01:02:03'); +select * from t1 where a = '01:02:03'; +drop table t1; +create table t1 (a year) partition by key (a); +insert into t1 values ('2001'); +select * from t1 where a = '2001'; +drop table t1; +create table t1 (a varchar(10) character set utf8) partition by key (a); +insert into t1 values ('abc'); +select * from t1 where a = 'abc'; +drop table t1; +create table t1 (a varchar(300) character set utf8) partition by key (a); +insert into t1 values ('abc'); +select * from t1 where a = 'abc'; +drop table t1; +create table t1 (a varchar(10) character set latin1) partition by key (a); +insert into t1 values ('abc'); +select * from t1 where a = 'abc'; +drop table t1; +create table t1 (a varchar(300) character set latin1) partition by key (a); +insert into t1 values ('abc'); +select * from t1 where a = 'abc'; +drop table t1; +create table t1 (a char(10) character set utf8) partition by key (a); +insert into t1 values ('abc'); +select * from t1 where a = 'abc'; +drop table t1; +create table t1 (a char(10) character set latin1) partition by key (a); +insert into t1 values ('abc'); +select * from t1 where a = 'abc'; +drop table t1; +create table t1 (a enum('y','n')) partition by key (a); +insert into t1 values ('y'); +select * from t1 where a = 'y'; +drop table t1; +create table t1 (a set('y','n')) partition by key (a); +insert into t1 values ('y'); +select * from t1 where a = 'y'; +drop table t1; +create table t1 (a varchar(65531)) partition by key (a); +insert into t1 values ('bbbb'); +insert into t1 values ('aaaa'); +select * from t1 where a = 'aaa%'; +select * from t1 where a like 'aaa%'; +drop table t1; +create table t1 (a varchar(65532)) partition by key (a); +insert into t1 values ('bbbb'); +insert into t1 values ('aaaa'); +select * from t1 where a = 'aaa%'; +select * from t1 where a like 'aaa%'; +drop table t1; +create table t1 (a varchar(65533) not null) partition by key (a); +insert into t1 values ('aaaa'); +select * from t1 where a = 'aaa%'; +drop table t1; +-- error ER_TOO_BIG_ROWSIZE +create table t1 (a varchar(65533)) partition by key (a); +-- error ER_TOO_BIG_ROWSIZE +create table t1 (a varchar(65534) not null) partition by key (a); +-- error ER_TOO_BIG_ROWSIZE +create table t1 (a varchar(65535)) partition by key (a); diff --git a/mysql-test/t/partition_error.test b/mysql-test/t/partition_error.test index 5fc2097cc52..c9b95fc1664 100644 --- a/mysql-test/t/partition_error.test +++ b/mysql-test/t/partition_error.test @@ -9,6 +9,19 @@ drop table if exists t1; --enable_warnings # +# Bug 29368: +# Incorrect error, 1467, for syntax error when creating partition +--error ER_PARTITION_REQUIRES_VALUES_ERROR +CREATE TABLE t1 ( + a int +) +PARTITION BY RANGE (a) +( + PARTITION p0 VALUES LESS THAN (1), + PARTITION p1 VALU ES LESS THAN (2) +); + +# # Partition by key stand-alone error # --error 1064 diff --git a/mysql-test/t/partition_hash.test b/mysql-test/t/partition_hash.test index 98add060a76..52caaa8c8e9 100644 --- a/mysql-test/t/partition_hash.test +++ b/mysql-test/t/partition_hash.test @@ -144,3 +144,13 @@ select * from t1 where c3 between '2002-01-01' and '2002-12-31'; drop table t1; +# +# Bug#31210 - INSERT DELAYED crashes server when used on partitioned table +# +CREATE TABLE t1 (c1 INT) ENGINE=MyISAM PARTITION BY HASH(c1) PARTITIONS 1; +# The test succeeds in an embedded server because normal insert is done. +# The test fails in a normal server with "engine doesn't have this option". +--error 0, ER_ILLEGAL_HA +INSERT DELAYED INTO t1 VALUES (1); +DROP TABLE t1; + diff --git a/mysql-test/t/partition_mgm.test b/mysql-test/t/partition_mgm.test index a06f8d1aee5..68da4a5b390 100644 --- a/mysql-test/t/partition_mgm.test +++ b/mysql-test/t/partition_mgm.test @@ -22,17 +22,18 @@ drop table t1; CREATE TABLE t1 (f_date DATE, f_varchar VARCHAR(30)) PARTITION BY HASH(YEAR(f_date)) PARTITIONS 2; SHOW CREATE TABLE t1; - ---replace_result $MYSQLTEST_VARDIR "hello" ---exec ls $MYSQLTEST_VARDIR/master-data/test/t1#* ---replace_result $MYSQLTEST_VARDIR "hello" ---exec ls $MYSQLTEST_VARDIR/master-data/test/t1.* +-- file_exists $MYSQLTEST_VARDIR/master-data/test/t1#P#p0.MYD +-- file_exists $MYSQLTEST_VARDIR/master-data/test/t1#P#p0.MYI +-- file_exists $MYSQLTEST_VARDIR/master-data/test/t1#P#p1.MYD +-- file_exists $MYSQLTEST_VARDIR/master-data/test/t1#P#p1.MYI +-- file_exists $MYSQLTEST_VARDIR/master-data/test/t1.frm +-- file_exists $MYSQLTEST_VARDIR/master-data/test/t1.par ALTER TABLE t1 COALESCE PARTITION 1; SHOW CREATE TABLE t1; ---replace_result $MYSQLTEST_VARDIR "hello" ---exec ls $MYSQLTEST_VARDIR/master-data/test/t1#* ---replace_result $MYSQLTEST_VARDIR "hello" ---exec ls $MYSQLTEST_VARDIR/master-data/test/t1.* +-- file_exists $MYSQLTEST_VARDIR/master-data/test/t1#P#p0.MYD +-- file_exists $MYSQLTEST_VARDIR/master-data/test/t1#P#p0.MYI +-- file_exists $MYSQLTEST_VARDIR/master-data/test/t1.frm +-- file_exists $MYSQLTEST_VARDIR/master-data/test/t1.par drop table t1; # # Bug 20767: REORGANIZE partition crashes diff --git a/mysql-test/t/partition_symlink.test b/mysql-test/t/partition_symlink.test new file mode 100644 index 00000000000..ab779ec2b68 --- /dev/null +++ b/mysql-test/t/partition_symlink.test @@ -0,0 +1,121 @@ +# Test that must have symlink. eg. using DATA/INDEX DIR +# (DATA/INDEX DIR requires symlinks) +-- source include/have_partition.inc +-- source include/have_symlink.inc +# remove the not_windows line after fixing bug#30459 +-- source include/not_windows.inc +-- disable_warnings +DROP TABLE IF EXISTS t1; +DROP DATABASE IF EXISTS mysqltest2; +-- enable_warnings + +# +# Bug 32091: Security breach via directory changes +# +# The below test shows that a pre-existing table mysqltest2.t1 cannot be +# replaced by a user with no rights in 'mysqltest2'. The altered table +# test.t1 will be altered (remove partitioning) into the test directory +# and having its partitions removed from the mysqltest2 directory. +# (the partitions data files are named <tablename>#P#<partname>.MYD +# and will not collide with a non partitioned table's data files.) +# NOTE: the privileges on files and directories are the same for all +# database users in mysqld, though mysqld enforces privileges on +# the database and table levels which in turn maps to directories and +# files, but not the other way around (any db-user can use any +# directory or file that the mysqld-process can use, via DATA/INDEX DIR) +# this is the security flaw that was used in bug#32091 and bug#32111 +-- echo # Creating two non colliding tables mysqltest2.t1 and test.t1 +-- echo # test.t1 have partitions in mysqltest2-directory! +-- echo # user root: + CREATE USER mysqltest_1@localhost; + CREATE DATABASE mysqltest2; + USE mysqltest2; + CREATE TABLE t1 (a INT); + INSERT INTO t1 VALUES (0); +connect(con1,localhost,mysqltest_1,,); +-- echo # user mysqltest_1: + USE test; + -- replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR + eval CREATE TABLE t1 (a INT) + PARTITION BY LIST (a) ( + PARTITION p0 VALUES IN (0) + DATA DIRECTORY '$MYSQLTEST_VARDIR/master-data/mysqltest2' + INDEX DIRECTORY '$MYSQLTEST_VARDIR/master-data/mysqltest2', + PARTITION p1 VALUES IN (1) + DATA DIRECTORY '$MYSQLTEST_VARDIR/master-data/test' + INDEX DIRECTORY '$MYSQLTEST_VARDIR/master-data/test', + PARTITION p2 VALUES IN (2) + ); + -- echo # without the patch for bug#32091 this would create + -- echo # files mysqltest2/t1.MYD + .MYI and possible overwrite + -- echo # the mysqltest2.t1 table (depending on bug#32111) + -- replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR + ALTER TABLE t1 REMOVE PARTITIONING; + INSERT INTO t1 VALUES (1); + SELECT * FROM t1; +connection default; +-- echo # user root: + USE mysqltest2; + FLUSH TABLES; + -- echo # if the patch works, this should be different + -- echo # and before the patch they were the same! + SELECT * FROM t1; + USE test; + SELECT * FROM t1; + DROP TABLE t1; + DROP DATABASE mysqltest2; +# The below test shows that a pre-existing partition can not be +# destroyed by a new partition from another table. +# (Remember that a table or partition that uses the DATA/INDEX DIR +# is symlinked and thus has +# 1. the real file in the DATA/INDEX DIR and +# 2. a symlink in its default database directory pointing to +# the real file. +# So it is using/blocking 2 files in (in 2 different directories +-- echo # test that symlinks can not overwrite files when CREATE TABLE +-- echo # user root: + CREATE DATABASE mysqltest2; + USE mysqltest2; + -- replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR + eval CREATE TABLE t1 (a INT) + PARTITION BY LIST (a) ( + PARTITION p0 VALUES IN (0) + DATA DIRECTORY '$MYSQLTEST_VARDIR/master-data/mysqltest2' + INDEX DIRECTORY '$MYSQLTEST_VARDIR/master-data/mysqltest2', + PARTITION p1 VALUES IN (1) + DATA DIRECTORY '$MYSQLTEST_VARDIR/master-data/test' + INDEX DIRECTORY '$MYSQLTEST_VARDIR/master-data/test' + ); +connection con1; +-- echo # user mysqltest_1: + USE test; + -- replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR + -- error 1,1 + eval CREATE TABLE t1 (a INT) + PARTITION BY LIST (a) ( + PARTITION p0 VALUES IN (0) + DATA DIRECTORY '$MYSQLTEST_VARDIR/master-data/mysqltest2' + INDEX DIRECTORY '$MYSQLTEST_VARDIR/master-data/mysqltest2', + PARTITION p1 VALUES IN (1) + DATA DIRECTORY '$MYSQLTEST_VARDIR/master-data/test' + INDEX DIRECTORY '$MYSQLTEST_VARDIR/master-data/test' + ); + -- replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR + -- error 1,1 + eval CREATE TABLE t1 (a INT) + PARTITION BY LIST (a) ( + PARTITION p0 VALUES IN (0) + DATA DIRECTORY '$MYSQLTEST_VARDIR/master-data/test' + INDEX DIRECTORY '$MYSQLTEST_VARDIR/master-data/test', + PARTITION p1 VALUES IN (1) + DATA DIRECTORY '$MYSQLTEST_VARDIR/master-data/mysqltest2' + INDEX DIRECTORY '$MYSQLTEST_VARDIR/master-data/mysqltest2' + ); +connection default; +-- echo # user root (cleanup): + DROP DATABASE mysqltest2; + USE test; + DROP USER mysqltest_1@localhost; + disconnect con1; + + diff --git a/mysql-test/t/symlink.test b/mysql-test/t/symlink.test index 15f50b11e73..f339b29c83a 100644 --- a/mysql-test/t/symlink.test +++ b/mysql-test/t/symlink.test @@ -121,6 +121,18 @@ show create table t1; drop table t1; # +# BUG#32111 - Security Breach via DATA/INDEX DIRECORY and RENAME TABLE +# +--replace_result $MYSQLTEST_VARDIR TEST_DIR +eval CREATE TABLE t1(a INT) +DATA DIRECTORY='$MYSQLTEST_VARDIR/master-data/mysql' +INDEX DIRECTORY='$MYSQLTEST_VARDIR/master-data/mysql'; +--replace_result $MYSQLTEST_VARDIR TEST_DIR +--error 1 +RENAME TABLE t1 TO user; +DROP TABLE t1; + +# # Test specifying DATA DIRECTORY that is the same as what would normally # have been chosen. (Bug #8707) # diff --git a/mysql-test/t/variables.test b/mysql-test/t/variables.test index 4a161ea3725..c1580390f63 100644 --- a/mysql-test/t/variables.test +++ b/mysql-test/t/variables.test @@ -161,7 +161,7 @@ select * from information_schema.session_variables where variable_name like 'net set net_buffer_length=1; show variables like 'net_buffer_length'; select * from information_schema.session_variables where variable_name like 'net_buffer_length'; ---warning 1292 +#warning 1292 set net_buffer_length=2000000000; show variables like 'net_buffer_length'; select * from information_schema.session_variables where variable_name like 'net_buffer_length'; diff --git a/mysys/my_symlink2.c b/mysys/my_symlink2.c index 2a46fb3abea..7c3ddbb911c 100644 --- a/mysys/my_symlink2.c +++ b/mysys/my_symlink2.c @@ -130,6 +130,7 @@ int my_rename_with_symlink(const char *from, const char *to, myf MyFlags) int was_symlink= (!my_disable_symlinks && !my_readlink(link_name, from, MYF(0))); int result=0; + int name_is_different; DBUG_ENTER("my_rename_with_symlink"); if (!was_symlink) @@ -138,6 +139,14 @@ int my_rename_with_symlink(const char *from, const char *to, myf MyFlags) /* Change filename that symlink pointed to */ strmov(tmp_name, to); fn_same(tmp_name,link_name,1); /* Copy dir */ + name_is_different= strcmp(link_name, tmp_name); + if (name_is_different && !access(tmp_name, F_OK)) + { + my_errno= EEXIST; + if (MyFlags & MY_WME) + my_error(EE_CANTCREATEFILE, MYF(0), tmp_name, EEXIST); + DBUG_RETURN(1); + } /* Create new symlink */ if (my_symlink(tmp_name, to, MyFlags)) @@ -149,7 +158,7 @@ int my_rename_with_symlink(const char *from, const char *to, myf MyFlags) the same basename and different directories. */ - if (strcmp(link_name, tmp_name) && my_rename(link_name, tmp_name, MyFlags)) + if (name_is_different && my_rename(link_name, tmp_name, MyFlags)) { int save_errno=my_errno; my_delete(to, MyFlags); /* Remove created symlink */ diff --git a/sql/CMakeLists.txt b/sql/CMakeLists.txt index 77f8bb9e5b2..77abc4e6fa5 100755 --- a/sql/CMakeLists.txt +++ b/sql/CMakeLists.txt @@ -90,6 +90,15 @@ TARGET_LINK_LIBRARIES(mysqld SET_TARGET_PROPERTIES(mysqld PROPERTIES OUTPUT_NAME mysqld${MYSQLD_EXE_SUFFIX}) +IF(cmake_version EQUAL 20406) +# Work around for 2.4.6 bug, OUTPUT_NAME will not set the right .PDB +# file name. Note that COMPILE_FLAGS set some temporary pdb during build, +# LINK_FLAGS sets the real one. +SET_TARGET_PROPERTIES(mysqld PROPERTIES + COMPILE_FLAGS "/Fd${CMAKE_CFG_INTDIR}/mysqld${MYSQLD_EXE_SUFFIX}.pdb" + LINK_FLAGS "/PDB:${CMAKE_CFG_INTDIR}/mysqld${MYSQLD_EXE_SUFFIX}.pdb") +ENDIF(cmake_version EQUAL 20406) + IF(EMBED_MANIFESTS) MYSQL_EMBED_MANIFEST("mysqld" "asInvoker") ENDIF(EMBED_MANIFESTS) diff --git a/sql/event_scheduler.cc b/sql/event_scheduler.cc index d3a031fd8f8..5655a8acc99 100644 --- a/sql/event_scheduler.cc +++ b/sql/event_scheduler.cc @@ -127,6 +127,7 @@ post_init_event_thread(THD *thd) thd->cleanup(); return TRUE; } + lex_start(thd); pthread_mutex_lock(&LOCK_thread_count); threads.append(thd); diff --git a/sql/events.cc b/sql/events.cc index 1bfbc5d6645..262c62bdbc8 100644 --- a/sql/events.cc +++ b/sql/events.cc @@ -884,6 +884,7 @@ Events::init(my_bool opt_noacl) */ thd->thread_stack= (char*) &thd; thd->store_globals(); + lex_start(thd); /* We will need Event_db_repository anyway, even if the scheduler is diff --git a/sql/ha_ndbcluster.cc b/sql/ha_ndbcluster.cc index 436710e3dee..bf2b19bfc9c 100644 --- a/sql/ha_ndbcluster.cc +++ b/sql/ha_ndbcluster.cc @@ -9073,6 +9073,7 @@ pthread_handler_t ndb_util_thread_func(void *arg __attribute__((unused))) thd->thread_stack= (char*)&thd; /* remember where our stack is */ if (thd->store_globals()) goto ndb_util_thread_fail; + lex_start(thd); thd->init_for_queries(); thd->version=refresh_version; thd->main_security_ctx.host_or_ip= ""; diff --git a/sql/ha_ndbcluster_binlog.cc b/sql/ha_ndbcluster_binlog.cc index fc35a7a930e..55af0c38aed 100644 --- a/sql/ha_ndbcluster_binlog.cc +++ b/sql/ha_ndbcluster_binlog.cc @@ -3621,6 +3621,7 @@ pthread_handler_t ndb_binlog_thread_func(void *arg) pthread_exit(0); DBUG_RETURN(NULL); } + lex_start(thd); thd->init_for_queries(); thd->command= COM_DAEMON; diff --git a/sql/ha_partition.cc b/sql/ha_partition.cc index 8afaab71160..b53a5e3da97 100644 --- a/sql/ha_partition.cc +++ b/sql/ha_partition.cc @@ -1599,6 +1599,7 @@ error: void ha_partition::update_create_info(HA_CREATE_INFO *create_info) { m_file[0]->update_create_info(create_info); + create_info->data_file_name= create_info->index_file_name = NULL; return; } @@ -2678,7 +2679,8 @@ int ha_partition::write_row(uchar * buf) uint32 part_id; int error; longlong func_value; - bool autoincrement_lock= false; + bool autoincrement_lock= FALSE; + my_bitmap_map *old_map; #ifdef NOT_NEEDED uchar *rec0= m_rec0; #endif @@ -2705,8 +2707,17 @@ int ha_partition::write_row(uchar * buf) use autoincrement_lock variable to avoid unnecessary locks. Probably not an ideal solution. */ - autoincrement_lock= true; - pthread_mutex_lock(&table_share->mutex); + if (table_share->tmp_table == NO_TMP_TABLE) + { + /* + Bug#30878 crash when alter table from non partitioned table + to partitioned. + Checking if tmp table then there is no need to lock, + and the table_share->mutex may not be initialised. + */ + autoincrement_lock= TRUE; + pthread_mutex_lock(&table_share->mutex); + } error= update_auto_increment(); /* @@ -2715,10 +2726,10 @@ int ha_partition::write_row(uchar * buf) the correct partition. We must check and fail if neccessary. */ if (error) - DBUG_RETURN(error); + goto exit; } - my_bitmap_map *old_map= dbug_tmp_use_all_columns(table, table->read_set); + old_map= dbug_tmp_use_all_columns(table, table->read_set); #ifdef NOT_NEEDED if (likely(buf == rec0)) #endif diff --git a/sql/handler.cc b/sql/handler.cc index 1606c160238..8a2355c8a87 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -2542,15 +2542,56 @@ int ha_enable_transaction(THD *thd, bool on) int handler::index_next_same(uchar *buf, const uchar *key, uint keylen) { int error; + DBUG_ENTER("index_next_same"); if (!(error=index_next(buf))) { + my_ptrdiff_t ptrdiff= buf - table->record[0]; + uchar *save_record_0; + KEY *key_info; + KEY_PART_INFO *key_part; + KEY_PART_INFO *key_part_end; + LINT_INIT(save_record_0); + LINT_INIT(key_info); + LINT_INIT(key_part); + LINT_INIT(key_part_end); + + /* + key_cmp_if_same() compares table->record[0] against 'key'. + In parts it uses table->record[0] directly, in parts it uses + field objects with their local pointers into table->record[0]. + If 'buf' is distinct from table->record[0], we need to move + all record references. This is table->record[0] itself and + the field pointers of the fields used in this key. + */ + if (ptrdiff) + { + save_record_0= table->record[0]; + table->record[0]= buf; + key_info= table->key_info + active_index; + key_part= key_info->key_part; + key_part_end= key_part + key_info->key_parts; + for (; key_part < key_part_end; key_part++) + { + DBUG_ASSERT(key_part->field); + key_part->field->move_field_offset(ptrdiff); + } + } + if (key_cmp_if_same(table, key, active_index, keylen)) { table->status=STATUS_NOT_FOUND; error=HA_ERR_END_OF_FILE; } + + /* Move back if necessary. */ + if (ptrdiff) + { + table->record[0]= save_record_0; + for (key_part= key_info->key_part; key_part < key_part_end; key_part++) + key_part->field->move_field_offset(-ptrdiff); + } } - return error; + DBUG_RETURN(error); } diff --git a/sql/opt_range.cc b/sql/opt_range.cc index 99c28be36b0..b89e8b3dcbb 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -3344,18 +3344,16 @@ static bool create_partition_index_description(PART_PRUNE_PARAM *ppar) { key_part->key= 0; key_part->part= part; - key_part->length= (uint16) (*field)->pack_length_in_rec(); - /* - psergey-todo: check yet again if this is correct for tricky field types, - e.g. see "Fix a fatal error in decimal key handling" in open_binary_frm() - */ - key_part->store_length= (uint16) (*field)->pack_length(); + key_part->store_length= key_part->length= (uint16) (*field)->key_length(); if ((*field)->real_maybe_null()) key_part->store_length+= HA_KEY_NULL_LENGTH; if ((*field)->type() == MYSQL_TYPE_BLOB || (*field)->real_type() == MYSQL_TYPE_VARCHAR) key_part->store_length+= HA_KEY_BLOB_LENGTH; + DBUG_PRINT("info", ("part %u length %u store_length %u", part, + key_part->length, key_part->store_length)); + key_part->field= (*field); key_part->image_type = Field::itRAW; /* diff --git a/sql/share/errmsg.txt b/sql/share/errmsg.txt index 8fad09eb221..257cea7c27b 100644 --- a/sql/share/errmsg.txt +++ b/sql/share/errmsg.txt @@ -5667,9 +5667,9 @@ ER_ILLEGAL_HA_CREATE_OPTION eng "Table storage engine '%-.64s' does not support the create option '%.64s'" ger "Speicher-Engine '%-.64s' der Tabelle unterstützt die Option '%.64s' nicht" ER_PARTITION_REQUIRES_VALUES_ERROR - eng "%-.64s PARTITIONING requires definition of VALUES %-.64s for each partition" - ger "%-.64s-PARTITIONierung erfordert Definition von VALUES %-.64s für jede Partition" - swe "%-.64s PARTITIONering kräver definition av VALUES %-.64s för varje partition" + eng "Syntax error: %-.64s PARTITIONING requires definition of VALUES %-.64s for each partition" + ger "Fehler in der SQL-Syntax: %-.64s-PARTITIONierung erfordert Definition von VALUES %-.64s für jede Partition" + swe "Syntaxfel: %-.64s PARTITIONering kräver definition av VALUES %-.64s för varje partition" ER_PARTITION_WRONG_VALUES_ERROR eng "Only %-.64s PARTITIONING can use VALUES %-.64s in partition definition" ger "Nur %-.64s-PARTITIONierung kann VALUES %-.64s in der Partitionsdefinition verwenden" diff --git a/sql/slave.cc b/sql/slave.cc index 7abcf50fa75..2512954f805 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -1510,6 +1510,7 @@ static int init_slave_thread(THD* thd, SLAVE_THD_TYPE thd_type) delete thd; DBUG_RETURN(-1); } + lex_start(thd); if (thd_type == SLAVE_THD_SQL) thd->proc_info= "Waiting for the next event in relay log"; diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index 070a943da9e..311b76c6149 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -277,6 +277,7 @@ my_bool acl_init(bool dont_read_acl_tables) DBUG_RETURN(1); /* purecov: inspected */ thd->thread_stack= (char*) &thd; thd->store_globals(); + lex_start(thd); /* It is safe to call acl_reload() since acl_* arrays and hashes which will be freed there are global static objects and thus are initialized @@ -3493,6 +3494,7 @@ my_bool grant_init() DBUG_RETURN(1); /* purecov: deadcode */ thd->thread_stack= (char*) &thd; thd->store_globals(); + lex_start(thd); return_val= grant_reload(thd); delete thd; /* Remember that we don't have a THD */ diff --git a/sql/sql_base.cc b/sql/sql_base.cc index ddc5f88f577..66d0cda2155 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -2289,6 +2289,9 @@ TABLE *open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root, HASH_SEARCH_STATE state; DBUG_ENTER("open_table"); + /* Parsing of partitioning information from .frm needs thd->lex set up. */ + DBUG_ASSERT(thd->lex->is_lex_started); + /* find a unused table in the open table cache */ if (refresh) *refresh=0; diff --git a/sql/sql_connect.cc b/sql/sql_connect.cc index 68872f85cd4..76237576764 100644 --- a/sql/sql_connect.cc +++ b/sql/sql_connect.cc @@ -1120,6 +1120,7 @@ pthread_handler_t handle_one_connection(void *arg) { NET *net= &thd->net; + lex_start(thd); if (login_connection(thd)) goto end_thread; diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index d3010e4309b..11e70a2e5da 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -2267,7 +2267,12 @@ pthread_handler_t handle_delayed_insert(void *arg) goto err; } - /* open table */ + /* + Open table requires an initialized lex in case the table is + partitioned. The .frm file contains a partial SQL string which is + parsed using a lex, that depends on initialized thd->lex. + */ + lex_start(thd); if (!(di->table=open_ltable(thd, &di->table_list, TL_WRITE_DELAYED, 0))) { thd->fatal_error(); // Abort waiting inserts diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 4ee66cb1e8d..7d6f21cad05 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -363,6 +363,7 @@ void lex_start(THD *thd) lex->server_options.owner= 0; lex->server_options.port= -1; + lex->is_lex_started= TRUE; DBUG_VOID_RETURN; } @@ -2139,7 +2140,7 @@ void Query_tables_list::destroy_query_tables_list() st_lex::st_lex() :result(0), yacc_yyss(0), yacc_yyvs(0), - sql_command(SQLCOM_END), option_type(OPT_DEFAULT) + sql_command(SQLCOM_END), option_type(OPT_DEFAULT), is_lex_started(0) { my_init_dynamic_array2(&plugins, sizeof(plugin_ref), diff --git a/sql/sql_lex.h b/sql/sql_lex.h index 507d64daf89..da0ff94ec96 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -1712,6 +1712,7 @@ typedef struct st_lex : public Query_tables_list st_alter_tablespace *alter_tablespace_info; bool escape_used; + bool is_lex_started; /* If lex_start() did run. For debugging. */ st_lex(); diff --git a/sql/sql_partition.cc b/sql/sql_partition.cc index 0cc2cac2a1a..ad9eec1906a 100644 --- a/sql/sql_partition.cc +++ b/sql/sql_partition.cc @@ -1856,6 +1856,20 @@ static int add_uint(File fptr, ulonglong number) return add_string(fptr, buff); } +/* + Must escape strings in partitioned tables frm-files, + parsing it later with mysql_unpack_partition will fail otherwise. +*/ +static int add_quoted_string(File fptr, const char *quotestr) +{ + String orgstr(quotestr, system_charset_info); + String escapedstr; + int err= add_string(fptr, "'"); + err+= append_escaped(&escapedstr, &orgstr); + err+= add_string(fptr, escapedstr.c_ptr_safe()); + return err + add_string(fptr, "'"); +} + static int add_keyword_string(File fptr, const char *keyword, bool should_use_quotes, const char *keystr) @@ -1866,10 +1880,9 @@ static int add_keyword_string(File fptr, const char *keyword, err+= add_equal(fptr); err+= add_space(fptr); if (should_use_quotes) - err+= add_string(fptr, "'"); - err+= add_string(fptr, keystr); - if (should_use_quotes) - err+= add_string(fptr, "'"); + err+= add_quoted_string(fptr, keystr); + else + err+= add_string(fptr, keystr); return err + add_space(fptr); } diff --git a/sql/sql_plugin.cc b/sql/sql_plugin.cc index 2af528f6699..c8d9116f196 100644 --- a/sql/sql_plugin.cc +++ b/sql/sql_plugin.cc @@ -1329,6 +1329,7 @@ static void plugin_load(MEM_ROOT *tmp_root, int *argc, char **argv) } new_thd->thread_stack= (char*) &tables; new_thd->store_globals(); + lex_start(new_thd); new_thd->db= my_strdup("mysql", MYF(0)); new_thd->db_length= 5; bzero((uchar*)&tables, sizeof(tables)); diff --git a/sql/sql_servers.cc b/sql/sql_servers.cc index a780c561ffe..602c289a605 100644 --- a/sql/sql_servers.cc +++ b/sql/sql_servers.cc @@ -140,6 +140,7 @@ bool servers_init(bool dont_read_servers_table) DBUG_RETURN(TRUE); thd->thread_stack= (char*) &thd; thd->store_globals(); + lex_start(thd); /* It is safe to call servers_reload() since servers_* arrays and hashes which will be freed there are global static objects and thus are initialized @@ -289,7 +290,7 @@ get_server_from_table_to_cache(TABLE *table) { /* alloc a server struct */ char *ptr; - char *blank= (char*)""; + char * const blank= (char*)""; FOREIGN_SERVER *server= (FOREIGN_SERVER *)alloc_root(&mem, sizeof(FOREIGN_SERVER)); DBUG_ENTER("get_server_from_table_to_cache"); @@ -312,7 +313,7 @@ get_server_from_table_to_cache(TABLE *table) server->port= server->sport ? atoi(server->sport) : 0; ptr= get_field(&mem, table->field[6]); - server->socket= ptr && strlen(ptr) ? ptr : NULL; + server->socket= ptr && strlen(ptr) ? ptr : blank; ptr= get_field(&mem, table->field[7]); server->scheme= ptr ? ptr : blank; ptr= get_field(&mem, table->field[8]); diff --git a/sql/sql_udf.cc b/sql/sql_udf.cc index 1076772d598..18511063117 100644 --- a/sql/sql_udf.cc +++ b/sql/sql_udf.cc @@ -135,6 +135,7 @@ void udf_init() initialized = 1; new_thd->thread_stack= (char*) &new_thd; new_thd->store_globals(); + lex_start(new_thd); new_thd->set_db(db, sizeof(db)-1); bzero((uchar*) &tables,sizeof(tables)); diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index b337f82dec3..04af253fec9 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -6492,7 +6492,7 @@ bool_pri: { $$= (*$2)(0)->create($1,$3); } | bool_pri comp_op all_or_any '(' subselect ')' %prec EQ { $$= all_any_subquery_creator($1, $2, $3, $5); } - | predicate ; + | predicate ; predicate: diff --git a/sql/table.cc b/sql/table.cc index a113975c5c5..c3ddb809b9e 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -1610,6 +1610,9 @@ int open_table_from_share(THD *thd, TABLE_SHARE *share, const char *alias, DBUG_PRINT("enter",("name: '%s.%s' form: 0x%lx", share->db.str, share->table_name.str, (long) outparam)); + /* Parsing of partitioning information from .frm needs thd->lex set up. */ + DBUG_ASSERT(thd->lex->is_lex_started); + error= 1; bzero((char*) outparam, sizeof(*outparam)); outparam->in_use= thd; @@ -1784,7 +1787,8 @@ int open_table_from_share(THD *thd, TABLE_SHARE *share, const char *alias, outparam, is_create_table, share->default_part_db_type, &work_part_info_used); - outparam->part_info->is_auto_partitioned= share->auto_partitioned; + if (!tmp) + outparam->part_info->is_auto_partitioned= share->auto_partitioned; DBUG_PRINT("info", ("autopartitioned: %u", share->auto_partitioned)); /* we should perform the fix_partition_func in either local or caller's arena depending on work_part_info_used value diff --git a/sql/tztime.cc b/sql/tztime.cc index 9eb38e97827..920f8e87d13 100644 --- a/sql/tztime.cc +++ b/sql/tztime.cc @@ -1575,6 +1575,7 @@ my_tz_init(THD *org_thd, const char *default_tzname, my_bool bootstrap) DBUG_RETURN(1); thd->thread_stack= (char*) &thd; thd->store_globals(); + lex_start(thd); /* Init all memory structures that require explicit destruction */ if (hash_init(&tz_names, &my_charset_latin1, 20, diff --git a/storage/myisam/mi_check.c b/storage/myisam/mi_check.c index fe6b716877c..7cd35295cb0 100644 --- a/storage/myisam/mi_check.c +++ b/storage/myisam/mi_check.c @@ -1376,6 +1376,139 @@ int chk_data_link(MI_CHECK *param, MI_INFO *info,int extend) } /* chk_data_link */ +/** + @brief Drop all indexes + + @param[in] param check parameters + @param[in] info MI_INFO handle + @param[in] force if to force drop all indexes + + @return status + @retval 0 OK + @retval != 0 Error + + @note + Once allocated, index blocks remain part of the key file forever. + When indexes are disabled, no block is freed. When enabling indexes, + no block is freed either. The new indexes are create from new + blocks. (Bug #4692) + + Before recreating formerly disabled indexes, the unused blocks + must be freed. There are two options to do this: + - Follow the tree of disabled indexes, add all blocks to the + deleted blocks chain. Would require a lot of random I/O. + - Drop all blocks by clearing all index root pointers and all + delete chain pointers and resetting key_file_length to the end + of the index file header. This requires to recreate all indexes, + even those that may still be intact. + The second method is probably faster in most cases. + + When disabling indexes, MySQL disables either all indexes or all + non-unique indexes. When MySQL [re-]enables disabled indexes + (T_CREATE_MISSING_KEYS), then we either have "lost" blocks in the + index file, or there are no non-unique indexes. In the latter case, + mi_repair*() would not be called as there would be no disabled + indexes. + + If there would be more unique indexes than disabled (non-unique) + indexes, we could do the first method. But this is not implemented + yet. By now we drop and recreate all indexes when repair is called. + + However, there is an exception. Sometimes MySQL disables non-unique + indexes when the table is empty (e.g. when copying a table in + mysql_alter_table()). When enabling the non-unique indexes, they + are still empty. So there is no index block that can be lost. This + optimization is implemented in this function. + + Note that in normal repair (T_CREATE_MISSING_KEYS not set) we + recreate all enabled indexes unconditonally. We do not change the + key_map. Otherwise we invert the key map temporarily (outside of + this function) and recreate the then "seemingly" enabled indexes. + When we cannot use the optimization, and drop all indexes, we + pretend that all indexes were disabled. By the inversion, we will + then recrate all indexes. +*/ + +static int mi_drop_all_indexes(MI_CHECK *param, MI_INFO *info, my_bool force) +{ + MYISAM_SHARE *share= info->s; + MI_STATE_INFO *state= &share->state; + uint i; + int error; + DBUG_ENTER("mi_drop_all_indexes"); + + /* + If any of the disabled indexes has a key block assigned, we must + drop and recreate all indexes to avoid losing index blocks. + + If we want to recreate disabled indexes only _and_ all of these + indexes are empty, we don't need to recreate the existing indexes. + */ + if (!force && (param->testflag & T_CREATE_MISSING_KEYS)) + { + DBUG_PRINT("repair", ("creating missing indexes")); + for (i= 0; i < share->base.keys; i++) + { + DBUG_PRINT("repair", ("index #: %u key_root: 0x%lx active: %d", + i, (long) state->key_root[i], + mi_is_key_active(state->key_map, i))); + if ((state->key_root[i] != HA_OFFSET_ERROR) && + !mi_is_key_active(state->key_map, i)) + { + /* + This index has at least one key block and it is disabled. + We would lose its block(s) if would just recreate it. + So we need to drop and recreate all indexes. + */ + DBUG_PRINT("repair", ("nonempty and disabled: recreate all")); + break; + } + } + if (i >= share->base.keys) + { + /* + All of the disabled indexes are empty. We can just recreate them. + Flush dirty blocks of this index file from key cache and remove + all blocks of this index file from key cache. + */ + DBUG_PRINT("repair", ("all disabled are empty: create missing")); + error= flush_key_blocks(share->key_cache, share->kfile, + FLUSH_FORCE_WRITE); + goto end; + } + /* + We do now drop all indexes and declare them disabled. With the + T_CREATE_MISSING_KEYS flag, mi_repair*() will recreate all + disabled indexes and enable them. + */ + mi_clear_all_keys_active(state->key_map); + DBUG_PRINT("repair", ("declared all indexes disabled")); + } + + /* Remove all key blocks of this index file from key cache. */ + if ((error= flush_key_blocks(share->key_cache, share->kfile, + FLUSH_IGNORE_CHANGED))) + goto end; + + /* Clear index root block pointers. */ + for (i= 0; i < share->base.keys; i++) + state->key_root[i]= HA_OFFSET_ERROR; + + /* Clear the delete chains. */ + for (i= 0; i < state->header.max_block_size_index; i++) + state->key_del[i]= HA_OFFSET_ERROR; + + /* Reset index file length to end of index file header. */ + info->state->key_file_length= share->base.keystart; + + DBUG_PRINT("repair", ("dropped all indexes")); + /* error= 0; set by last (error= flush_key_bocks()). */ + + end: + DBUG_RETURN(error); +} + + /* Recover old table by reading each record and writing all keys */ /* Save new datafile-name in temp_filename */ @@ -1383,7 +1516,6 @@ int mi_repair(MI_CHECK *param, register MI_INFO *info, char * name, int rep_quick) { int error,got_error; - uint i; ha_rows start_records,new_header_length; my_off_t del; File new_file; @@ -1487,25 +1619,10 @@ int mi_repair(MI_CHECK *param, register MI_INFO *info, info->update= (short) (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED); - /* - Clear all keys. Note that all key blocks allocated until now remain - "dead" parts of the key file. (Bug #4692) - */ - for (i=0 ; i < info->s->base.keys ; i++) - share->state.key_root[i]= HA_OFFSET_ERROR; - - /* Drop the delete chain. */ - for (i=0 ; i < share->state.header.max_block_size_index ; i++) - share->state.key_del[i]= HA_OFFSET_ERROR; - - /* - If requested, activate (enable) all keys in key_map. In this case, - all indexes will be (re-)built. - */ + /* This function always recreates all enabled indexes. */ if (param->testflag & T_CREATE_MISSING_KEYS) mi_set_all_keys_active(share->state.key_map, share->base.keys); - - info->state->key_file_length=share->base.keystart; + mi_drop_all_indexes(param, info, TRUE); lock_memory(param); /* Everything is alloced */ @@ -2106,8 +2223,9 @@ int mi_repair_by_sort(MI_CHECK *param, register MI_INFO *info, ulong *rec_per_key_part; char llbuff[22]; SORT_INFO sort_info; - ulonglong key_map=share->state.key_map; + ulonglong key_map; DBUG_ENTER("mi_repair_by_sort"); + LINT_INIT(key_map); start_records=info->state->records; got_error=1; @@ -2180,25 +2298,14 @@ int mi_repair_by_sort(MI_CHECK *param, register MI_INFO *info, } info->update= (short) (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED); - if (!(param->testflag & T_CREATE_MISSING_KEYS)) - { - /* - Flush key cache for this file if we are calling this outside - myisamchk - */ - flush_key_blocks(share->key_cache,share->kfile, FLUSH_IGNORE_CHANGED); - /* Clear the pointers to the given rows */ - for (i=0 ; i < share->base.keys ; i++) - share->state.key_root[i]= HA_OFFSET_ERROR; - for (i=0 ; i < share->state.header.max_block_size_index ; i++) - share->state.key_del[i]= HA_OFFSET_ERROR; - info->state->key_file_length=share->base.keystart; - } - else + + /* Optionally drop indexes and optionally modify the key_map. */ + mi_drop_all_indexes(param, info, FALSE); + key_map= share->state.key_map; + if (param->testflag & T_CREATE_MISSING_KEYS) { - if (flush_key_blocks(share->key_cache,share->kfile, FLUSH_FORCE_WRITE)) - goto err; - key_map= ~key_map; /* Create the missing keys */ + /* Invert the copied key_map to recreate all disabled indexes. */ + key_map= ~key_map; } sort_info.info=info; @@ -2242,6 +2349,10 @@ int mi_repair_by_sort(MI_CHECK *param, register MI_INFO *info, sort_param.read_cache=param->read_cache; sort_param.keyinfo=share->keyinfo+sort_param.key; sort_param.seg=sort_param.keyinfo->seg; + /* + Skip this index if it is marked disabled in the copied + (and possibly inverted) key_map. + */ if (! mi_is_key_active(key_map, sort_param.key)) { /* Remember old statistics for key */ @@ -2249,6 +2360,8 @@ int mi_repair_by_sort(MI_CHECK *param, register MI_INFO *info, (char*) (share->state.rec_per_key_part + (uint) (rec_per_key_part - param->rec_per_key_part)), sort_param.keyinfo->keysegs*sizeof(*rec_per_key_part)); + DBUG_PRINT("repair", ("skipping seemingly disabled index #: %u", + sort_param.key)); continue; } @@ -2329,8 +2442,11 @@ int mi_repair_by_sort(MI_CHECK *param, register MI_INFO *info, if (param->testflag & T_STATISTICS) update_key_parts(sort_param.keyinfo, rec_per_key_part, sort_param.unique, param->stats_method == MI_STATS_METHOD_IGNORE_NULLS? - sort_param.notnull: NULL,(ulonglong) info->state->records); + sort_param.notnull: NULL, + (ulonglong) info->state->records); + /* Enable this index in the permanent (not the copied) key_map. */ mi_set_key_active(share->state.key_map, sort_param.key); + DBUG_PRINT("repair", ("set enabled index #: %u", sort_param.key)); if (sort_param.fix_datafile) { @@ -2531,9 +2647,10 @@ int mi_repair_parallel(MI_CHECK *param, register MI_INFO *info, IO_CACHE new_data_cache; /* For non-quick repair. */ IO_CACHE_SHARE io_share; SORT_INFO sort_info; - ulonglong key_map=share->state.key_map; + ulonglong key_map; pthread_attr_t thr_attr; DBUG_ENTER("mi_repair_parallel"); + LINT_INIT(key_map); start_records=info->state->records; got_error=1; @@ -2635,25 +2752,14 @@ int mi_repair_parallel(MI_CHECK *param, register MI_INFO *info, } info->update= (short) (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED); - if (!(param->testflag & T_CREATE_MISSING_KEYS)) - { - /* - Flush key cache for this file if we are calling this outside - myisamchk - */ - flush_key_blocks(share->key_cache,share->kfile, FLUSH_IGNORE_CHANGED); - /* Clear the pointers to the given rows */ - for (i=0 ; i < share->base.keys ; i++) - share->state.key_root[i]= HA_OFFSET_ERROR; - for (i=0 ; i < share->state.header.max_block_size_index ; i++) - share->state.key_del[i]= HA_OFFSET_ERROR; - info->state->key_file_length=share->base.keystart; - } - else + + /* Optionally drop indexes and optionally modify the key_map. */ + mi_drop_all_indexes(param, info, FALSE); + key_map= share->state.key_map; + if (param->testflag & T_CREATE_MISSING_KEYS) { - if (flush_key_blocks(share->key_cache,share->kfile, FLUSH_FORCE_WRITE)) - goto err; - key_map= ~key_map; /* Create the missing keys */ + /* Invert the copied key_map to recreate all disabled indexes. */ + key_map= ~key_map; } sort_info.info=info; @@ -2709,6 +2815,10 @@ int mi_repair_parallel(MI_CHECK *param, register MI_INFO *info, sort_param[i].key=key; sort_param[i].keyinfo=share->keyinfo+key; sort_param[i].seg=sort_param[i].keyinfo->seg; + /* + Skip this index if it is marked disabled in the copied + (and possibly inverted) key_map. + */ if (! mi_is_key_active(key_map, key)) { /* Remember old statistics for key */ |