diff --git a/mysql-test/r/csv.result b/mysql-test/r/csv.result index b0033383f00..b91272f7e59 100644 --- a/mysql-test/r/csv.result +++ b/mysql-test/r/csv.result @@ -5379,4 +5379,13 @@ SHOW WARNINGS; Level Code Message Error 1178 The storage engine for the table doesn't support nullable columns Error 1005 Can't create table 'test.t1' (errno: 138) +create table t1 (c1 tinyblob not null) engine=csv; +insert into t1 values("This"); +update t1 set c1="That" where c1="This"; +affected rows: 1 +info: Rows matched: 1 Changed: 1 Warnings: 0 +select * from t1; +c1 +That +drop table t1; End of 5.1 tests diff --git a/mysql-test/r/ctype_ucs2_def.result b/mysql-test/r/ctype_ucs2_def.result index 6fd45428368..005d46062fb 100644 --- a/mysql-test/r/ctype_ucs2_def.result +++ b/mysql-test/r/ctype_ucs2_def.result @@ -21,4 +21,14 @@ INSERT INTO t1 VALUES('A', 'A'), ('B', 'B'), ('C', 'C'); INSERT INTO t1 VALUES('A ', 'A '); ERROR 23000: Duplicate entry '' for key 'key1' DROP TABLE t1; +CREATE TABLE t1 ( +c1 CHAR(255) CHARACTER SET UCS2 COLLATE UCS2_BIN NOT NULL, +KEY(c1) +) ENGINE=MyISAM; +INSERT INTO t1 VALUES ('marshall\'s'); +INSERT INTO t1 VALUES ('marsh'); +CHECK TABLE t1 EXTENDED; +Table Op Msg_type Msg_text +test.t1 check status OK +DROP TABLE t1; End of 5.0 tests diff --git a/mysql-test/r/myisam.result b/mysql-test/r/myisam.result index 1c8b5e9d7d9..bf57b6e1006 100644 --- a/mysql-test/r/myisam.result +++ b/mysql-test/r/myisam.result @@ -2023,4 +2023,185 @@ CHECK TABLE t1; Table Op Msg_type Msg_text test.t1 check status OK DROP TABLE t1; +CREATE TABLE t1 ( +c1 CHAR(130), +c2 VARCHAR(1) +) ENGINE=MyISAM; +INSERT INTO t1 VALUES(REPEAT("a",128), 'b'); +SELECT COUNT(*) FROM t1; +COUNT(*) +1 +CHECK TABLE t1; +Table Op Msg_type Msg_text +test.t1 check status OK +REPAIR TABLE t1; +Table Op Msg_type Msg_text +test.t1 repair status OK +SELECT COUNT(*) FROM t1; +COUNT(*) +1 +CHECK TABLE t1; +Table Op Msg_type Msg_text +test.t1 check status OK +DROP TABLE t1; +CREATE TABLE t1 ( +c1 CHAR(130), +c2 VARCHAR(1) +) ENGINE=MyISAM; +INSERT INTO t1 VALUES(REPEAT("a",128), 'b'); +SELECT COUNT(*) FROM t1; +COUNT(*) +1 +CHECK TABLE t1 EXTENDED; +Table Op Msg_type Msg_text +test.t1 check status OK +REPAIR TABLE t1 EXTENDED; +Table Op Msg_type Msg_text +test.t1 repair status OK +SELECT COUNT(*) FROM t1; +COUNT(*) +1 +CHECK TABLE t1 EXTENDED; +Table Op Msg_type Msg_text +test.t1 check status OK +DROP TABLE t1; +CREATE TABLE t1 ( +c1 CHAR(130), +c2 VARCHAR(1) +) ENGINE=MyISAM; +INSERT INTO t1 VALUES(REPEAT("a",128), 'b'); +INSERT INTO t1 VALUES('b', 'b'); +INSERT INTO t1 VALUES('c', 'b'); +DELETE FROM t1 WHERE c1='b'; +SELECT COUNT(*) FROM t1; +COUNT(*) +2 +OPTIMIZE TABLE t1; +Table Op Msg_type Msg_text +test.t1 optimize status OK +SELECT COUNT(*) FROM t1; +COUNT(*) +2 +DROP TABLE t1; +CREATE TABLE t1 ( +c1 CHAR(130), +c2 VARCHAR(1), +KEY (c1) +) ENGINE=MyISAM; +# Insert 100 rows. Query log disabled. +UPDATE t1 SET c1=REPEAT("a",128) LIMIT 90; +SELECT COUNT(*) FROM t1; +COUNT(*) +100 +ALTER TABLE t1 ENGINE=MyISAM; +SELECT COUNT(*) FROM t1; +COUNT(*) +100 +CHECK TABLE t1; +Table Op Msg_type Msg_text +test.t1 check status OK +CHECK TABLE t1 EXTENDED; +Table Op Msg_type Msg_text +test.t1 check status OK +DROP TABLE t1; +CREATE TABLE t1 ( +c1 CHAR(50), +c2 VARCHAR(1) +) ENGINE=MyISAM DEFAULT CHARSET UTF8; +INSERT INTO t1 VALUES(REPEAT(_utf8 x'e0ae85',43), 'b'); +SELECT COUNT(*) FROM t1; +COUNT(*) +1 +CHECK TABLE t1; +Table Op Msg_type Msg_text +test.t1 check status OK +REPAIR TABLE t1; +Table Op Msg_type Msg_text +test.t1 repair status OK +SELECT COUNT(*) FROM t1; +COUNT(*) +1 +CHECK TABLE t1; +Table Op Msg_type Msg_text +test.t1 check status OK +DROP TABLE t1; +CREATE TABLE t1 ( +c1 CHAR(50), +c2 VARCHAR(1) +) ENGINE=MyISAM DEFAULT CHARSET UTF8; +INSERT INTO t1 VALUES(REPEAT(_utf8 x'e0ae85',43), 'b'); +SELECT COUNT(*) FROM t1; +COUNT(*) +1 +CHECK TABLE t1 EXTENDED; +Table Op Msg_type Msg_text +test.t1 check status OK +REPAIR TABLE t1 EXTENDED; +Table Op Msg_type Msg_text +test.t1 repair status OK +SELECT COUNT(*) FROM t1; +COUNT(*) +1 +CHECK TABLE t1 EXTENDED; +Table Op Msg_type Msg_text +test.t1 check status OK +DROP TABLE t1; +CREATE TABLE t1 ( +c1 CHAR(50), +c2 VARCHAR(1) +) ENGINE=MyISAM DEFAULT CHARSET UTF8; +INSERT INTO t1 VALUES(REPEAT(_utf8 x'e0ae85',43), 'b'); +INSERT INTO t1 VALUES('b', 'b'); +INSERT INTO t1 VALUES('c', 'b'); +DELETE FROM t1 WHERE c1='b'; +SELECT COUNT(*) FROM t1; +COUNT(*) +2 +OPTIMIZE TABLE t1; +Table Op Msg_type Msg_text +test.t1 optimize status OK +SELECT COUNT(*) FROM t1; +COUNT(*) +2 +DROP TABLE t1; +CREATE TABLE t1 ( +c1 CHAR(50), +c2 VARCHAR(1), +KEY (c1) +) ENGINE=MyISAM DEFAULT CHARSET UTF8; +# Insert 100 rows. Query log disabled. +UPDATE t1 SET c1=REPEAT(_utf8 x'e0ae85',43) LIMIT 90; +SELECT COUNT(*) FROM t1; +COUNT(*) +100 +ALTER TABLE t1 ENGINE=MyISAM; +SELECT COUNT(*) FROM t1; +COUNT(*) +100 +CHECK TABLE t1; +Table Op Msg_type Msg_text +test.t1 check status OK +CHECK TABLE t1 EXTENDED; +Table Op Msg_type Msg_text +test.t1 check status OK +DROP TABLE t1; +CREATE TABLE t1 ( +c1 VARCHAR(10) NOT NULL, +c2 CHAR(10) DEFAULT NULL, +c3 VARCHAR(10) NOT NULL, +KEY (c1), +KEY (c2) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 PACK_KEYS=0; + +MyISAM file: MYSQLTEST_VARDIR/master-data/test/t1 +Record format: Packed +Character set: utf8_general_ci (33) +Data records: 0 Deleted blocks: 0 +Recordlength: 94 + +table description: +Key Start Len Index Type +1 2 30 multip. varchar +2 33 30 multip. char NULL +DROP TABLE t1; End of 5.1 tests diff --git a/mysql-test/r/plugin_load.result b/mysql-test/r/plugin_load.result new file mode 100644 index 00000000000..33116cc20ab --- /dev/null +++ b/mysql-test/r/plugin_load.result @@ -0,0 +1,3 @@ +SELECT @@global.example_enum_var = 'e2'; +@@global.example_enum_var = 'e2' +1 diff --git a/mysql-test/r/symlink.result b/mysql-test/r/symlink.result index 4eece9d5b5a..7599d80588a 100644 --- a/mysql-test/r/symlink.result +++ b/mysql-test/r/symlink.result @@ -162,3 +162,11 @@ DROP DATABASE db1; DROP DATABASE db2; USE test; End of 5.0 tests +SET @OLD_SQL_MODE=@@SQL_MODE, @@SQL_MODE='NO_DIR_IN_CREATE'; +CREATE TABLE t1(a INT) DATA DIRECTORY='MYSQLTEST_VARDIR/tmp' INDEX DIRECTORY='MYSQLTEST_VARDIR/tmp'; +Warnings: +Warning 0 DATA DIRECTORY option ignored +Warning 0 INDEX DIRECTORY option ignored +DROP TABLE t1; +SET @@SQL_MODE=@OLD_SQL_MODE; +End of 5.1 tests diff --git a/mysql-test/t/csv.test b/mysql-test/t/csv.test index 7b4f95bbf8a..dd8c940ac44 100644 --- a/mysql-test/t/csv.test +++ b/mysql-test/t/csv.test @@ -1773,4 +1773,15 @@ drop table t1; CREATE TABLE t1(a INT) ENGINE=CSV; SHOW WARNINGS; +# +# BUG#33067 - . +# +create table t1 (c1 tinyblob not null) engine=csv; +insert into t1 values("This"); +--enable_info +update t1 set c1="That" where c1="This"; +--disable_info +select * from t1; +drop table t1; + --echo End of 5.1 tests diff --git a/mysql-test/t/ctype_ucs2_def.test b/mysql-test/t/ctype_ucs2_def.test index c80444daddd..b146dc63626 100644 --- a/mysql-test/t/ctype_ucs2_def.test +++ b/mysql-test/t/ctype_ucs2_def.test @@ -39,4 +39,17 @@ INSERT INTO t1 VALUES('A', 'A'), ('B', 'B'), ('C', 'C'); INSERT INTO t1 VALUES('A ', 'A '); DROP TABLE t1; +# +# Bug#32705 - myisam corruption: Key in wrong position +# at page 1024 with ucs2_bin +# +CREATE TABLE t1 ( + c1 CHAR(255) CHARACTER SET UCS2 COLLATE UCS2_BIN NOT NULL, + KEY(c1) + ) ENGINE=MyISAM; +INSERT INTO t1 VALUES ('marshall\'s'); +INSERT INTO t1 VALUES ('marsh'); +CHECK TABLE t1 EXTENDED; +DROP TABLE t1; + --echo End of 5.0 tests diff --git a/mysql-test/t/myisam.test b/mysql-test/t/myisam.test index fbd0a5ac4e7..21ffa0683b6 100644 --- a/mysql-test/t/myisam.test +++ b/mysql-test/t/myisam.test @@ -1278,5 +1278,189 @@ DELETE FROM t1 WHERE c1 >= 10; CHECK TABLE t1; DROP TABLE t1; +# +# Bug#33222 - myisam-table drops rows when column is added +# and a char-field > 128 exists +# +# Test #1 - CHECK TABLE sees wrong record, REPAR TABLE deletes it. +# Using a CHAR column that can have > 127 characters. +# Using a VARCHAR to create a table with dynamic row format. +CREATE TABLE t1 ( + c1 CHAR(130), + c2 VARCHAR(1) +) ENGINE=MyISAM; +INSERT INTO t1 VALUES(REPEAT("a",128), 'b'); +SELECT COUNT(*) FROM t1; +CHECK TABLE t1; +REPAIR TABLE t1; +SELECT COUNT(*) FROM t1; +CHECK TABLE t1; +DROP TABLE t1; +# +# Test #2 - same as test #1, but using EXTENDED. +# Using a CHAR column that can have > 127 characters. +# Using a VARCHAR to create a table with dynamic row format. +CREATE TABLE t1 ( + c1 CHAR(130), + c2 VARCHAR(1) +) ENGINE=MyISAM; +INSERT INTO t1 VALUES(REPEAT("a",128), 'b'); +SELECT COUNT(*) FROM t1; +CHECK TABLE t1 EXTENDED; +REPAIR TABLE t1 EXTENDED; +SELECT COUNT(*) FROM t1; +CHECK TABLE t1 EXTENDED; +DROP TABLE t1; +# +# Test #3 - same as test #1, but using OPTIMIZE TABLE. +# Using a CHAR column that can have > 127 characters. +# Using a VARCHAR to create a table with dynamic row format. +CREATE TABLE t1 ( + c1 CHAR(130), + c2 VARCHAR(1) +) ENGINE=MyISAM; +INSERT INTO t1 VALUES(REPEAT("a",128), 'b'); +# Insert more rows and delete one in the middle to force optimize. +INSERT INTO t1 VALUES('b', 'b'); +INSERT INTO t1 VALUES('c', 'b'); +DELETE FROM t1 WHERE c1='b'; +SELECT COUNT(*) FROM t1; +OPTIMIZE TABLE t1; +SELECT COUNT(*) FROM t1; +DROP TABLE t1; +# +# Test #4 - ALTER TABLE deletes rows. +# Using a CHAR column that can have > 127 characters. +# Using a VARCHAR to create a table with dynamic row format. +# Using an index which can be disabled during bulk insert. +CREATE TABLE t1 ( + c1 CHAR(130), + c2 VARCHAR(1), + KEY (c1) +) ENGINE=MyISAM; +# +# Insert 100 rows. This turns bulk insert on during the copy phase of +# ALTER TABLE. Bulk insert disables keys before the insert and re-enables +# them by repair after the insert. +--disable_query_log +let $count= 100; +--echo # Insert $count rows. Query log disabled. +while ($count) +{ + INSERT INTO t1 VALUES ('a', 'b'); + dec $count; +} +--enable_query_log +# +# Change most of the rows into long character values with > 127 characters. +UPDATE t1 SET c1=REPEAT("a",128) LIMIT 90; +SELECT COUNT(*) FROM t1; +ALTER TABLE t1 ENGINE=MyISAM; +# +# With bug present, this shows that all long rows are gone. +SELECT COUNT(*) FROM t1; +CHECK TABLE t1; +CHECK TABLE t1 EXTENDED; +DROP TABLE t1; +# +# Test #5 - same as test #1 but UTF-8. +# Using a CHAR column that can have > 127 characters. +# Using a VARCHAR to create a table with dynamic row format. +CREATE TABLE t1 ( + c1 CHAR(50), + c2 VARCHAR(1) +) ENGINE=MyISAM DEFAULT CHARSET UTF8; +# Using Tamil Letter A, Unicode U+0B85 +INSERT INTO t1 VALUES(REPEAT(_utf8 x'e0ae85',43), 'b'); +SELECT COUNT(*) FROM t1; +CHECK TABLE t1; +REPAIR TABLE t1; +SELECT COUNT(*) FROM t1; +CHECK TABLE t1; +DROP TABLE t1; +# +# Test #6 - same as test #2, but UTF-8. +# Using a CHAR column that can have > 127 characters. +# Using a VARCHAR to create a table with dynamic row format. +CREATE TABLE t1 ( + c1 CHAR(50), + c2 VARCHAR(1) +) ENGINE=MyISAM DEFAULT CHARSET UTF8; +# Using Tamil Letter A, Unicode U+0B85 +INSERT INTO t1 VALUES(REPEAT(_utf8 x'e0ae85',43), 'b'); +SELECT COUNT(*) FROM t1; +CHECK TABLE t1 EXTENDED; +REPAIR TABLE t1 EXTENDED; +SELECT COUNT(*) FROM t1; +CHECK TABLE t1 EXTENDED; +DROP TABLE t1; +# +# Test #7 - same as test #3, but UTF-8. +# Using a CHAR column that can have > 127 characters. +# Using a VARCHAR to create a table with dynamic row format. +CREATE TABLE t1 ( + c1 CHAR(50), + c2 VARCHAR(1) +) ENGINE=MyISAM DEFAULT CHARSET UTF8; +# Using Tamil Letter A, Unicode U+0B85 +INSERT INTO t1 VALUES(REPEAT(_utf8 x'e0ae85',43), 'b'); +# Insert more rows and delete one in the middle to force optimize. +INSERT INTO t1 VALUES('b', 'b'); +INSERT INTO t1 VALUES('c', 'b'); +DELETE FROM t1 WHERE c1='b'; +SELECT COUNT(*) FROM t1; +OPTIMIZE TABLE t1; +SELECT COUNT(*) FROM t1; +DROP TABLE t1; +# +# Test #8 - same as test #4, but UTF-8. +# Using a CHAR column that can have > 42 UTF-8 characters. +# Using a VARCHAR to create a table with dynamic row format. +# Using an index which can be disabled during bulk insert. +CREATE TABLE t1 ( + c1 CHAR(50), + c2 VARCHAR(1), + KEY (c1) +) ENGINE=MyISAM DEFAULT CHARSET UTF8; +# +# Insert 100 rows. This turns bulk insert on during the copy phase of +# ALTER TABLE. Bulk insert disables keys before the insert and re-enables +# them by repair after the insert. +--disable_query_log +let $count= 100; +--echo # Insert $count rows. Query log disabled. +while ($count) +{ + INSERT INTO t1 VALUES ('a', 'b'); + dec $count; +} +--enable_query_log +# +# Change most of the rows into long character values with > 42 characters. +# Using Tamil Letter A, Unicode U+0B85 +UPDATE t1 SET c1=REPEAT(_utf8 x'e0ae85',43) LIMIT 90; +SELECT COUNT(*) FROM t1; +ALTER TABLE t1 ENGINE=MyISAM; +# +# With bug present, this shows that all long rows are gone. +SELECT COUNT(*) FROM t1; +CHECK TABLE t1; +CHECK TABLE t1 EXTENDED; +DROP TABLE t1; + +# +# Bug#29182 - MyISAMCHK reports wrong character set +# +CREATE TABLE t1 ( + c1 VARCHAR(10) NOT NULL, + c2 CHAR(10) DEFAULT NULL, + c3 VARCHAR(10) NOT NULL, + KEY (c1), + KEY (c2) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 PACK_KEYS=0; +--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR +--exec $MYISAMCHK -d $MYSQLTEST_VARDIR/master-data/test/t1 +DROP TABLE t1; + --echo End of 5.1 tests diff --git a/mysql-test/t/plugin_load-master.opt b/mysql-test/t/plugin_load-master.opt new file mode 100644 index 00000000000..66637841f16 --- /dev/null +++ b/mysql-test/t/plugin_load-master.opt @@ -0,0 +1,3 @@ +$EXAMPLE_PLUGIN_OPT +"--plugin-load=;EXAMPLE=ha_example.so;" +--loose-plugin-example-enum-var=e2 diff --git a/mysql-test/t/plugin_load.test b/mysql-test/t/plugin_load.test new file mode 100644 index 00000000000..8555247dd71 --- /dev/null +++ b/mysql-test/t/plugin_load.test @@ -0,0 +1,3 @@ +--source include/have_example_plugin.inc + +SELECT @@global.example_enum_var = 'e2'; diff --git a/mysql-test/t/symlink.test b/mysql-test/t/symlink.test index f339b29c83a..eaad45d7d5d 100644 --- a/mysql-test/t/symlink.test +++ b/mysql-test/t/symlink.test @@ -226,3 +226,15 @@ USE test; --echo End of 5.0 tests + +# +# BUG#25677 - With --skip-symbolic-links option on, DATA DIRECTORY clause is +# silently ignored +# +SET @OLD_SQL_MODE=@@SQL_MODE, @@SQL_MODE='NO_DIR_IN_CREATE'; +--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR +eval CREATE TABLE t1(a INT) DATA DIRECTORY='$MYSQLTEST_VARDIR/tmp' INDEX DIRECTORY='$MYSQLTEST_VARDIR/tmp'; +DROP TABLE t1; +SET @@SQL_MODE=@OLD_SQL_MODE; + +--echo End of 5.1 tests diff --git a/mysys/base64.c b/mysys/base64.c index dbe8927290d..6157dcaa5af 100644 --- a/mysys/base64.c +++ b/mysys/base64.c @@ -256,6 +256,7 @@ main(void) char * str; char * dst; + require(src); for (j= 0; jalias; -#ifndef HAVE_READLINK - if (create_info.data_file_name) - push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, 0, - "DATA DIRECTORY option ignored"); - if (create_info.index_file_name) - push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, 0, - "INDEX DIRECTORY option ignored"); - create_info.data_file_name= create_info.index_file_name= NULL; -#else +#ifdef HAVE_READLINK /* Fix names if symlinked tables */ if (append_file_to_dir(thd, &create_info.data_file_name, create_table->table_name) || diff --git a/sql/sql_plugin.cc b/sql/sql_plugin.cc index 2a86844c8c6..bae4a85fd8a 100644 --- a/sql/sql_plugin.cc +++ b/sql/sql_plugin.cc @@ -1181,9 +1181,8 @@ int plugin_init(int *argc, char **argv, int flags) /* Register all dynamic plugins */ if (!(flags & PLUGIN_INIT_SKIP_DYNAMIC_LOADING)) { - if (opt_plugin_load && - plugin_load_list(&tmp_root, argc, argv, opt_plugin_load)) - goto err; + if (opt_plugin_load) + plugin_load_list(&tmp_root, argc, argv, opt_plugin_load); if (!(flags & PLUGIN_INIT_SKIP_PLUGIN_TABLE)) plugin_load(&tmp_root, argc, argv); } @@ -1412,7 +1411,11 @@ static bool plugin_load_list(MEM_ROOT *tmp_root, int *argc, char **argv, while (list) { if (p == buffer + sizeof(buffer) - 1) - break; + { + sql_print_error("plugin-load parameter too long"); + DBUG_RETURN(TRUE); + } + switch ((*(p++)= *(list++))) { case '\0': list= NULL; /* terminate the loop */ @@ -1421,10 +1424,17 @@ static bool plugin_load_list(MEM_ROOT *tmp_root, int *argc, char **argv, case ':': /* can't use this as delimiter as it may be drive letter */ #endif case ';': - name.str[name.length]= '\0'; - if (str != &dl) // load all plugins in named module + str->str[str->length]= '\0'; + if (str == &name) // load all plugins in named module { + if (!name.length) + { + p--; /* reset pointer */ + continue; + } + dl= name; + pthread_mutex_lock(&LOCK_plugin); if ((plugin_dl= plugin_dl_add(&dl, REPORT_TO_LOG))) { for (plugin= plugin_dl->plugins; plugin->info; plugin++) @@ -1434,7 +1444,10 @@ static bool plugin_load_list(MEM_ROOT *tmp_root, int *argc, char **argv, free_root(tmp_root, MYF(MY_MARK_BLOCKS_FREE)); if (plugin_add(tmp_root, &name, &dl, argc, argv, REPORT_TO_LOG)) + { + pthread_mutex_unlock(&LOCK_plugin); goto error; + } } plugin_dl_del(&dl); // reduce ref count } @@ -1442,9 +1455,14 @@ static bool plugin_load_list(MEM_ROOT *tmp_root, int *argc, char **argv, else { free_root(tmp_root, MYF(MY_MARK_BLOCKS_FREE)); + pthread_mutex_lock(&LOCK_plugin); if (plugin_add(tmp_root, &name, &dl, argc, argv, REPORT_TO_LOG)) + { + pthread_mutex_unlock(&LOCK_plugin); goto error; + } } + pthread_mutex_unlock(&LOCK_plugin); name.length= dl.length= 0; dl.str= NULL; name.str= p= buffer; str= &name; @@ -1453,6 +1471,7 @@ static bool plugin_load_list(MEM_ROOT *tmp_root, int *argc, char **argv, case '#': if (str == &name) { + name.str[name.length]= '\0'; str= &dl; str->str= p; continue; @@ -2999,7 +3018,8 @@ static int construct_options(MEM_ROOT *mem_root, struct st_plugin_int *tmp, DBUG_RETURN(-1); } - if (opt->flags & PLUGIN_VAR_NOCMDOPT) + if ((opt->flags & (PLUGIN_VAR_NOCMDOPT | PLUGIN_VAR_THDLOCAL)) + == PLUGIN_VAR_NOCMDOPT) continue; if (!opt->name) @@ -3009,7 +3029,7 @@ static int construct_options(MEM_ROOT *mem_root, struct st_plugin_int *tmp, DBUG_RETURN(-1); } - if (!(v= find_bookmark(name, opt->name, opt->flags))) + if (!(opt->flags & PLUGIN_VAR_THDLOCAL)) { optnamelen= strlen(opt->name); optname= (char*) alloc_root(mem_root, namelen + optnamelen + 2); @@ -3017,7 +3037,23 @@ static int construct_options(MEM_ROOT *mem_root, struct st_plugin_int *tmp, optnamelen= namelen + optnamelen + 1; } else - optname= (char*) memdup_root(mem_root, v->key + 1, (optnamelen= v->name_len) + 1); + { + /* this should not fail because register_var should create entry */ + if (!(v= find_bookmark(name, opt->name, opt->flags))) + { + sql_print_error("Thread local variable '%s' not allocated " + "in plugin '%s'.", opt->name, plugin_name); + DBUG_RETURN(-1); + } + + *(int*)(opt + 1)= offset= v->offset; + + if (opt->flags & PLUGIN_VAR_NOCMDOPT) + continue; + + optname= (char*) memdup_root(mem_root, v->key + 1, + (optnamelen= v->name_len) + 1); + } /* convert '_' to '-' */ for (p= optname; *p; p++) @@ -3029,20 +3065,13 @@ static int construct_options(MEM_ROOT *mem_root, struct st_plugin_int *tmp, options->app_type= opt; options->id= (options-1)->id + 1; - if (opt->flags & PLUGIN_VAR_THDLOCAL) - *(int*)(opt + 1)= offset= v->offset; - plugin_opt_set_limits(options, opt); - if ((opt->flags & PLUGIN_VAR_TYPEMASK) != PLUGIN_VAR_ENUM && - (opt->flags & PLUGIN_VAR_TYPEMASK) != PLUGIN_VAR_SET) - { - if (opt->flags & PLUGIN_VAR_THDLOCAL) - options->value= options->u_max_value= (uchar**) - (global_system_variables.dynamic_variables_ptr + offset); - else - options->value= options->u_max_value= *(uchar***) (opt + 1); - } + if (opt->flags & PLUGIN_VAR_THDLOCAL) + options->value= options->u_max_value= (uchar**) + (global_system_variables.dynamic_variables_ptr + offset); + else + options->value= options->u_max_value= *(uchar***) (opt + 1); options[1]= options[0]; options[1].name= p= (char*) alloc_root(mem_root, optnamelen + 8); diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 505bcd1b421..ca7b8fafd3c 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -3480,8 +3480,18 @@ bool mysql_create_table_no_lock(THD *thd, thd_proc_info(thd, "creating table"); create_info->table_existed= 0; // Mark that table is created - if (thd->variables.sql_mode & MODE_NO_DIR_IN_CREATE) +#ifdef HAVE_READLINK + if (!my_use_symdir || (thd->variables.sql_mode & MODE_NO_DIR_IN_CREATE)) +#endif + { + if (create_info->data_file_name) + push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, 0, + "DATA DIRECTORY option ignored"); + if (create_info->index_file_name) + push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, 0, + "INDEX DIRECTORY option ignored"); create_info->data_file_name= create_info->index_file_name= 0; + } create_info->table_options=db_options; path[path_length - reg_ext_length]= '\0'; // Remove .frm extension diff --git a/sql/table.cc b/sql/table.cc index cacb3a94582..100821f28d5 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -892,26 +892,31 @@ static int open_binary_frm(THD *thd, TABLE_SHARE *share, uchar *head, ha_legacy_type(share->db_type()))); } #ifdef WITH_PARTITION_STORAGE_ENGINE - else + else if (str_db_type_length == 9 && + !strncmp((char *) next_chunk + 2, "partition", 9)) { - LEX_STRING pname= { C_STRING_WITH_LEN( "partition" ) }; - if (str_db_type_length == pname.length && - !strncmp((char *) next_chunk + 2, pname.str, pname.length)) - { - /* - Use partition handler - tmp_plugin is locked with a local lock. - we unlock the old value of share->db_plugin before - replacing it with a globally locked version of tmp_plugin - */ - plugin_unlock(NULL, share->db_plugin); - share->db_plugin= ha_lock_engine(NULL, partition_hton); - DBUG_PRINT("info", ("setting dbtype to '%.*s' (%d)", - str_db_type_length, next_chunk + 2, - ha_legacy_type(share->db_type()))); - } + /* + Use partition handler + tmp_plugin is locked with a local lock. + we unlock the old value of share->db_plugin before + replacing it with a globally locked version of tmp_plugin + */ + plugin_unlock(NULL, share->db_plugin); + share->db_plugin= ha_lock_engine(NULL, partition_hton); + DBUG_PRINT("info", ("setting dbtype to '%.*s' (%d)", + str_db_type_length, next_chunk + 2, + ha_legacy_type(share->db_type()))); } #endif + else if (!tmp_plugin) + { + /* purecov: begin inspected */ + error= 8; + my_error(ER_UNKNOWN_STORAGE_ENGINE, MYF(0), name.str); + my_free(buff, MYF(0)); + goto err; + /* purecov: end */ + } next_chunk+= str_db_type_length + 2; } if (next_chunk + 5 < buff_end) @@ -2200,6 +2205,8 @@ void open_table_error(TABLE_SHARE *share, int error, int db_errno, int errarg) "of MySQL and cannot be read", MYF(0), buff); break; + case 8: + break; default: /* Better wrong error than none */ case 4: strxmov(buff, share->normalized_path.str, reg_ext, NullS); diff --git a/storage/archive/azio.c b/storage/archive/azio.c index cada6c57918..59fbe2182ee 100644 --- a/storage/archive/azio.c +++ b/storage/archive/azio.c @@ -225,11 +225,17 @@ int get_byte(s) if (s->stream.avail_in == 0) { errno = 0; - s->stream.avail_in = my_read(s->file, (uchar *)s->inbuf, AZ_BUFSIZE_READ, MYF(0)); + s->stream.avail_in= (uInt) my_read(s->file, (uchar *)s->inbuf, + AZ_BUFSIZE_READ, MYF(0)); if (s->stream.avail_in == 0) { s->z_eof = 1; - /* if (ferror(s->file)) s->z_err = Z_ERRNO; */ + return EOF; + } + else if (s->stream.avail_in == (uInt) -1) + { + s->z_eof= 1; + s->z_err= Z_ERRNO; return EOF; } s->stream.next_in = s->inbuf; diff --git a/storage/csv/ha_tina.cc b/storage/csv/ha_tina.cc index c9fab79a4c5..f8dd778045f 100644 --- a/storage/csv/ha_tina.cc +++ b/storage/csv/ha_tina.cc @@ -56,6 +56,7 @@ TODO: #define META_BUFFER_SIZE sizeof(uchar) + sizeof(uchar) + sizeof(ulonglong) \ + sizeof(ulonglong) + sizeof(ulonglong) + sizeof(ulonglong) + sizeof(uchar) #define TINA_CHECK_HEADER 254 // The number we use to determine corruption +#define BLOB_MEMROOT_ALLOC_SIZE 8192 /* The file extension */ #define CSV_EXT ".CSV" // The data file @@ -597,6 +598,8 @@ int ha_tina::find_current_row(uchar *buf) bool read_all; DBUG_ENTER("ha_tina::find_current_row"); + free_root(&blobroot, MYF(MY_MARK_BLOCKS_FREE)); + /* We do not read further then local_saved_data_file_length in order not to conflict with undergoing concurrent insert. @@ -684,6 +687,22 @@ int ha_tina::find_current_row(uchar *buf) if ((*field)->store(buffer.ptr(), buffer.length(), buffer.charset(), CHECK_FIELD_WARN)) goto err; + if ((*field)->flags & BLOB_FLAG) + { + Field_blob *blob= *(Field_blob**) field; + uchar *src, *tgt; + uint length, packlength; + + packlength= blob->pack_length_no_ptr(); + length= blob->get_length(blob->ptr); + memcpy_fixed(&src, blob->ptr + packlength, sizeof(char*)); + if (src) + { + tgt= (uchar*) alloc_root(&blobroot, length); + bmove(tgt, src, length); + memcpy_fixed(blob->ptr + packlength, &tgt, sizeof(char*)); + } + } } } next_position= end_offset + eoln_len; @@ -914,9 +933,10 @@ int ha_tina::open_update_temp_file_if_needed() int ha_tina::update_row(const uchar * old_data, uchar * new_data) { int size; + int rc= -1; DBUG_ENTER("ha_tina::update_row"); - ha_statistic_increment(&SSV::ha_read_rnd_next_count); + ha_statistic_increment(&SSV::ha_update_count); if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_UPDATE) table->timestamp_field->set_time(); @@ -931,20 +951,23 @@ int ha_tina::update_row(const uchar * old_data, uchar * new_data) The temp_file_length is used to calculate new data file length. */ if (chain_append()) - DBUG_RETURN(-1); + goto err; if (open_update_temp_file_if_needed()) - DBUG_RETURN(-1); + goto err; if (my_write(update_temp_file, (uchar*)buffer.ptr(), size, MYF(MY_WME | MY_NABP))) - DBUG_RETURN(-1); + goto err; temp_file_length+= size; + rc= 0; /* UPDATE should never happen on the log tables */ DBUG_ASSERT(!share->is_log_table); - DBUG_RETURN(0); +err: + DBUG_PRINT("info",("rc = %d", rc)); + DBUG_RETURN(rc); } @@ -1050,6 +1073,8 @@ int ha_tina::rnd_init(bool scan) records_is_known= 0; chain_ptr= chain; + init_alloc_root(&blobroot, BLOB_MEMROOT_ALLOC_SIZE, 0); + DBUG_RETURN(0); } @@ -1115,7 +1140,7 @@ void ha_tina::position(const uchar *record) int ha_tina::rnd_pos(uchar * buf, uchar *pos) { DBUG_ENTER("ha_tina::rnd_pos"); - ha_statistic_increment(&SSV::ha_read_rnd_next_count); + ha_statistic_increment(&SSV::ha_read_rnd_count); current_position= (off_t)my_get_ptr(pos,ref_length); DBUG_RETURN(find_current_row(buf)); } @@ -1179,6 +1204,7 @@ int ha_tina::rnd_end() off_t file_buffer_start= 0; DBUG_ENTER("ha_tina::rnd_end"); + free_root(&blobroot, MYF(0)); records_is_known= 1; if ((chain_ptr - chain) > 0) @@ -1350,6 +1376,8 @@ int ha_tina::repair(THD* thd, HA_CHECK_OPT* check_opt) /* set current position to the beginning of the file */ current_position= next_position= 0; + init_alloc_root(&blobroot, BLOB_MEMROOT_ALLOC_SIZE, 0); + /* Read the file row-by-row. If everything is ok, repair is not needed. */ while (!(rc= find_current_row(buf))) { @@ -1358,6 +1386,8 @@ int ha_tina::repair(THD* thd, HA_CHECK_OPT* check_opt) current_position= next_position; } + free_root(&blobroot, MYF(0)); + my_free((char*)buf, MYF(0)); if (rc == HA_ERR_END_OF_FILE) @@ -1535,6 +1565,9 @@ int ha_tina::check(THD* thd, HA_CHECK_OPT* check_opt) local_saved_data_file_length= share->saved_data_file_length; /* set current position to the beginning of the file */ current_position= next_position= 0; + + init_alloc_root(&blobroot, BLOB_MEMROOT_ALLOC_SIZE, 0); + /* Read the file row-by-row. If everything is ok, repair is not needed. */ while (!(rc= find_current_row(buf))) { @@ -1542,6 +1575,8 @@ int ha_tina::check(THD* thd, HA_CHECK_OPT* check_opt) count--; current_position= next_position; } + + free_root(&blobroot, MYF(0)); my_free((char*)buf, MYF(0)); thd_proc_info(thd, old_proc_info); diff --git a/storage/csv/ha_tina.h b/storage/csv/ha_tina.h index 5ce09783b9b..5b4381396fc 100644 --- a/storage/csv/ha_tina.h +++ b/storage/csv/ha_tina.h @@ -82,6 +82,7 @@ class ha_tina: public handler uint32 chain_size; uint local_data_file_version; /* Saved version of the data file used */ bool records_is_known; + MEM_ROOT blobroot; private: bool get_write_pos(off_t *end_pos, tina_set *closest_hole); diff --git a/storage/myisam/ha_myisam.cc b/storage/myisam/ha_myisam.cc index e74464a1834..dfb36700288 100644 --- a/storage/myisam/ha_myisam.cc +++ b/storage/myisam/ha_myisam.cc @@ -1859,6 +1859,7 @@ int ha_myisam::create(const char *name, register TABLE *table_arg, share->avg_row_length); create_info.data_file_name= ha_create_info->data_file_name; create_info.index_file_name= ha_create_info->index_file_name; + create_info.language= share->table_charset->number; if (ha_create_info->options & HA_LEX_CREATE_TMP_TABLE) create_flags|= HA_CREATE_TMP_TABLE; diff --git a/storage/myisam/mi_dynrec.c b/storage/myisam/mi_dynrec.c index 9940cf62204..22fa3d18802 100644 --- a/storage/myisam/mi_dynrec.c +++ b/storage/myisam/mi_dynrec.c @@ -1006,12 +1006,12 @@ uint _mi_rec_pack(MI_INFO *info, register uchar *to, { if (rec->length > 255 && new_length > 127) { - to[0]=(char) ((new_length & 127)+128); - to[1]=(char) (new_length >> 7); - to+=2; - } - else - *to++= (char) new_length; + to[0]= (uchar) ((new_length & 127) + 128); + to[1]= (uchar) (new_length >> 7); + to+=2; + } + else + *to++= (uchar) new_length; memcpy((uchar*) to,pos,(size_t) new_length); to+=new_length; flag|=bit; } @@ -1045,7 +1045,7 @@ uint _mi_rec_pack(MI_INFO *info, register uchar *to, } if ((bit= bit << 1) >= 256) { - *packpos++ = (char) (uchar) flag; + *packpos++= (uchar) flag; bit=1; flag=0; } } @@ -1055,9 +1055,9 @@ uint _mi_rec_pack(MI_INFO *info, register uchar *to, } } if (bit != 1) - *packpos= (char) (uchar) flag; + *packpos= (uchar) flag; if (info->s->calc_checksum) - *to++=(char) info->checksum; + *to++= (uchar) info->checksum; DBUG_PRINT("exit",("packed length: %d",(int) (to-startpos))); DBUG_RETURN((uint) (to-startpos)); } /* _mi_rec_pack */ @@ -1128,12 +1128,14 @@ my_bool _mi_rec_check(MI_INFO *info,const uchar *record, uchar *rec_buff, goto err; if (rec->length > 255 && new_length > 127) { - if (to[0] != (char) ((new_length & 127)+128) || - to[1] != (char) (new_length >> 7)) - goto err; - to+=2; - } - else if (*to++ != (char) new_length) + /* purecov: begin inspected */ + if (to[0] != (uchar) ((new_length & 127) + 128) || + to[1] != (uchar) (new_length >> 7)) + goto err; + to+=2; + /* purecov: end */ + } + else if (*to++ != (uchar) new_length) goto err; to+=new_length; } diff --git a/storage/myisam/mi_open.c b/storage/myisam/mi_open.c index a4f6e1291db..de42bdcd53d 100644 --- a/storage/myisam/mi_open.c +++ b/storage/myisam/mi_open.c @@ -815,8 +815,17 @@ static void setup_key_functions(register MI_KEYDEF *keyinfo) keyinfo->get_key= _mi_get_pack_key; if (keyinfo->seg[0].flag & HA_PACK_KEY) { /* Prefix compression */ + /* + _mi_prefix_search() compares end-space against ASCII blank (' '). + It cannot be used for character sets, that do not encode the + blank character like ASCII does. UCS2 is an example. All + character sets with a fixed width > 1 or a mimimum width > 1 + cannot represent blank like ASCII does. In these cases we have + to use _mi_seq_search() for the search. + */ if (!keyinfo->seg->charset || use_strnxfrm(keyinfo->seg->charset) || - (keyinfo->seg->flag & HA_NULL_PART)) + (keyinfo->seg->flag & HA_NULL_PART) || + (keyinfo->seg->charset->mbminlen > 1)) keyinfo->bin_search=_mi_seq_search; else keyinfo->bin_search=_mi_prefix_search;