diff --git a/mysql-test/r/ctype_filesystem.result b/mysql-test/r/ctype_filesystem.result new file mode 100644 index 00000000000..8a8f0f7f8cc --- /dev/null +++ b/mysql-test/r/ctype_filesystem.result @@ -0,0 +1,11 @@ +SET CHARACTER SET utf8; +SHOW VARIABLES like 'character_sets_dir'; +Variable_name Value +character_sets_dir /ß/ +SHOW VARIABLES like 'character_set_filesystem'; +Variable_name Value +character_set_filesystem latin1 +SHOW VARIABLES like 'character_set_client'; +Variable_name Value +character_set_client utf8 +SET CHARACTER SET default; diff --git a/mysql-test/r/update.result b/mysql-test/r/update.result index b861ec96882..7a51649fac5 100644 --- a/mysql-test/r/update.result +++ b/mysql-test/r/update.result @@ -491,4 +491,15 @@ update t1 join t2 on (t1.a=t2.a) set t1.id=t2.id; affected rows: 127 info: Rows matched: 128 Changed: 127 Warnings: 0 drop table t1,t2; +DROP TABLE IF EXISTS t1; +DROP FUNCTION IF EXISTS f1; +CREATE FUNCTION f1() RETURNS INT RETURN f1(); +CREATE TABLE t1 (i INT); +INSERT INTO t1 VALUES (1); +UPDATE t1 SET i = 3 WHERE f1(); +ERROR HY000: Recursive stored functions and triggers are not allowed. +UPDATE t1 SET i = f1(); +ERROR HY000: Recursive stored functions and triggers are not allowed. +DROP TABLE t1; +DROP FUNCTION f1; End of 5.0 tests diff --git a/mysql-test/r/view.result b/mysql-test/r/view.result index 90530462732..2fefa21eaca 100644 --- a/mysql-test/r/view.result +++ b/mysql-test/r/view.result @@ -625,7 +625,7 @@ drop table t1; create table t1 (a int, b int); create view v1 as select a, sum(b) from t1 group by a; select b from v1 use index (some_index) where b=1; -ERROR HY000: Incorrect usage of index hints and VIEW +ERROR 42000: Key 'some_index' doesn't exist in table 'v1' drop view v1; drop table t1; create table t1 (col1 char(5),col2 char(5)); @@ -3562,11 +3562,11 @@ CREATE TABLE t1 (a INT); INSERT INTO t1 VALUES (1),(2); CREATE VIEW v1 AS SELECT * FROM t1; SELECT * FROM v1 USE KEY(non_existant); -ERROR HY000: Incorrect usage of index hints and VIEW +ERROR 42000: Key 'non_existant' doesn't exist in table 'v1' SELECT * FROM v1 FORCE KEY(non_existant); -ERROR HY000: Incorrect usage of index hints and VIEW +ERROR 42000: Key 'non_existant' doesn't exist in table 'v1' SELECT * FROM v1 IGNORE KEY(non_existant); -ERROR HY000: Incorrect usage of index hints and VIEW +ERROR 42000: Key 'non_existant' doesn't exist in table 'v1' DROP VIEW v1; DROP TABLE t1; CREATE TABLE t1 (a INT NOT NULL AUTO_INCREMENT, b INT NOT NULL DEFAULT 0, @@ -3674,6 +3674,31 @@ DROP VIEW v1; CREATE VIEW v1 AS SELECT 1; DROP VIEW v1; +CREATE TABLE t1 (c1 INT PRIMARY KEY, c2 INT, INDEX (c2)); +INSERT INTO t1 VALUES (1,1), (2,2), (3,3); +SELECT * FROM t1 USE INDEX (PRIMARY) WHERE c1=2; +c1 c2 +2 2 +SELECT * FROM t1 USE INDEX (c2) WHERE c2=2; +c1 c2 +2 2 +CREATE VIEW v1 AS SELECT c1, c2 FROM t1; +SHOW INDEX FROM v1; +Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment +SELECT * FROM v1 USE INDEX (PRIMARY) WHERE c1=2; +ERROR 42000: Key 'PRIMARY' doesn't exist in table 'v1' +SELECT * FROM v1 FORCE INDEX (PRIMARY) WHERE c1=2; +ERROR 42000: Key 'PRIMARY' doesn't exist in table 'v1' +SELECT * FROM v1 IGNORE INDEX (PRIMARY) WHERE c1=2; +ERROR 42000: Key 'PRIMARY' doesn't exist in table 'v1' +SELECT * FROM v1 USE INDEX (c2) WHERE c2=2; +ERROR 42000: Key 'c2' doesn't exist in table 'v1' +SELECT * FROM v1 FORCE INDEX (c2) WHERE c2=2; +ERROR 42000: Key 'c2' doesn't exist in table 'v1' +SELECT * FROM v1 IGNORE INDEX (c2) WHERE c2=2; +ERROR 42000: Key 'c2' doesn't exist in table 'v1' +DROP VIEW v1; +DROP TABLE t1; # ----------------------------------------------------------------- # -- End of 5.0 tests. # ----------------------------------------------------------------- diff --git a/mysql-test/t/ctype_filesystem-master.opt b/mysql-test/t/ctype_filesystem-master.opt new file mode 100644 index 00000000000..cb3427571b5 --- /dev/null +++ b/mysql-test/t/ctype_filesystem-master.opt @@ -0,0 +1,2 @@ +--character-sets-dir=/ß +--character-set-filesystem=latin1 diff --git a/mysql-test/t/ctype_filesystem.test b/mysql-test/t/ctype_filesystem.test new file mode 100644 index 00000000000..30b1607008b --- /dev/null +++ b/mysql-test/t/ctype_filesystem.test @@ -0,0 +1,5 @@ +SET CHARACTER SET utf8; +SHOW VARIABLES like 'character_sets_dir'; +SHOW VARIABLES like 'character_set_filesystem'; +SHOW VARIABLES like 'character_set_client'; +SET CHARACTER SET default; diff --git a/mysql-test/t/update.test b/mysql-test/t/update.test index f79c9e773aa..7d56df259ba 100644 --- a/mysql-test/t/update.test +++ b/mysql-test/t/update.test @@ -430,4 +430,25 @@ drop table t1,t2; connection default; disconnect con1; +# +# Bug #40745: Error during WHERE clause calculation in UPDATE +# leads to an assertion failure +# +--disable_warnings +DROP TABLE IF EXISTS t1; +DROP FUNCTION IF EXISTS f1; +--enable_warnings + +CREATE FUNCTION f1() RETURNS INT RETURN f1(); +CREATE TABLE t1 (i INT); +INSERT INTO t1 VALUES (1); + +--error ER_SP_NO_RECURSION +UPDATE t1 SET i = 3 WHERE f1(); +--error ER_SP_NO_RECURSION +UPDATE t1 SET i = f1(); + +DROP TABLE t1; +DROP FUNCTION f1; + --echo End of 5.0 tests diff --git a/mysql-test/t/view.test b/mysql-test/t/view.test index 05aa76d492d..1ea248f1fe9 100644 --- a/mysql-test/t/view.test +++ b/mysql-test/t/view.test @@ -510,7 +510,7 @@ drop table t1; # create table t1 (a int, b int); create view v1 as select a, sum(b) from t1 group by a; ---error ER_WRONG_USAGE +--error ER_KEY_DOES_NOT_EXITS select b from v1 use index (some_index) where b=1; drop view v1; drop table t1; @@ -3421,11 +3421,11 @@ drop table t1; CREATE TABLE t1 (a INT); INSERT INTO t1 VALUES (1),(2); CREATE VIEW v1 AS SELECT * FROM t1; ---error ER_WRONG_USAGE +--error ER_KEY_DOES_NOT_EXITS SELECT * FROM v1 USE KEY(non_existant); ---error ER_WRONG_USAGE +--error ER_KEY_DOES_NOT_EXITS SELECT * FROM v1 FORCE KEY(non_existant); ---error ER_WRONG_USAGE +--error ER_KEY_DOES_NOT_EXITS SELECT * FROM v1 IGNORE KEY(non_existant); DROP VIEW v1; @@ -3564,6 +3564,32 @@ DROP VIEW v1; CREATE VIEW v1 AS SELECT 1; DROP VIEW v1; +# +# Bug #33461: SELECT ... FROM USE INDEX (...) throws an error +# + +CREATE TABLE t1 (c1 INT PRIMARY KEY, c2 INT, INDEX (c2)); +INSERT INTO t1 VALUES (1,1), (2,2), (3,3); +SELECT * FROM t1 USE INDEX (PRIMARY) WHERE c1=2; +SELECT * FROM t1 USE INDEX (c2) WHERE c2=2; + +CREATE VIEW v1 AS SELECT c1, c2 FROM t1; +SHOW INDEX FROM v1; +--error ER_KEY_DOES_NOT_EXITS +SELECT * FROM v1 USE INDEX (PRIMARY) WHERE c1=2; +--error ER_KEY_DOES_NOT_EXITS +SELECT * FROM v1 FORCE INDEX (PRIMARY) WHERE c1=2; +--error ER_KEY_DOES_NOT_EXITS +SELECT * FROM v1 IGNORE INDEX (PRIMARY) WHERE c1=2; +--error ER_KEY_DOES_NOT_EXITS +SELECT * FROM v1 USE INDEX (c2) WHERE c2=2; +--error ER_KEY_DOES_NOT_EXITS +SELECT * FROM v1 FORCE INDEX (c2) WHERE c2=2; +--error ER_KEY_DOES_NOT_EXITS +SELECT * FROM v1 IGNORE INDEX (c2) WHERE c2=2; + +DROP VIEW v1; +DROP TABLE t1; --echo # ----------------------------------------------------------------- --echo # -- End of 5.0 tests. diff --git a/sql/mysqld.cc b/sql/mysqld.cc index a3ef599e1f9..e6980318a66 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -3377,12 +3377,14 @@ static int init_common_variables(const char *conf_file_name, int argc, sys_init_connect.value_length= strlen(opt_init_connect); else sys_init_connect.value=my_strdup("",MYF(0)); + sys_init_connect.is_os_charset= TRUE; sys_init_slave.value_length= 0; if ((sys_init_slave.value= opt_init_slave)) sys_init_slave.value_length= strlen(opt_init_slave); else sys_init_slave.value=my_strdup("",MYF(0)); + sys_init_slave.is_os_charset= TRUE; /* check log options and issue warnings if needed */ if (opt_log && opt_logname && !(log_output_options & LOG_FILE) && diff --git a/sql/set_var.cc b/sql/set_var.cc index 07ab82c77e0..a371c1113ef 100644 --- a/sql/set_var.cc +++ b/sql/set_var.cc @@ -176,14 +176,14 @@ static sys_var_bool_ptr sys_automatic_sp_privileges(&vars, "automatic_sp_privile static sys_var_const sys_back_log(&vars, "back_log", OPT_GLOBAL, SHOW_LONG, (uchar*) &back_log); -static sys_var_const_str sys_basedir(&vars, "basedir", mysql_home); +static sys_var_const_os_str sys_basedir(&vars, "basedir", mysql_home); static sys_var_long_ptr sys_binlog_cache_size(&vars, "binlog_cache_size", &binlog_cache_size); static sys_var_thd_binlog_format sys_binlog_format(&vars, "binlog_format", &SV::binlog_format); static sys_var_thd_ulong sys_bulk_insert_buff_size(&vars, "bulk_insert_buffer_size", &SV::bulk_insert_buff_size); -static sys_var_const sys_character_sets_dir(&vars, +static sys_var_const_os sys_character_sets_dir(&vars, "character_sets_dir", OPT_GLOBAL, SHOW_CHAR, (uchar*) @@ -233,7 +233,7 @@ static sys_var_long_ptr sys_concurrent_insert(&vars, "concurrent_insert", &myisam_concurrent_insert); static sys_var_long_ptr sys_connect_timeout(&vars, "connect_timeout", &connect_timeout); -static sys_var_const_str sys_datadir(&vars, "datadir", mysql_real_data_home); +static sys_var_const_os_str sys_datadir(&vars, "datadir", mysql_real_data_home); #ifndef DBUG_OFF static sys_var_thd_dbug sys_dbug(&vars, "debug"); #endif @@ -466,7 +466,7 @@ static sys_var_thd_ulong sys_optimizer_search_depth(&vars, "optimizer_sea static sys_var_const sys_pid_file(&vars, "pid_file", OPT_GLOBAL, SHOW_CHAR, (uchar*) pidfile_name); -static sys_var_const sys_plugin_dir(&vars, "plugin_dir", +static sys_var_const_os sys_plugin_dir(&vars, "plugin_dir", OPT_GLOBAL, SHOW_CHAR, (uchar*) opt_plugin_dir); static sys_var_const sys_port(&vars, "port", @@ -538,7 +538,7 @@ static sys_var_const sys_thread_concurrency(&vars, "thread_concurrency", static sys_var_const sys_thread_stack(&vars, "thread_stack", OPT_GLOBAL, SHOW_LONG, (uchar*) &my_thread_stack_size); -static sys_var_readonly sys_tmpdir(&vars, "tmpdir", OPT_GLOBAL, SHOW_CHAR, get_tmpdir); +static sys_var_readonly_os sys_tmpdir(&vars, "tmpdir", OPT_GLOBAL, SHOW_CHAR, get_tmpdir); static sys_var_thd_ulong sys_trans_alloc_block_size(&vars, "transaction_alloc_block_size", &SV::trans_alloc_block_size, 0, fix_trans_mem_root); @@ -589,17 +589,17 @@ static sys_var_thd_sql_mode sys_sql_mode(&vars, "sql_mode", #ifdef HAVE_OPENSSL extern char *opt_ssl_ca, *opt_ssl_capath, *opt_ssl_cert, *opt_ssl_cipher, *opt_ssl_key; -static sys_var_const_str_ptr sys_ssl_ca(&vars, "ssl_ca", &opt_ssl_ca); -static sys_var_const_str_ptr sys_ssl_capath(&vars, "ssl_capath", &opt_ssl_capath); -static sys_var_const_str_ptr sys_ssl_cert(&vars, "ssl_cert", &opt_ssl_cert); -static sys_var_const_str_ptr sys_ssl_cipher(&vars, "ssl_cipher", &opt_ssl_cipher); -static sys_var_const_str_ptr sys_ssl_key(&vars, "ssl_key", &opt_ssl_key); +static sys_var_const_os_str_ptr sys_ssl_ca(&vars, "ssl_ca", &opt_ssl_ca); +static sys_var_const_os_str_ptr sys_ssl_capath(&vars, "ssl_capath", &opt_ssl_capath); +static sys_var_const_os_str_ptr sys_ssl_cert(&vars, "ssl_cert", &opt_ssl_cert); +static sys_var_const_os_str_ptr sys_ssl_cipher(&vars, "ssl_cipher", &opt_ssl_cipher); +static sys_var_const_os_str_ptr sys_ssl_key(&vars, "ssl_key", &opt_ssl_key); #else -static sys_var_const_str sys_ssl_ca(&vars, "ssl_ca", NULL); -static sys_var_const_str sys_ssl_capath(&vars, "ssl_capath", NULL); -static sys_var_const_str sys_ssl_cert(&vars, "ssl_cert", NULL); -static sys_var_const_str sys_ssl_cipher(&vars, "ssl_cipher", NULL); -static sys_var_const_str sys_ssl_key(&vars, "ssl_key", NULL); +static sys_var_const_os_str sys_ssl_ca(&vars, "ssl_ca", NULL); +static sys_var_const_os_str sys_ssl_capath(&vars, "ssl_capath", NULL); +static sys_var_const_os_str sys_ssl_cert(&vars, "ssl_cert", NULL); +static sys_var_const_os_str sys_ssl_cipher(&vars, "ssl_cipher", NULL); +static sys_var_const_os_str sys_ssl_key(&vars, "ssl_key", NULL); #endif static sys_var_thd_enum sys_updatable_views_with_limit(&vars, "updatable_views_with_limit", @@ -936,6 +936,7 @@ bool update_sys_var_str(sys_var_str *var_str, rw_lock_t *var_mutex, old_value= var_str->value; var_str->value= res; var_str->value_length= new_length; + var_str->is_os_charset= FALSE; rw_unlock(var_mutex); my_free(old_value, MYF(MY_ALLOW_ZERO_PTR)); return 0; @@ -1805,6 +1806,13 @@ err: } +CHARSET_INFO *sys_var::charset(THD *thd) +{ + return is_os_charset ? thd->variables.character_set_filesystem : + system_charset_info; +} + + bool sys_var_thd_enum::update(THD *thd, set_var *var) { if (var->type == OPT_GLOBAL) diff --git a/sql/set_var.h b/sql/set_var.h index 6b62d62706e..2e58b2faa7d 100644 --- a/sql/set_var.h +++ b/sql/set_var.h @@ -71,6 +71,14 @@ public: sys_after_update_func after_update; bool no_support_one_shot; + /* + true if the value is in character_set_filesystem, + false otherwise. + Note that we can't use a pointer to the charset as the system var is + instantiated in global scope and the charset pointers are initialized + later. + */ + bool is_os_charset; sys_var(const char *name_arg, sys_after_update_func func= NULL, Binlog_status_enum binlog_status_arg= NOT_IN_BINLOG) :name(name_arg), after_update(func), no_support_one_shot(1), @@ -107,6 +115,7 @@ public: { return option_limits == 0; } virtual bool is_struct() { return 0; } virtual bool is_readonly() const { return 0; } + CHARSET_INFO *charset(THD *thd); virtual sys_var_pluginvar *cast_pluginvar() { return 0; } protected: @@ -291,6 +300,18 @@ public: }; +class sys_var_const_os_str: public sys_var_const_str +{ +public: + sys_var_const_os_str(sys_var_chain *chain, const char *name_arg, + const char *value_arg) + :sys_var_const_str(chain, name_arg, value_arg) + { + is_os_charset= TRUE; + } +}; + + class sys_var_const_str_ptr :public sys_var { public: @@ -320,6 +341,18 @@ public: }; +class sys_var_const_os_str_ptr :public sys_var_const_str_ptr +{ +public: + sys_var_const_os_str_ptr(sys_var_chain *chain, const char *name_arg, + char **value_arg) + :sys_var_const_str_ptr(chain, name_arg, value_arg) + { + is_os_charset= TRUE; + } +}; + + class sys_var_enum :public sys_var { uint *value; @@ -929,6 +962,19 @@ public: }; +class sys_var_readonly_os: public sys_var_readonly +{ +public: + sys_var_readonly_os(sys_var_chain *chain, const char *name_arg, enum_var_type type, + SHOW_TYPE show_type_arg, + sys_value_ptr_func value_ptr_func_arg) + :sys_var_readonly(chain, name_arg, type, show_type_arg, value_ptr_func_arg) + { + is_os_charset= TRUE; + } +}; + + /** Global-only, read-only variable. E.g. command line option. */ @@ -957,6 +1003,22 @@ public: }; +class sys_var_const_os: public sys_var_const +{ +public: + enum_var_type var_type; + SHOW_TYPE show_type_value; + uchar *ptr; + sys_var_const_os(sys_var_chain *chain, const char *name_arg, + enum_var_type type, + SHOW_TYPE show_type_arg, uchar *ptr_arg) + :sys_var_const(chain, name_arg, type, show_type_arg, ptr_arg) + { + is_os_charset= TRUE; + } +}; + + class sys_var_have_option: public sys_var { protected: diff --git a/sql/sql_show.cc b/sql/sql_show.cc index 76496db4817..28e8c028362 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -2087,6 +2087,7 @@ static bool show_status_array(THD *thd, const char *wild, COND *partial_cond= 0; enum_check_fields save_count_cuted_fields= thd->count_cuted_fields; bool res= FALSE; + CHARSET_INFO *charset= system_charset_info; DBUG_ENTER("show_status_array"); thd->count_cuted_fields= CHECK_FIELD_WARN; @@ -2135,9 +2136,10 @@ static bool show_status_array(THD *thd, const char *wild, if (show_type == SHOW_SYS) { - show_type= ((sys_var*) value)->show_type(); - value= (char*) ((sys_var*) value)->value_ptr(thd, value_type, - &null_lex_str); + sys_var *var= ((sys_var *) value); + show_type= var->show_type(); + value= (char*) var->value_ptr(thd, value_type, &null_lex_str); + charset= var->charset(thd); } pos= end= buff; @@ -2213,7 +2215,7 @@ static bool show_status_array(THD *thd, const char *wild, DBUG_ASSERT(0); break; } - table->field[1]->store(pos, (uint32) (end - pos), system_charset_info); + table->field[1]->store(pos, (uint32) (end - pos), charset); thd->count_cuted_fields= CHECK_FIELD_IGNORE; table->field[1]->set_notnull(); diff --git a/sql/sql_update.cc b/sql/sql_update.cc index 4fbf08c44d3..dbdd30552ec 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -715,6 +715,11 @@ int mysql_update(THD *thd, else table->file->unlock_row(); thd->row_count++; + if (thd->is_error()) + { + error= 1; + break; + } } dup_key_found= 0; /* diff --git a/sql/sql_view.cc b/sql/sql_view.cc index 7b5a4ec17ca..be66f7c2d80 100644 --- a/sql/sql_view.cc +++ b/sql/sql_view.cc @@ -1049,8 +1049,9 @@ bool mysql_make_view(THD *thd, File_parser *parser, TABLE_LIST *table, if (table->index_hints && table->index_hints->elements) { - my_error(ER_WRONG_USAGE, MYF(0), "index hints", "VIEW"); - DBUG_RETURN(TRUE); + my_error(ER_KEY_DOES_NOT_EXITS, MYF(0), + table->index_hints->head()->key_name.str, table->table_name); + DBUG_RETURN(TRUE); } /* check loop via view definition */