From d02b8a3bcc2f3f0d088a8f2dfb45a15c79d56833 Mon Sep 17 00:00:00 2001 From: Kristofer Pettersson Date: Tue, 14 Oct 2008 15:41:35 +0200 Subject: [PATCH 001/219] Bug#37416 When SQL_NO_CACHE is used, MySQL still lookup into the query cache The query cache module did not check for the SQL_NO_CACHE keyword before attempting to query the hash lookup table. This had a small performance impact. By introducing a check on the query string before obtaining the hash mutex we can gain some performance if the SQL_NO_CACHE directive is used often. --- sql/sql_cache.cc | 47 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/sql/sql_cache.cc b/sql/sql_cache.cc index b487f092f75..b4fe1e65bbc 100644 --- a/sql/sql_cache.cc +++ b/sql/sql_cache.cc @@ -363,6 +363,43 @@ TYPELIB query_cache_type_typelib= array_elements(query_cache_type_names)-1,"", query_cache_type_names, NULL }; + +/** + Helper function for determine if a SELECT statement has a SQL_NO_CACHE + directive. + + @param sql A pointer to the first white space character after SELECT + + @return + @retval TRUE The character string contains SQL_NO_CACHE + @retval FALSE No directive found. +*/ + +static bool has_no_cache_directive(char *sql) +{ + int i=0; + while (sql[i] == ' ') + ++i; + + if (my_toupper(system_charset_info, sql[i]) == 'S' && + my_toupper(system_charset_info, sql[i+1]) == 'Q' && + my_toupper(system_charset_info, sql[i+2]) == 'L' && + my_toupper(system_charset_info, sql[i+3]) == '_' && + my_toupper(system_charset_info, sql[i+4]) == 'N' && + my_toupper(system_charset_info, sql[i+5]) == 'O' && + my_toupper(system_charset_info, sql[i+6]) == '_' && + my_toupper(system_charset_info, sql[i+7]) == 'C' && + my_toupper(system_charset_info, sql[i+8]) == 'A' && + my_toupper(system_charset_info, sql[i+9]) == 'C' && + my_toupper(system_charset_info, sql[i+10]) == 'H' && + my_toupper(system_charset_info, sql[i+11]) == 'E' && + my_toupper(system_charset_info, sql[i+12]) == ' ') + return TRUE; + + return FALSE; +} + + /***************************************************************************** Query_cache_block_table method(s) *****************************************************************************/ @@ -1085,6 +1122,16 @@ Query_cache::send_result_to_client(THD *thd, char *sql, uint query_length) DBUG_PRINT("qcache", ("The statement is not a SELECT; Not cached")); goto err; } + + if (query_length > 20 && has_no_cache_directive(&sql[i+6])) + { + /* + We do not increase 'refused' statistics here since it will be done + later when the query is parsed. + */ + DBUG_PRINT("qcache", ("The statement has a SQL_NO_CACHE directive")); + goto err; + } } #ifdef __WIN__ From be66e43dabe2681705a9adfe3d385496dc827882 Mon Sep 17 00:00:00 2001 From: Alexey Botchkov Date: Mon, 27 Oct 2008 13:57:59 +0400 Subject: [PATCH 002/219] Bug#39289 libmysqld.a calls exit() upon error Several functions (mostly in mysqld.cc) directly call exit() function in case of errors, which is not a desired behaviour expecially in the embedded-server library. Fixed by making these functions return error sign instead of exiting. per-file comments: include/my_getopt.h Bug#39289 libmysqld.a calls exit() upon error added 'error' retvalue for my_getopt_register_get_addr libmysqld/lib_sql.cc Bug#39289 libmysqld.a calls exit() upon error unireg_clear() function implemented mysys/default.c Bug#39289 libmysqld.a calls exit() upon error error returned instead of exit() call mysys/mf_tempdir.c Bug#39289 libmysqld.a calls exit() upon error free_tmpdir() - fixed so it's not produce crash on uninitialized tmpdir structure mysys/my_getopt.c Bug#39289 libmysqld.a calls exit() upon error error returned instead of exit() call sql/mysql_priv.h Bug#39289 libmysqld.a calls exit() upon error unireg_abort definition fixed for the embedded server sql/mysqld.cc Bug#39289 libmysqld.a calls exit() upon error various functions fixed error returned instead of exit() call --- include/my_getopt.h | 2 +- libmysqld/lib_sql.cc | 9 +++ mysys/default.c | 10 +-- mysys/mf_tempdir.c | 7 +- mysys/my_getopt.c | 33 +++++---- sql/mysql_priv.h | 3 +- sql/mysqld.cc | 163 ++++++++++++++++++++++++++----------------- 7 files changed, 142 insertions(+), 85 deletions(-) diff --git a/include/my_getopt.h b/include/my_getopt.h index 50ebe9190d8..7cbad607aac 100644 --- a/include/my_getopt.h +++ b/include/my_getopt.h @@ -72,7 +72,7 @@ extern void my_cleanup_options(const struct my_option *options); extern void my_print_help(const struct my_option *options); extern void my_print_variables(const struct my_option *options); extern void my_getopt_register_get_addr(uchar ** (*func_addr)(const char *, uint, - const struct my_option *)); + const struct my_option *, int *)); ulonglong getopt_ull_limit_value(ulonglong num, const struct my_option *optp, my_bool *fix); diff --git a/libmysqld/lib_sql.cc b/libmysqld/lib_sql.cc index 6e82812239e..4888ebca533 100644 --- a/libmysqld/lib_sql.cc +++ b/libmysqld/lib_sql.cc @@ -43,6 +43,15 @@ extern char mysql_server_last_error[MYSQL_ERRMSG_SIZE]; static my_bool emb_read_query_result(MYSQL *mysql); +extern "C" void unireg_clear(int exit_code) +{ + DBUG_ENTER("unireg_clear"); + clean_up(!opt_help && (exit_code || !opt_bootstrap)); /* purecov: inspected */ + my_end(opt_endinfo ? MY_CHECK_ERROR | MY_GIVE_INFO : 0); + DBUG_VOID_RETURN; +} + + /* Reads error information from the MYSQL_DATA and puts it into proper MYSQL members diff --git a/mysys/default.c b/mysys/default.c index 6b2b31d43ec..c7e1e513e1e 100644 --- a/mysys/default.c +++ b/mysys/default.c @@ -144,6 +144,7 @@ static char *remove_end_comment(char *ptr); RETURN 0 ok 1 given cinf_file doesn't exist + 2 out of memory The global variable 'my_defaults_group_suffix' is updated with value for --defaults_group_suffix @@ -190,7 +191,7 @@ int my_search_option_files(const char *conf_file, int *argc, char ***argv, if (!(extra_groups= (const char**)alloc_root(ctx->alloc, (2*group->count+1)*sizeof(char*)))) - goto err; + DBUG_RETURN(2); for (i= 0; i < group->count; i++) { @@ -199,7 +200,7 @@ int my_search_option_files(const char *conf_file, int *argc, char ***argv, len= strlen(extra_groups[i]); if (!(ptr= alloc_root(ctx->alloc, len+instance_len+1))) - goto err; + DBUG_RETURN(2); extra_groups[i+group->count]= ptr; @@ -254,12 +255,11 @@ int my_search_option_files(const char *conf_file, int *argc, char ***argv, } } - DBUG_RETURN(error); + DBUG_RETURN(0); err: fprintf(stderr,"Fatal error in defaults handling. Program aborted\n"); - exit(1); - return 0; /* Keep compiler happy */ + DBUG_RETURN(1); } diff --git a/mysys/mf_tempdir.c b/mysys/mf_tempdir.c index b2c18c74347..6ad0f95a342 100644 --- a/mysys/mf_tempdir.c +++ b/mysys/mf_tempdir.c @@ -85,8 +85,11 @@ char *my_tmpdir(MY_TMPDIR *tmpdir) void free_tmpdir(MY_TMPDIR *tmpdir) { uint i; - for (i=0; i<=tmpdir->max; i++) - my_free(tmpdir->list[i], MYF(0)); + if (tmpdir->full_list.elements) + { + for (i=0; i<=tmpdir->max; i++) + my_free(tmpdir->list[i], MYF(0)); + } delete_dynamic(&tmpdir->full_list); pthread_mutex_destroy(&tmpdir->mutex); } diff --git a/mysys/my_getopt.c b/mysys/my_getopt.c index 6a7ee748930..5c7e3ecef34 100644 --- a/mysys/my_getopt.c +++ b/mysys/my_getopt.c @@ -100,10 +100,10 @@ static void default_reporter(enum loglevel level, one. Call function 'get_one_option()' once for each option. */ -static uchar** (*getopt_get_addr)(const char *, uint, const struct my_option *); +static uchar** (*getopt_get_addr)(const char *, uint, const struct my_option *, int *); void my_getopt_register_get_addr(uchar** (*func_addr)(const char *, uint, - const struct my_option *)) + const struct my_option *, int *)) { getopt_get_addr= func_addr; } @@ -362,8 +362,12 @@ int handle_options(int *argc, char ***argv, my_progname, optp->name); return EXIT_NO_ARGUMENT_ALLOWED; } + error= 0; value= optp->var_type & GET_ASK_ADDR ? - (*getopt_get_addr)(key_name, (uint) strlen(key_name), optp) : optp->value; + (*getopt_get_addr)(key_name, (uint) strlen(key_name), optp, &error) : + optp->value; + if (error) + return error; if (optp->arg_type == NO_ARG) { @@ -397,9 +401,10 @@ invalid value '%s'", my_progname, optp->name, optend); continue; } - get_one_option(optp->id, optp, - *((my_bool*) value) ? - (char*) "1" : disabled_my_option); + if (get_one_option(optp->id, optp, + *((my_bool*) value) ? + (char*) "1" : disabled_my_option)) + return EXIT_UNSPECIFIED_ERROR; continue; } argument= optend; @@ -457,7 +462,8 @@ invalid value '%s'", optp->arg_type == NO_ARG) { *((my_bool*) optp->value)= (my_bool) 1; - get_one_option(optp->id, optp, argument); + if (get_one_option(optp->id, optp, argument)) + return EXIT_UNSPECIFIED_ERROR; continue; } else if (optp->arg_type == REQUIRED_ARG || @@ -476,7 +482,8 @@ invalid value '%s'", { if (optp->var_type == GET_BOOL) *((my_bool*) optp->value)= (my_bool) 1; - get_one_option(optp->id, optp, argument); + if (get_one_option(optp->id, optp, argument)) + return EXIT_UNSPECIFIED_ERROR; continue; } /* Check if there are more arguments after this one */ @@ -501,7 +508,8 @@ invalid value '%s'", my_progname, argument, optp->name); return error; } - get_one_option(optp->id, optp, argument); + if (get_one_option(optp->id, optp, argument)) + return EXIT_UNSPECIFIED_ERROR; break; } } @@ -524,7 +532,8 @@ invalid value '%s'", my_progname, argument, optp->name); return error; } - get_one_option(optp->id, optp, argument); + if (get_one_option(optp->id, optp, argument)) + return EXIT_UNSPECIFIED_ERROR; (*argc)--; /* option handled (short or long), decrease argument count */ } @@ -1085,7 +1094,7 @@ static void init_variables(const struct my_option *options, if (options->value) init_one_value(options, options->value, options->def_value); if (options->var_type & GET_ASK_ADDR && - (variable= (*getopt_get_addr)("", 0, options))) + (variable= (*getopt_get_addr)("", 0, options, 0))) init_one_value(options, variable, options->def_value); } DBUG_VOID_RETURN; @@ -1189,7 +1198,7 @@ void my_print_variables(const struct my_option *options) for (optp= options; optp->id; optp++) { uchar* *value= (optp->var_type & GET_ASK_ADDR ? - (*getopt_get_addr)("", 0, optp) : optp->value); + (*getopt_get_addr)("", 0, optp, 0) : optp->value); if (value) { printf("%s ", optp->name); diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index d11f2838e3a..192da33422e 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -2406,7 +2406,8 @@ extern "C" void unireg_abort(int exit_code) __attribute__((noreturn)); void kill_delayed_threads(void); bool check_stack_overrun(THD *thd, long margin, uchar *dummy); #else -#define unireg_abort(exit_code) DBUG_RETURN(exit_code) +extern "C" void unireg_clear(int exit_code); +#define unireg_abort(exit_code) do { unireg_clear(exit_code); DBUG_RETURN(exit_code); } while(0) inline void kill_delayed_threads(void) {} #define check_stack_overrun(A, B, C) 0 #endif diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 76deffec789..601bdcaeaa5 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -733,13 +733,13 @@ uint connection_count= 0; /* Function declarations */ pthread_handler_t signal_hand(void *arg); -static void mysql_init_variables(void); -static void get_options(int *argc,char **argv); +static int mysql_init_variables(void); +static int get_options(int *argc,char **argv); extern "C" my_bool mysqld_get_one_option(int, const struct my_option *, char *); static void set_server_version(void); static int init_thread_environment(); static char *get_relative_path(const char *path); -static void fix_paths(void); +static int fix_paths(void); pthread_handler_t handle_connections_sockets(void *arg); pthread_handler_t kill_server_thread(void *arg); static void bootstrap(FILE *file); @@ -753,7 +753,7 @@ pthread_handler_t handle_connections_shared_memory(void *arg); pthread_handler_t handle_slave(void *arg); static ulong find_bit_type(const char *x, TYPELIB *bit_lib); static ulong find_bit_type_or_exit(const char *x, TYPELIB *bit_lib, - const char *option); + const char *option, int *error); static void clean_up(bool print_message); static int test_if_case_insensitive(const char *dir_name); @@ -1187,7 +1187,8 @@ extern "C" void unireg_abort(int exit_code) my_end(opt_endinfo ? MY_CHECK_ERROR | MY_GIVE_INFO : 0); exit(exit_code); /* purecov: inspected */ } -#endif + +#endif /*EMBEDDED_LIBRARY*/ void clean_up(bool print_message) @@ -3141,12 +3142,12 @@ static int init_common_variables(const char *conf_file_name, int argc, if (!rpl_filter || !binlog_filter) { sql_perror("Could not allocate replication and binlog filters"); - exit(1); + return 1; } - if (init_thread_environment()) + if (init_thread_environment() || + mysql_init_variables()) return 1; - mysql_init_variables(); #ifdef HAVE_TZNAME { @@ -3222,7 +3223,8 @@ static int init_common_variables(const char *conf_file_name, int argc, load_defaults(conf_file_name, groups, &argc, &argv); defaults_argv=argv; defaults_argc=argc; - get_options(&defaults_argc, defaults_argv); + if (get_options(&defaults_argc, defaults_argv)) + return 1; set_server_version(); DBUG_PRINT("info",("%s Ver %s for %s on %s\n",my_progname, @@ -7347,6 +7349,8 @@ SHOW_VAR status_vars[]= { {NullS, NullS, SHOW_LONG} }; +#ifndef EMBEDDED_LIBRARY + static void print_version(void) { set_server_version(); @@ -7358,7 +7362,6 @@ static void print_version(void) server_version,SYSTEM_TYPE,MACHINE_TYPE, MYSQL_COMPILATION_COMMENT); } -#ifndef EMBEDDED_LIBRARY static void usage(void) { if (!(default_charset_info= get_charset_by_csname(default_character_set_name, @@ -7423,8 +7426,9 @@ To see what values a running MySQL server is using, type\n\ as these are initialized by my_getopt. */ -static void mysql_init_variables(void) +static int mysql_init_variables(void) { + int error; /* Things reset to zero */ opt_skip_slave_start= opt_reckless_slave = 0; mysql_home[0]= pidfile_name[0]= log_error_file[0]= 0; @@ -7481,7 +7485,10 @@ static void mysql_init_variables(void) delay_key_write_options= (uint) DELAY_KEY_WRITE_ON; slave_exec_mode_options= 0; slave_exec_mode_options= (uint) - find_bit_type_or_exit(slave_exec_mode_str, &slave_exec_mode_typelib, NULL); + find_bit_type_or_exit(slave_exec_mode_str, &slave_exec_mode_typelib, NULL, + &error); + if (error) + return 1; opt_specialflag= SPECIAL_ENGLISH; unix_sock= ip_sock= INVALID_SOCKET; mysql_home_ptr= mysql_home; @@ -7504,7 +7511,7 @@ static void mysql_init_variables(void) key_caches.empty(); if (!(dflt_key_cache= get_or_create_key_cache(default_key_cache_base.str, default_key_cache_base.length))) - exit(1); + return 1; /* set key_cache_hash.default_value = dflt_key_cache */ multi_keycache_init(); @@ -7647,6 +7654,7 @@ static void mysql_init_variables(void) tmpenv = DEFAULT_MYSQL_HOME; (void) strmake(mysql_home, tmpenv, sizeof(mysql_home)-1); #endif + return 0; } @@ -7655,6 +7663,8 @@ mysqld_get_one_option(int optid, const struct my_option *opt __attribute__((unused)), char *argument) { + int error; + switch(optid) { case '#': #ifndef DBUG_OFF @@ -7700,7 +7710,9 @@ mysqld_get_one_option(int optid, break; case OPT_SLAVE_EXEC_MODE: slave_exec_mode_options= (uint) - find_bit_type_or_exit(argument, &slave_exec_mode_typelib, ""); + find_bit_type_or_exit(argument, &slave_exec_mode_typelib, "", &error); + if (error) + return 1; break; #endif case OPT_SAFEMALLOC_MEM_LIMIT: @@ -7709,9 +7721,11 @@ mysqld_get_one_option(int optid, #endif break; #include +#ifndef EMBEDDED_LIBRARY case 'V': print_version(); exit(0); +#endif /*EMBEDDED_LIBRARY*/ case 'W': if (!argument) global_system_variables.log_warnings++; @@ -7763,18 +7777,16 @@ mysqld_get_one_option(int optid, if (!(p= strstr(argument, "->"))) { - fprintf(stderr, - "Bad syntax in replicate-rewrite-db - missing '->'!\n"); - exit(1); + sql_print_error("Bad syntax in replicate-rewrite-db - missing '->'!\n"); + return 1; } val= p--; while (my_isspace(mysqld_charset, *p) && p > argument) *p-- = 0; if (p == argument) { - fprintf(stderr, - "Bad syntax in replicate-rewrite-db - empty FROM db!\n"); - exit(1); + sql_print_error("Bad syntax in replicate-rewrite-db - empty FROM db!\n"); + return 1; } *val= 0; val+= 2; @@ -7782,9 +7794,8 @@ mysqld_get_one_option(int optid, *val++; if (!*val) { - fprintf(stderr, - "Bad syntax in replicate-rewrite-db - empty TO db!\n"); - exit(1); + sql_print_error("Bad syntax in replicate-rewrite-db - empty TO db!\n"); + return 1; } rpl_filter->add_db_rewrite(key, val); @@ -7812,8 +7823,8 @@ mysqld_get_one_option(int optid, { if (rpl_filter->add_do_table(argument)) { - fprintf(stderr, "Could not add do table rule '%s'!\n", argument); - exit(1); + sql_print_error("Could not add do table rule '%s'!\n", argument); + return 1; } break; } @@ -7821,8 +7832,8 @@ mysqld_get_one_option(int optid, { if (rpl_filter->add_wild_do_table(argument)) { - fprintf(stderr, "Could not add do table rule '%s'!\n", argument); - exit(1); + sql_print_error("Could not add do table rule '%s'!\n", argument); + return 1; } break; } @@ -7830,8 +7841,8 @@ mysqld_get_one_option(int optid, { if (rpl_filter->add_wild_ignore_table(argument)) { - fprintf(stderr, "Could not add ignore table rule '%s'!\n", argument); - exit(1); + sql_print_error("Could not add ignore table rule '%s'!\n", argument); + return 1; } break; } @@ -7839,8 +7850,8 @@ mysqld_get_one_option(int optid, { if (rpl_filter->add_ignore_table(argument)) { - fprintf(stderr, "Could not add ignore table rule '%s'!\n", argument); - exit(1); + sql_print_error("Could not add ignore table rule '%s'!\n", argument); + return 1; } break; } @@ -7863,7 +7874,9 @@ mysqld_get_one_option(int optid, { log_output_str= argument; log_output_options= - find_bit_type_or_exit(argument, &log_output_typelib, opt->name); + find_bit_type_or_exit(argument, &log_output_typelib, opt->name, &error); + if (error) + return 1; } break; } @@ -7873,7 +7886,7 @@ mysqld_get_one_option(int optid, sql_perror("Event scheduler is not supported in embedded build."); #else if (Events::set_opt_event_scheduler(argument)) - exit(1); + return 1; #endif break; case (int) OPT_SKIP_NEW: @@ -7912,7 +7925,7 @@ mysqld_get_one_option(int optid, case (int) OPT_SKIP_NETWORKING: #if defined(__NETWARE__) sql_perror("Can't start server: skip-networking option is currently not supported on NetWare"); - exit(1); + return 1; #endif opt_disable_networking=1; mysqld_port=0; @@ -7942,14 +7955,14 @@ mysqld_get_one_option(int optid, if (gethostname(myhostname,sizeof(myhostname)) < 0) { sql_perror("Can't start server: cannot get my own hostname!"); - exit(1); + return 1; } ent=gethostbyname(myhostname); } if (!ent) { sql_perror("Can't start server: cannot resolve hostname!"); - exit(1); + return 1; } my_bind_addr = (ulong) ((in_addr*)ent->h_addr_list[0])->s_addr; } @@ -8083,7 +8096,10 @@ mysqld_get_one_option(int optid, { myisam_recover_options_str=argument; myisam_recover_options= - find_bit_type_or_exit(argument, &myisam_recover_typelib, opt->name); + find_bit_type_or_exit(argument, &myisam_recover_typelib, opt->name, + &error); + if (error) + return 1; } ha_open_options|=HA_OPEN_ABORT_IF_CRASHED; break; @@ -8128,7 +8144,9 @@ mysqld_get_one_option(int optid, { sql_mode_str= argument; global_system_variables.sql_mode= - find_bit_type_or_exit(argument, &sql_mode_typelib, opt->name); + find_bit_type_or_exit(argument, &sql_mode_typelib, opt->name, &error); + if (error) + return 1; global_system_variables.sql_mode= fix_sql_mode(global_system_variables. sql_mode); break; @@ -8147,7 +8165,7 @@ mysqld_get_one_option(int optid, if (ft_boolean_check_syntax_string((uchar*) argument)) { fprintf(stderr, "Invalid ft-boolean-syntax string: %s\n", argument); - exit(1); + return 1; } strmake(ft_boolean_syntax, argument, sizeof(ft_boolean_syntax)-1); break; @@ -8167,13 +8185,17 @@ mysqld_get_one_option(int optid, /** Handle arguments for multiple key caches. */ -extern "C" uchar **mysql_getopt_value(const char *keyname, uint key_length, - const struct my_option *option); +extern "C" int mysql_getopt_value(uchar **value, + const char *keyname, uint key_length, + const struct my_option *option, + int *error); -uchar* * +static uchar* * mysql_getopt_value(const char *keyname, uint key_length, - const struct my_option *option) + const struct my_option *option, int *error) { + if (error) + *error= 0; switch (option->id) { case OPT_KEY_BUFFER_SIZE: case OPT_KEY_CACHE_BLOCK_SIZE: @@ -8182,7 +8204,11 @@ mysql_getopt_value(const char *keyname, uint key_length, { KEY_CACHE *key_cache; if (!(key_cache= get_or_create_key_cache(keyname, key_length))) - exit(1); + { + if (error) + *error= EXIT_OUT_OF_MEMORY; + return 0; + } switch (option->id) { case OPT_KEY_BUFFER_SIZE: return (uchar**) &key_cache->param_buff_size; @@ -8220,7 +8246,7 @@ void option_error_reporter(enum loglevel level, const char *format, ...) @todo - FIXME add EXIT_TOO_MANY_ARGUMENTS to "mysys_err.h" and return that code? */ -static void get_options(int *argc,char **argv) +static int get_options(int *argc,char **argv) { int ho_error; @@ -8234,7 +8260,7 @@ static void get_options(int *argc,char **argv) if ((ho_error= handle_options(argc, &argv, my_long_options, mysqld_get_one_option))) - exit(ho_error); + return ho_error; (*argc)++; /* add back one for the progname handle_options removes */ /* no need to do this for argv as we are discarding it. */ @@ -8273,7 +8299,8 @@ static void get_options(int *argc,char **argv) max_allowed_packet= global_system_variables.max_allowed_packet; net_buffer_length= global_system_variables.net_buffer_length; #endif - fix_paths(); + if (fix_paths()) + return 1; /* Set some global variables from the global_system_variables @@ -8300,7 +8327,7 @@ static void get_options(int *argc,char **argv) &global_system_variables.time_format) || init_global_datetime_format(MYSQL_TIMESTAMP_DATETIME, &global_system_variables.datetime_format)) - exit(1); + return 1; #ifdef EMBEDDED_LIBRARY one_thread_scheduler(&thread_scheduler); @@ -8313,6 +8340,7 @@ static void get_options(int *argc,char **argv) else pool_of_threads_scheduler(&thread_scheduler); /* purecov: tested */ #endif + return 0; } @@ -8376,7 +8404,7 @@ fn_format_relative_to_data_home(char * to, const char *name, } -static void fix_paths(void) +static int fix_paths(void) { char buff[FN_REFLEN],*pos; convert_dirname(mysql_home,mysql_home,NullS); @@ -8423,12 +8451,12 @@ static void fix_paths(void) charsets_dir=mysql_charsets_dir; if (init_tmpdir(&mysql_tmpdir_list, opt_mysql_tmpdir)) - exit(1); + return 1; #ifdef HAVE_REPLICATION if (!slave_load_tmpdir) { if (!(slave_load_tmpdir = (char*) my_strdup(mysql_tmpdir, MYF(MY_FAE)))) - exit(1); + return 1; } #endif /* HAVE_REPLICATION */ /* @@ -8441,30 +8469,37 @@ static void fix_paths(void) my_free(opt_secure_file_priv, MYF(0)); opt_secure_file_priv= my_strdup(buff, MYF(MY_FAE)); } + return 0; } static ulong find_bit_type_or_exit(const char *x, TYPELIB *bit_lib, - const char *option) + const char *option, int *error) { - ulong res; - + ulong result; const char **ptr; - if ((res= find_bit_type(x, bit_lib)) == ~(ulong) 0) + *error= 0; + if ((result= find_bit_type(x, bit_lib)) == ~(ulong) 0) { + char *buff= (char *) my_alloca(2048); + char *cbuf; ptr= bit_lib->type_names; - if (!*x) - fprintf(stderr, "No option given to %s\n", option); - else - fprintf(stderr, "Wrong option to %s. Option(s) given: %s\n", option, x); - fprintf(stderr, "Alternatives are: '%s'", *ptr); + cbuf= buff + ((!*x) ? + my_snprintf(buff, 2048, "No option given to %s\n", option) : + my_snprintf(buff, 2048, "Wrong option to %s. Option(s) given: %s\n", + option, x)); + cbuf+= my_snprintf(cbuf, 2048 - (cbuf-buff), "Alternatives are: '%s'", *ptr); while (*++ptr) - fprintf(stderr, ",'%s'", *ptr); - fprintf(stderr, "\n"); - exit(1); + cbuf+= my_snprintf(cbuf, 2048 - (cbuf-buff), ",'%s'", *ptr); + my_snprintf(cbuf, 2048 - (cbuf-buff), "\n"); + sql_perror(buff); + *error= 1; + my_afree(buff); + return 0; } - return res; + + return result; } From ff707d56d4e0bdb21149a70e34acc5e047506c5b Mon Sep 17 00:00:00 2001 From: Alexey Botchkov Date: Tue, 11 Nov 2008 14:42:32 +0400 Subject: [PATCH 003/219] Bug#31435 ha_innodb.cc:3983: ulint convert_search_mode_to_innobase(ha_rkey_function): Asse I think we don't need to issue an error statement in the convert_search_mode_to_innobase(). Returning the PAGE_CUR_UNSUPP value is enough as allows to handle this case depending on the requirements. per-file comments: sql/ha_innodb.cc Bug#31435 ha_innodb.cc:3983: ulint convert_search_mode_to_innobase(ha_rkey_function): Asse no error issued in convert_search_mode_to_innobase. ha_innobase::records_in_range() returns HA_POS_ERROR if search mode isn't supported. --- sql/ha_innodb.cc | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/sql/ha_innodb.cc b/sql/ha_innodb.cc index 1c0f8a6e9b3..611a1197215 100644 --- a/sql/ha_innodb.cc +++ b/sql/ha_innodb.cc @@ -3723,7 +3723,6 @@ convert_search_mode_to_innobase( case HA_READ_MBR_WITHIN: case HA_READ_MBR_DISJOINT: case HA_READ_MBR_EQUAL: - my_error(ER_TABLE_CANT_HANDLE_SPKEYS, MYF(0)); return(PAGE_CUR_UNSUPP); /* do not use "default:" in order to produce a gcc warning: enumeration value '...' not handled in switch @@ -5204,7 +5203,7 @@ ha_innobase::records_in_range( mode2); } else { - n_rows = 0; + n_rows = HA_POS_ERROR; } dtuple_free_for_mysql(heap1); From fc570243cf717ca0bd2bca2963ecdf99e402b212 Mon Sep 17 00:00:00 2001 From: Alexey Botchkov Date: Thu, 20 Nov 2008 19:16:20 +0400 Subject: [PATCH 004/219] Bug#40634 table scan temporary table is 4x slower due to mmap instead instead of caching mmap is slower that caching indeed. Here the problem is that mmap is used even if --myisam-use-mmap=OFF solved by checking the flag in ha_myisam::extra() as it is called in init_read_record() per-file comments: storage/myisam/ha_myisam.cc Bug#40634 table scan temporary table is 4x slower due to mmap instead instead of caching do nothing for HA_EXTRA_MMAP if no opt_myisam_use_mmap --- storage/myisam/ha_myisam.cc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/storage/myisam/ha_myisam.cc b/storage/myisam/ha_myisam.cc index b8d5a9af8d2..3d0ebd3e04a 100644 --- a/storage/myisam/ha_myisam.cc +++ b/storage/myisam/ha_myisam.cc @@ -1789,6 +1789,8 @@ int ha_myisam::extra(enum ha_extra_function operation) { if ((specialflag & SPECIAL_SAFE_MODE) && operation == HA_EXTRA_KEYREAD) return 0; + if (operation == HA_EXTRA_MMAP && !opt_myisam_use_mmap) + return 0; return mi_extra(file, operation, 0); } From 79dccabc22456659dc0fa11ebb02bebb4129b9c2 Mon Sep 17 00:00:00 2001 From: Chad MILLER Date: Wed, 26 Nov 2008 10:51:59 -0500 Subject: [PATCH 005/219] Bug#32136: mysqld_multi --defaults-file not respected while using \ --mysqld=mysqld_safe The server run didn't know the correct section to read in a configuration file, and would read from "[mysqld]" even though mysqld_multi had already read the defaults and made them into explicit parameters. Worse, the "defaults-file" parameter says that it means "Read only this configuration file, do not read the standard system-wide and user-specific files", which should apply not only to mysql-multi, but to the server also. So, now if "defaults-file" is given, put "no-defaults" before all the explicit parameters we read from the defaults-file and feed to the mysqld or mysqld_safe. --- scripts/mysqld_multi.sh | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/scripts/mysqld_multi.sh b/scripts/mysqld_multi.sh index 3cb4665eb1c..631e1e38cc7 100644 --- a/scripts/mysqld_multi.sh +++ b/scripts/mysqld_multi.sh @@ -293,7 +293,12 @@ sub start_mysqlds() @groups = &find_groups($groupids); for ($i = 0; defined($groups[$i]); $i++) { + # Defaults are made explicit parameters to server execution... @options = defaults_for_group($groups[$i]); + # ...so server MUST NOT try to read again from some config file, especially + # as the "right" file may be unknown to the server if we are using + # --defaults-file=... params in here. + unshift(@options,"--no-defaults"); $mysqld_found= 1; # The default $mysqld_found= 0 if (!length($mysqld)); From e99057881800367c02fa6febddbaa1d8a6147000 Mon Sep 17 00:00:00 2001 From: MySQL Build Team Date: Thu, 15 Jan 2009 20:09:58 +0100 Subject: [PATCH 006/219] Added option "--short-product-tag=" to "make_binary_distribution.sh", to enable product name and server suffix to differ. --- scripts/make_binary_distribution.sh | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/scripts/make_binary_distribution.sh b/scripts/make_binary_distribution.sh index 339b2a4c219..0c4a6e2a717 100644 --- a/scripts/make_binary_distribution.sh +++ b/scripts/make_binary_distribution.sh @@ -60,13 +60,16 @@ STRIP=1 # Option ignored SILENT=0 PLATFORM="" TMP=/tmp +NEW_NAME="" # Final top directory and TAR package name SUFFIX="" +SHORT_PRODUCT_TAG="" # If don't want server suffix in package name NDBCLUSTER="" # Option ignored for arg do case "$arg" in --tmp=*) TMP=`echo "$arg" | sed -e "s;--tmp=;;"` ;; --suffix=*) SUFFIX=`echo "$arg" | sed -e "s;--suffix=;;"` ;; + --short-product-tag=*) SHORT_PRODUCT_TAG=`echo "$arg" | sed -e "s;--short-product-tag=;;"` ;; --no-strip) STRIP=0 ;; --machine=*) machine=`echo "$arg" | sed -e "s;--machine=;;"` ;; --platform=*) PLATFORM=`echo "$arg" | sed -e "s;--platform=;;"` ;; @@ -113,7 +116,11 @@ case $PLATFORM in esac # Change the distribution to a long descriptive name -NEW_NAME=mysql@MYSQL_SERVER_SUFFIX@-@VERSION@-$PLATFORM$SUFFIX +if [ x"$SHORT_PRODUCT_TAG = x"" ] ; then + NEW_NAME=mysql-$SHORT_PRODUCT_TAG-@VERSION@-$PLATFORM$SUFFIX +else + NEW_NAME=mysql@MYSQL_SERVER_SUFFIX@-@VERSION@-$PLATFORM$SUFFIX +fi # ---------------------------------------------------------------------- # Define BASE, and remove the old BASE directory if any From e9f9afc2888835528ce5e3b8887d2c90524a7a03 Mon Sep 17 00:00:00 2001 From: MySQL Build Team Date: Thu, 15 Jan 2009 21:16:18 +0100 Subject: [PATCH 007/219] Cherry-pick fix for bug#40386, "Not flushing query cache after truncate", out of 5.1-bugteam branch. This fix is r3114 from innodb-5.1-ss3603. --- storage/innobase/handler/ha_innodb.cc | 8 +++++--- storage/innobase/row/row0mysql.c | 2 +- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index 6358f7ce055..4d1f1b4c734 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -6024,11 +6024,13 @@ ha_innobase::info( n_rows++; } - /* Fix bug#29507: TRUNCATE shows too many rows affected. - Do not show the estimates for TRUNCATE command. */ + /* Fix bug#40386: Not flushing query cache after truncate. + n_rows can not be 0 unless the table is empty, set to 1 + instead. The original problem of bug#29507 is actually + fixed in the server code. */ if (thd_sql_command(user_thd) == SQLCOM_TRUNCATE) { - n_rows = 0; + n_rows = 1; /* We need to reset the prebuilt value too, otherwise checks for values greater than the last value written diff --git a/storage/innobase/row/row0mysql.c b/storage/innobase/row/row0mysql.c index d76af54b420..1019f33efef 100644 --- a/storage/innobase/row/row0mysql.c +++ b/storage/innobase/row/row0mysql.c @@ -342,7 +342,7 @@ row_mysql_store_col_in_innobase_format( /* In some cases we strip trailing spaces from UTF-8 and other multibyte charsets, from FIXED-length CHAR columns, to save space. UTF-8 would otherwise normally use 3 * the string length - bytes to store a latin1 string! */ + bytes to store an ASCII string! */ /* We assume that this CHAR field is encoded in a variable-length character set where spaces have From afb33a2a66dc5bd35fe80caeba3953a7b76f01ec Mon Sep 17 00:00:00 2001 From: MySQL Build Team Date: Sat, 17 Jan 2009 09:29:40 +0100 Subject: [PATCH 008/219] Fixed typo --- scripts/make_binary_distribution.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/make_binary_distribution.sh b/scripts/make_binary_distribution.sh index 0c4a6e2a717..c5f1813aaf7 100644 --- a/scripts/make_binary_distribution.sh +++ b/scripts/make_binary_distribution.sh @@ -116,7 +116,7 @@ case $PLATFORM in esac # Change the distribution to a long descriptive name -if [ x"$SHORT_PRODUCT_TAG = x"" ] ; then +if [ x"$SHORT_PRODUCT_TAG" = x"" ] ; then NEW_NAME=mysql-$SHORT_PRODUCT_TAG-@VERSION@-$PLATFORM$SUFFIX else NEW_NAME=mysql@MYSQL_SERVER_SUFFIX@-@VERSION@-$PLATFORM$SUFFIX From e3d717099822cedb0722c054d3f131d4989efb1a Mon Sep 17 00:00:00 2001 From: MySQL Build Team Date: Mon, 19 Jan 2009 17:48:05 +0100 Subject: [PATCH 009/219] Incorrect test if "--short-product-tag=" was given or not --- scripts/make_binary_distribution.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/make_binary_distribution.sh b/scripts/make_binary_distribution.sh index c5f1813aaf7..ee7c36b097d 100644 --- a/scripts/make_binary_distribution.sh +++ b/scripts/make_binary_distribution.sh @@ -116,7 +116,7 @@ case $PLATFORM in esac # Change the distribution to a long descriptive name -if [ x"$SHORT_PRODUCT_TAG" = x"" ] ; then +if [ x"$SHORT_PRODUCT_TAG" != x"" ] ; then NEW_NAME=mysql-$SHORT_PRODUCT_TAG-@VERSION@-$PLATFORM$SUFFIX else NEW_NAME=mysql@MYSQL_SERVER_SUFFIX@-@VERSION@-$PLATFORM$SUFFIX From 8096efa703825dacdf7d6e935cbaabec7097c5f5 Mon Sep 17 00:00:00 2001 From: Bjorn Munch Date: Tue, 20 Jan 2009 11:40:10 +0100 Subject: [PATCH 010/219] Bug #41420 MTR fails on windows with "The symlink function is unimplemented" Don't do the symlink if running on Windows --- mysql-test/mysql-test-run.pl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl index 981ac74fb93..65c1f2ad0f6 100755 --- a/mysql-test/mysql-test-run.pl +++ b/mysql-test/mysql-test-run.pl @@ -2442,7 +2442,8 @@ sub setup_vardir() { mkpath("$opt_vardir/tmp"); mkpath($opt_tmpdir) if $opt_tmpdir ne "$opt_vardir/tmp"; - if ($master->[0]->{'path_sock'} !~ m/^$opt_tmpdir/) + # Set up link to master sock if not in var/tmp (not on Windows) + if (! $glob_win32 && $master->[0]->{'path_sock'} !~ m/^$opt_tmpdir/) { mtr_report("Symlinking $master->[0]->{'path_sock'}"); symlink($master->[0]->{'path_sock'}, "$opt_tmpdir/master.sock"); From 3e625f987b5d1027ae4db4bc9e66559f8e2eec12 Mon Sep 17 00:00:00 2001 From: Joerg Bruehe Date: Mon, 26 Jan 2009 22:06:42 +0100 Subject: [PATCH 011/219] Backport of a fix done by Kent for bug#42278 into the 5.0.72sp1 branch. Original changeset (in the main 5.0 branch): > committer: Kent Boortz > branch nick: mysql-5.0-build-bug42278 > timestamp: Fri 2009-01-23 02:59:03 +0100 scripts/make_binary_distribution.sh: From 5.0.48 the NDB client libraries has been missing in the cluster packages, this is now corrected (Bug#42278) --- scripts/make_binary_distribution.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/make_binary_distribution.sh b/scripts/make_binary_distribution.sh index e5e08038bff..f156ea3b986 100644 --- a/scripts/make_binary_distribution.sh +++ b/scripts/make_binary_distribution.sh @@ -372,8 +372,8 @@ fi # NDB Cluster if [ x$NDBCLUSTER = x1 ]; then - ( cd ndb ; @MAKE@ DESTDIR=$BASE/ndb-stage install ) - ( cd mysql-test/ndb ; @MAKE@ DESTDIR=$BASE/ndb-stage install ) + ( cd ndb ; @MAKE@ DESTDIR=$BASE/ndb-stage install pkglibdir=@pkglibdir@ ) + ( cd mysql-test/ndb ; @MAKE@ DESTDIR=$BASE/ndb-stage install pkglibdir=@pkglibdir@ ) $CP $BASE/ndb-stage@bindir@/* $BASE/bin/. $CP $BASE/ndb-stage@libexecdir@/* $BASE/bin/. $CP $BASE/ndb-stage@pkglibdir@/* $BASE/lib/. From 0d2fecc9779c71bb9b2e214efad369a6f07f69c6 Mon Sep 17 00:00:00 2001 From: Chad MILLER Date: Tue, 27 Jan 2009 09:43:55 -0500 Subject: [PATCH 012/219] Bug#34309: '_PC' macro redefinition For reasons that are now a mystery, we had defined a CPP symbol to help ancient compilers work better (in some way that's lost to history). This interferes with at least one modern compiler. Now, don't define the _PC symbol. Those other underscore-leading symbols are suspect also, but at least the names aren't inscrutable. Let's leave them for now. --- include/my_global.h | 1 - 1 file changed, 1 deletion(-) diff --git a/include/my_global.h b/include/my_global.h index 8fb5a6b69da..feabb714004 100644 --- a/include/my_global.h +++ b/include/my_global.h @@ -621,7 +621,6 @@ C_MODE_END */ #define _VARARGS(X) X #define _STATIC_VARARGS(X) X -#define _PC(X) X /* The DBUG_ON flag always takes precedence over default DBUG_OFF */ #if defined(DBUG_ON) && defined(DBUG_OFF) From a01946373d5752c921c4daddfec5c6cdfdbfa627 Mon Sep 17 00:00:00 2001 From: Alexey Kopytov Date: Wed, 28 Jan 2009 20:59:08 +0300 Subject: [PATCH 013/219] Fix for bug #21205: Different number of digits for float/double/real in --ps-protocol Various parts of code used different 'precision' arguments for sprintf("%g") when converting floating point numbers to a string. This led to differences in results in some cases depending on whether the text-based or prepared statements protocol is used for a query. Fixed by changing arguments to sprintf("%g") to always be 15 (DBL_DIG) so that results are consistent regardless of the protocol. This patch will be null-merged to 6.0 as the problem does not exists there (fixed by the patch for WL#2934). client/sql_string.cc: Use 15 (DBL_DIG) as a precision argument for sprintf(), as Field_double::val_str() does. libmysql/libmysql.c: Use 15 (DBL_DIG) as a precision argument for sprintf(), as Field_double::val_str() does. mysql-test/r/archive_gis.result: Fixed test results to take additional precision into account. mysql-test/r/func_group.result: Fixed test results to take additional precision into account. mysql-test/r/func_math.result: Fixed test results to take additional precision into account. mysql-test/r/func_str.result: Fixed test results to take additional precision into account. mysql-test/r/gis.result: Fixed test results to take additional precision into account. mysql-test/r/innodb_gis.result: Fixed test results to take additional precision into account. mysql-test/r/select.result: Fixed test results to take additional precision into account. mysql-test/r/sp.result: Fixed test results to take additional precision into account. mysql-test/r/type_float.result: Fixed test results to take additional precision into account. mysql-test/t/type_float.test: Fixed test results to take additional precision into account. sql/sql_string.cc: Use 15 (DBL_DIG) as a precision argument for sprintf(), as Field_double::val_str() does. --- client/sql_string.cc | 4 ++-- libmysql/libmysql.c | 4 ++-- mysql-test/r/archive_gis.result | 6 +++--- mysql-test/r/func_group.result | 8 ++++---- mysql-test/r/func_math.result | 10 +++++----- mysql-test/r/func_str.result | 4 ++-- mysql-test/r/gis.result | 10 +++++----- mysql-test/r/innodb_gis.result | 6 +++--- mysql-test/r/select.result | 14 +++++++------- mysql-test/r/sp.result | 8 ++++---- mysql-test/r/type_float.result | 17 +++++++++++------ mysql-test/t/type_float.test | 8 ++++++++ sql/sql_string.cc | 4 ++-- 13 files changed, 58 insertions(+), 45 deletions(-) diff --git a/client/sql_string.cc b/client/sql_string.cc index 9d887ff031c..7767711e62f 100644 --- a/client/sql_string.cc +++ b/client/sql_string.cc @@ -125,7 +125,7 @@ bool String::set(double num,uint decimals, CHARSET_INFO *cs) str_charset=cs; if (decimals >= NOT_FIXED_DEC) { - uint32 len= my_sprintf(buff,(buff, "%.14g",num));// Enough for a DATETIME + uint32 len= my_sprintf(buff,(buff, "%.15g",num));// Enough for a DATETIME return copy(buff, len, &my_charset_latin1, cs, &dummy_errors); } #ifdef HAVE_FCONVERT @@ -677,7 +677,7 @@ void String::qs_append(const char *str, uint32 len) void String::qs_append(double d) { char *buff = Ptr + str_length; - str_length+= my_sprintf(buff, (buff, "%.14g", d)); + str_length+= my_sprintf(buff, (buff, "%.15g", d)); } void String::qs_append(double *d) diff --git a/libmysql/libmysql.c b/libmysql/libmysql.c index dd66a325169..2a5e1cc657b 100644 --- a/libmysql/libmysql.c +++ b/libmysql/libmysql.c @@ -3786,13 +3786,13 @@ static void fetch_float_with_conversion(MYSQL_BIND *param, MYSQL_FIELD *field, #undef NOT_FIXED_DEC { /* - The 14 below is to ensure that the server and client has the same + DBL_DIG below is to ensure that the server and client has the same precisions. This will ensure that on the same machine you get the same value as a string independent of the protocol you use. */ sprintf(buff, "%-*.*g", (int) min(sizeof(buff)-1, param->buffer_length), - min(14,width), value); + min(DBL_DIG, width), value); end= strcend(buff, ' '); *end= 0; } diff --git a/mysql-test/r/archive_gis.result b/mysql-test/r/archive_gis.result index 3137d43ec3a..5a8ccea7cc5 100644 --- a/mysql-test/r/archive_gis.result +++ b/mysql-test/r/archive_gis.result @@ -291,7 +291,7 @@ Note 1003 select astext(startpoint(`test`.`gis_line`.`g`)) AS `AsText(StartPoint SELECT fid, AsText(Centroid(g)) FROM gis_polygon ORDER by fid; fid AsText(Centroid(g)) 108 POINT(15 15) -109 POINT(25.416666666667 25.416666666667) +109 POINT(25.4166666666667 25.4166666666667) 110 POINT(20 10) SELECT fid, Area(g) FROM gis_polygon ORDER by fid; fid Area(g) @@ -325,8 +325,8 @@ fid IsClosed(g) 116 0 SELECT fid, AsText(Centroid(g)) FROM gis_multi_polygon ORDER by fid; fid AsText(Centroid(g)) -117 POINT(55.588527753042 17.426536064114) -118 POINT(55.588527753042 17.426536064114) +117 POINT(55.5885277530424 17.426536064114) +118 POINT(55.5885277530424 17.426536064114) 119 POINT(2 2) SELECT fid, Area(g) FROM gis_multi_polygon ORDER by fid; fid Area(g) diff --git a/mysql-test/r/func_group.result b/mysql-test/r/func_group.result index a7f4c58f4af..85ddfaac4e0 100644 --- a/mysql-test/r/func_group.result +++ b/mysql-test/r/func_group.result @@ -61,7 +61,7 @@ grp sum NULL NULL 1 7 2 20.25 -3 45.483163247594 +3 45.4831632475944 create table t2 (grp int, a bigint unsigned, c char(10)); insert into t2 select grp,max(a)+max(grp),max(c) from t1 group by grp; replace into t2 select grp, a, c from t1 limit 2,1; @@ -1195,7 +1195,7 @@ std(s1/s2) 0.21325764 select std(o1/o2) from bug22555; std(o1/o2) -0.21325763586649 +0.213257635866493 select std(e1/e2) from bug22555; std(e1/e2) 0.21325764 @@ -1221,7 +1221,7 @@ round(std(s1/s2), 17) 0.21325763586649341 select std(o1/o2) from bug22555; std(o1/o2) -0.21325763586649 +0.213257635866493 select round(std(e1/e2), 17) from bug22555; round(std(e1/e2), 17) 0.21325763586649341 @@ -1246,7 +1246,7 @@ round(std(s1/s2), 17) 0.21325763586649341 select std(o1/o2) from bug22555; std(o1/o2) -0.21325763586649 +0.213257635866493 select round(std(e1/e2), 17) from bug22555; round(std(e1/e2), 17) 0.21325763586649341 diff --git a/mysql-test/r/func_math.result b/mysql-test/r/func_math.result index 150b6003dbe..0d7adbbba5e 100644 --- a/mysql-test/r/func_math.result +++ b/mysql-test/r/func_math.result @@ -60,7 +60,7 @@ Warnings: Note 1003 select ln(exp(10)) AS `ln(exp(10))`,exp((ln(sqrt(10)) * 2)) AS `exp(ln(sqrt(10))*2)`,ln(-(1)) AS `ln(-1)`,ln(0) AS `ln(0)`,ln(NULL) AS `ln(NULL)` select log2(8),log2(15),log2(-2),log2(0),log2(NULL); log2(8) log2(15) log2(-2) log2(0) log2(NULL) -3 3.9068905956085 NULL NULL NULL +3 3.90689059560852 NULL NULL NULL explain extended select log2(8),log2(15),log2(-2),log2(0),log2(NULL); id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE NULL NULL NULL NULL NULL NULL NULL No tables used @@ -68,7 +68,7 @@ Warnings: Note 1003 select log2(8) AS `log2(8)`,log2(15) AS `log2(15)`,log2(-(2)) AS `log2(-2)`,log2(0) AS `log2(0)`,log2(NULL) AS `log2(NULL)` select log10(100),log10(18),log10(-4),log10(0),log10(NULL); log10(100) log10(18) log10(-4) log10(0) log10(NULL) -2 1.2552725051033 NULL NULL NULL +2 1.25527250510331 NULL NULL NULL explain extended select log10(100),log10(18),log10(-4),log10(0),log10(NULL); id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE NULL NULL NULL NULL NULL NULL NULL No tables used @@ -85,7 +85,7 @@ Note 1003 select pow(10,log10(10)) AS `pow(10,log10(10))`,pow(2,4) AS `power(2,4 set @@rand_seed1=10000000,@@rand_seed2=1000000; select rand(999999),rand(); rand(999999) rand() -0.014231365187309 0.028870999839968 +0.0142313651873091 0.028870999839968 explain extended select rand(999999),rand(); id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE NULL NULL NULL NULL NULL NULL NULL No tables used @@ -101,7 +101,7 @@ Warnings: Note 1003 select pi() AS `pi()`,format(sin((pi() / 2)),6) AS `format(sin(pi()/2),6)`,format(cos((pi() / 2)),6) AS `format(cos(pi()/2),6)`,format(abs(tan(pi())),6) AS `format(abs(tan(pi())),6)`,format((1 / tan(1)),6) AS `format(cot(1),6)`,format(asin(1),6) AS `format(asin(1),6)`,format(acos(0),6) AS `format(acos(0),6)`,format(atan(1),6) AS `format(atan(1),6)` select degrees(pi()),radians(360); degrees(pi()) radians(360) -180 6.2831853071796 +180 6.28318530717959 SELECT ACOS(1.0); ACOS(1.0) 0 @@ -321,7 +321,7 @@ mod(5, cast(-2 as unsigned)) mod(5, 18446744073709551614) mod(5, -2) 5 5 1 select pow(cast(-2 as unsigned), 5), pow(18446744073709551614, 5), pow(-2, 5); pow(cast(-2 as unsigned), 5) pow(18446744073709551614, 5) pow(-2, 5) -2.1359870359209e+96 2.1359870359209e+96 -32 +2.13598703592091e+96 2.13598703592091e+96 -32 CREATE TABLE t1 (a timestamp, b varchar(20), c bit(1)); INSERT INTO t1 VALUES('1998-09-23', 'str1', 1), ('2003-03-25', 'str2', 0); SELECT a DIV 900 y FROM t1 GROUP BY y; diff --git a/mysql-test/r/func_str.result b/mysql-test/r/func_str.result index c121c8937d7..b8d915d0c4f 100644 --- a/mysql-test/r/func_str.result +++ b/mysql-test/r/func_str.result @@ -1131,10 +1131,10 @@ cast(rtrim(ltrim(' 20.06 ')) as decimal(19,2)) 20.06 select conv("18383815659218730760",10,10) + 0; conv("18383815659218730760",10,10) + 0 -1.8383815659219e+19 +1.83838156592187e+19 select "18383815659218730760" + 0; "18383815659218730760" + 0 -1.8383815659219e+19 +1.83838156592187e+19 CREATE TABLE t1 (code varchar(10)); INSERT INTO t1 VALUES ('a12'), ('A12'), ('a13'); SELECT ASCII(code), code FROM t1 WHERE code='A12'; diff --git a/mysql-test/r/gis.result b/mysql-test/r/gis.result index ac6356f8203..e3b2ea751d9 100644 --- a/mysql-test/r/gis.result +++ b/mysql-test/r/gis.result @@ -284,7 +284,7 @@ Note 1003 select astext(startpoint(`test`.`gis_line`.`g`)) AS `AsText(StartPoint SELECT fid, AsText(Centroid(g)) FROM gis_polygon; fid AsText(Centroid(g)) 108 POINT(15 15) -109 POINT(25.416666666667 25.416666666667) +109 POINT(25.4166666666667 25.4166666666667) 110 POINT(20 10) SELECT fid, Area(g) FROM gis_polygon; fid Area(g) @@ -318,8 +318,8 @@ fid IsClosed(g) 116 0 SELECT fid, AsText(Centroid(g)) FROM gis_multi_polygon; fid AsText(Centroid(g)) -117 POINT(55.588527753042 17.426536064114) -118 POINT(55.588527753042 17.426536064114) +117 POINT(55.5885277530424 17.426536064114) +118 POINT(55.5885277530424 17.426536064114) 119 POINT(2 2) SELECT fid, Area(g) FROM gis_multi_polygon; fid Area(g) @@ -651,11 +651,11 @@ insert into t1 values ('85984',GeomFromText('MULTIPOLYGON(((-115.006363 select object_id, geometrytype(geo), ISSIMPLE(GEO), ASTEXT(centroid(geo)) from t1 where object_id=85998; object_id geometrytype(geo) ISSIMPLE(GEO) ASTEXT(centroid(geo)) -85998 MULTIPOLYGON 0 POINT(115.31877315203 -36.237472821022) +85998 MULTIPOLYGON 0 POINT(115.318773152032 -36.2374728210215) select object_id, geometrytype(geo), ISSIMPLE(GEO), ASTEXT(centroid(geo)) from t1 where object_id=85984; object_id geometrytype(geo) ISSIMPLE(GEO) ASTEXT(centroid(geo)) -85984 MULTIPOLYGON 0 POINT(-114.87787186923 36.33101763469) +85984 MULTIPOLYGON 0 POINT(-114.877871869233 36.3310176346905) drop table t1; create table t1 (fl geometry not null); insert into t1 values (1); diff --git a/mysql-test/r/innodb_gis.result b/mysql-test/r/innodb_gis.result index bfe8c984b7b..0f2607e9787 100644 --- a/mysql-test/r/innodb_gis.result +++ b/mysql-test/r/innodb_gis.result @@ -291,7 +291,7 @@ Note 1003 select astext(startpoint(`test`.`gis_line`.`g`)) AS `AsText(StartPoint SELECT fid, AsText(Centroid(g)) FROM gis_polygon ORDER by fid; fid AsText(Centroid(g)) 108 POINT(15 15) -109 POINT(25.416666666667 25.416666666667) +109 POINT(25.4166666666667 25.4166666666667) 110 POINT(20 10) SELECT fid, Area(g) FROM gis_polygon ORDER by fid; fid Area(g) @@ -325,8 +325,8 @@ fid IsClosed(g) 116 0 SELECT fid, AsText(Centroid(g)) FROM gis_multi_polygon ORDER by fid; fid AsText(Centroid(g)) -117 POINT(55.588527753042 17.426536064114) -118 POINT(55.588527753042 17.426536064114) +117 POINT(55.5885277530424 17.426536064114) +118 POINT(55.5885277530424 17.426536064114) 119 POINT(2 2) SELECT fid, Area(g) FROM gis_multi_polygon ORDER by fid; fid Area(g) diff --git a/mysql-test/r/select.result b/mysql-test/r/select.result index 67ce231a157..9558b0533ad 100644 --- a/mysql-test/r/select.result +++ b/mysql-test/r/select.result @@ -2790,26 +2790,26 @@ id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Select tables optimized away select max(key1) from t1 where key1 <= 0.6158; max(key1) -0.61580002307892 +0.615800023078918 select max(key2) from t2 where key2 <= 1.6158; max(key2) -1.6158000230789 +1.61580002307892 select min(key1) from t1 where key1 >= 0.3762; min(key1) -0.37619999051094 +0.376199990510941 select min(key2) from t2 where key2 >= 1.3762; min(key2) -1.3761999607086 +1.37619996070862 select max(key1), min(key2) from t1, t2 where key1 <= 0.6158 and key2 >= 1.3762; max(key1) min(key2) -0.61580002307892 1.3761999607086 +0.615800023078918 1.37619996070862 select max(key1) from t1 where key1 <= 0.6158 and rand() + 0.5 >= 0.5; max(key1) -0.61580002307892 +0.615800023078918 select min(key1) from t1 where key1 >= 0.3762 and rand() + 0.5 >= 0.5; min(key1) -0.37619999051094 +0.376199990510941 DROP TABLE t1,t2; create table t1(a bigint unsigned, b bigint); insert into t1 values (0xfffffffffffffffff, 0xfffffffffffffffff), diff --git a/mysql-test/r/sp.result b/mysql-test/r/sp.result index ec00435548c..bfa2f51e4fc 100644 --- a/mysql-test/r/sp.result +++ b/mysql-test/r/sp.result @@ -581,7 +581,7 @@ return 2.7182818284590452354| set @e = e()| select e(), @e| e() @e -2.718281828459 2.718281828459 +2.71828182845905 2.71828182845905 drop function if exists inc| create function inc(i int) returns int return i+1| @@ -618,7 +618,7 @@ create function fun(d double, i int, u int unsigned) returns double return mul(inc(i), fac(u)) / e()| select fun(2.3, 3, 5)| fun(2.3, 3, 5) -176.58213176229 +176.582131762292 insert into t2 values (append("xxx", "yyy"), mul(4,3), e())| insert into t2 values (append("a", "b"), mul(2,mul(3,4)), fun(1.7, 4, 6))| select * from t2 where s = append("a", "b")| @@ -5972,9 +5972,9 @@ CREATE TABLE t3 (f1 INT, f2 FLOAT)| INSERT INTO t3 VALUES (1, 3.4), (1, 2), (1, 0.9), (2, 8), (2, 7)| SELECT SUM(f2), bug25373(f1) FROM t3 GROUP BY bug25373(f1) WITH ROLLUP| SUM(f2) bug25373(f1) -6.3000000715256 1 +6.30000007152557 1 15 2 -21.300000071526 NULL +21.3000000715256 NULL DROP FUNCTION bug25373| DROP TABLE t3| DROP DATABASE IF EXISTS mysqltest1| diff --git a/mysql-test/r/type_float.result b/mysql-test/r/type_float.result index 8caabbff047..757cd6f5d71 100644 --- a/mysql-test/r/type_float.result +++ b/mysql-test/r/type_float.result @@ -385,12 +385,12 @@ Warning 1264 Out of range value adjusted for column 'f1' at row 1 Warning 1264 Out of range value adjusted for column 'f1' at row 2 select f1 + 0e0 from t1; f1 + 0e0 -1.0000000150475e+29 --1.0000000150475e+29 -1.0000000150475e+30 --1.0000000150475e+30 -1.0000000150475e+30 --1.0000000150475e+30 +1.00000001504747e+29 +-1.00000001504747e+29 +1.00000001504747e+30 +-1.00000001504747e+30 +1.00000001504747e+30 +-1.00000001504747e+30 drop table t1; create table t1(d double, u bigint unsigned); insert into t1(d) values (9.22337203685479e18), @@ -401,4 +401,9 @@ u 9223372036854790144 18400000000000000000 drop table t1; +CREATE TABLE t1 (f1 DOUBLE); +INSERT INTO t1 VALUES(-1.79769313486231e+308); +SELECT f1 FROM t1; +f1 +-1.79769313486231e+308 End of 5.0 tests diff --git a/mysql-test/t/type_float.test b/mysql-test/t/type_float.test index 53bcf44061d..42703e11863 100644 --- a/mysql-test/t/type_float.test +++ b/mysql-test/t/type_float.test @@ -267,4 +267,12 @@ select u from t1; drop table t1; +# +# Bug #21205: Different number of digits for float/doble/real in --ps-protocol +# + +CREATE TABLE t1 (f1 DOUBLE); +INSERT INTO t1 VALUES(-1.79769313486231e+308); +SELECT f1 FROM t1; + --echo End of 5.0 tests diff --git a/sql/sql_string.cc b/sql/sql_string.cc index 75e47dd0c8e..a7d6d5db411 100644 --- a/sql/sql_string.cc +++ b/sql/sql_string.cc @@ -125,7 +125,7 @@ bool String::set(double num,uint decimals, CHARSET_INFO *cs) str_charset=cs; if (decimals >= NOT_FIXED_DEC) { - uint32 len= my_sprintf(buff,(buff, "%.14g",num));// Enough for a DATETIME + uint32 len= my_sprintf(buff,(buff, "%.15g",num));// Enough for a DATETIME return copy(buff, len, &my_charset_latin1, cs, &dummy_errors); } #ifdef HAVE_FCONVERT @@ -677,7 +677,7 @@ void String::qs_append(const char *str, uint32 len) void String::qs_append(double d) { char *buff = Ptr + str_length; - str_length+= my_sprintf(buff, (buff, "%.14g", d)); + str_length+= my_sprintf(buff, (buff, "%.15g", d)); } void String::qs_append(double *d) From 0ad6e488a2e5f0964a303ba4908ac18a4683b403 Mon Sep 17 00:00:00 2001 From: "Tatiana A. Nurnberg" Date: Mon, 2 Feb 2009 18:19:07 +0100 Subject: [PATCH 014/219] Bug#33550: mysqldump 4.0 compatibility broken mysqldump included character_set_client magic that is unknown before 4.1 even when asked for an appropriate compatibility mode. In compatibility (3.23, 4.0) mode, we do not output charset statements (not even in a "comment conditional"), nor do we do magic on the server, even if the server is sufficient new (4.1+). Table-names will be output converted to the charset requested by mysqldump; if such a conversion is not possible (Ivrit -> Latin), mysqldump will fail. client/mysqldump.c: in 3.23/4.0 compat mode, don't do charset magic, period. not in output, but not on the server, either! mysql-test/r/mysqldump-max.result: character_set_client magic lives in version-conditional now (except in compat 3.23/4.0 mode, in which case we don't output any at all!). mysql-test/r/mysqldump.result: character_set_client magic lives in version-conditional now (except in compat 3.23/4.0 mode, in which case we don't output any at all!). mysql-test/r/openssl_1.result: character_set_client magic lives in version-conditional now (except in compat 3.23/4.0 mode, in which case we don't output any at all!). mysql-test/t/mysqldump.test: character_set_client magic lives in version-conditional now (except in compat 3.23/4.0 mode, in which case we don't output any at all!). --- client/mysqldump.c | 11 +- mysql-test/r/mysqldump-max.result | 72 ++--- mysql-test/r/mysqldump.result | 422 +++++++++++++++++------------- mysql-test/r/openssl_1.result | 18 +- mysql-test/t/mysqldump.test | 18 ++ 5 files changed, 311 insertions(+), 230 deletions(-) diff --git a/client/mysqldump.c b/client/mysqldump.c index ced34f16212..97e8d6ed5ef 100644 --- a/client/mysqldump.c +++ b/client/mysqldump.c @@ -1129,7 +1129,8 @@ static int connect_to_db(char *host, char *user,char *passwd) DB_error(&mysql_connection, "when trying to connect"); DBUG_RETURN(1); } - if (mysql_get_server_version(&mysql_connection) < 40100) + if ((mysql_get_server_version(&mysql_connection) < 40100) || + (opt_compatible_mode & 3)) { /* Don't dump SET NAMES with a pre-4.1 server (bug#7997). */ opt_set_charset= 0; @@ -1857,11 +1858,11 @@ static uint get_table_structure(char *table, char *db, char *table_type, row= mysql_fetch_row(result); - fprintf(sql_file, - "SET @saved_cs_client = @@character_set_client;\n" - "SET character_set_client = utf8;\n" + fprintf(sql_file, (opt_compatible_mode & 3) ? "%s;\n" : + "/*!40101 SET @saved_cs_client = @@character_set_client */;\n" + "/*!40101 SET character_set_client = utf8 */;\n" "%s;\n" - "SET character_set_client = @saved_cs_client;\n", + "/*!40101 SET character_set_client = @saved_cs_client */;\n", row[1]); check_io(sql_file); diff --git a/mysql-test/r/mysqldump-max.result b/mysql-test/r/mysqldump-max.result index 261c7a7f197..b3a966b9b39 100644 --- a/mysql-test/r/mysqldump-max.result +++ b/mysql-test/r/mysqldump-max.result @@ -93,73 +93,73 @@ CREATE DATABASE /*!32312 IF NOT EXISTS*/ `test` /*!40100 DEFAULT CHARACTER SET l USE `test`; DROP TABLE IF EXISTS `t1`; -SET @saved_cs_client = @@character_set_client; -SET character_set_client = utf8; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; CREATE TABLE `t1` ( `id` int(8) default NULL, `name` varchar(32) default NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1; -SET character_set_client = @saved_cs_client; +/*!40101 SET character_set_client = @saved_cs_client */; /*!40000 ALTER TABLE `t1` DISABLE KEYS */; INSERT DELAYED IGNORE INTO `t1` VALUES (1,'first value'),(2,'first value'),(3,'first value'),(4,'first value'),(5,'first value'); /*!40000 ALTER TABLE `t1` ENABLE KEYS */; DROP TABLE IF EXISTS `t2`; -SET @saved_cs_client = @@character_set_client; -SET character_set_client = utf8; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; CREATE TABLE `t2` ( `id` int(8) default NULL, `name` varchar(32) default NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1; -SET character_set_client = @saved_cs_client; +/*!40101 SET character_set_client = @saved_cs_client */; /*!40000 ALTER TABLE `t2` DISABLE KEYS */; INSERT DELAYED IGNORE INTO `t2` VALUES (1,'first value'),(2,'first value'),(3,'first value'),(4,'first value'),(5,'first value'); /*!40000 ALTER TABLE `t2` ENABLE KEYS */; DROP TABLE IF EXISTS `t3`; -SET @saved_cs_client = @@character_set_client; -SET character_set_client = utf8; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; CREATE TABLE `t3` ( `id` int(8) default NULL, `name` varchar(32) default NULL ) ENGINE=MEMORY DEFAULT CHARSET=latin1; -SET character_set_client = @saved_cs_client; +/*!40101 SET character_set_client = @saved_cs_client */; /*!40000 ALTER TABLE `t3` DISABLE KEYS */; INSERT DELAYED IGNORE INTO `t3` VALUES (1,'first value'),(2,'first value'),(3,'first value'),(4,'first value'),(5,'first value'); /*!40000 ALTER TABLE `t3` ENABLE KEYS */; DROP TABLE IF EXISTS `t4`; -SET @saved_cs_client = @@character_set_client; -SET character_set_client = utf8; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; CREATE TABLE `t4` ( `id` int(8) default NULL, `name` varchar(32) default NULL ) ENGINE=MEMORY DEFAULT CHARSET=latin1; -SET character_set_client = @saved_cs_client; +/*!40101 SET character_set_client = @saved_cs_client */; /*!40000 ALTER TABLE `t4` DISABLE KEYS */; INSERT DELAYED IGNORE INTO `t4` VALUES (1,'first value'),(2,'first value'),(3,'first value'),(4,'first value'),(5,'first value'); /*!40000 ALTER TABLE `t4` ENABLE KEYS */; DROP TABLE IF EXISTS `t5`; -SET @saved_cs_client = @@character_set_client; -SET character_set_client = utf8; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; CREATE TABLE `t5` ( `id` int(8) default NULL, `name` varchar(32) default NULL ) ENGINE=ARCHIVE DEFAULT CHARSET=latin1; -SET character_set_client = @saved_cs_client; +/*!40101 SET character_set_client = @saved_cs_client */; /*!40000 ALTER TABLE `t5` DISABLE KEYS */; INSERT DELAYED IGNORE INTO `t5` VALUES (1,'first value'),(2,'first value'),(3,'first value'),(4,'first value'),(5,'first value'); /*!40000 ALTER TABLE `t5` ENABLE KEYS */; DROP TABLE IF EXISTS `t6`; -SET @saved_cs_client = @@character_set_client; -SET character_set_client = utf8; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; CREATE TABLE `t6` ( `id` int(8) default NULL, `name` varchar(32) default NULL ) ENGINE=InnoDB DEFAULT CHARSET=latin1; -SET character_set_client = @saved_cs_client; +/*!40101 SET character_set_client = @saved_cs_client */; /*!40000 ALTER TABLE `t6` DISABLE KEYS */; INSERT IGNORE INTO `t6` VALUES (1,'first value'),(2,'first value'),(3,'first value'),(4,'first value'),(5,'first value'); @@ -190,73 +190,73 @@ CREATE DATABASE /*!32312 IF NOT EXISTS*/ `test` /*!40100 DEFAULT CHARACTER SET l USE `test`; DROP TABLE IF EXISTS `t1`; -SET @saved_cs_client = @@character_set_client; -SET character_set_client = utf8; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; CREATE TABLE `t1` ( `id` int(8) default NULL, `name` varchar(32) default NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1; -SET character_set_client = @saved_cs_client; +/*!40101 SET character_set_client = @saved_cs_client */; /*!40000 ALTER TABLE `t1` DISABLE KEYS */; INSERT DELAYED INTO `t1` VALUES (1,'first value'),(2,'first value'),(3,'first value'),(4,'first value'),(5,'first value'); /*!40000 ALTER TABLE `t1` ENABLE KEYS */; DROP TABLE IF EXISTS `t2`; -SET @saved_cs_client = @@character_set_client; -SET character_set_client = utf8; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; CREATE TABLE `t2` ( `id` int(8) default NULL, `name` varchar(32) default NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1; -SET character_set_client = @saved_cs_client; +/*!40101 SET character_set_client = @saved_cs_client */; /*!40000 ALTER TABLE `t2` DISABLE KEYS */; INSERT DELAYED INTO `t2` VALUES (1,'first value'),(2,'first value'),(3,'first value'),(4,'first value'),(5,'first value'); /*!40000 ALTER TABLE `t2` ENABLE KEYS */; DROP TABLE IF EXISTS `t3`; -SET @saved_cs_client = @@character_set_client; -SET character_set_client = utf8; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; CREATE TABLE `t3` ( `id` int(8) default NULL, `name` varchar(32) default NULL ) ENGINE=MEMORY DEFAULT CHARSET=latin1; -SET character_set_client = @saved_cs_client; +/*!40101 SET character_set_client = @saved_cs_client */; /*!40000 ALTER TABLE `t3` DISABLE KEYS */; INSERT DELAYED INTO `t3` VALUES (1,'first value'),(2,'first value'),(3,'first value'),(4,'first value'),(5,'first value'); /*!40000 ALTER TABLE `t3` ENABLE KEYS */; DROP TABLE IF EXISTS `t4`; -SET @saved_cs_client = @@character_set_client; -SET character_set_client = utf8; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; CREATE TABLE `t4` ( `id` int(8) default NULL, `name` varchar(32) default NULL ) ENGINE=MEMORY DEFAULT CHARSET=latin1; -SET character_set_client = @saved_cs_client; +/*!40101 SET character_set_client = @saved_cs_client */; /*!40000 ALTER TABLE `t4` DISABLE KEYS */; INSERT DELAYED INTO `t4` VALUES (1,'first value'),(2,'first value'),(3,'first value'),(4,'first value'),(5,'first value'); /*!40000 ALTER TABLE `t4` ENABLE KEYS */; DROP TABLE IF EXISTS `t5`; -SET @saved_cs_client = @@character_set_client; -SET character_set_client = utf8; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; CREATE TABLE `t5` ( `id` int(8) default NULL, `name` varchar(32) default NULL ) ENGINE=ARCHIVE DEFAULT CHARSET=latin1; -SET character_set_client = @saved_cs_client; +/*!40101 SET character_set_client = @saved_cs_client */; /*!40000 ALTER TABLE `t5` DISABLE KEYS */; INSERT DELAYED INTO `t5` VALUES (1,'first value'),(2,'first value'),(3,'first value'),(4,'first value'),(5,'first value'); /*!40000 ALTER TABLE `t5` ENABLE KEYS */; DROP TABLE IF EXISTS `t6`; -SET @saved_cs_client = @@character_set_client; -SET character_set_client = utf8; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; CREATE TABLE `t6` ( `id` int(8) default NULL, `name` varchar(32) default NULL ) ENGINE=InnoDB DEFAULT CHARSET=latin1; -SET character_set_client = @saved_cs_client; +/*!40101 SET character_set_client = @saved_cs_client */; /*!40000 ALTER TABLE `t6` DISABLE KEYS */; INSERT INTO `t6` VALUES (1,'first value'),(2,'first value'),(3,'first value'),(4,'first value'),(5,'first value'); diff --git a/mysql-test/r/mysqldump.result b/mysql-test/r/mysqldump.result index 08a18d8de75..8b7e8f4430f 100644 --- a/mysql-test/r/mysqldump.result +++ b/mysql-test/r/mysqldump.result @@ -33,12 +33,12 @@ DROP TABLE t1; CREATE TABLE t1 (a decimal(64, 20)); INSERT INTO t1 VALUES ("1234567890123456789012345678901234567890"), ("0987654321098765432109876543210987654321"); -SET @saved_cs_client = @@character_set_client; -SET character_set_client = utf8; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; CREATE TABLE `t1` ( `a` decimal(64,20) default NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1; -SET character_set_client = @saved_cs_client; +/*!40101 SET character_set_client = @saved_cs_client */; INSERT INTO `t1` VALUES ('1234567890123456789012345678901234567890.00000000000000000000'),('987654321098765432109876543210987654321.00000000000000000000'); DROP TABLE t1; # @@ -48,12 +48,12 @@ CREATE TABLE t1 (a double); INSERT INTO t1 VALUES ('-9e999999'); Warnings: Warning 1264 Out of range value adjusted for column 'a' at row 1 -SET @saved_cs_client = @@character_set_client; -SET character_set_client = utf8; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; CREATE TABLE `t1` ( `a` double default NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1; -SET character_set_client = @saved_cs_client; +/*!40101 SET character_set_client = @saved_cs_client */; INSERT INTO `t1` VALUES (RES); DROP TABLE t1; # @@ -69,21 +69,21 @@ INSERT INTO t1 VALUES ('1.2345', 2.3456); INSERT INTO t1 VALUES ("1.2345", 2.3456); ERROR 42S22: Unknown column '1.2345' in 'field list' SET SQL_MODE=@OLD_SQL_MODE; -SET @saved_cs_client = @@character_set_client; -SET character_set_client = utf8; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; CREATE TABLE `t1` ( `a` decimal(10,5) default NULL, `b` float default NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1; -SET character_set_client = @saved_cs_client; +/*!40101 SET character_set_client = @saved_cs_client */; INSERT INTO `t1` VALUES ('1.23450',2.3456),('1.23450',2.3456),('1.23450',2.3456),('1.23450',2.3456),('1.23450',2.3456); -SET @saved_cs_client = @@character_set_client; -SET character_set_client = utf8; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; CREATE TABLE `t1` ( `a` decimal(10,5) default NULL, `b` float default NULL ); -SET character_set_client = @saved_cs_client; +/*!40101 SET character_set_client = @saved_cs_client */; INSERT INTO `t1` VALUES ('1.23450',2.3456),('1.23450',2.3456),('1.23450',2.3456),('1.23450',2.3456),('1.23450',2.3456); /*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; @@ -97,13 +97,13 @@ INSERT INTO `t1` VALUES ('1.23450',2.3456),('1.23450',2.3456),('1.23450',2.3456) /*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; DROP TABLE IF EXISTS `t1`; -SET @saved_cs_client = @@character_set_client; -SET character_set_client = utf8; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; CREATE TABLE `t1` ( `a` decimal(10,5) default NULL, `b` float default NULL ); -SET character_set_client = @saved_cs_client; +/*!40101 SET character_set_client = @saved_cs_client */; LOCK TABLES `t1` WRITE; /*!40000 ALTER TABLE `t1` DISABLE KEYS */; @@ -126,13 +126,13 @@ UNLOCK TABLES; /*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; /*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; -SET @saved_cs_client = @@character_set_client; -SET character_set_client = utf8; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; CREATE TABLE `t1` ( `a` decimal(10,5) default NULL, `b` float default NULL ); -SET character_set_client = @saved_cs_client; +/*!40101 SET character_set_client = @saved_cs_client */; INSERT INTO `t1` VALUES ('1.23450',2.3456),('1.23450',2.3456),('1.23450',2.3456),('1.23450',2.3456),('1.23450',2.3456); /*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */; @@ -208,12 +208,12 @@ INSERT INTO t1 VALUES (_koi8r x'C1C2C3C4C5'), (NULL); /*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; DROP TABLE IF EXISTS `t1`; -SET @saved_cs_client = @@character_set_client; -SET character_set_client = utf8; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; CREATE TABLE `t1` ( `a` varchar(255) default NULL ) ENGINE=MyISAM DEFAULT CHARSET=koi8r; -SET character_set_client = @saved_cs_client; +/*!40101 SET character_set_client = @saved_cs_client */; LOCK TABLES `t1` WRITE; /*!40000 ALTER TABLE `t1` DISABLE KEYS */; @@ -244,12 +244,9 @@ INSERT INTO t1 VALUES (1), (2); /*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO,MYSQL40' */; /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; DROP TABLE IF EXISTS `t1`; -SET @saved_cs_client = @@character_set_client; -SET character_set_client = utf8; CREATE TABLE `t1` ( `a` int(11) default NULL ) TYPE=MyISAM; -SET character_set_client = @saved_cs_client; LOCK TABLES `t1` WRITE; /*!40000 ALTER TABLE `t1` DISABLE KEYS */; @@ -270,12 +267,9 @@ UNLOCK TABLES; /*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO,MYSQL323' */; /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; DROP TABLE IF EXISTS `t1`; -SET @saved_cs_client = @@character_set_client; -SET character_set_client = utf8; CREATE TABLE `t1` ( `a` int(11) default NULL ) TYPE=MyISAM; -SET character_set_client = @saved_cs_client; LOCK TABLES `t1` WRITE; /*!40000 ALTER TABLE `t1` DISABLE KEYS */; @@ -294,12 +288,12 @@ DROP TABLE t1; # Bug #2592 'mysqldump doesn't quote "tricky" names correctly' # create table ```a` (i int); -SET @saved_cs_client = @@character_set_client; -SET character_set_client = utf8; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; CREATE TABLE ```a` ( `i` int(11) default NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1; -SET character_set_client = @saved_cs_client; +/*!40101 SET character_set_client = @saved_cs_client */; drop table ```a`; # # Bug #2591 "mysqldump quotes names inconsistently" @@ -317,12 +311,12 @@ create table t1(a int); /*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; DROP TABLE IF EXISTS `t1`; -SET @saved_cs_client = @@character_set_client; -SET character_set_client = utf8; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; CREATE TABLE `t1` ( `a` int(11) default NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1; -SET character_set_client = @saved_cs_client; +/*!40101 SET character_set_client = @saved_cs_client */; LOCK TABLES `t1` WRITE; /*!40000 ALTER TABLE `t1` DISABLE KEYS */; @@ -345,12 +339,12 @@ UNLOCK TABLES; /*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO,ANSI' */; /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; DROP TABLE IF EXISTS "t1"; -SET @saved_cs_client = @@character_set_client; -SET character_set_client = utf8; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; CREATE TABLE "t1" ( "a" int(11) default NULL ); -SET character_set_client = @saved_cs_client; +/*!40101 SET character_set_client = @saved_cs_client */; LOCK TABLES "t1" WRITE; /*!40000 ALTER TABLE "t1" DISABLE KEYS */; @@ -376,12 +370,12 @@ set global sql_mode='ANSI_QUOTES'; /*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; DROP TABLE IF EXISTS `t1`; -SET @saved_cs_client = @@character_set_client; -SET character_set_client = utf8; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; CREATE TABLE `t1` ( `a` int(11) default NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1; -SET character_set_client = @saved_cs_client; +/*!40101 SET character_set_client = @saved_cs_client */; LOCK TABLES `t1` WRITE; /*!40000 ALTER TABLE `t1` DISABLE KEYS */; @@ -404,12 +398,12 @@ UNLOCK TABLES; /*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO,ANSI' */; /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; DROP TABLE IF EXISTS "t1"; -SET @saved_cs_client = @@character_set_client; -SET character_set_client = utf8; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; CREATE TABLE "t1" ( "a" int(11) default NULL ); -SET character_set_client = @saved_cs_client; +/*!40101 SET character_set_client = @saved_cs_client */; LOCK TABLES "t1" WRITE; /*!40000 ALTER TABLE "t1" DISABLE KEYS */; @@ -439,12 +433,12 @@ insert into t1 values (1),(2),(3); /*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='' */; /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; DROP TABLE IF EXISTS `t1`; -SET @saved_cs_client = @@character_set_client; -SET character_set_client = utf8; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; CREATE TABLE `t1` ( `a` int(11) default NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1; -SET character_set_client = @saved_cs_client; +/*!40101 SET character_set_client = @saved_cs_client */; /*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */; @@ -533,12 +527,12 @@ INSERT INTO t1 VALUES (_latin1 ' /*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; DROP TABLE IF EXISTS `t1`; -SET @saved_cs_client = @@character_set_client; -SET character_set_client = utf8; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; CREATE TABLE `t1` ( `a` char(10) default NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1; -SET character_set_client = @saved_cs_client; +/*!40101 SET character_set_client = @saved_cs_client */; LOCK TABLES `t1` WRITE; /*!40000 ALTER TABLE `t1` DISABLE KEYS */; @@ -569,12 +563,9 @@ UNLOCK TABLES; /*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO,MYSQL323' */; /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; DROP TABLE IF EXISTS `t1`; -SET @saved_cs_client = @@character_set_client; -SET character_set_client = utf8; CREATE TABLE `t1` ( `a` char(10) default NULL ) TYPE=MyISAM; -SET character_set_client = @saved_cs_client; LOCK TABLES `t1` WRITE; /*!40000 ALTER TABLE `t1` DISABLE KEYS */; @@ -595,12 +586,9 @@ UNLOCK TABLES; /*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO,MYSQL323' */; /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; DROP TABLE IF EXISTS `t1`; -SET @saved_cs_client = @@character_set_client; -SET character_set_client = utf8; CREATE TABLE `t1` ( `a` char(10) default NULL ) TYPE=MyISAM; -SET character_set_client = @saved_cs_client; LOCK TABLES `t1` WRITE; /*!40000 ALTER TABLE `t1` DISABLE KEYS */; @@ -621,12 +609,9 @@ UNLOCK TABLES; /*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO,MYSQL323' */; /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; DROP TABLE IF EXISTS `t1`; -SET @saved_cs_client = @@character_set_client; -SET character_set_client = utf8; CREATE TABLE `t1` ( `a` char(10) default NULL ) TYPE=MyISAM; -SET character_set_client = @saved_cs_client; LOCK TABLES `t1` WRITE; /*!40000 ALTER TABLE `t1` DISABLE KEYS */; @@ -660,12 +645,12 @@ INSERT INTO t2 VALUES (4),(5),(6); /*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; DROP TABLE IF EXISTS `t2`; -SET @saved_cs_client = @@character_set_client; -SET character_set_client = utf8; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; CREATE TABLE `t2` ( `a` int(11) default NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1; -SET character_set_client = @saved_cs_client; +/*!40101 SET character_set_client = @saved_cs_client */; LOCK TABLES `t2` WRITE; /*!40000 ALTER TABLE `t2` DISABLE KEYS */; @@ -701,12 +686,12 @@ INSERT INTO `t1` VALUES (0x602010000280100005E71A); /*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; DROP TABLE IF EXISTS `t1`; -SET @saved_cs_client = @@character_set_client; -SET character_set_client = utf8; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; CREATE TABLE `t1` ( `b` blob ) ENGINE=MyISAM DEFAULT CHARSET=latin1; -SET character_set_client = @saved_cs_client; +/*!40101 SET character_set_client = @saved_cs_client */; LOCK TABLES `t1` WRITE; /*!40000 ALTER TABLE `t1` DISABLE KEYS */; @@ -742,12 +727,12 @@ INSERT INTO t1 VALUES (4),(5),(6); /*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; DROP TABLE IF EXISTS `t1`; -SET @saved_cs_client = @@character_set_client; -SET character_set_client = utf8; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; CREATE TABLE `t1` ( `a` int(11) default NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1; -SET character_set_client = @saved_cs_client; +/*!40101 SET character_set_client = @saved_cs_client */; LOCK TABLES `t1` WRITE; /*!40000 ALTER TABLE `t1` DISABLE KEYS */; @@ -776,12 +761,12 @@ UNLOCK TABLES; /*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; DROP TABLE IF EXISTS `t1`; -SET @saved_cs_client = @@character_set_client; -SET character_set_client = utf8; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; CREATE TABLE `t1` ( `a` int(11) default NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1; -SET character_set_client = @saved_cs_client; +/*!40101 SET character_set_client = @saved_cs_client */; /*!40000 ALTER TABLE `t1` DISABLE KEYS */; INSERT DELAYED IGNORE INTO `t1` VALUES (1),(2),(3),(4),(5),(6); @@ -1145,8 +1130,8 @@ insert into t1 (F_8d3bba7425e7c98c50f52ca1b52d3735) values (1); /*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; DROP TABLE IF EXISTS `t1`; -SET @saved_cs_client = @@character_set_client; -SET character_set_client = utf8; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; CREATE TABLE `t1` ( `F_c4ca4238a0b923820dcc509a6f75849b` int(11) default NULL, `F_c81e728d9d4c2f636f067f89cc14862c` int(11) default NULL, @@ -1479,7 +1464,7 @@ CREATE TABLE `t1` ( `F_6faa8040da20ef399b63a72d0e4ab575` int(11) default NULL, `F_fe73f687e5bc5280214e0486b273a5f9` int(11) default NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1; -SET character_set_client = @saved_cs_client; +/*!40101 SET character_set_client = @saved_cs_client */; LOCK TABLES `t1` WRITE; /*!40000 ALTER TABLE `t1` DISABLE KEYS */; @@ -1520,12 +1505,12 @@ CREATE DATABASE /*!32312 IF NOT EXISTS*/ `test` /*!40100 DEFAULT CHARACTER SET l USE `test`; DROP TABLE IF EXISTS `t1`; -SET @saved_cs_client = @@character_set_client; -SET character_set_client = utf8; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; CREATE TABLE `t1` ( `a` int(11) default NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1; -SET character_set_client = @saved_cs_client; +/*!40101 SET character_set_client = @saved_cs_client */; LOCK TABLES `t1` WRITE; /*!40000 ALTER TABLE `t1` DISABLE KEYS */; @@ -1564,19 +1549,19 @@ INSERT INTO t2 VALUES (1), (2); /*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; DROP TABLE IF EXISTS `t1`; -SET @saved_cs_client = @@character_set_client; -SET character_set_client = utf8; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; CREATE TABLE `t1` ( `a` int(11) default NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1; -SET character_set_client = @saved_cs_client; +/*!40101 SET character_set_client = @saved_cs_client */; DROP TABLE IF EXISTS `t2`; -SET @saved_cs_client = @@character_set_client; -SET character_set_client = utf8; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; CREATE TABLE `t2` ( `a` int(11) default NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1; -SET character_set_client = @saved_cs_client; +/*!40101 SET character_set_client = @saved_cs_client */; /*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */; /*!40101 SET SQL_MODE=@OLD_SQL_MODE */; @@ -1599,19 +1584,19 @@ SET character_set_client = @saved_cs_client; /*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; DROP TABLE IF EXISTS `t1`; -SET @saved_cs_client = @@character_set_client; -SET character_set_client = utf8; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; CREATE TABLE `t1` ( `a` int(11) default NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1; -SET character_set_client = @saved_cs_client; +/*!40101 SET character_set_client = @saved_cs_client */; DROP TABLE IF EXISTS `t2`; -SET @saved_cs_client = @@character_set_client; -SET character_set_client = utf8; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; CREATE TABLE `t2` ( `a` int(11) default NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1; -SET character_set_client = @saved_cs_client; +/*!40101 SET character_set_client = @saved_cs_client */; /*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */; /*!40101 SET SQL_MODE=@OLD_SQL_MODE */; @@ -1811,26 +1796,26 @@ create table t3(a int); /*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; DROP TABLE IF EXISTS `t3`; -SET @saved_cs_client = @@character_set_client; -SET character_set_client = utf8; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; CREATE TABLE `t3` ( `a` int(11) default NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1; -SET character_set_client = @saved_cs_client; +/*!40101 SET character_set_client = @saved_cs_client */; DROP TABLE IF EXISTS `t1`; -SET @saved_cs_client = @@character_set_client; -SET character_set_client = utf8; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; CREATE TABLE `t1` ( `a` int(11) default NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1; -SET character_set_client = @saved_cs_client; +/*!40101 SET character_set_client = @saved_cs_client */; DROP TABLE IF EXISTS `t2`; -SET @saved_cs_client = @@character_set_client; -SET character_set_client = utf8; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; CREATE TABLE `t2` ( `a` int(11) default NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1; -SET character_set_client = @saved_cs_client; +/*!40101 SET character_set_client = @saved_cs_client */; /*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */; /*!40101 SET SQL_MODE=@OLD_SQL_MODE */; @@ -1860,12 +1845,12 @@ mysqldump: Got error: 1064: You have an error in your SQL syntax; check the manu /*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; DROP TABLE IF EXISTS `t1`; -SET @saved_cs_client = @@character_set_client; -SET character_set_client = utf8; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; CREATE TABLE `t1` ( `a` int(11) default NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1; -SET character_set_client = @saved_cs_client; +/*!40101 SET character_set_client = @saved_cs_client */; /*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */; @@ -1896,15 +1881,15 @@ insert into t1 values (0815, 4711, 2006); /*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO,ANSI' */; /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; DROP TABLE IF EXISTS "t1"; -SET @saved_cs_client = @@character_set_client; -SET character_set_client = utf8; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; CREATE TABLE "t1" ( "a b" int(11) NOT NULL default '0', "c""d" int(11) NOT NULL default '0', "e`f" int(11) NOT NULL default '0', PRIMARY KEY ("a b","c""d","e`f") ); -SET character_set_client = @saved_cs_client; +/*!40101 SET character_set_client = @saved_cs_client */; LOCK TABLES "t1" WRITE; /*!40000 ALTER TABLE "t1" DISABLE KEYS */; @@ -1930,15 +1915,15 @@ UNLOCK TABLES; /*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; DROP TABLE IF EXISTS `t1`; -SET @saved_cs_client = @@character_set_client; -SET character_set_client = utf8; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; CREATE TABLE `t1` ( `a b` int(11) NOT NULL default '0', `c"d` int(11) NOT NULL default '0', `e``f` int(11) NOT NULL default '0', PRIMARY KEY (`a b`,`c"d`,`e``f`) ) ENGINE=MyISAM DEFAULT CHARSET=latin1; -SET character_set_client = @saved_cs_client; +/*!40101 SET character_set_client = @saved_cs_client */; LOCK TABLES `t1` WRITE; /*!40000 ALTER TABLE `t1` DISABLE KEYS */; @@ -1984,13 +1969,13 @@ create view v2 as select * from t2 where a like 'a%' with check option; /*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; DROP TABLE IF EXISTS `t2`; -SET @saved_cs_client = @@character_set_client; -SET character_set_client = utf8; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; CREATE TABLE `t2` ( `a` varchar(30) default NULL, KEY `a` (`a`(5)) ) ENGINE=MyISAM DEFAULT CHARSET=latin1; -SET character_set_client = @saved_cs_client; +/*!40101 SET character_set_client = @saved_cs_client */; LOCK TABLES `t2` WRITE; /*!40000 ALTER TABLE `t2` DISABLE KEYS */; @@ -2068,12 +2053,12 @@ create view v1 as select * from t1; /*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; DROP TABLE IF EXISTS `t1`; -SET @saved_cs_client = @@character_set_client; -SET character_set_client = utf8; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; CREATE TABLE `t1` ( `a` int(11) default NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1; -SET character_set_client = @saved_cs_client; +/*!40101 SET character_set_client = @saved_cs_client */; LOCK TABLES `t1` WRITE; /*!40000 ALTER TABLE `t1` DISABLE KEYS */; @@ -2128,13 +2113,13 @@ create view v2 as select * from t2 where a like 'a%' with check option; /*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; DROP TABLE IF EXISTS `t2`; -SET @saved_cs_client = @@character_set_client; -SET character_set_client = utf8; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; CREATE TABLE `t2` ( `a` varchar(30) default NULL, KEY `a` (`a`(5)) ) ENGINE=MyISAM DEFAULT CHARSET=latin1; -SET character_set_client = @saved_cs_client; +/*!40101 SET character_set_client = @saved_cs_client */; LOCK TABLES `t2` WRITE; /*!40000 ALTER TABLE `t2` DISABLE KEYS */; @@ -2183,12 +2168,12 @@ INSERT INTO t1 VALUES ('\''); /*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; DROP TABLE IF EXISTS `t1`; -SET @saved_cs_client = @@character_set_client; -SET character_set_client = utf8; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; CREATE TABLE `t1` ( `a` char(10) default NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1; -SET character_set_client = @saved_cs_client; +/*!40101 SET character_set_client = @saved_cs_client */; LOCK TABLES `t1` WRITE; /*!40000 ALTER TABLE `t1` DISABLE KEYS */; @@ -2229,14 +2214,14 @@ select v3.a from v3, v1 where v1.a=v3.a and v3.b=3 limit 1; /*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; DROP TABLE IF EXISTS `t1`; -SET @saved_cs_client = @@character_set_client; -SET character_set_client = utf8; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; CREATE TABLE `t1` ( `a` int(11) default NULL, `b` int(11) default NULL, `c` varchar(30) default NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1; -SET character_set_client = @saved_cs_client; +/*!40101 SET character_set_client = @saved_cs_client */; LOCK TABLES `t1` WRITE; /*!40000 ALTER TABLE `t1` DISABLE KEYS */; @@ -2352,13 +2337,13 @@ CREATE DATABASE /*!32312 IF NOT EXISTS*/ `test` /*!40100 DEFAULT CHARACTER SET l USE `test`; DROP TABLE IF EXISTS `t1`; -SET @saved_cs_client = @@character_set_client; -SET character_set_client = utf8; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; CREATE TABLE `t1` ( `a` int(11) default NULL, `b` bigint(20) default NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1; -SET character_set_client = @saved_cs_client; +/*!40101 SET character_set_client = @saved_cs_client */; LOCK TABLES `t1` WRITE; /*!40000 ALTER TABLE `t1` DISABLE KEYS */; @@ -2392,12 +2377,12 @@ end */;; DELIMITER ; /*!50003 SET SESSION SQL_MODE=@SAVE_SQL_MODE*/; DROP TABLE IF EXISTS `t2`; -SET @saved_cs_client = @@character_set_client; -SET character_set_client = utf8; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; CREATE TABLE `t2` ( `a` int(11) default NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1; -SET character_set_client = @saved_cs_client; +/*!40101 SET character_set_client = @saved_cs_client */; LOCK TABLES `t2` WRITE; /*!40000 ALTER TABLE `t2` DISABLE KEYS */; @@ -2442,13 +2427,13 @@ CREATE DATABASE /*!32312 IF NOT EXISTS*/ `test` /*!40100 DEFAULT CHARACTER SET l USE `test`; DROP TABLE IF EXISTS `t1`; -SET @saved_cs_client = @@character_set_client; -SET character_set_client = utf8; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; CREATE TABLE `t1` ( `a` int(11) default NULL, `b` bigint(20) default NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1; -SET character_set_client = @saved_cs_client; +/*!40101 SET character_set_client = @saved_cs_client */; LOCK TABLES `t1` WRITE; /*!40000 ALTER TABLE `t1` DISABLE KEYS */; @@ -2456,12 +2441,12 @@ INSERT INTO `t1` VALUES (1,NULL),(2,NULL),(4,NULL),(11,NULL); /*!40000 ALTER TABLE `t1` ENABLE KEYS */; UNLOCK TABLES; DROP TABLE IF EXISTS `t2`; -SET @saved_cs_client = @@character_set_client; -SET character_set_client = utf8; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; CREATE TABLE `t2` ( `a` int(11) default NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1; -SET character_set_client = @saved_cs_client; +/*!40101 SET character_set_client = @saved_cs_client */; LOCK TABLES `t2` WRITE; /*!40000 ALTER TABLE `t2` DISABLE KEYS */; @@ -2585,12 +2570,12 @@ CREATE DATABASE /*!32312 IF NOT EXISTS*/ `test` /*!40100 DEFAULT CHARACTER SET l USE `test`; DROP TABLE IF EXISTS `t1`; -SET @saved_cs_client = @@character_set_client; -SET character_set_client = utf8; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; CREATE TABLE `t1` ( `id` int(11) default NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1; -SET character_set_client = @saved_cs_client; +/*!40101 SET character_set_client = @saved_cs_client */; LOCK TABLES `t1` WRITE; /*!40000 ALTER TABLE `t1` DISABLE KEYS */; @@ -2678,13 +2663,13 @@ CREATE DATABASE /*!32312 IF NOT EXISTS*/ `test` /*!40100 DEFAULT CHARACTER SET l USE `test`; DROP TABLE IF EXISTS `t1`; -SET @saved_cs_client = @@character_set_client; -SET character_set_client = utf8; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; CREATE TABLE `t1` ( `d` timestamp NOT NULL default CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP, UNIQUE KEY `d` (`d`) ) ENGINE=MyISAM DEFAULT CHARSET=latin1; -SET character_set_client = @saved_cs_client; +/*!40101 SET character_set_client = @saved_cs_client */; LOCK TABLES `t1` WRITE; /*!40000 ALTER TABLE `t1` DISABLE KEYS */; @@ -2715,13 +2700,13 @@ CREATE DATABASE /*!32312 IF NOT EXISTS*/ `test` /*!40100 DEFAULT CHARACTER SET l USE `test`; DROP TABLE IF EXISTS `t1`; -SET @saved_cs_client = @@character_set_client; -SET character_set_client = utf8; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; CREATE TABLE `t1` ( `d` timestamp NOT NULL default CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP, UNIQUE KEY `d` (`d`) ) ENGINE=MyISAM DEFAULT CHARSET=latin1; -SET character_set_client = @saved_cs_client; +/*!40101 SET character_set_client = @saved_cs_client */; LOCK TABLES `t1` WRITE; /*!40000 ALTER TABLE `t1` DISABLE KEYS */; @@ -2768,12 +2753,12 @@ a2 /*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO,ANSI' */; /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; DROP TABLE IF EXISTS "t1 test"; -SET @saved_cs_client = @@character_set_client; -SET character_set_client = utf8; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; CREATE TABLE "t1 test" ( "a1" int(11) default NULL ); -SET character_set_client = @saved_cs_client; +/*!40101 SET character_set_client = @saved_cs_client */; LOCK TABLES "t1 test" WRITE; /*!40000 ALTER TABLE "t1 test" DISABLE KEYS */; @@ -2791,12 +2776,12 @@ INSERT INTO `t2 test` SET a2 = NEW.a1; END */;; DELIMITER ; /*!50003 SET SESSION SQL_MODE=@SAVE_SQL_MODE*/; DROP TABLE IF EXISTS "t2 test"; -SET @saved_cs_client = @@character_set_client; -SET character_set_client = utf8; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; CREATE TABLE "t2 test" ( "a2" int(11) default NULL ); -SET character_set_client = @saved_cs_client; +/*!40101 SET character_set_client = @saved_cs_client */; LOCK TABLES "t2 test" WRITE; /*!40000 ALTER TABLE "t2 test" DISABLE KEYS */; @@ -2845,14 +2830,14 @@ CREATE DATABASE /*!32312 IF NOT EXISTS*/ `test` /*!40100 DEFAULT CHARACTER SET l USE `test`; DROP TABLE IF EXISTS `t1`; -SET @saved_cs_client = @@character_set_client; -SET character_set_client = utf8; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; CREATE TABLE `t1` ( `a` int(11) default NULL, `b` varchar(32) default NULL, `c` varchar(32) default NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1; -SET character_set_client = @saved_cs_client; +/*!40101 SET character_set_client = @saved_cs_client */; LOCK TABLES `t1` WRITE; /*!40000 ALTER TABLE `t1` DISABLE KEYS */; @@ -2940,12 +2925,12 @@ CREATE DATABASE /*!32312 IF NOT EXISTS*/ `test` /*!40100 DEFAULT CHARACTER SET l USE `test`; DROP TABLE IF EXISTS `t1`; -SET @saved_cs_client = @@character_set_client; -SET character_set_client = utf8; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; CREATE TABLE `t1` ( `a` int(11) default NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1; -SET character_set_client = @saved_cs_client; +/*!40101 SET character_set_client = @saved_cs_client */; LOCK TABLES `t1` WRITE; /*!40000 ALTER TABLE `t1` DISABLE KEYS */; @@ -2991,13 +2976,13 @@ insert into t1 values ('',''); /*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; DROP TABLE IF EXISTS `t1`; -SET @saved_cs_client = @@character_set_client; -SET character_set_client = utf8; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; CREATE TABLE `t1` ( `a` binary(1) default NULL, `b` blob ) ENGINE=MyISAM DEFAULT CHARSET=latin1; -SET character_set_client = @saved_cs_client; +/*!40101 SET character_set_client = @saved_cs_client */; LOCK TABLES `t1` WRITE; /*!40000 ALTER TABLE `t1` DISABLE KEYS */; @@ -3026,13 +3011,13 @@ UNLOCK TABLES; /*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; DROP TABLE IF EXISTS `t1`; -SET @saved_cs_client = @@character_set_client; -SET character_set_client = utf8; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; CREATE TABLE `t1` ( `a` binary(1) default NULL, `b` blob ) ENGINE=MyISAM DEFAULT CHARSET=latin1; -SET character_set_client = @saved_cs_client; +/*!40101 SET character_set_client = @saved_cs_client */; LOCK TABLES `t1` WRITE; /*!40000 ALTER TABLE `t1` DISABLE KEYS */; @@ -3187,12 +3172,12 @@ CREATE DATABASE /*!32312 IF NOT EXISTS*/ `mysqldump_test_db` /*!40100 DEFAULT CH USE `mysqldump_test_db`; DROP TABLE IF EXISTS `t1`; -SET @saved_cs_client = @@character_set_client; -SET character_set_client = utf8; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; CREATE TABLE `t1` ( `id` int(11) default NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1; -SET character_set_client = @saved_cs_client; +/*!40101 SET character_set_client = @saved_cs_client */; LOCK TABLES `t1` WRITE; /*!40000 ALTER TABLE `t1` DISABLE KEYS */; @@ -3237,14 +3222,14 @@ create view nasishnasifu as select mysqldump_tables.basetable.id from mysqldump_ CREATE DATABASE /*!32312 IF NOT EXISTS*/ `mysqldump_tables` /*!40100 DEFAULT CHARACTER SET latin1 */; USE `mysqldump_tables`; -SET @saved_cs_client = @@character_set_client; -SET character_set_client = utf8; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; CREATE TABLE `basetable` ( `id` bigint(20) unsigned NOT NULL auto_increment, `tag` varchar(64) default NULL, UNIQUE KEY `id` (`id`) ) ENGINE=MyISAM DEFAULT CHARSET=latin1; -SET character_set_client = @saved_cs_client; +/*!40101 SET character_set_client = @saved_cs_client */; CREATE DATABASE /*!32312 IF NOT EXISTS*/ `mysqldump_views` /*!40100 DEFAULT CHARACTER SET latin1 */; @@ -3312,13 +3297,13 @@ mysqldump: Couldn't execute 'SHOW MASTER STATUS': Access denied; you need the SU mysqldump: Couldn't execute 'SHOW MASTER STATUS': Access denied; you need the SUPER,REPLICATION CLIENT privilege for this operation (1227) grant REPLICATION CLIENT on *.* to mysqltest_1@localhost; CHANGE MASTER TO MASTER_LOG_FILE='master-bin.000001', MASTER_LOG_POS=#; -SET @saved_cs_client = @@character_set_client; -SET character_set_client = utf8; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; CREATE TABLE `t1` ( `a` int(11) default NULL, `b` varchar(34) default NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1; -SET character_set_client = @saved_cs_client; +/*!40101 SET character_set_client = @saved_cs_client */; drop table t1; drop user mysqltest_1@localhost; # @@ -3407,31 +3392,31 @@ CREATE TABLE t1 (a int) ENGINE=merge UNION=(t2, t3); /*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; DROP TABLE IF EXISTS `t1`; -SET @saved_cs_client = @@character_set_client; -SET character_set_client = utf8; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; CREATE TABLE `t1` ( `a` int(11) default NULL ) ENGINE=MRG_MyISAM DEFAULT CHARSET=latin1 UNION=(`t2`,`t3`); -SET character_set_client = @saved_cs_client; +/*!40101 SET character_set_client = @saved_cs_client */; DROP TABLE IF EXISTS `t2`; -SET @saved_cs_client = @@character_set_client; -SET character_set_client = utf8; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; CREATE TABLE `t2` ( `a` int(11) default NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1; -SET character_set_client = @saved_cs_client; +/*!40101 SET character_set_client = @saved_cs_client */; LOCK TABLES `t2` WRITE; /*!40000 ALTER TABLE `t2` DISABLE KEYS */; /*!40000 ALTER TABLE `t2` ENABLE KEYS */; UNLOCK TABLES; DROP TABLE IF EXISTS `t3`; -SET @saved_cs_client = @@character_set_client; -SET character_set_client = utf8; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; CREATE TABLE `t3` ( `a` int(11) default NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1; -SET character_set_client = @saved_cs_client; +/*!40101 SET character_set_client = @saved_cs_client */; LOCK TABLES `t3` WRITE; /*!40000 ALTER TABLE `t3` DISABLE KEYS */; @@ -3507,13 +3492,13 @@ drop database mysqldump_test_db; # CREATE TABLE t1 (c1 INT, c2 LONGBLOB); INSERT INTO t1 SET c1=11, c2=REPEAT('q',509); -SET @saved_cs_client = @@character_set_client; -SET character_set_client = utf8; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; CREATE TABLE `t1` ( `c1` int(11) default NULL, `c2` longblob ); -SET character_set_client = @saved_cs_client; +/*!40101 SET character_set_client = @saved_cs_client */; INSERT INTO `t1` VALUES (11,0x7171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171); DROP TABLE t1; # @@ -3571,6 +3556,83 @@ DROP TABLE t1,t2; -- Dump completed on DATE SET @@GLOBAL.CONCURRENT_INSERT = @OLD_CONCURRENT_INSERT; +SET NAMES utf8; +CREATE TABLE `straße` ( f1 INT ); +/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */; +/*!40103 SET TIME_ZONE='+00:00' */; +/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; +/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; +/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO,MYSQL323' */; +/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; +DROP TABLE IF EXISTS `straße`; +CREATE TABLE `straße` ( + `f1` int(11) default NULL +) TYPE=MyISAM; + +LOCK TABLES `straße` WRITE; +/*!40000 ALTER TABLE `straße` DISABLE KEYS */; +/*!40000 ALTER TABLE `straße` ENABLE KEYS */; +UNLOCK TABLES; +/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */; + +/*!40101 SET SQL_MODE=@OLD_SQL_MODE */; +/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */; +/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; +/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; + +/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */; +/*!40103 SET TIME_ZONE='+00:00' */; +/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; +/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; +/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO,MYSQL323' */; +/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; +DROP TABLE IF EXISTS `straße`; +CREATE TABLE `straße` ( + `f1` int(11) default NULL +) TYPE=MyISAM; + +LOCK TABLES `straße` WRITE; +/*!40000 ALTER TABLE `straße` DISABLE KEYS */; +/*!40000 ALTER TABLE `straße` ENABLE KEYS */; +UNLOCK TABLES; +/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */; + +/*!40101 SET SQL_MODE=@OLD_SQL_MODE */; +/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */; +/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; +/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; + +DROP TABLE `straße`; +CREATE TABLE `כדשגכחךלדגכחשךדגחכךלדגכ` ( f1 INT ); +/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */; +/*!40103 SET TIME_ZONE='+00:00' */; +/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; +/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; +/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO,MYSQL323' */; +/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; +DROP TABLE IF EXISTS `כדשגכחךלדגכחשךדגחכךלדגכ`; +CREATE TABLE `כדשגכחךלדגכחשךדגחכךלדגכ` ( + `f1` int(11) default NULL +) TYPE=MyISAM; + +LOCK TABLES `כדשגכחךלדגכחשךדגחכךלדגכ` WRITE; +/*!40000 ALTER TABLE `כדשגכחךלדגכחשךדגחכךלדגכ` DISABLE KEYS */; +/*!40000 ALTER TABLE `כדשגכחךלדגכחשךדגחכךלדגכ` ENABLE KEYS */; +UNLOCK TABLES; +/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */; + +/*!40101 SET SQL_MODE=@OLD_SQL_MODE */; +/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */; +/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; +/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; + +/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */; +/*!40103 SET TIME_ZONE='+00:00' */; +/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; +/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; +/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO,MYSQL323' */; +/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; +DROP TABLE `כדשגכחךלדגכחשךדגחכךלדגכ`; # # End of 5.0 tests # diff --git a/mysql-test/r/openssl_1.result b/mysql-test/r/openssl_1.result index 9c6c29eea47..32c8dfeac1c 100644 --- a/mysql-test/r/openssl_1.result +++ b/mysql-test/r/openssl_1.result @@ -77,12 +77,12 @@ INSERT INTO t1 VALUES (1), (2); /*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; DROP TABLE IF EXISTS `t1`; -SET @saved_cs_client = @@character_set_client; -SET character_set_client = utf8; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; CREATE TABLE `t1` ( `a` int(11) default NULL ); -SET character_set_client = @saved_cs_client; +/*!40101 SET character_set_client = @saved_cs_client */; LOCK TABLES `t1` WRITE; /*!40000 ALTER TABLE `t1` DISABLE KEYS */; @@ -111,12 +111,12 @@ UNLOCK TABLES; /*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; DROP TABLE IF EXISTS `t1`; -SET @saved_cs_client = @@character_set_client; -SET character_set_client = utf8; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; CREATE TABLE `t1` ( `a` int(11) default NULL ); -SET character_set_client = @saved_cs_client; +/*!40101 SET character_set_client = @saved_cs_client */; LOCK TABLES `t1` WRITE; /*!40000 ALTER TABLE `t1` DISABLE KEYS */; @@ -145,12 +145,12 @@ UNLOCK TABLES; /*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; DROP TABLE IF EXISTS `t1`; -SET @saved_cs_client = @@character_set_client; -SET character_set_client = utf8; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; CREATE TABLE `t1` ( `a` int(11) default NULL ); -SET character_set_client = @saved_cs_client; +/*!40101 SET character_set_client = @saved_cs_client */; LOCK TABLES `t1` WRITE; /*!40000 ALTER TABLE `t1` DISABLE KEYS */; diff --git a/mysql-test/t/mysqldump.test b/mysql-test/t/mysqldump.test index 2f11685385f..5b2af21c691 100644 --- a/mysql-test/t/mysqldump.test +++ b/mysql-test/t/mysqldump.test @@ -1606,6 +1606,24 @@ DROP TABLE t1,t2; SET @@GLOBAL.CONCURRENT_INSERT = @OLD_CONCURRENT_INSERT; +# +# Bug #33550 - mysqldump 4.0 compatibility broken +# + +SET NAMES utf8; +CREATE TABLE `straße` ( f1 INT ); +--exec $MYSQL_DUMP --character-sets-dir=$CHARSETSDIR --skip-comments --default-character-set=utf8 --compatible=mysql323 test +--exec $MYSQL_DUMP --character-sets-dir=$CHARSETSDIR --skip-comments --default-character-set=latin1 --compatible=mysql323 test +DROP TABLE `straße`; + +CREATE TABLE `כדשגכחךלדגכחשךדגחכךלדגכ` ( f1 INT ); +--exec $MYSQL_DUMP --character-sets-dir=$CHARSETSDIR --skip-comments --default-character-set=utf8 --compatible=mysql323 test +--error 2 +--exec $MYSQL_DUMP --character-sets-dir=$CHARSETSDIR --skip-comments --default-character-set=latin1 --compatible=mysql323 test +DROP TABLE `כדשגכחךלדגכחשךדגחכךלדגכ`; + + --echo # --echo # End of 5.0 tests --echo # + From 1a04fc03fee176c5732897b687f5f5c4f1708d1c Mon Sep 17 00:00:00 2001 From: Matthias Leich Date: Mon, 2 Feb 2009 22:20:25 +0100 Subject: [PATCH 015/219] 1. Slice of fix for Bug#42003 tests missing the disconnect of connections <> default - If missing: add "disconnect " - If physical disconnect of non "default" sessions is not finished at test end: add routine which waits till this happened + additional improvements like - remove superfluous files created by the test - replace error numbers by error names - remove trailing spaces, replace tabs by spaces - unify writing of bugs within comments - correct comments - minor changes of formatting Modifications according to the code review are included. Fixed tests: grant2 grant3 lock_tables_lost_commit mysqldump openssl_1 outfile --- mysql-test/include/count_sessions.inc | 21 ++ .../include/wait_until_count_sessions.inc | 112 +++++++++ mysql-test/r/grant2.result | 23 +- mysql-test/r/lock_tables_lost_commit.result | 12 +- mysql-test/r/mysqldump.result | 166 ++++++------- mysql-test/r/outfile.result | Bin 2135 -> 2134 bytes mysql-test/t/grant2.test | 123 +++++----- mysql-test/t/grant3.test | 16 +- mysql-test/t/lock_tables_lost_commit.test | 27 ++- mysql-test/t/mysqldump.test | 223 +++++++++++------- mysql-test/t/openssl_1.test | 26 +- mysql-test/t/outfile.test | 16 +- 12 files changed, 499 insertions(+), 266 deletions(-) create mode 100644 mysql-test/include/count_sessions.inc create mode 100644 mysql-test/include/wait_until_count_sessions.inc diff --git a/mysql-test/include/count_sessions.inc b/mysql-test/include/count_sessions.inc new file mode 100644 index 00000000000..4728e39ce74 --- /dev/null +++ b/mysql-test/include/count_sessions.inc @@ -0,0 +1,21 @@ +# include/count_sessions.inc +# +# SUMMARY +# +# Stores the number of current sessions in $count_sessions. +# +# +# USAGE +# +# Please look into include/wait_until_count_sessions.inc +# for examples of typical usage. +# +# +# EXAMPLE +# backup.test, grant3.test +# +# +# Created: 2009-01-14 mleich +# + +let $count_sessions= query_get_value(SHOW STATUS LIKE 'Threads_connected', Value, 1); diff --git a/mysql-test/include/wait_until_count_sessions.inc b/mysql-test/include/wait_until_count_sessions.inc new file mode 100644 index 00000000000..36fa9accafe --- /dev/null +++ b/mysql-test/include/wait_until_count_sessions.inc @@ -0,0 +1,112 @@ +# include/wait_until_count_sessions.inc +# +# SUMMARY +# +# Waits until the passed number ($count_sessions) of concurrent sessions was +# observed via +# SHOW STATUS LIKE 'Threads_connected' +# or the operation times out. +# Note: Starting with 5.1 we could also use +# SELECT COUNT(*) FROM information_schema.processlist +# I stay with "SHOW STATUS LIKE 'Threads_connected'" because this +# runs in all versions 5.0+ +# +# +# USAGE +# +# let $count_sessions= 3; +# --source include/wait_until_count_sessions.inc +# +# OR typical example of a test which uses more than one session +# Such a test could harm successing tests if there is no server shutdown +# and start between.cw +# +# If the testing box is slow than the disconnect of sessions belonging to +# the current test might happen when the successing test gets executed. +# This means the successing test might see activities like unexpected +# rows within the general log or the PROCESSLIST. +# Example from bug http://bugs.mysql.com/bug.php?id=40377 +# --- bzr_mysql-6.0-rpl/.../r/log_state.result +# +++ bzr_mysql-6.0-rpl/.../r/log_state.reject +# @@ -25,6 +25,7 @@ +# event_time user_host ... command_type argument +# TIMESTAMP USER_HOST ... Query create table t1(f1 int) +# TIMESTAMP USER_HOST ... Query select * from mysql.general_log +# +TIMESTAMP USER_HOST ... Quit +# .... +# +# What to do? +# ----------- +# +# # Determine initial number of connections (set $count_sessions) +# --source include/count_sessions.inc +# ... +# connect (con1,.....) +# ... +# connection default; +# ... +# disconnect con1; +# ... +# # Wait until we have reached the initial number of connections +# # or more than the sleep time above (10 seconds) has passed. +# # $count_sessions +# --source include/wait_until_count_sessions.inc +# +# +# Important note about tests with unfortunate (= not cooperative +# to successing tests) architecture: +# connection con1; +# send SELECT ..., sleep(10) +# connection default; +# ... +# disconnect con1; +# +# should be fixed by +# connection con1; +# send SELECT ..., sleep(10) +# connection default; +# ... +# connect con1; +# reap; +# connection default; +# disconnect con1; +# +# and not only by appending include/wait_until_count_sessions.inc etc. +# +# +# EXAMPLE +# +# backup.test, grant3.test +# +# +# Created: 2009-01-14 mleich +# + +let $wait_counter= 50; +if ($wait_timeout) +{ + let $wait_counter= `SELECT $wait_timeout * 10`; +} +# Reset $wait_timeout so that its value won't be used on subsequent +# calls, and default will be used instead. +let $wait_timeout= 0; +while ($wait_counter) +{ + let $current_sessions= query_get_value(SHOW STATUS LIKE 'Threads_connected', Value, 1); + let $success= `SELECT $current_sessions = $count_sessions`; + if ($success) + { + let $wait_counter= 0; + } + if (!$success) + { + real_sleep 0.1; + dec $wait_counter; + } +} +if (!$success) +{ + --echo # Timeout in wait_until_count_sessions.inc + --echo # Number of sessions expected: $count_sessions found: $current_sessions +} + diff --git a/mysql-test/r/grant2.result b/mysql-test/r/grant2.result index e3c92ecc7c8..95748c89103 100644 --- a/mysql-test/r/grant2.result +++ b/mysql-test/r/grant2.result @@ -366,20 +366,20 @@ insert into mysql.user select * from t1; drop table t1, t2; drop database TESTDB; flush privileges; -grant all privileges on test.* to `a@`@localhost; -grant execute on * to `a@`@localhost; -create table t2 (s1 int); -insert into t2 values (1); -drop function if exists f2; -create function f2 () returns int begin declare v int; select s1 from t2 -into v; return v; end// -select f2(); +GRANT ALL PRIVILEGES ON test.* TO `a@`@localhost; +GRANT EXECUTE ON * TO `a@`@localhost; +CREATE TABLE t2 (s1 INT); +INSERT INTO t2 VALUES (1); +DROP FUNCTION IF EXISTS f2; +CREATE FUNCTION f2 () RETURNS INT +BEGIN DECLARE v INT; SELECT s1 FROM t2 INTO v; RETURN v; END// +SELECT f2(); f2() 1 -drop function f2; -drop table t2; +DROP FUNCTION f2; +DROP TABLE t2; REVOKE ALL PRIVILEGES, GRANT OPTION FROM `a@`@localhost; -drop user `a@`@localhost; +DROP USER `a@`@localhost; drop database if exists mysqltest_1; drop database if exists mysqltest_2; drop user mysqltest_u1@localhost; @@ -436,6 +436,7 @@ SELECT * FROM t2; ERROR 42000: SELECT command denied to user 'mysqltest1'@'localhost' for column 'c' in table 't2' SELECT * FROM t1 JOIN t2 USING (b); ERROR 42000: SELECT command denied to user 'mysqltest1'@'localhost' for column 'c' in table 't2' +USE test; DROP TABLE db1.t1, db1.t2; DROP USER mysqltest1@localhost; DROP DATABASE db1; diff --git a/mysql-test/r/lock_tables_lost_commit.result b/mysql-test/r/lock_tables_lost_commit.result index 22885d93d40..df4b6eff5cf 100644 --- a/mysql-test/r/lock_tables_lost_commit.result +++ b/mysql-test/r/lock_tables_lost_commit.result @@ -1,8 +1,8 @@ -drop table if exists t1; -create table t1(a int) engine=innodb; -lock tables t1 write; -insert into t1 values(10); -select * from t1; +DROP TABLE IF EXISTS t1; +CREATE TABLE t1(a INT) ENGINE=innodb; +LOCK TABLES t1 WRITE; +INSERT INTO t1 VALUES(10); +SELECT * FROM t1; a 10 -drop table t1; +DROP TABLE t1; diff --git a/mysql-test/r/mysqldump.result b/mysql-test/r/mysqldump.result index 08a18d8de75..76e553dea42 100644 --- a/mysql-test/r/mysqldump.result +++ b/mysql-test/r/mysqldump.result @@ -1,6 +1,6 @@ -Bug#37938 - Test "mysqldump" lacks various insert statements -Turn off concurrent inserts to avoid random errors -NOTE: We reset the variable back to saved value at the end of test +# Bug#37938 Test "mysqldump" lacks various insert statements +# Turn off concurrent inserts to avoid random errors +# NOTE: We reset the variable back to saved value at the end of test SET @OLD_CONCURRENT_INSERT = @@GLOBAL.CONCURRENT_INSERT; SET @@GLOBAL.CONCURRENT_INSERT = 0; DROP TABLE IF EXISTS t1, `"t"1`, t1aa, t2, t2aa, t3; @@ -8,7 +8,7 @@ drop database if exists mysqldump_test_db; drop database if exists db1; drop database if exists db2; drop view if exists v1, v2, v3; -CREATE TABLE t1(a int); +CREATE TABLE t1(a INT); INSERT INTO t1 VALUES (1), (2); @@ -28,7 +28,7 @@ INSERT INTO t1 VALUES (1), (2); DROP TABLE t1; # -# Bug #2005 +# Bug#2005 Long decimal comparison bug. # CREATE TABLE t1 (a decimal(64, 20)); INSERT INTO t1 VALUES ("1234567890123456789012345678901234567890"), @@ -42,7 +42,7 @@ SET character_set_client = @saved_cs_client; INSERT INTO `t1` VALUES ('1234567890123456789012345678901234567890.00000000000000000000'),('987654321098765432109876543210987654321.00000000000000000000'); DROP TABLE t1; # -# Bug #2055 +# Bug#2055 mysqldump should replace "-inf" numeric field values with "NULL" # CREATE TABLE t1 (a double); INSERT INTO t1 VALUES ('-9e999999'); @@ -57,7 +57,7 @@ SET character_set_client = @saved_cs_client; INSERT INTO `t1` VALUES (RES); DROP TABLE t1; # -# Bug #3361 mysqldump quotes DECIMAL values inconsistently +# Bug#3361 mysqldump quotes DECIMAL values inconsistently # CREATE TABLE t1 (a DECIMAL(10,5), b FLOAT); INSERT INTO t1 VALUES (1.2345, 2.3456); @@ -169,7 +169,7 @@ INSERT INTO t1 VALUES (1, "test", "tes"), (2, "TEST", "TES"); DROP TABLE t1; # -# Bug #1707 +# Bug#1707 mysqldump -X does't quote field and table names # CREATE TABLE t1 (`a"b"` char(2)); INSERT INTO t1 VALUES ("1\""), ("\"2"); @@ -191,8 +191,8 @@ INSERT INTO t1 VALUES ("1\""), ("\"2"); DROP TABLE t1; # -# Bug #1994 -# Bug #4261 +# Bug#1994 mysqldump does not correctly dump UCS2 data +# Bug#4261 mysqldump 10.7 (mysql 4.1.2) --skip-extended-insert drops NULL from inserts # CREATE TABLE t1 (a VARCHAR(255)) DEFAULT CHARSET koi8r; INSERT INTO t1 VALUES (_koi8r x'C1C2C3C4C5'), (NULL); @@ -233,7 +233,7 @@ UNLOCK TABLES; DROP TABLE t1; # -# Bug #2634 +# Bug#2634 mysqldump in --compatible=mysql4 # CREATE TABLE t1 (a int) ENGINE=MYISAM; INSERT INTO t1 VALUES (1), (2); @@ -291,7 +291,7 @@ UNLOCK TABLES; DROP TABLE t1; # -# Bug #2592 'mysqldump doesn't quote "tricky" names correctly' +# Bug#2592 mysqldump doesn't quote "tricky" names correctly # create table ```a` (i int); SET @saved_cs_client = @@character_set_client; @@ -302,7 +302,7 @@ CREATE TABLE ```a` ( SET character_set_client = @saved_cs_client; drop table ```a`; # -# Bug #2591 "mysqldump quotes names inconsistently" +# Bug#2591 mysqldump quotes names inconsistently # create table t1(a int); @@ -425,7 +425,7 @@ UNLOCK TABLES; set global sql_mode=''; drop table t1; # -# Bug #2705 'mysqldump --tab extra output' +# Bug#2705 mysqldump --tab extra output # create table t1(a int); insert into t1 values (1),(2),(3); @@ -459,7 +459,7 @@ SET character_set_client = @saved_cs_client; 3 drop table t1; # -# Bug #6101: create database problem +# Bug#6101 create database problem # /*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; @@ -514,7 +514,7 @@ USE `mysqldump_test_db`; drop database mysqldump_test_db; # -# Bug #7020 +# Bug#7020 mysqldump --compatible=mysql40 should set --skip-set-charset --default-char... # Check that we don't dump in UTF8 in compatible mode by default, # but use the default compiled values, or the values given in # --default-character-set=xxx. However, we should dump in UTF8 @@ -556,8 +556,8 @@ UNLOCK TABLES; /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; # -# Bug#8063: make test mysqldump [ fail ] -# We cannot tes this command because its output depends +# Bug#8063 make test mysqldump [ fail ] +# We cannot test this command because its output depends # on --default-character-set incompiled into "mysqldump" program. # If the future we can move this command into a separate test with # checking that "mysqldump" is compiled with "latin1" @@ -642,7 +642,7 @@ UNLOCK TABLES; DROP TABLE t1; # -# WL #2319: Exclude Tables from dump +# WL#2319 Exclude Tables from dump # CREATE TABLE t1 (a int); CREATE TABLE t2 (a int); @@ -685,7 +685,7 @@ UNLOCK TABLES; DROP TABLE t1; DROP TABLE t2; # -# Bug #8830 +# Bug#8830 mysqldump --skip-extended-insert causes --hex-blob to dump wrong values # CREATE TABLE t1 (`b` blob); INSERT INTO `t1` VALUES (0x602010000280100005E71A); @@ -727,7 +727,7 @@ DROP TABLE t1; # # Test for --insert-ignore # -CREATE TABLE t1 (a int); +CREATE TABLE t1 (a INT); INSERT INTO t1 VALUES (1),(2),(3); INSERT INTO t1 VALUES (4),(5),(6); @@ -798,9 +798,9 @@ INSERT DELAYED IGNORE INTO `t1` VALUES (1),(2),(3),(4),(5),(6); DROP TABLE t1; # -# Bug #10286: mysqldump -c crashes on table that has many fields with long -# names -# +# Bug#10286 mysqldump -c crashes on table that has many fields with long +# names +# create table t1 ( F_c4ca4238a0b923820dcc509a6f75849b int, F_c81e728d9d4c2f636f067f89cc14862c int, @@ -1544,7 +1544,7 @@ UNLOCK TABLES; DROP TABLE t1; # -# Bug #9558 mysqldump --no-data db t1 t2 format still dumps data +# Bug#9558 mysqldump --no-data db t1 t2 format still dumps data # CREATE DATABASE mysqldump_test_db; USE mysqldump_test_db; @@ -1649,7 +1649,7 @@ DROP DATABASE mysqldump_test_db; # # Testing with tables and databases that don't exists # or contains illegal characters -# (Bug #9358 mysqldump crashes if tablename starts with \) +# (Bug#9358 mysqldump crashes if tablename starts with \) # create database mysqldump_test_db; use mysqldump_test_db; @@ -1678,7 +1678,7 @@ drop table t1, t2, t3; drop database mysqldump_test_db; use test; # -# Bug #9657 mysqldump xml ( -x ) does not format NULL fields correctly +# Bug#9657 mysqldump xml ( -x ) does not format NULL fields correctly # create table t1 (a int(10)); create table t2 (pk int primary key auto_increment, @@ -1737,7 +1737,7 @@ insert into t2 (a, b) values (NULL, NULL),(10, NULL),(NULL, "twenty"),(30, "thir drop table t1, t2; # -# BUG #12123 +# Bug#12123 mysqldump --tab results in text file which can't be imported # create table t1 (a text character set utf8, b text character set latin1); insert t1 values (0x4F736E616272C3BC636B, 0x4BF66C6E); @@ -1750,11 +1750,11 @@ a b Osnabrück Köln drop table t1; # -# BUG#15328 Segmentation fault occured if my.cnf is invalid for escape sequence +# Bug#15328 Segmentation fault occured if my.cnf is invalid for escape sequence # --fields-optionally-enclosed-by=" # -# BUG #19025 mysqldump doesn't correctly dump "auto_increment = [int]" +# Bug#19025 mysqldump doesn't correctly dump "auto_increment = [int]" # create table `t1` ( t1_name varchar(255) default null, @@ -1794,7 +1794,7 @@ t1 CREATE TABLE `t1` ( ) ENGINE=MyISAM AUTO_INCREMENT=1003 DEFAULT CHARSET=latin1 drop table `t1`; # -# Bug #18536: wrong table order +# Bug#18536 wrong table order # create table t1(a int); create table t2(a int); @@ -1843,7 +1843,7 @@ SET character_set_client = @saved_cs_client; drop table t1, t2, t3; # -# Bug #21288: mysqldump segmentation fault when using --where +# Bug#21288 mysqldump segmentation fault when using --where # create table t1 (a int); mysqldump: Couldn't execute 'SELECT /*!40001 SQL_NO_CACHE */ * FROM `t1` WHERE xx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx': You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' at line 1 (1064) @@ -1879,7 +1879,7 @@ SET character_set_client = @saved_cs_client; drop table t1; # -# BUG#13926: --order-by-primary fails if PKEY contains quote character +# Bug#13926 --order-by-primary fails if PKEY contains quote character # DROP TABLE IF EXISTS `t1`; CREATE TABLE `t1` ( @@ -1958,7 +1958,7 @@ UNLOCK TABLES; DROP TABLE `t1`; End of 4.1 tests # -# Bug #10213 mysqldump crashes when dumping VIEWs(on MacOS X) +# Bug#10213 mysqldump crashes when dumping VIEWs(on MacOS X) # create database db1; use db1; @@ -2023,7 +2023,7 @@ drop view v2; drop database db1; use test; # -# Bug 10713 mysqldump includes database in create view and referenced tables +# Bug#10713 mysqldump includes database in create view and referenced tables # create database db2; use db2; @@ -2102,7 +2102,7 @@ DROP TABLE IF EXISTS `v1`; drop view v1; drop table t1; # -# Bug #10213 mysqldump crashes when dumping VIEWs(on MacOS X) +# Bug#10213 mysqldump crashes when dumping VIEWs(on MacOS X) # create database mysqldump_test_db; use mysqldump_test_db; @@ -2167,7 +2167,7 @@ drop view v2; drop database mysqldump_test_db; use test; # -# Bug #9756 +# Bug#9756 mysql client failing on dumps containing certain \ sequences # CREATE TABLE t1 (a char(10)); INSERT INTO t1 VALUES ('\''); @@ -2207,7 +2207,7 @@ UNLOCK TABLES; DROP TABLE t1; # -# Bug #10927 mysqldump: Can't reload dump with view that consist of other view +# Bug#10927 mysqldump: Can't reload dump with view that consist of other view # create table t1(a int, b int, c varchar(30)); insert into t1 values(1, 2, "one"), (2, 4, "two"), (3, 6, "three"); @@ -2505,12 +2505,14 @@ end if; end BEFORE # STRICT_TRANS_TABLES,STRICT_ALL_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,TRADITIONAL,NO_AUTO_CREATE_USER root@localhost DROP TABLE t1, t2; # -# Bugs #9136, #12917: problems with --defaults-extra-file option +# Bug#9136 my_print_defaults changed behaviour between 4.1.7 and 4.1.10a +# Bug#12917 The --defaults-extra-file option is ignored by the 5.0 client binaries +# (Problems with --defaults-extra-file option) # --port=1234 --port=1234 # -# Test of fix to BUG 12597 +# Test of fix to Bug#12597 mysqldump dumps triggers wrongly # DROP TABLE IF EXISTS `test1`; Warnings: @@ -2544,7 +2546,7 @@ DROP TRIGGER testref; DROP TABLE test1; DROP TABLE test2; # -# BUG#9056 - mysqldump does not dump routines +# Bug#9056 mysqldump does not dump routines # DROP TABLE IF EXISTS t1; DROP FUNCTION IF EXISTS bug9056_func1; @@ -2562,9 +2564,9 @@ begin set f1= concat( 'hello', f1 ); return f1; end // -CREATE PROCEDURE bug9056_proc2(OUT a INT) -BEGIN -select sum(id) from t1 into a; +CREATE PROCEDURE bug9056_proc2(OUT a INT) +BEGIN +select sum(id) from t1 into a; END // set sql_mode='ansi'; create procedure `a'b` () select 1; @@ -2624,8 +2626,8 @@ BEGIN SELECT a+b INTO c; end */;; /*!50003 DROP PROCEDURE IF EXISTS `bug9056_proc2` */;; /*!50003 SET SESSION SQL_MODE=""*/;; /*!50003 CREATE*/ /*!50020 DEFINER=`root`@`localhost`*/ /*!50003 PROCEDURE `bug9056_proc2`(OUT a INT) -BEGIN -select sum(id) from t1 into a; +BEGIN +select sum(id) from t1 into a; END */;; /*!50003 SET SESSION SQL_MODE=@OLD_SQL_MODE*/;; DELIMITER ; @@ -2646,7 +2648,7 @@ DROP PROCEDURE bug9056_proc2; DROP PROCEDURE `a'b`; drop table t1; # -# BUG# 13052 - mysqldump timestamp reloads broken +# Bug#13052 mysqldump timestamp reloads broken # drop table if exists t1; create table t1 (`d` timestamp, unique (`d`)); @@ -2741,7 +2743,7 @@ drop table t1; set global time_zone=default; set time_zone=default; # -# Test of fix to BUG 13146 - ansi quotes break loading of triggers +# Test of fix to Bug#13146 ansi quotes break loading of triggers # DROP TABLE IF EXISTS `t1 test`; DROP TABLE IF EXISTS `t2 test`; @@ -2814,7 +2816,7 @@ DROP TRIGGER `test trig`; DROP TABLE `t1 test`; DROP TABLE `t2 test`; # -# BUG# 12838 mysqldump -x with views exits with error +# Bug#12838 mysqldump -x with views exits with error # drop table if exists t1; create table t1 (a int, b varchar(32), c varchar(32)); @@ -2912,7 +2914,7 @@ drop view v0; drop view v1; drop table t1; # -# BUG#14554 - mysqldump does not separate words "ROW" and "BEGIN" +# Bug#14554 mysqldump does not separate words "ROW" and "BEGIN" # for tables with trigger created in the IGNORE_SPACE sql mode. # SET @old_sql_mode = @@SQL_MODE; @@ -2975,8 +2977,8 @@ DELIMITER ; DROP TRIGGER tr1; DROP TABLE t1; # -# Bug #13318: Bad result with empty field and --hex-blob -# +# Bug#13318 Bad result with empty field and --hex-blob +# create table t1 (a binary(1), b blob); insert into t1 values ('',''); @@ -3051,7 +3053,7 @@ UNLOCK TABLES; drop table t1; # -# Bug 14871 Invalid view dump output +# Bug#14871 Invalid view dump output # create table t1 (a int); insert into t1 values (289), (298), (234), (456), (789); @@ -3080,7 +3082,7 @@ a drop table t1; drop view v1, v2, v3, v4, v5; # -# Bug #16878 dump of trigger +# Bug#16878 dump of trigger # create table t1 (a int, created datetime); create table t2 (b int, created datetime); @@ -3130,7 +3132,7 @@ drop view v2; drop table t; # # Bug#14857 Reading dump files with single statement stored routines fails. -# fixed by patch for bug#16878 +# fixed by patch for Bug#16878 # /*!50003 CREATE FUNCTION `f`() RETURNS bigint(20) return 42 */| @@ -3147,7 +3149,7 @@ select 42 drop function f; drop procedure p; # -# Bug #17371 Unable to dump a schema with invalid views +# Bug#17371 Unable to dump a schema with invalid views # create table t1 ( id serial ); create view v1 as select * from t1; @@ -3158,7 +3160,7 @@ mysqldump { } mysqldump drop view v1; -# BUG#17201 Spurious 'DROP DATABASE' in output, +# Bug#17201 Spurious 'DROP DATABASE' in output, # also confusion between tables and views. # Example code from Markus Popp create database mysqldump_test_db; @@ -3225,7 +3227,7 @@ drop view v1; drop table t1; drop database mysqldump_test_db; # -# Bug21014 Segmentation fault of mysqldump on view +# Bug#21014 Segmentation fault of mysqldump on view # create database mysqldump_tables; use mysqldump_tables; @@ -3265,7 +3267,7 @@ drop database mysqldump_views; drop table mysqldump_tables.basetable; drop database mysqldump_tables; # -# Bug20221 Dumping of multiple databases containing view(s) yields maleformed dumps +# Bug#20221 Dumping of multiple databases containing view(s) yields maleformed dumps # create database mysqldump_dba; use mysqldump_dba; @@ -3322,10 +3324,10 @@ SET character_set_client = @saved_cs_client; drop table t1; drop user mysqltest_1@localhost; # -# Bug #21527 mysqldump incorrectly tries to LOCK TABLES on the -# information_schema database. +# Bug#21527 mysqldump incorrectly tries to LOCK TABLES on the +# information_schema database. # -# Bug #21424 mysqldump failing to export/import views +# Bug#21424 mysqldump failing to export/import views # create database mysqldump_myDB; use mysqldump_myDB; @@ -3345,8 +3347,8 @@ revoke all privileges on mysqldump_myDB.* from myDB_User@localhost; drop user myDB_User@localhost; drop database mysqldump_myDB; flush privileges; -# Bug #21424 continues from here. -# Restore. Flush Privileges test ends. +# Bug#21424 continues from here. +# Restore. Flush Privileges test ends. # use mysqldump_myDB; select * from mysqldump_myDB.v1; @@ -3364,7 +3366,7 @@ drop user myDB_User@localhost; drop database mysqldump_myDB; use test; # -# Bug #19745: mysqldump --xml produces invalid xml +# Bug#19745 mysqldump --xml produces invalid xml # DROP TABLE IF EXISTS t1; CREATE TABLE t1 (f1 int(10), data MEDIUMBLOB); @@ -3386,15 +3388,15 @@ INSERT INTO t1 VALUES(1,0xff00fef0); DROP TABLE t1; # -# Bug#26346: stack + buffer overrun in mysqldump +# Bug#26346 stack + buffer overrun in mysqldump # CREATE TABLE t1(a int); INSERT INTO t1 VALUES (1), (2); mysqldump: Input filename too long: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa DROP TABLE t1; -CREATE TABLE t2 (a int); -CREATE TABLE t3 (a int); -CREATE TABLE t1 (a int) ENGINE=merge UNION=(t2, t3); +CREATE TABLE t2 (a INT); +CREATE TABLE t3 (a INT); +CREATE TABLE t1 (a INT) ENGINE=merge UNION=(t2, t3); /*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; /*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; @@ -3449,7 +3451,7 @@ UNLOCK TABLES; DROP TABLE t1, t2, t3; # -# Bug #23491: MySQLDump prefix function call in a view by database name +# Bug#23491 MySQLDump prefix function call in a view by database name # create database bug23491_original; create database bug23491_restore; @@ -3471,12 +3473,12 @@ v3 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VI drop database bug23491_original; drop database bug23491_restore; use test; -# -# Bug 27293: mysqldump crashes when dumping routines -# defined by a different user # -# Bug #22761: mysqldump reports no errors when using -# --routines without mysql.proc privileges +# Bug#27293 mysqldump crashes when dumping routines +# defined by a different user +# +# Bug#22761 mysqldump reports no errors when using +# --routines without mysql.proc privileges # create database mysqldump_test_db; grant all privileges on mysqldump_test_db.* to user1; @@ -3503,7 +3505,7 @@ drop user user1; drop user user2; drop database mysqldump_test_db; # -# Bug #28522: buffer overrun by '\0' byte using --hex-blob. +# Bug#28522 buffer overrun by '\0' byte using --hex-blob. # CREATE TABLE t1 (c1 INT, c2 LONGBLOB); INSERT INTO t1 SET c1=11, c2=REPEAT('q',509); @@ -3517,8 +3519,8 @@ SET character_set_client = @saved_cs_client; INSERT INTO `t1` VALUES (11,0x7171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171); DROP TABLE t1; # -# Bug #28524: mysqldump --skip-add-drop-table is not -# compatible with views +# Bug#28524 mysqldump --skip-add-drop-table is not +# compatible with views # CREATE VIEW v1 AS SELECT 1; DROP VIEW v1; @@ -3527,8 +3529,8 @@ SELECT * FROM v1; 1 DROP VIEW v1; # -# Bug #29788: mysqldump discards the NO_AUTO_VALUE_ON_ZERO value of -# the SQL_MODE variable after the dumping of triggers. +# Bug#29788 mysqldump discards the NO_AUTO_VALUE_ON_ZERO value of +# the SQL_MODE variable after the dumping of triggers. # CREATE TABLE t1 (c1 INT); CREATE TRIGGER t1bd BEFORE DELETE ON t1 FOR EACH ROW BEGIN END; @@ -3549,8 +3551,8 @@ c1 2 DROP TABLE t1,t2; # -# Bug#29815: new option for suppressing last line of mysqldump: -# "Dump completed on" +# Bug#29815 new option for suppressing last line of mysqldump: +# "Dump completed on" # # --skip-dump-date: -- diff --git a/mysql-test/r/outfile.result b/mysql-test/r/outfile.result index 8503df545d2d0bfc67d5c8aa9e6e8a51ca23d5ca..e8c62098f95925a2ad465b451b4f275b67f9dc5a 100644 GIT binary patch delta 12 TcmcaEa7|!C8T00H<_9bQBd`Ss delta 14 Vcmca6a9v&1 - + --error 6 --exec $MYSQL_DUMP --compact --skip-comments mysqldump_test_db "\\\\t1" 2>&1 @@ -644,7 +647,7 @@ use test; --echo # ---echo # Bug #9657 mysqldump xml ( -x ) does not format NULL fields correctly +--echo # Bug#9657 mysqldump xml ( -x ) does not format NULL fields correctly --echo # create table t1 (a int(10)); @@ -655,8 +658,9 @@ insert into t2 (a, b) values (NULL, NULL),(10, NULL),(NULL, "twenty"),(30, "thir --exec $MYSQL_DUMP --skip-comments --xml --no-create-info test drop table t1, t2; + --echo # ---echo # BUG #12123 +--echo # Bug#12123 mysqldump --tab results in text file which can't be imported --echo # create table t1 (a text character set utf8, b text character set latin1); @@ -669,14 +673,15 @@ select * from t1; drop table t1; + --echo # ---echo # BUG#15328 Segmentation fault occured if my.cnf is invalid for escape sequence +--echo # Bug#15328 Segmentation fault occured if my.cnf is invalid for escape sequence --echo # --exec $MYSQL_MY_PRINT_DEFAULTS --config-file=$MYSQL_TEST_DIR/std_data/bug15328.cnf mysqldump --echo # ---echo # BUG #19025 mysqldump doesn't correctly dump "auto_increment = [int]" +--echo # Bug#19025 mysqldump doesn't correctly dump "auto_increment = [int]" --echo # create table `t1` ( @@ -704,9 +709,11 @@ select * from t1; show create table `t1`; drop table `t1`; +--remove_file $MYSQLTEST_VARDIR/tmp/bug19025.sql + --echo # ---echo # Bug #18536: wrong table order +--echo # Bug#18536 wrong table order --echo # create table t1(a int); @@ -716,8 +723,9 @@ create table t3(a int); --exec $MYSQL_DUMP --skip-comments --force --no-data test t3 t1 non_existing t2 drop table t1, t2, t3; + --echo # ---echo # Bug #21288: mysqldump segmentation fault when using --where +--echo # Bug#21288 mysqldump segmentation fault when using --where --echo # create table t1 (a int); @@ -725,8 +733,9 @@ create table t1 (a int); --exec $MYSQL_DUMP --skip-comments --force test t1 --where="xx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" 2>&1 drop table t1; + --echo # ---echo # BUG#13926: --order-by-primary fails if PKEY contains quote character +--echo # Bug#13926 --order-by-primary fails if PKEY contains quote character --echo # --disable_warnings @@ -746,8 +755,9 @@ DROP TABLE `t1`; --echo End of 4.1 tests + --echo # ---echo # Bug #10213 mysqldump crashes when dumping VIEWs(on MacOS X) +--echo # Bug#10213 mysqldump crashes when dumping VIEWs(on MacOS X) --echo # create database db1; @@ -770,8 +780,9 @@ drop view v2; drop database db1; use test; + --echo # ---echo # Bug 10713 mysqldump includes database in create view and referenced tables +--echo # Bug#10713 mysqldump includes database in create view and referenced tables --echo # # create table and views in db2 @@ -805,18 +816,21 @@ select * from t2 order by a; drop table t1, t2; drop database db1; use test; +--remove_file $MYSQLTEST_VARDIR/tmp/bug10713.sql # # dump of view # + create table t1(a int); create view v1 as select * from t1; --exec $MYSQL_DUMP --skip-comments test drop view v1; drop table t1; + --echo # ---echo # Bug #10213 mysqldump crashes when dumping VIEWs(on MacOS X) +--echo # Bug#10213 mysqldump crashes when dumping VIEWs(on MacOS X) --echo # create database mysqldump_test_db; @@ -840,7 +854,7 @@ drop database mysqldump_test_db; use test; --echo # ---echo # Bug #9756 +--echo # Bug#9756 mysql client failing on dumps containing certain \ sequences --echo # CREATE TABLE t1 (a char(10)); @@ -849,7 +863,7 @@ INSERT INTO t1 VALUES ('\''); DROP TABLE t1; --echo # ---echo # Bug #10927 mysqldump: Can't reload dump with view that consist of other view +--echo # Bug#10927 mysqldump: Can't reload dump with view that consist of other view --echo # create table t1(a int, b int, c varchar(30)); @@ -921,7 +935,9 @@ show triggers; DROP TABLE t1, t2; --echo # ---echo # Bugs #9136, #12917: problems with --defaults-extra-file option +--echo # Bug#9136 my_print_defaults changed behaviour between 4.1.7 and 4.1.10a +--echo # Bug#12917 The --defaults-extra-file option is ignored by the 5.0 client binaries +--echo # (Problems with --defaults-extra-file option) --echo # --write_file $MYSQLTEST_VARDIR/tmp/tmp.cnf @@ -933,7 +949,7 @@ EOF --remove_file $MYSQLTEST_VARDIR/tmp/tmp.cnf --echo # ---echo # Test of fix to BUG 12597 +--echo # Test of fix to Bug#12597 mysqldump dumps triggers wrongly --echo # DROP TABLE IF EXISTS `test1`; @@ -969,9 +985,11 @@ SELECT * FROM `test2`; DROP TRIGGER testref; DROP TABLE test1; DROP TABLE test2; +--remove_file $MYSQLTEST_VARDIR/tmp/mysqldump.sql + --echo # ---echo # BUG#9056 - mysqldump does not dump routines +--echo # Bug#9056 mysqldump does not dump routines --echo # --disable_warnings @@ -997,9 +1015,9 @@ begin return f1; end // -CREATE PROCEDURE bug9056_proc2(OUT a INT) -BEGIN - select sum(id) from t1 into a; +CREATE PROCEDURE bug9056_proc2(OUT a INT) +BEGIN + select sum(id) from t1 into a; END // DELIMITER ;// @@ -1008,7 +1026,7 @@ set sql_mode='ansi'; create procedure `a'b` () select 1; # to fix syntax highlighting :') set sql_mode=''; -# Dump the DB and ROUTINES +# Dump the DB and ROUTINES --exec $MYSQL_DUMP --skip-comments --routines --databases test # ok, now blow it all away @@ -1019,8 +1037,9 @@ DROP PROCEDURE bug9056_proc2; DROP PROCEDURE `a'b`; drop table t1; + --echo # ---echo # BUG# 13052 - mysqldump timestamp reloads broken +--echo # Bug#13052 mysqldump timestamp reloads broken --echo # --disable_warnings @@ -1043,7 +1062,7 @@ set global time_zone=default; set time_zone=default; --echo # ---echo # Test of fix to BUG 13146 - ansi quotes break loading of triggers +--echo # Test of fix to Bug#13146 ansi quotes break loading of triggers --echo # --disable_warnings @@ -1068,7 +1087,7 @@ INSERT INTO `t1 test` VALUES (1); INSERT INTO `t1 test` VALUES (2); INSERT INTO `t1 test` VALUES (3); SELECT * FROM `t2 test`; -# dump with compatible=ansi. Everything except triggers should be double +# dump with compatible=ansi. Everything except triggers should be double # quoted --exec $MYSQL_DUMP --skip-comments --compatible=ansi --triggers test @@ -1077,7 +1096,7 @@ DROP TABLE `t1 test`; DROP TABLE `t2 test`; --echo # ---echo # BUG# 12838 mysqldump -x with views exits with error +--echo # Bug#12838 mysqldump -x with views exits with error --echo # --disable_warnings @@ -1101,7 +1120,7 @@ drop view v1; drop table t1; --echo # ---echo # BUG#14554 - mysqldump does not separate words "ROW" and "BEGIN" +--echo # Bug#14554 mysqldump does not separate words "ROW" and "BEGIN" --echo # for tables with trigger created in the IGNORE_SPACE sql mode. --echo # @@ -1125,8 +1144,8 @@ DROP TRIGGER tr1; DROP TABLE t1; --echo # ---echo # Bug #13318: Bad result with empty field and --hex-blob ---echo # +--echo # Bug#13318 Bad result with empty field and --hex-blob +--echo # create table t1 (a binary(1), b blob); insert into t1 values ('',''); @@ -1135,7 +1154,7 @@ insert into t1 values ('',''); drop table t1; --echo # ---echo # Bug 14871 Invalid view dump output +--echo # Bug#14871 Invalid view dump output --echo # create table t1 (a int); @@ -1162,9 +1181,11 @@ select * from v3 order by a; drop table t1; drop view v1, v2, v3, v4, v5; +--remove_file $MYSQLTEST_VARDIR/tmp/bug14871.sql + --echo # ---echo # Bug #16878 dump of trigger +--echo # Bug#16878 dump of trigger --echo # create table t1 (a int, created datetime); @@ -1192,6 +1213,8 @@ show triggers; drop trigger tr1; drop trigger tr2; drop table t1, t2; +--remove_file $MYSQLTEST_VARDIR/tmp/bug16878.sql + --echo # --echo # Bug#18462 mysqldump does not dump view structures correctly @@ -1211,11 +1234,15 @@ create view v2 as select qty from v1; drop view v1; drop view v2; drop table t; +--remove_file $MYSQLTEST_VARDIR/tmp/v1.sql +--remove_file $MYSQLTEST_VARDIR/tmp/v2.sql +--remove_file $MYSQLTEST_VARDIR/tmp/t.sql +--remove_file $MYSQLTEST_VARDIR/tmp/t.txt --echo # --echo # Bug#14857 Reading dump files with single statement stored routines fails. ---echo # fixed by patch for bug#16878 +--echo # fixed by patch for Bug#16878 --echo # DELIMITER |; @@ -1230,7 +1257,7 @@ drop function f; drop procedure p; --echo # ---echo # Bug #17371 Unable to dump a schema with invalid views +--echo # Bug#17371 Unable to dump a schema with invalid views --echo # create table t1 ( id serial ); @@ -1243,7 +1270,8 @@ drop table t1; --echo } mysqldump drop view v1; ---echo # BUG#17201 Spurious 'DROP DATABASE' in output, + +--echo # Bug#17201 Spurious 'DROP DATABASE' in output, --echo # also confusion between tables and views. --echo # Example code from Markus Popp @@ -1260,8 +1288,9 @@ drop view v1; drop table t1; drop database mysqldump_test_db; + --echo # ---echo # Bug21014 Segmentation fault of mysqldump on view +--echo # Bug#21014 Segmentation fault of mysqldump on view --echo # create database mysqldump_tables; @@ -1280,7 +1309,7 @@ drop table mysqldump_tables.basetable; drop database mysqldump_tables; --echo # ---echo # Bug20221 Dumping of multiple databases containing view(s) yields maleformed dumps +--echo # Bug#20221 Dumping of multiple databases containing view(s) yields maleformed dumps --echo # create database mysqldump_dba; @@ -1318,6 +1347,7 @@ use mysqldump_dbb; drop view v1; drop table t1; drop database mysqldump_dbb; +--remove_file $MYSQLTEST_VARDIR/tmp/bug20221_backup use test; --echo # @@ -1363,11 +1393,12 @@ grant REPLICATION CLIENT on *.* to mysqltest_1@localhost; drop table t1; drop user mysqltest_1@localhost; + --echo # ---echo # Bug #21527 mysqldump incorrectly tries to LOCK TABLES on the ---echo # information_schema database. +--echo # Bug#21527 mysqldump incorrectly tries to LOCK TABLES on the +--echo # information_schema database. --echo # ---echo # Bug #21424 mysqldump failing to export/import views +--echo # Bug#21424 mysqldump failing to export/import views --echo # # Do as root @@ -1388,7 +1419,7 @@ create table u1 (f1 int); insert into u1 values (4); create view v1 (c1) as select * from t1; -# Backup should not fail for Bug #21527. Flush priviliges test begins. +# Backup should not fail for Bug#21527. Flush priviliges test begins. --exec $MYSQL_DUMP --skip-comments --add-drop-table --flush-privileges --ignore-table=mysql.general_log --ignore-table=mysql.slow_log --databases mysqldump_myDB mysql > $MYSQLTEST_VARDIR/tmp/bug21527.sql # Clean up @@ -1402,8 +1433,9 @@ drop user myDB_User@localhost; drop database mysqldump_myDB; flush privileges; ---echo # Bug #21424 continues from here. ---echo # Restore. Flush Privileges test ends. + +--echo # Bug#21424 continues from here. +--echo # Restore. Flush Privileges test ends. --echo # --exec $MYSQL < $MYSQLTEST_VARDIR/tmp/bug21527.sql @@ -1416,8 +1448,9 @@ use mysqldump_myDB; select * from mysqldump_myDB.v1; select * from mysqldump_myDB.u1; -#Final cleanup. +# Final cleanup. connection root; +disconnect user1; use mysqldump_myDB; drop view v1; drop table t1; @@ -1425,10 +1458,14 @@ drop table u1; revoke all privileges on mysqldump_myDB.* from myDB_User@localhost; drop user myDB_User@localhost; drop database mysqldump_myDB; +connection default; +disconnect root; +--remove_file $MYSQLTEST_VARDIR/tmp/bug21527.sql use test; + --echo # ---echo # Bug #19745: mysqldump --xml produces invalid xml +--echo # Bug#19745 mysqldump --xml produces invalid xml --echo # --disable_warnings @@ -1443,9 +1480,8 @@ INSERT INTO t1 VALUES(1,0xff00fef0); DROP TABLE t1; - --echo # ---echo # Bug#26346: stack + buffer overrun in mysqldump +--echo # Bug#26346 stack + buffer overrun in mysqldump --echo # CREATE TABLE t1(a int); @@ -1466,18 +1502,20 @@ INSERT INTO t1 VALUES (1), (2); DROP TABLE t1; + # -# Bug #25993: crashe with a merge table and -c +# Bug#25993 crashes with a merge table and -c # -CREATE TABLE t2 (a int); -CREATE TABLE t3 (a int); -CREATE TABLE t1 (a int) ENGINE=merge UNION=(t2, t3); +CREATE TABLE t2 (a INT); +CREATE TABLE t3 (a INT); +CREATE TABLE t1 (a INT) ENGINE=merge UNION=(t2, t3); --exec $MYSQL_DUMP --skip-comments -c test DROP TABLE t1, t2, t3; + --echo # ---echo # Bug #23491: MySQLDump prefix function call in a view by database name +--echo # Bug#23491 MySQLDump prefix function call in a view by database name --echo # # Setup @@ -1507,15 +1545,16 @@ show create view bug23491_restore.v3; drop database bug23491_original; drop database bug23491_restore; use test; +--remove_file $MYSQLTEST_VARDIR/tmp/bug23491_backup.sql ---echo # ---echo # Bug 27293: mysqldump crashes when dumping routines ---echo # defined by a different user --echo # ---echo # Bug #22761: mysqldump reports no errors when using ---echo # --routines without mysql.proc privileges +--echo # Bug#27293 mysqldump crashes when dumping routines +--echo # defined by a different user +--echo # +--echo # Bug#22761 mysqldump reports no errors when using +--echo # --routines without mysql.proc privileges --echo # create database mysqldump_test_db; @@ -1536,13 +1575,14 @@ create procedure mysqldump_test_db.sp1() select 'hello'; drop procedure sp1; connection default; +disconnect user27293; drop user user1; drop user user2; drop database mysqldump_test_db; --echo # ---echo # Bug #28522: buffer overrun by '\0' byte using --hex-blob. +--echo # Bug#28522 buffer overrun by '\0' byte using --hex-blob. --echo # CREATE TABLE t1 (c1 INT, c2 LONGBLOB); @@ -1551,8 +1591,8 @@ INSERT INTO t1 SET c1=11, c2=REPEAT('q',509); DROP TABLE t1; --echo # ---echo # Bug #28524: mysqldump --skip-add-drop-table is not ---echo # compatible with views +--echo # Bug#28524 mysqldump --skip-add-drop-table is not +--echo # compatible with views --echo # CREATE VIEW v1 AS SELECT 1; @@ -1562,10 +1602,12 @@ DROP VIEW v1; --exec $MYSQL test < $MYSQLTEST_VARDIR/tmp/bug28524.sql SELECT * FROM v1; DROP VIEW v1; +--remove_file $MYSQLTEST_VARDIR/tmp/bug28524.sql + --echo # ---echo # Bug #29788: mysqldump discards the NO_AUTO_VALUE_ON_ZERO value of ---echo # the SQL_MODE variable after the dumping of triggers. +--echo # Bug#29788 mysqldump discards the NO_AUTO_VALUE_ON_ZERO value of +--echo # the SQL_MODE variable after the dumping of triggers. --echo # CREATE TABLE t1 (c1 INT); @@ -1584,10 +1626,12 @@ SELECT * FROM t2; SELECT * FROM t2; DROP TABLE t1,t2; +--remove_file $MYSQLTEST_VARDIR/tmp/bug29788.sql + --echo # ---echo # Bug#29815: new option for suppressing last line of mysqldump: ---echo # "Dump completed on" +--echo # Bug#29815 new option for suppressing last line of mysqldump: +--echo # "Dump completed on" --echo # --echo # --skip-dump-date: @@ -1609,3 +1653,6 @@ SET @@GLOBAL.CONCURRENT_INSERT = @OLD_CONCURRENT_INSERT; --echo # --echo # End of 5.0 tests --echo # + +# Wait till we reached the initial number of concurrent sessions +--source include/wait_until_count_sessions.inc diff --git a/mysql-test/t/openssl_1.test b/mysql-test/t/openssl_1.test index 14c14fca0c6..ad051503fd6 100644 --- a/mysql-test/t/openssl_1.test +++ b/mysql-test/t/openssl_1.test @@ -3,6 +3,10 @@ -- source include/have_ssl.inc +# Save the initial number of concurrent sessions +--source include/count_sessions.inc + + --disable_warnings drop table if exists t1; --enable_warnings @@ -21,38 +25,42 @@ connect (con2,localhost,ssl_user2,,,,,SSL); connect (con3,localhost,ssl_user3,,,,,SSL); connect (con4,localhost,ssl_user4,,,,,SSL); --replace_result $MASTER_MYSOCK MASTER_SOCKET $MASTER_MYPORT MASTER_PORT ---error 1045 +--error ER_ACCESS_DENIED_ERROR connect (con5,localhost,ssl_user5,,,,,SSL); connection con1; # Check ssl turned on SHOW STATUS LIKE 'Ssl_cipher'; select * from t1; ---error 1142 +--error ER_TABLEACCESS_DENIED_ERROR delete from t1; connection con2; # Check ssl turned on SHOW STATUS LIKE 'Ssl_cipher'; select * from t1; ---error 1142 +--error ER_TABLEACCESS_DENIED_ERROR delete from t1; connection con3; # Check ssl turned on SHOW STATUS LIKE 'Ssl_cipher'; select * from t1; ---error 1142 +--error ER_TABLEACCESS_DENIED_ERROR delete from t1; connection con4; # Check ssl turned on SHOW STATUS LIKE 'Ssl_cipher'; select * from t1; ---error 1142 +--error ER_TABLEACCESS_DENIED_ERROR delete from t1; connection default; +disconnect con1; +disconnect con2; +disconnect con3; +disconnect con4; drop user ssl_user1@localhost, ssl_user2@localhost, ssl_user3@localhost, ssl_user4@localhost, ssl_user5@localhost; @@ -97,7 +105,7 @@ drop table t1; --exec $MYSQL_TEST --ssl-cert= --max-connect-retries=1 < $MYSQLTEST_VARDIR/tmp/test.sql 2>&1 # -# BUG#21611 Slave can't connect when master-ssl-cipher specified +# Bug#21611 Slave can't connect when master-ssl-cipher specified # - Apparently selecting a cipher doesn't work at all # - Usa a cipher that both yaSSL and OpenSSL supports # @@ -133,7 +141,7 @@ drop table t1; --exec $MYSQL_TEST --ssl-cipher=UNKNOWN-CIPHER < $MYSQLTEST_VARDIR/tmp/test.sql 2>&1 # -# Bug #27669 mysqldump: SSL connection error when trying to connect +# Bug#27669 mysqldump: SSL connection error when trying to connect # CREATE TABLE t1(a int); @@ -152,3 +160,7 @@ INSERT INTO t1 VALUES (1), (2); --exec $MYSQL_DUMP --skip-create --skip-comments --ssl --ssl-cert=$MYSQL_TEST_DIR/std_data/client-cert.pem test 2>&1 DROP TABLE t1; +--remove_file $MYSQLTEST_VARDIR/tmp/test.sql + +# Wait till we reached the initial number of concurrent sessions +--source include/wait_until_count_sessions.inc diff --git a/mysql-test/t/outfile.test b/mysql-test/t/outfile.test index 527a4d398d8..4398f9fa741 100644 --- a/mysql-test/t/outfile.test +++ b/mysql-test/t/outfile.test @@ -5,6 +5,10 @@ eval set @tmpdir="../tmp"; enable_query_log; -- source include/have_outfile.inc +# Save the initial number of concurrent sessions +--source include/count_sessions.inc + + # # test of into outfile|dumpfile # @@ -46,7 +50,7 @@ select load_file(concat(@tmpdir,"/outfile-test.not-exist")); --remove_file $MYSQLTEST_VARDIR/tmp/outfile-test.3 drop table t1; -# Bug#8191 +# Bug#8191 SELECT INTO OUTFILE insists on FROM clause disable_query_log; eval select 1 into outfile "../tmp/outfile-test.4"; enable_query_log; @@ -54,11 +58,11 @@ select load_file(concat(@tmpdir,"/outfile-test.4")); --remove_file $MYSQLTEST_VARDIR/tmp/outfile-test.4 # -# Bug #5382: 'explain select into outfile' crashes the server +# Bug#5382 'explain select into outfile' crashes the server # CREATE TABLE t1 (a INT); -EXPLAIN +EXPLAIN SELECT * INTO OUTFILE '/tmp/t1.txt' FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"' LINES TERMINATED BY '\r\n' @@ -68,7 +72,7 @@ DROP TABLE t1; # End of 4.1 tests # -# Bug#13202 SELECT * INTO OUTFILE ... FROM information_schema.schemata now fails +# Bug#13202 SELECT * INTO OUTFILE ... FROM information_schema.schemata now fails # disable_query_log; eval SELECT * INTO OUTFILE "../tmp/outfile-test.4" @@ -114,6 +118,7 @@ from information_schema.schemata where schema_name like 'mysqltest'; connection default; +disconnect con28181_1; grant file on *.* to user_1@localhost; connect (con28181_2,localhost,user_1,,mysqltest); @@ -125,9 +130,12 @@ from information_schema.schemata where schema_name like 'mysqltest'; connection default; +disconnect con28181_2; --remove_file $MYSQLTEST_VARDIR/tmp/outfile-test.4 use test; revoke all privileges on *.* from user_1@localhost; drop user user_1@localhost; drop database mysqltest; +# Wait till we reached the initial number of concurrent sessions +--source include/wait_until_count_sessions.inc From d1fb6bbcc890955e634d644a002a707c3d8e7f67 Mon Sep 17 00:00:00 2001 From: "Tatiana A. Nurnberg" Date: Tue, 3 Feb 2009 02:43:32 +0100 Subject: [PATCH 016/219] Bug#40657: assertion with out of range variables and traditional sql_mode In STRICT mode, out-of-bounds values caused an error message to be queued (rather than just a warning), without any further error-like processing happening. (The error is queued during update, at which time it's too late. For it to be processed properly, it would need to be queued during check-stage.) The assertion rightfully complains that we're trying to send an OK while having an error queued. Changeset breaks a lot of tests out into check-stage. This also allows us to send more correct warnings/error messages. mysql-test/r/auto_increment_increment_basic.result: update test results reflecting more correct warnings mysql-test/r/auto_increment_increment_func.result: update test results reflecting more correct warnings mysql-test/r/auto_increment_offset_basic.result: update test results reflecting more correct warnings mysql-test/r/auto_increment_offset_func.result: update test results reflecting more correct warnings mysql-test/r/concurrent_insert_basic.result: update test results reflecting more correct warnings mysql-test/r/connect_timeout_basic.result: update test results reflecting more correct warnings mysql-test/r/default_week_format_basic.result: update test results reflecting more correct warnings mysql-test/r/delayed_insert_timeout_basic.result: update test results reflecting more correct warnings mysql-test/r/div_precision_increment_basic.result: update test results reflecting more correct warnings mysql-test/r/expire_logs_days_basic.result: update test results reflecting more correct warnings mysql-test/r/group_concat_max_len_basic.result: update test results reflecting more correct warnings mysql-test/r/interactive_timeout_basic.result: update test results reflecting more correct warnings mysql-test/r/max_allowed_packet_basic.result: update test results reflecting more correct warnings mysql-test/r/max_binlog_size_basic.result: update test results reflecting more correct warnings mysql-test/r/max_connections_basic.result: update test results reflecting more correct warnings mysql-test/r/max_delayed_threads_basic.result: update test results reflecting more correct warnings mysql-test/r/max_error_count_basic.result: update test results reflecting more correct warnings mysql-test/r/max_insert_delayed_threads_basic.result: update test results reflecting more correct warnings mysql-test/r/max_length_for_sort_data_basic.result: update test results reflecting more correct warnings mysql-test/r/max_prepared_stmt_count_basic.result: update test results reflecting more correct warnings mysql-test/r/max_relay_log_size_basic.result: update test results reflecting more correct warnings mysql-test/r/max_sort_length_basic.result: update test results reflecting more correct warnings mysql-test/r/max_sp_recursion_depth_basic.result: update test results reflecting more correct warnings mysql-test/r/myisam_data_pointer_size_basic.result: update test results reflecting more correct warnings mysql-test/r/net_buffer_length_basic.result: update test results reflecting more correct warnings mysql-test/r/net_read_timeout_basic.result: update test results reflecting more correct warnings mysql-test/r/net_write_timeout_basic.result: update test results reflecting more correct warnings mysql-test/r/optimizer_prune_level_basic.result: update test results reflecting more correct warnings mysql-test/r/optimizer_search_depth_basic.result: update test results reflecting more correct warnings mysql-test/r/preload_buffer_size_basic.result: update test results reflecting more correct warnings mysql-test/r/ps.result: update test results reflecting more correct warnings mysql-test/r/read_buffer_size_basic.result: update test results reflecting more correct warnings mysql-test/r/read_rnd_buffer_size_basic.result: update test results reflecting more correct warnings mysql-test/r/slave_net_timeout_basic.result: update test results reflecting more correct warnings mysql-test/r/slow_launch_time_basic.result: update test results reflecting more correct warnings mysql-test/r/table_definition_cache_basic.result: update test results reflecting more correct warnings mysql-test/r/table_lock_wait_timeout_basic.result: update test results reflecting more correct warnings mysql-test/r/table_open_cache_basic.result: update test results reflecting more correct warnings mysql-test/r/variables.result: add test case that throws error (rather than warning) in the middle of trying to set a system-variable. mysql-test/t/variables.test: add test case that throws error (rather than warning) in the middle of trying to set a system-variable. sql/set_var.cc: Add comments. Prevent double-warnings. Through warnings for negative values given to unsigned system-variables. Process errors and warnings at check() stage rather than update() stage, since we may only issue warnings at the latter. --- .../r/auto_increment_increment_basic.result | 4 +- .../r/auto_increment_increment_func.result | 2 +- .../r/auto_increment_offset_basic.result | 4 +- .../r/auto_increment_offset_func.result | 2 +- mysql-test/r/concurrent_insert_basic.result | 2 + mysql-test/r/connect_timeout_basic.result | 2 +- mysql-test/r/default_week_format_basic.result | 4 + .../r/delayed_insert_timeout_basic.result | 2 +- .../r/div_precision_increment_basic.result | 4 + mysql-test/r/expire_logs_days_basic.result | 4 + .../r/group_concat_max_len_basic.result | 4 +- mysql-test/r/interactive_timeout_basic.result | 4 +- mysql-test/r/max_allowed_packet_basic.result | 2 +- mysql-test/r/max_binlog_size_basic.result | 4 +- mysql-test/r/max_connections_basic.result | 4 +- mysql-test/r/max_delayed_threads_basic.result | 4 + mysql-test/r/max_error_count_basic.result | 8 + .../r/max_insert_delayed_threads_basic.result | 4 + .../r/max_length_for_sort_data_basic.result | 4 +- .../r/max_prepared_stmt_count_basic.result | 4 + mysql-test/r/max_relay_log_size_basic.result | 4 + mysql-test/r/max_sort_length_basic.result | 4 +- .../r/max_sp_recursion_depth_basic.result | 8 + .../r/myisam_data_pointer_size_basic.result | 2 +- mysql-test/r/net_buffer_length_basic.result | 2 +- mysql-test/r/net_read_timeout_basic.result | 4 +- mysql-test/r/net_write_timeout_basic.result | 4 +- .../r/optimizer_prune_level_basic.result | 4 + .../r/optimizer_search_depth_basic.result | 4 + mysql-test/r/preload_buffer_size_basic.result | 4 +- mysql-test/r/ps.result | 2 + mysql-test/r/read_buffer_size_basic.result | 4 +- .../r/read_rnd_buffer_size_basic.result | 4 +- mysql-test/r/slave_net_timeout_basic.result | 4 +- mysql-test/r/slow_launch_time_basic.result | 4 + .../r/table_definition_cache_basic.result | 2 +- .../r/table_lock_wait_timeout_basic.result | 4 +- mysql-test/r/table_open_cache_basic.result | 4 +- mysql-test/r/variables.result | 35 +++- mysql-test/t/variables.test | 35 ++++ sql/set_var.cc | 181 +++++++++++++----- 41 files changed, 297 insertions(+), 94 deletions(-) diff --git a/mysql-test/r/auto_increment_increment_basic.result b/mysql-test/r/auto_increment_increment_basic.result index c453d2322cf..75f76a60b33 100644 --- a/mysql-test/r/auto_increment_increment_basic.result +++ b/mysql-test/r/auto_increment_increment_basic.result @@ -61,7 +61,7 @@ SELECT @@global.auto_increment_increment; 1 SET @@global.auto_increment_increment = -1024; Warnings: -Warning 1292 Truncated incorrect auto-increment-increment value: '0' +Warning 1292 Truncated incorrect auto_increment_increment value: '-1024' SELECT @@global.auto_increment_increment; @@global.auto_increment_increment 1 @@ -89,7 +89,7 @@ SELECT @@session.auto_increment_increment; 1 SET @@session.auto_increment_increment = -2; Warnings: -Warning 1292 Truncated incorrect auto-increment-increment value: '0' +Warning 1292 Truncated incorrect auto_increment_increment value: '-2' SELECT @@session.auto_increment_increment; @@session.auto_increment_increment 1 diff --git a/mysql-test/r/auto_increment_increment_func.result b/mysql-test/r/auto_increment_increment_func.result index f0f1ada6d95..eeaa3949886 100644 --- a/mysql-test/r/auto_increment_increment_func.result +++ b/mysql-test/r/auto_increment_increment_func.result @@ -169,7 +169,7 @@ id name ## Verifying behavior of variable with negative value ## SET @@auto_increment_increment = -10; Warnings: -Warning 1292 Truncated incorrect auto-increment-increment value: '0' +Warning 1292 Truncated incorrect auto_increment_increment value: '-10' INSERT into t1(name) values('Record_17'); INSERT into t1(name) values('Record_18'); SELECT * from t1; diff --git a/mysql-test/r/auto_increment_offset_basic.result b/mysql-test/r/auto_increment_offset_basic.result index b5ccca8ce56..f91037cb7cf 100644 --- a/mysql-test/r/auto_increment_offset_basic.result +++ b/mysql-test/r/auto_increment_offset_basic.result @@ -61,7 +61,7 @@ SELECT @@global.auto_increment_offset; 1 SET @@global.auto_increment_offset = -1024; Warnings: -Warning 1292 Truncated incorrect auto-increment-offset value: '0' +Warning 1292 Truncated incorrect auto_increment_offset value: '-1024' SELECT @@global.auto_increment_offset; @@global.auto_increment_offset 1 @@ -94,7 +94,7 @@ SELECT @@session.auto_increment_offset; 1 SET @@session.auto_increment_offset = -2; Warnings: -Warning 1292 Truncated incorrect auto-increment-offset value: '0' +Warning 1292 Truncated incorrect auto_increment_offset value: '-2' SELECT @@session.auto_increment_offset; @@session.auto_increment_offset 1 diff --git a/mysql-test/r/auto_increment_offset_func.result b/mysql-test/r/auto_increment_offset_func.result index 5c953544e73..e166cb149f6 100644 --- a/mysql-test/r/auto_increment_offset_func.result +++ b/mysql-test/r/auto_increment_offset_func.result @@ -178,7 +178,7 @@ id name ## Assigning -ve value to variable ## SET @@auto_increment_offset = -10; Warnings: -Warning 1292 Truncated incorrect auto-increment-offset value: '0' +Warning 1292 Truncated incorrect auto_increment_offset value: '-10' SELECT @@auto_increment_offset = -10; @@auto_increment_offset = -10 0 diff --git a/mysql-test/r/concurrent_insert_basic.result b/mysql-test/r/concurrent_insert_basic.result index e6614ea6abb..2c7fc4296dd 100644 --- a/mysql-test/r/concurrent_insert_basic.result +++ b/mysql-test/r/concurrent_insert_basic.result @@ -28,6 +28,8 @@ SELECT @@global.concurrent_insert; 2 '#--------------------FN_DYNVARS_018_04-------------------------#' SET @@global.concurrent_insert = -1; +Warnings: +Warning 1292 Truncated incorrect concurrent_insert value: '-1' Select @@global.concurrent_insert; @@global.concurrent_insert 0 diff --git a/mysql-test/r/connect_timeout_basic.result b/mysql-test/r/connect_timeout_basic.result index 7cdd747fc15..cc84405cf86 100644 --- a/mysql-test/r/connect_timeout_basic.result +++ b/mysql-test/r/connect_timeout_basic.result @@ -35,7 +35,7 @@ SELECT @@global.connect_timeout; 2 SET @@global.connect_timeout = -1024; Warnings: -Warning 1292 Truncated incorrect connect_timeout value: '0' +Warning 1292 Truncated incorrect connect_timeout value: '-1024' SELECT @@global.connect_timeout; @@global.connect_timeout 2 diff --git a/mysql-test/r/default_week_format_basic.result b/mysql-test/r/default_week_format_basic.result index d513ef1c41e..aa5e0b264d3 100644 --- a/mysql-test/r/default_week_format_basic.result +++ b/mysql-test/r/default_week_format_basic.result @@ -64,6 +64,8 @@ SELECT @@global.default_week_format; @@global.default_week_format 7 SET @@global.default_week_format = -1024; +Warnings: +Warning 1292 Truncated incorrect default_week_format value: '-1024' SELECT @@global.default_week_format; @@global.default_week_format 0 @@ -100,6 +102,8 @@ SELECT @@session.default_week_format; @@session.default_week_format 7 SET @@session.default_week_format = -2; +Warnings: +Warning 1292 Truncated incorrect default_week_format value: '-2' SELECT @@session.default_week_format; @@session.default_week_format 0 diff --git a/mysql-test/r/delayed_insert_timeout_basic.result b/mysql-test/r/delayed_insert_timeout_basic.result index 4049907eb80..e8eab4da3cc 100644 --- a/mysql-test/r/delayed_insert_timeout_basic.result +++ b/mysql-test/r/delayed_insert_timeout_basic.result @@ -35,7 +35,7 @@ SELECT @@global.delayed_insert_timeout; 1 SET @@global.delayed_insert_timeout = -1024; Warnings: -Warning 1292 Truncated incorrect delayed_insert_timeout value: '0' +Warning 1292 Truncated incorrect delayed_insert_timeout value: '-1024' SELECT @@global.delayed_insert_timeout; @@global.delayed_insert_timeout 1 diff --git a/mysql-test/r/div_precision_increment_basic.result b/mysql-test/r/div_precision_increment_basic.result index d0311afa681..f78855fcaae 100644 --- a/mysql-test/r/div_precision_increment_basic.result +++ b/mysql-test/r/div_precision_increment_basic.result @@ -78,6 +78,8 @@ SELECT @@global.div_precision_increment; @@global.div_precision_increment 30 SET @@global.div_precision_increment = -1024; +Warnings: +Warning 1292 Truncated incorrect div_precision_increment value: '-1024' SELECT @@global.div_precision_increment; @@global.div_precision_increment 0 @@ -100,6 +102,8 @@ SELECT @@session.div_precision_increment; @@session.div_precision_increment 30 SET @@session.div_precision_increment = -2; +Warnings: +Warning 1292 Truncated incorrect div_precision_increment value: '-2' SELECT @@session.div_precision_increment; @@session.div_precision_increment 0 diff --git a/mysql-test/r/expire_logs_days_basic.result b/mysql-test/r/expire_logs_days_basic.result index 66aa5fa42a5..1abab8e68b0 100644 --- a/mysql-test/r/expire_logs_days_basic.result +++ b/mysql-test/r/expire_logs_days_basic.result @@ -32,6 +32,8 @@ SELECT @@global.expire_logs_days; 21 '#--------------------FN_DYNVARS_029_04-------------------------#' SET @@global.expire_logs_days = -1; +Warnings: +Warning 1292 Truncated incorrect expire_logs_days value: '-1' SELECT @@global.expire_logs_days; @@global.expire_logs_days 0 @@ -53,6 +55,8 @@ SELECT @@global.expire_logs_days; @@global.expire_logs_days 99 SET @@global.expire_logs_days = -1024; +Warnings: +Warning 1292 Truncated incorrect expire_logs_days value: '-1024' SELECT @@global.expire_logs_days; @@global.expire_logs_days 0 diff --git a/mysql-test/r/group_concat_max_len_basic.result b/mysql-test/r/group_concat_max_len_basic.result index 5704f00c014..4821ca91308 100644 --- a/mysql-test/r/group_concat_max_len_basic.result +++ b/mysql-test/r/group_concat_max_len_basic.result @@ -65,7 +65,7 @@ SELECT @@global.group_concat_max_len; 4 SET @@global.group_concat_max_len = -1024; Warnings: -Warning 1292 Truncated incorrect group_concat_max_len value: '0' +Warning 1292 Truncated incorrect group_concat_max_len value: '-1024' SELECT @@global.group_concat_max_len; @@global.group_concat_max_len 4 @@ -91,7 +91,7 @@ SELECT @@session.group_concat_max_len; 4 SET @@session.group_concat_max_len = -2; Warnings: -Warning 1292 Truncated incorrect group_concat_max_len value: '0' +Warning 1292 Truncated incorrect group_concat_max_len value: '-2' SELECT @@session.group_concat_max_len; @@session.group_concat_max_len 4 diff --git a/mysql-test/r/interactive_timeout_basic.result b/mysql-test/r/interactive_timeout_basic.result index 0777596db07..519fef8a6e5 100644 --- a/mysql-test/r/interactive_timeout_basic.result +++ b/mysql-test/r/interactive_timeout_basic.result @@ -61,7 +61,7 @@ SELECT @@global.interactive_timeout; 1 SET @@global.interactive_timeout = -1024; Warnings: -Warning 1292 Truncated incorrect interactive_timeout value: '0' +Warning 1292 Truncated incorrect interactive_timeout value: '-1024' SELECT @@global.interactive_timeout; @@global.interactive_timeout 1 @@ -89,7 +89,7 @@ SELECT @@session.interactive_timeout; 1 SET @@session.interactive_timeout = -2; Warnings: -Warning 1292 Truncated incorrect interactive_timeout value: '0' +Warning 1292 Truncated incorrect interactive_timeout value: '-2' SELECT @@session.interactive_timeout; @@session.interactive_timeout 1 diff --git a/mysql-test/r/max_allowed_packet_basic.result b/mysql-test/r/max_allowed_packet_basic.result index 0745d5a36e1..ca5b87f19cb 100644 --- a/mysql-test/r/max_allowed_packet_basic.result +++ b/mysql-test/r/max_allowed_packet_basic.result @@ -76,7 +76,7 @@ SELECT @@global.max_allowed_packet; 1024 SET @@global.max_allowed_packet = -1024; Warnings: -Warning 1292 Truncated incorrect max_allowed_packet value: '0' +Warning 1292 Truncated incorrect max_allowed_packet value: '-1024' SELECT @@global.max_allowed_packet; @@global.max_allowed_packet 1024 diff --git a/mysql-test/r/max_binlog_size_basic.result b/mysql-test/r/max_binlog_size_basic.result index 291b687f76c..658289628b0 100644 --- a/mysql-test/r/max_binlog_size_basic.result +++ b/mysql-test/r/max_binlog_size_basic.result @@ -39,7 +39,7 @@ SELECT @@global.max_binlog_size; '#--------------------FN_DYNVARS_072_04-------------------------#' SET @@global.max_binlog_size = -1; Warnings: -Warning 1292 Truncated incorrect max_binlog_size value: '0' +Warning 1292 Truncated incorrect max_binlog_size value: '-1' SELECT @@global.max_binlog_size; @@global.max_binlog_size 4096 @@ -56,7 +56,7 @@ SELECT @@global.max_binlog_size; 1073741824 SET @@global.max_binlog_size = -1024; Warnings: -Warning 1292 Truncated incorrect max_binlog_size value: '0' +Warning 1292 Truncated incorrect max_binlog_size value: '-1024' SELECT @@global.max_binlog_size; @@global.max_binlog_size 4096 diff --git a/mysql-test/r/max_connections_basic.result b/mysql-test/r/max_connections_basic.result index ccedff01c54..d917cd97b25 100644 --- a/mysql-test/r/max_connections_basic.result +++ b/mysql-test/r/max_connections_basic.result @@ -39,7 +39,7 @@ SELECT @@global.max_connections; '#--------------------FN_DYNVARS_074_04-------------------------#' SET @@global.max_connections = -1; Warnings: -Warning 1292 Truncated incorrect max_connections value: '0' +Warning 1292 Truncated incorrect max_connections value: '-1' SELECT @@global.max_connections; @@global.max_connections 1 @@ -56,7 +56,7 @@ SELECT @@global.max_connections; 100000 SET @@global.max_connections = -1024; Warnings: -Warning 1292 Truncated incorrect max_connections value: '0' +Warning 1292 Truncated incorrect max_connections value: '-1024' SELECT @@global.max_connections; @@global.max_connections 1 diff --git a/mysql-test/r/max_delayed_threads_basic.result b/mysql-test/r/max_delayed_threads_basic.result index e0b2a3ee1cd..946c24e3082 100644 --- a/mysql-test/r/max_delayed_threads_basic.result +++ b/mysql-test/r/max_delayed_threads_basic.result @@ -76,10 +76,14 @@ SELECT @@session.max_delayed_threads; 16383 '#------------------FN_DYNVARS_075_05-----------------------#' SET @@global.max_delayed_threads = -1024; +Warnings: +Warning 1292 Truncated incorrect max_delayed_threads value: '-1024' SELECT @@global.max_delayed_threads; @@global.max_delayed_threads 0 SET @@global.max_delayed_threads = -1; +Warnings: +Warning 1292 Truncated incorrect max_delayed_threads value: '-1' SELECT @@global.max_delayed_threads; @@global.max_delayed_threads 0 diff --git a/mysql-test/r/max_error_count_basic.result b/mysql-test/r/max_error_count_basic.result index 2046a5e9dfa..7be8e0f37a3 100644 --- a/mysql-test/r/max_error_count_basic.result +++ b/mysql-test/r/max_error_count_basic.result @@ -63,10 +63,14 @@ SELECT @@session.max_error_count; 65534 '#------------------FN_DYNVARS_076_05-----------------------#' SET @@global.max_error_count = -1; +Warnings: +Warning 1292 Truncated incorrect max_error_count value: '-1' SELECT @@global.max_error_count; @@global.max_error_count 0 SET @@global.max_error_count = -1024; +Warnings: +Warning 1292 Truncated incorrect max_error_count value: '-1024' SELECT @@global.max_error_count; @@global.max_error_count 0 @@ -93,6 +97,8 @@ SELECT @@global.max_error_count; @@global.max_error_count 65535 SET @@session.max_error_count = -1; +Warnings: +Warning 1292 Truncated incorrect max_error_count value: '-1' SELECT @@session.max_error_count; @@session.max_error_count 0 @@ -102,6 +108,8 @@ SELECT @@session.max_error_count; @@session.max_error_count 65535 SET @@session.max_error_count = -2; +Warnings: +Warning 1292 Truncated incorrect max_error_count value: '-2' SELECT @@session.max_error_count; @@session.max_error_count 0 diff --git a/mysql-test/r/max_insert_delayed_threads_basic.result b/mysql-test/r/max_insert_delayed_threads_basic.result index 31c1fcec396..2f2f7f0c0fc 100644 --- a/mysql-test/r/max_insert_delayed_threads_basic.result +++ b/mysql-test/r/max_insert_delayed_threads_basic.result @@ -77,10 +77,14 @@ SELECT @@session.max_insert_delayed_threads; 16383 '#------------------FN_DYNVARS_078_05-----------------------#' SET @@global.max_insert_delayed_threads = -1024; +Warnings: +Warning 1292 Truncated incorrect max_insert_delayed_threads value: '-1024' SELECT @@global.max_insert_delayed_threads; @@global.max_insert_delayed_threads 0 SET @@global.max_insert_delayed_threads = -1; +Warnings: +Warning 1292 Truncated incorrect max_insert_delayed_threads value: '-1' SELECT @@global.max_insert_delayed_threads; @@global.max_insert_delayed_threads 0 diff --git a/mysql-test/r/max_length_for_sort_data_basic.result b/mysql-test/r/max_length_for_sort_data_basic.result index 3edd3e86262..8936946c774 100644 --- a/mysql-test/r/max_length_for_sort_data_basic.result +++ b/mysql-test/r/max_length_for_sort_data_basic.result @@ -71,7 +71,7 @@ SELECT @@session.max_length_for_sort_data; '#------------------FN_DYNVARS_080_05-----------------------#' SET @@global.max_length_for_sort_data = -1024; Warnings: -Warning 1292 Truncated incorrect max_length_for_sort_data value: '0' +Warning 1292 Truncated incorrect max_length_for_sort_data value: '-1024' SELECT @@global.max_length_for_sort_data; @@global.max_length_for_sort_data 4 @@ -111,7 +111,7 @@ SELECT @@session.max_length_for_sort_data; 8388608 SET @@session.max_length_for_sort_data = -1; Warnings: -Warning 1292 Truncated incorrect max_length_for_sort_data value: '0' +Warning 1292 Truncated incorrect max_length_for_sort_data value: '-1' SELECT @@session.max_length_for_sort_data; @@session.max_length_for_sort_data 4 diff --git a/mysql-test/r/max_prepared_stmt_count_basic.result b/mysql-test/r/max_prepared_stmt_count_basic.result index ebc7da8c7f8..9c28c287980 100644 --- a/mysql-test/r/max_prepared_stmt_count_basic.result +++ b/mysql-test/r/max_prepared_stmt_count_basic.result @@ -36,6 +36,8 @@ SELECT @@global.max_prepared_stmt_count; 65535 '#--------------------FN_DYNVARS_081_04-------------------------#' SET @@global.max_prepared_stmt_count = -1; +Warnings: +Warning 1292 Truncated incorrect max_prepared_stmt_count value: '-1' SELECT @@global.max_prepared_stmt_count; @@global.max_prepared_stmt_count 0 @@ -51,6 +53,8 @@ SELECT @@global.max_prepared_stmt_count; @@global.max_prepared_stmt_count 1048576 SET @@global.max_prepared_stmt_count = -1024; +Warnings: +Warning 1292 Truncated incorrect max_prepared_stmt_count value: '-1024' SELECT @@global.max_prepared_stmt_count; @@global.max_prepared_stmt_count 0 diff --git a/mysql-test/r/max_relay_log_size_basic.result b/mysql-test/r/max_relay_log_size_basic.result index c0042f497ad..168459cf7b6 100644 --- a/mysql-test/r/max_relay_log_size_basic.result +++ b/mysql-test/r/max_relay_log_size_basic.result @@ -38,6 +38,8 @@ SELECT @@global.max_relay_log_size; 'Bug# 34877: Invalid Values are coming in variable on assigning valid values'; '#--------------------FN_DYNVARS_082_04-------------------------#' SET @@global.max_relay_log_size = -1; +Warnings: +Warning 1292 Truncated incorrect max_relay_log_size value: '-1' SELECT @@global.max_relay_log_size; @@global.max_relay_log_size 0 @@ -53,6 +55,8 @@ SELECT @@global.max_relay_log_size; @@global.max_relay_log_size 1073741824 SET @@global.max_relay_log_size = -1024; +Warnings: +Warning 1292 Truncated incorrect max_relay_log_size value: '-1024' SELECT @@global.max_relay_log_size; @@global.max_relay_log_size 0 diff --git a/mysql-test/r/max_sort_length_basic.result b/mysql-test/r/max_sort_length_basic.result index 73dd31ea4e7..f0a9ca83376 100644 --- a/mysql-test/r/max_sort_length_basic.result +++ b/mysql-test/r/max_sort_length_basic.result @@ -71,7 +71,7 @@ SELECT @@session.max_sort_length; '#------------------FN_DYNVARS_084_05-----------------------#' SET @@global.max_sort_length = -1024; Warnings: -Warning 1292 Truncated incorrect max_sort_length value: '0' +Warning 1292 Truncated incorrect max_sort_length value: '-1024' SELECT @@global.max_sort_length; @@global.max_sort_length 4 @@ -111,7 +111,7 @@ SELECT @@session.max_sort_length; 8388608 SET @@session.max_sort_length = -1; Warnings: -Warning 1292 Truncated incorrect max_sort_length value: '0' +Warning 1292 Truncated incorrect max_sort_length value: '-1' SELECT @@session.max_sort_length; @@session.max_sort_length 4 diff --git a/mysql-test/r/max_sp_recursion_depth_basic.result b/mysql-test/r/max_sp_recursion_depth_basic.result index 8c79f3c5fc7..e5f267253f4 100644 --- a/mysql-test/r/max_sp_recursion_depth_basic.result +++ b/mysql-test/r/max_sp_recursion_depth_basic.result @@ -74,6 +74,8 @@ SELECT @@session.max_sp_recursion_depth; 150 '#------------------FN_DYNVARS_085_05-----------------------#' SET @@global.max_sp_recursion_depth = -1024; +Warnings: +Warning 1292 Truncated incorrect max_sp_recursion_depth value: '-1024' SELECT @@global.max_sp_recursion_depth; @@global.max_sp_recursion_depth 0 @@ -84,6 +86,8 @@ SELECT @@global.max_sp_recursion_depth; @@global.max_sp_recursion_depth 255 SET @@global.max_sp_recursion_depth = -1; +Warnings: +Warning 1292 Truncated incorrect max_sp_recursion_depth value: '-1' SELECT @@global.max_sp_recursion_depth; @@global.max_sp_recursion_depth 0 @@ -110,6 +114,8 @@ SELECT @@session.max_sp_recursion_depth; @@session.max_sp_recursion_depth 255 SET @@session.max_sp_recursion_depth = -1; +Warnings: +Warning 1292 Truncated incorrect max_sp_recursion_depth value: '-1' SELECT @@session.max_sp_recursion_depth; @@session.max_sp_recursion_depth 0 @@ -120,6 +126,8 @@ SELECT @@session.max_sp_recursion_depth; @@session.max_sp_recursion_depth 255 SET @@session.max_sp_recursion_depth = -001; +Warnings: +Warning 1292 Truncated incorrect max_sp_recursion_depth value: '-1' SELECT @@session.max_sp_recursion_depth; @@session.max_sp_recursion_depth 0 diff --git a/mysql-test/r/myisam_data_pointer_size_basic.result b/mysql-test/r/myisam_data_pointer_size_basic.result index d2b0bebe029..86f7788fcdf 100644 --- a/mysql-test/r/myisam_data_pointer_size_basic.result +++ b/mysql-test/r/myisam_data_pointer_size_basic.result @@ -48,7 +48,7 @@ ERROR HY000: Variable 'myisam_data_pointer_size' is a GLOBAL variable and should '#------------------FN_DYNVARS_093_05-----------------------#' SET @@global.myisam_data_pointer_size = -1; Warnings: -Warning 1292 Truncated incorrect myisam_data_pointer_size value: '0' +Warning 1292 Truncated incorrect myisam_data_pointer_size value: '-1' SELECT @@global.myisam_data_pointer_size; @@global.myisam_data_pointer_size 2 diff --git a/mysql-test/r/net_buffer_length_basic.result b/mysql-test/r/net_buffer_length_basic.result index be7e9082332..07f933b5a4b 100644 --- a/mysql-test/r/net_buffer_length_basic.result +++ b/mysql-test/r/net_buffer_length_basic.result @@ -50,7 +50,7 @@ SELECT @@global.net_buffer_length; 1024 SET @@global.net_buffer_length = -1024; Warnings: -Warning 1292 Truncated incorrect net_buffer_length value: '0' +Warning 1292 Truncated incorrect net_buffer_length value: '-1024' SELECT @@global.net_buffer_length; @@global.net_buffer_length 1024 diff --git a/mysql-test/r/net_read_timeout_basic.result b/mysql-test/r/net_read_timeout_basic.result index 90a6ef72718..aeee25c6526 100644 --- a/mysql-test/r/net_read_timeout_basic.result +++ b/mysql-test/r/net_read_timeout_basic.result @@ -61,7 +61,7 @@ SELECT @@global.net_read_timeout; 1 SET @@global.net_read_timeout = -1024; Warnings: -Warning 1292 Truncated incorrect net_read_timeout value: '0' +Warning 1292 Truncated incorrect net_read_timeout value: '-1024' SELECT @@global.net_read_timeout; @@global.net_read_timeout 1 @@ -89,7 +89,7 @@ SELECT @@session.net_read_timeout; 1 SET @@session.net_read_timeout = -2; Warnings: -Warning 1292 Truncated incorrect net_read_timeout value: '0' +Warning 1292 Truncated incorrect net_read_timeout value: '-2' SELECT @@session.net_read_timeout; @@session.net_read_timeout 1 diff --git a/mysql-test/r/net_write_timeout_basic.result b/mysql-test/r/net_write_timeout_basic.result index 35a2cf069e3..8857b8c0e37 100644 --- a/mysql-test/r/net_write_timeout_basic.result +++ b/mysql-test/r/net_write_timeout_basic.result @@ -61,7 +61,7 @@ SELECT @@global.net_write_timeout; 1 SET @@global.net_write_timeout = -1024; Warnings: -Warning 1292 Truncated incorrect net_write_timeout value: '0' +Warning 1292 Truncated incorrect net_write_timeout value: '-1024' SELECT @@global.net_write_timeout; @@global.net_write_timeout 1 @@ -89,7 +89,7 @@ SELECT @@session.net_write_timeout; 1 SET @@session.net_write_timeout = -2; Warnings: -Warning 1292 Truncated incorrect net_write_timeout value: '0' +Warning 1292 Truncated incorrect net_write_timeout value: '-2' SELECT @@session.net_write_timeout; @@session.net_write_timeout 1 diff --git a/mysql-test/r/optimizer_prune_level_basic.result b/mysql-test/r/optimizer_prune_level_basic.result index 46fe70c40d0..c126569ebcd 100644 --- a/mysql-test/r/optimizer_prune_level_basic.result +++ b/mysql-test/r/optimizer_prune_level_basic.result @@ -81,6 +81,8 @@ ERROR 42000: Incorrect argument type to variable 'optimizer_prune_level' SET @@global.optimizer_prune_level = FELSE; ERROR 42000: Incorrect argument type to variable 'optimizer_prune_level' SET @@global.optimizer_prune_level = -1024; +Warnings: +Warning 1292 Truncated incorrect optimizer_prune_level value: '-1024' SELECT @@global.optimizer_prune_level; @@global.optimizer_prune_level 0 @@ -107,6 +109,8 @@ ERROR 42000: Incorrect argument type to variable 'optimizer_prune_level' SET @@session.optimizer_prune_level = 'OFN'; ERROR 42000: Incorrect argument type to variable 'optimizer_prune_level' SET @@session.optimizer_prune_level = -2; +Warnings: +Warning 1292 Truncated incorrect optimizer_prune_level value: '-2' SELECT @@session.optimizer_prune_level; @@session.optimizer_prune_level 0 diff --git a/mysql-test/r/optimizer_search_depth_basic.result b/mysql-test/r/optimizer_search_depth_basic.result index 9c26339839e..9c49ae7e73f 100644 --- a/mysql-test/r/optimizer_search_depth_basic.result +++ b/mysql-test/r/optimizer_search_depth_basic.result @@ -72,6 +72,8 @@ SELECT @@global.optimizer_search_depth; @@global.optimizer_search_depth 63 SET @@global.optimizer_search_depth = -1; +Warnings: +Warning 1292 Truncated incorrect optimizer_search_depth value: '-1' SELECT @@global.optimizer_search_depth; @@global.optimizer_search_depth 0 @@ -98,6 +100,8 @@ SELECT @@session.optimizer_search_depth; @@session.optimizer_search_depth 63 SET @@session.optimizer_search_depth = -2; +Warnings: +Warning 1292 Truncated incorrect optimizer_search_depth value: '-2' SELECT @@session.optimizer_search_depth; @@session.optimizer_search_depth 0 diff --git a/mysql-test/r/preload_buffer_size_basic.result b/mysql-test/r/preload_buffer_size_basic.result index 775b670d3bc..fd8bdd222d2 100644 --- a/mysql-test/r/preload_buffer_size_basic.result +++ b/mysql-test/r/preload_buffer_size_basic.result @@ -77,7 +77,7 @@ SELECT @@global.preload_buffer_size; 1024 SET @@global.preload_buffer_size = -1; Warnings: -Warning 1292 Truncated incorrect preload_buffer_size value: '0' +Warning 1292 Truncated incorrect preload_buffer_size value: '-1' SELECT @@global.preload_buffer_size; @@global.preload_buffer_size 1024 @@ -111,7 +111,7 @@ SELECT @@session.preload_buffer_size; 1024 SET @@session.preload_buffer_size = -2; Warnings: -Warning 1292 Truncated incorrect preload_buffer_size value: '0' +Warning 1292 Truncated incorrect preload_buffer_size value: '-2' SELECT @@session.preload_buffer_size; @@session.preload_buffer_size 1024 diff --git a/mysql-test/r/ps.result b/mysql-test/r/ps.result index 05b2d18889b..df996f0f515 100644 --- a/mysql-test/r/ps.result +++ b/mysql-test/r/ps.result @@ -803,6 +803,8 @@ select @@max_prepared_stmt_count; @@max_prepared_stmt_count 16382 set global max_prepared_stmt_count=-1; +Warnings: +Warning 1292 Truncated incorrect max_prepared_stmt_count value: '-1' select @@max_prepared_stmt_count; @@max_prepared_stmt_count 0 diff --git a/mysql-test/r/read_buffer_size_basic.result b/mysql-test/r/read_buffer_size_basic.result index 799f7b56235..fe4fa4138c1 100644 --- a/mysql-test/r/read_buffer_size_basic.result +++ b/mysql-test/r/read_buffer_size_basic.result @@ -81,7 +81,7 @@ SELECT @@global.read_buffer_size= 8200 OR @@global.read_buffer_size= 8228 ; 1 SET @@global.read_buffer_size = -1024; Warnings: -Warning 1292 Truncated incorrect read_buffer_size value: '0' +Warning 1292 Truncated incorrect read_buffer_size value: '-1024' SELECT @@global.read_buffer_size= 8200 OR @@global.read_buffer_size= 8228 ; @@global.read_buffer_size= 8200 OR @@global.read_buffer_size= 8228 1 @@ -107,7 +107,7 @@ SELECT @@session.read_buffer_size= 8200 OR @@session.read_buffer_size= 8228 ; 1 SET @@session.read_buffer_size = -2; Warnings: -Warning 1292 Truncated incorrect read_buffer_size value: '0' +Warning 1292 Truncated incorrect read_buffer_size value: '-2' SELECT @@session.read_buffer_size= 8200 OR @@session.read_buffer_size= 8228 ; @@session.read_buffer_size= 8200 OR @@session.read_buffer_size= 8228 1 diff --git a/mysql-test/r/read_rnd_buffer_size_basic.result b/mysql-test/r/read_rnd_buffer_size_basic.result index c51b0591054..f0c73409430 100644 --- a/mysql-test/r/read_rnd_buffer_size_basic.result +++ b/mysql-test/r/read_rnd_buffer_size_basic.result @@ -83,7 +83,7 @@ SELECT @@global.read_rnd_buffer_size= 8200 OR @@global.read_rnd_buffer_size= 822 1 SET @@global.read_rnd_buffer_size = -1024; Warnings: -Warning 1292 Truncated incorrect read_rnd_buffer_size value: '0' +Warning 1292 Truncated incorrect read_rnd_buffer_size value: '-1024' SELECT @@global.read_rnd_buffer_size= 8200 OR @@global.read_rnd_buffer_size= 8228; @@global.read_rnd_buffer_size= 8200 OR @@global.read_rnd_buffer_size= 8228 1 @@ -109,7 +109,7 @@ SELECT @@session.read_rnd_buffer_size= 8200 OR @@session.read_rnd_buffer_size= 8 1 SET @@session.read_rnd_buffer_size = -2; Warnings: -Warning 1292 Truncated incorrect read_rnd_buffer_size value: '0' +Warning 1292 Truncated incorrect read_rnd_buffer_size value: '-2' SELECT @@session.read_rnd_buffer_size= 8200 OR @@session.read_rnd_buffer_size= 8228; @@session.read_rnd_buffer_size= 8200 OR @@session.read_rnd_buffer_size= 8228 1 diff --git a/mysql-test/r/slave_net_timeout_basic.result b/mysql-test/r/slave_net_timeout_basic.result index d672d0152d7..fb8812745cc 100644 --- a/mysql-test/r/slave_net_timeout_basic.result +++ b/mysql-test/r/slave_net_timeout_basic.result @@ -58,13 +58,13 @@ ERROR HY000: Variable 'slave_net_timeout' is a GLOBAL variable and should be set '#------------------FN_DYNVARS_146_05-----------------------#' SET @@global.slave_net_timeout = -1; Warnings: -Warning 1292 Truncated incorrect slave_net_timeout value: '0' +Warning 1292 Truncated incorrect slave_net_timeout value: '-1' SELECT @@global.slave_net_timeout; @@global.slave_net_timeout 1 SET @@global.slave_net_timeout = -2147483648; Warnings: -Warning 1292 Truncated incorrect slave_net_timeout value: '0' +Warning 1292 Truncated incorrect slave_net_timeout value: '-2147483648' SELECT @@global.slave_net_timeout; @@global.slave_net_timeout 1 diff --git a/mysql-test/r/slow_launch_time_basic.result b/mysql-test/r/slow_launch_time_basic.result index c42942fba1a..da13af4f4e8 100644 --- a/mysql-test/r/slow_launch_time_basic.result +++ b/mysql-test/r/slow_launch_time_basic.result @@ -36,6 +36,8 @@ SELECT @@global.slow_launch_time; 65536 '#--------------------FN_DYNVARS_150_04-------------------------#' SET @@global.slow_launch_time = -1; +Warnings: +Warning 1292 Truncated incorrect slow_launch_time value: '-1' SELECT @@global.slow_launch_time; @@global.slow_launch_time 0 @@ -57,6 +59,8 @@ SELECT @@global.slow_launch_time; @@global.slow_launch_time 31536000 SET @@global.slow_launch_time = -1024; +Warnings: +Warning 1292 Truncated incorrect slow_launch_time value: '-1024' SELECT @@global.slow_launch_time; @@global.slow_launch_time 0 diff --git a/mysql-test/r/table_definition_cache_basic.result b/mysql-test/r/table_definition_cache_basic.result index 5f0e1960358..612d4138003 100644 --- a/mysql-test/r/table_definition_cache_basic.result +++ b/mysql-test/r/table_definition_cache_basic.result @@ -45,7 +45,7 @@ SELECT @@global.table_definition_cache; 256 SET @@global.table_definition_cache = -1024; Warnings: -Warning 1292 Truncated incorrect table_definition_cache value: '0' +Warning 1292 Truncated incorrect table_definition_cache value: '-1024' SELECT @@global.table_definition_cache; @@global.table_definition_cache 256 diff --git a/mysql-test/r/table_lock_wait_timeout_basic.result b/mysql-test/r/table_lock_wait_timeout_basic.result index 13771980188..a500581c228 100644 --- a/mysql-test/r/table_lock_wait_timeout_basic.result +++ b/mysql-test/r/table_lock_wait_timeout_basic.result @@ -37,13 +37,13 @@ SELECT @@global.table_lock_wait_timeout ; '#--------------------FN_DYNVARS_001_04-------------------------#' SET @@global.table_lock_wait_timeout = -1; Warnings: -Warning 1292 Truncated incorrect table_lock_wait_timeout value: '0' +Warning 1292 Truncated incorrect table_lock_wait_timeout value: '-1' SET @@global.table_lock_wait_timeout= 100000000000; Warnings: Warning 1292 Truncated incorrect table_lock_wait_timeout value: '100000000000' SET @@global.table_lock_wait_timeout= -1024; Warnings: -Warning 1292 Truncated incorrect table_lock_wait_timeout value: '0' +Warning 1292 Truncated incorrect table_lock_wait_timeout value: '-1024' SET @@global.table_lock_wait_timeout= 0; Warnings: Warning 1292 Truncated incorrect table_lock_wait_timeout value: '0' diff --git a/mysql-test/r/table_open_cache_basic.result b/mysql-test/r/table_open_cache_basic.result index ca02d32386f..080bcb6537e 100644 --- a/mysql-test/r/table_open_cache_basic.result +++ b/mysql-test/r/table_open_cache_basic.result @@ -39,7 +39,7 @@ SELECT @@global.table_open_cache ; '#--------------------FN_DYNVARS_001_04-------------------------#' SET @@global.table_open_cache = -1; Warnings: -Warning 1292 Truncated incorrect table_open_cache value: '0' +Warning 1292 Truncated incorrect table_open_cache value: '-1' SELECT @@global.table_open_cache ; @@global.table_open_cache 1 @@ -51,7 +51,7 @@ SELECT @@global.table_open_cache ; 524288 SET @@global.table_open_cache = -1024; Warnings: -Warning 1292 Truncated incorrect table_open_cache value: '0' +Warning 1292 Truncated incorrect table_open_cache value: '-1024' SELECT @@global.table_open_cache ; @@global.table_open_cache 1 diff --git a/mysql-test/r/variables.result b/mysql-test/r/variables.result index ac78d8e1871..9fe565f938c 100644 --- a/mysql-test/r/variables.result +++ b/mysql-test/r/variables.result @@ -703,7 +703,7 @@ VARIABLE_NAME VARIABLE_VALUE MYISAM_DATA_POINTER_SIZE 7 SET GLOBAL table_open_cache=-1; Warnings: -Warning 1292 Truncated incorrect table_open_cache value: '0' +Warning 1292 Truncated incorrect table_open_cache value: '-1' SHOW VARIABLES LIKE 'table_open_cache'; Variable_name Value table_open_cache 1 @@ -1337,3 +1337,36 @@ SET @@session.thread_stack= 7; ERROR HY000: Variable 'thread_stack' is a read only variable SET @@global.thread_stack= 7; ERROR HY000: Variable 'thread_stack' is a read only variable +SELECT @@global.expire_logs_days INTO @old_eld; +SET GLOBAL expire_logs_days = -1; +Warnings: +Warning 1292 Truncated incorrect expire_logs_days value: '-1' +needs to've been adjusted (0) +SELECT @@global.expire_logs_days; +@@global.expire_logs_days +0 +SET GLOBAL expire_logs_days = 11; +SET @old_mode=@@sql_mode; +SET SESSION sql_mode = 'TRADITIONAL'; +SET GLOBAL expire_logs_days = 100; +ERROR 42000: Variable 'expire_logs_days' can't be set to the value of '100' +needs to be unchanged (11) +SELECT @@global.expire_logs_days; +@@global.expire_logs_days +11 +SET SESSION sql_mode = @old_mode; +SET GLOBAL expire_logs_days = 100; +Warnings: +Warning 1292 Truncated incorrect expire_logs_days value: '100' +needs to've been adjusted (99) +SELECT @@global.expire_logs_days; +@@global.expire_logs_days +99 +SET GLOBAL expire_logs_days = 11; +SET GLOBAL expire_logs_days = 99; +needs to pass with no warnings (99) +SELECT @@global.expire_logs_days; +@@global.expire_logs_days +99 +SET GLOBAL expire_logs_days = @old_eld; +End of 5.1 tests diff --git a/mysql-test/t/variables.test b/mysql-test/t/variables.test index 828cb3a2916..9b611558447 100644 --- a/mysql-test/t/variables.test +++ b/mysql-test/t/variables.test @@ -1077,3 +1077,38 @@ SET @@session.thread_stack= 7; --error ER_INCORRECT_GLOBAL_LOCAL_VAR SET @@global.thread_stack= 7; # + +# +# Bug #40657 - assertion with out of range variables and traditional sql_mode +# + +SELECT @@global.expire_logs_days INTO @old_eld; + +SET GLOBAL expire_logs_days = -1; +--echo needs to've been adjusted (0) +SELECT @@global.expire_logs_days; + +SET GLOBAL expire_logs_days = 11; +SET @old_mode=@@sql_mode; +SET SESSION sql_mode = 'TRADITIONAL'; +--error ER_WRONG_VALUE_FOR_VAR +SET GLOBAL expire_logs_days = 100; +--echo needs to be unchanged (11) +SELECT @@global.expire_logs_days; +SET SESSION sql_mode = @old_mode; + +SET GLOBAL expire_logs_days = 100; +--echo needs to've been adjusted (99) +SELECT @@global.expire_logs_days; + +SET GLOBAL expire_logs_days = 11; +SET GLOBAL expire_logs_days = 99; +--echo needs to pass with no warnings (99) +SELECT @@global.expire_logs_days; + +# cleanup +SET GLOBAL expire_logs_days = @old_eld; + + + +--echo End of 5.1 tests diff --git a/sql/set_var.cc b/sql/set_var.cc index a371c1113ef..e2f3590311c 100644 --- a/sql/set_var.cc +++ b/sql/set_var.cc @@ -134,8 +134,8 @@ static int check_max_delayed_threads(THD *thd, set_var *var); static void fix_thd_mem_root(THD *thd, enum_var_type type); static void fix_trans_mem_root(THD *thd, enum_var_type type); static void fix_server_id(THD *thd, enum_var_type type); -static ulonglong fix_unsigned(THD *, ulonglong, const struct my_option *); -static bool get_unsigned(THD *thd, set_var *var); +static int get_unsigned(THD *thd, set_var *var); +static bool fix_unsigned(THD *, ulonglong *, bool, const struct my_option *); bool throw_bounds_warning(THD *thd, bool fixed, bool unsignd, const char *name, longlong val); static KEY_CACHE *create_key_cache(const char *name, uint length); @@ -1365,6 +1365,19 @@ static void fix_server_id(THD *thd, enum_var_type type) } +/** + Throw warning (error in STRICT mode) if value for variable needed bounding. + Only call from check(), not update(), because an error in update() would be + bad mojo. Plug-in interface also uses this. + + @param thd thread handle + @param fixed did we have to correct the value? (throw warn/err if so) + @param unsignd is value's type unsigned? + @param name variable's name + @param val variable's value + + @retval TRUE on error, FALSE otherwise (warning or OK) + */ bool throw_bounds_warning(THD *thd, bool fixed, bool unsignd, const char *name, longlong val) { @@ -1390,17 +1403,44 @@ bool throw_bounds_warning(THD *thd, bool fixed, bool unsignd, return FALSE; } -static ulonglong fix_unsigned(THD *thd, ulonglong num, - const struct my_option *option_limits) -{ - my_bool fixed= FALSE; - ulonglong out= getopt_ull_limit_value(num, option_limits, &fixed); - throw_bounds_warning(thd, fixed, TRUE, option_limits->name, (longlong) num); - return out; +/** + check an unsigned user-supplied value for a systemvariable against bounds. + if we needed to adjust the value, throw a warning/error. + + @param thd thread handle + @param num the value the user gave + @param warn throw warning/error (FALSE if we get here from + get_unsigned(), so we don't throw two warnings if + user supplies negative value to an unsigned variable) + @param option_limits the bounds-record + + @retval TRUE on error, FALSE otherwise (warning or OK) + */ +static bool fix_unsigned(THD *thd, ulonglong *num, bool warn, + const struct my_option *option_limits) +{ + my_bool fixed = FALSE; + ulonglong unadjusted= *num; + + *num= getopt_ull_limit_value(unadjusted, option_limits, &fixed); + + return warn && throw_bounds_warning(thd, fixed, TRUE, option_limits->name, + (longlong) unadjusted); + } -static bool get_unsigned(THD *thd, set_var *var) + +/** + Get unsigned system-variable. + Negative value does not wrap around, but becomes zero. + + @param thd thread handle + @param var the system-variable to get + + @retval 0 - OK, 1 - warning, 2 - error + */ +static int get_unsigned(THD *thd, set_var *var) { if (var->value->unsigned_flag) var->save_result.ulonglong_value= (ulonglong) var->value->val_int(); @@ -1408,6 +1448,8 @@ static bool get_unsigned(THD *thd, set_var *var) { longlong v= var->value->val_int(); var->save_result.ulonglong_value= (ulonglong) ((v < 0) ? 0 : v); + if (v < 0) + return throw_bounds_warning(thd, TRUE, FALSE, var->var->name, v) ? 2 : 1; } return 0; } @@ -1423,29 +1465,33 @@ sys_var_long_ptr(sys_var_chain *chain, const char *name_arg, ulong *value_ptr_ar bool sys_var_long_ptr_global::check(THD *thd, set_var *var) { - return get_unsigned(thd, var); -} + bool ret = FALSE; + int got_warnings= get_unsigned(thd, var); -bool sys_var_long_ptr_global::update(THD *thd, set_var *var) -{ - ulonglong tmp= var->save_result.ulonglong_value; - pthread_mutex_lock(guard); - if (option_limits) - *value= (ulong) fix_unsigned(thd, tmp, option_limits); + if (got_warnings == 2) + ret= TRUE; + else if (option_limits) + ret= fix_unsigned(thd, &var->save_result.ulonglong_value, + (got_warnings == 0), option_limits); else { #if SIZEOF_LONG < SIZEOF_LONG_LONG /* Avoid overflows on 32 bit systems */ - if (tmp > ULONG_MAX) + if (var->save_result.ulonglong_value > ULONG_MAX) { - tmp= ULONG_MAX; - throw_bounds_warning(thd, TRUE, TRUE, name, - (longlong) var->save_result.ulonglong_value); + ret= throw_bounds_warning(thd, TRUE, TRUE, name, + (longlong) var->save_result.ulonglong_value); + var->save_result.ulonglong_value= ULONG_MAX; } #endif - *value= (ulong) tmp; } + return ret; +} +bool sys_var_long_ptr_global::update(THD *thd, set_var *var) +{ + pthread_mutex_lock(guard); + *value= (ulong) var->save_result.ulonglong_value; pthread_mutex_unlock(guard); return 0; } @@ -1466,9 +1512,8 @@ bool sys_var_ulonglong_ptr::update(THD *thd, set_var *var) ulonglong tmp= var->save_result.ulonglong_value; pthread_mutex_lock(&LOCK_global_system_variables); if (option_limits) - *value= (ulonglong) fix_unsigned(thd, tmp, option_limits); - else - *value= (ulonglong) tmp; + fix_unsigned(thd, &tmp, FALSE, option_limits); + *value= (ulonglong) tmp; pthread_mutex_unlock(&LOCK_global_system_variables); return 0; } @@ -1518,35 +1563,47 @@ uchar *sys_var_enum_const::value_ptr(THD *thd, enum_var_type type, bool sys_var_thd_ulong::check(THD *thd, set_var *var) { - return (get_unsigned(thd, var) || - (check_func && (*check_func)(thd, var))); -} + ulonglong tmp; + int got_warnings= get_unsigned(thd, var); -bool sys_var_thd_ulong::update(THD *thd, set_var *var) -{ - ulonglong tmp= var->save_result.ulonglong_value; + if (got_warnings == 2) + return TRUE; + + tmp= var->save_result.ulonglong_value; /* Don't use bigger value than given with --maximum-variable-name=.. */ if ((ulong) tmp > max_system_variables.*offset) { - throw_bounds_warning(thd, TRUE, TRUE, name, (longlong) tmp); + if (throw_bounds_warning(thd, TRUE, TRUE, name, (longlong) tmp)) + return TRUE; tmp= max_system_variables.*offset; } if (option_limits) - tmp= (ulong) fix_unsigned(thd, tmp, option_limits); + { + if (fix_unsigned(thd, &tmp, (got_warnings == 0), option_limits)) + return TRUE; + } #if SIZEOF_LONG < SIZEOF_LONG_LONG else if (tmp > ULONG_MAX) { + if (throw_bounds_warning(thd, TRUE, TRUE, name, (longlong) tmp)) + return TRUE; tmp= ULONG_MAX; - throw_bounds_warning(thd, TRUE, TRUE, name, (longlong) var->save_result.ulonglong_value); } #endif + var->save_result.ulonglong_value= (ulong) tmp; + + return ((check_func && (*check_func)(thd, var))); +} + +bool sys_var_thd_ulong::update(THD *thd, set_var *var) +{ if (var->type == OPT_GLOBAL) - global_system_variables.*offset= (ulong) tmp; + global_system_variables.*offset= (ulong) var->save_result.ulonglong_value; else - thd->variables.*offset= (ulong) tmp; + thd->variables.*offset= (ulong) var->save_result.ulonglong_value; return 0; } @@ -1585,7 +1642,8 @@ bool sys_var_thd_ha_rows::update(THD *thd, set_var *var) tmp= max_system_variables.*offset; if (option_limits) - tmp= (ha_rows) fix_unsigned(thd, tmp, option_limits); + fix_unsigned(thd, &tmp, FALSE, option_limits); + if (var->type == OPT_GLOBAL) { /* Lock is needed to make things safe on 32 bit systems */ @@ -1626,27 +1684,44 @@ uchar *sys_var_thd_ha_rows::value_ptr(THD *thd, enum_var_type type, bool sys_var_thd_ulonglong::check(THD *thd, set_var *var) { - return get_unsigned(thd, var); + ulonglong tmp; + int got_warnings= get_unsigned(thd, var); + + if (got_warnings == 2) + return TRUE; + + tmp= var->save_result.ulonglong_value; + + if (tmp > max_system_variables.*offset) + { + if (throw_bounds_warning(thd, TRUE, TRUE, name, (longlong) tmp)) + return TRUE; + tmp= max_system_variables.*offset; + } + + if (option_limits) + { + if (fix_unsigned(thd, &tmp, (got_warnings == 0), option_limits)) + return TRUE; + } + + var->save_result.ulonglong_value= tmp; + + return FALSE; } bool sys_var_thd_ulonglong::update(THD *thd, set_var *var) { - ulonglong tmp= var->save_result.ulonglong_value; - - if (tmp > max_system_variables.*offset) - tmp= max_system_variables.*offset; - - if (option_limits) - tmp= fix_unsigned(thd, tmp, option_limits); if (var->type == OPT_GLOBAL) { /* Lock is needed to make things safe on 32 bit systems */ pthread_mutex_lock(&LOCK_global_system_variables); - global_system_variables.*offset= (ulonglong) tmp; + global_system_variables.*offset= (ulonglong) + var->save_result.ulonglong_value; pthread_mutex_unlock(&LOCK_global_system_variables); } else - thd->variables.*offset= (ulonglong) tmp; + thd->variables.*offset= (ulonglong) var->save_result.ulonglong_value; return 0; } @@ -2278,8 +2353,8 @@ bool sys_var_key_buffer_size::update(THD *thd, set_var *var) goto end; } - key_cache->param_buff_size= - (ulonglong) fix_unsigned(thd, tmp, option_limits); + fix_unsigned(thd, &tmp, FALSE, option_limits); + key_cache->param_buff_size= (ulonglong) tmp; /* If key cache didn't existed initialize it, else resize it */ key_cache->in_init= 1; @@ -2307,7 +2382,7 @@ end: */ bool sys_var_key_cache_long::update(THD *thd, set_var *var) { - ulong tmp= (ulong) var->value->val_int(); + ulonglong tmp= (ulonglong) (ulong) var->value->val_int(); LEX_STRING *base_name= &var->base; bool error= 0; @@ -2332,8 +2407,8 @@ bool sys_var_key_cache_long::update(THD *thd, set_var *var) if (key_cache->in_init) goto end; - *((ulong*) (((char*) key_cache) + offset))= - (ulong) fix_unsigned(thd, tmp, option_limits); + fix_unsigned(thd, &tmp, FALSE, option_limits); + *((ulong*) (((char*) key_cache) + offset))= (ulong) tmp; /* Don't create a new key cache if it didn't exist From c29994edb197c7698dc550aaab3e1debdfe50b33 Mon Sep 17 00:00:00 2001 From: Alfranio Correia Date: Tue, 3 Feb 2009 11:36:46 +0000 Subject: [PATCH 017/219] BUG#42445 Warning messages in innobase/handler/ha_innodb.cc There was a type casting problem in the storage/innobase/handler/ha_innodb.cc, (int ha_innobase::write_row(...)). Innobase uses has an internal error variable of type 'ulint' while mysql uses an 'int'. To fix the problem the function manipulates an error variable of type 'ulint' and only casts it into 'int' when needs to return the value. --- storage/innobase/handler/ha_innodb.cc | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index 5d895833f42..50c3917c43c 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -3577,7 +3577,8 @@ ha_innobase::write_row( /* out: error code */ uchar* record) /* in: a row in MySQL format */ { - int error = 0; + ulint error = 0; + int error_result= 0; ibool auto_inc_used= FALSE; ulint sql_command; trx_t* trx = thd_to_trx(user_thd); @@ -3693,6 +3694,7 @@ no_commit: } /* MySQL errors are passed straight back. */ + error_result = (int) error; goto func_exit; } @@ -3786,7 +3788,7 @@ set_max_autoinc: err = innobase_set_max_autoinc(auto_inc); if (err != DB_SUCCESS) { - error = (int) err; + error = err; } } break; @@ -3796,12 +3798,12 @@ set_max_autoinc: innodb_srv_conc_exit_innodb(prebuilt->trx); report_error: - error = convert_error_code_to_mysql(error, user_thd); + error_result = convert_error_code_to_mysql((int) error, user_thd); func_exit: innobase_active_small(); - DBUG_RETURN(error); + DBUG_RETURN(error_result); } /************************************************************************** From 40eec6c544b2e4e65f1e1689407ea4ed0847fc77 Mon Sep 17 00:00:00 2001 From: Staale Smedseng Date: Tue, 3 Feb 2009 13:46:25 +0100 Subject: [PATCH 018/219] Bug #41580 opt_threads option is not used anywhere at all Option opt_threads is deprecated in 5.1, and a warning is printed when used. Will remove in 6.0. --- sql-bench/bench-init.pl.sh | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/sql-bench/bench-init.pl.sh b/sql-bench/bench-init.pl.sh index a728086760a..588e518a648 100644 --- a/sql-bench/bench-init.pl.sh +++ b/sql-bench/bench-init.pl.sh @@ -47,7 +47,7 @@ $opt_machine=""; $opt_suffix=""; $opt_create_options=undef; $opt_optimization="None"; $opt_hw=""; -$opt_threads=5; +$opt_threads=-1; if (!defined($opt_time_limit)) { @@ -68,6 +68,11 @@ $limits=merge_limits($server,$opt_cmp); $date=date(); @estimated=(0.0,0.0,0.0); # For estimated time support +if ($opt_threads != -1) +{ + print "WARNING: Option --threads is deprecated and has no effect\n" +} + if ($opt_hires) { eval "use Time::HiRes;"; @@ -560,8 +565,8 @@ All benchmarks takes the following options: Inform test suite that we are generate random inital values for sequence of test executions. It should be used for imitation of real conditions. ---threads=# (Default 5) - Number of threads for multi-user benchmarks. +--threads=# **DEPRECATED** + This option has no effect, and will be removed in a future version. --tcpip Inform test suite that we are using TCP/IP to connect to the server. In From c9dc936a2bf850132513059732bc8f7fe8441e53 Mon Sep 17 00:00:00 2001 From: Davi Arnaut Date: Tue, 3 Feb 2009 15:16:24 -0200 Subject: [PATCH 019/219] Bug#40536: SELECT is blocked by INSERT DELAYED waiting on upgrading lock, even with low_priority_updates The problem is that there is no mechanism to control whether a delayed insert takes a high or low priority lock on a table. The solution is to modify the delayed insert thread ("handler") to take into account the global value of low_priority_updates when taking table locks. The value of low_priority_updates is retrieved when the insert delayed thread is created and will remain the same for the duration of the thread. include/thr_lock.h: Update prototype. mysql-test/r/delayed.result: Add test case result for Bug#40536 mysql-test/t/delayed.test: Add test case for Bug#40536 mysys/thr_lock.c: Add function parameter which specifies the write lock type. sql/sql_insert.cc: Take a low priority write lock if global value of low_priority_updates was ON when the thread was created. --- include/thr_lock.h | 3 ++- mysql-test/r/delayed.result | 26 ++++++++++++++++++++++ mysql-test/t/delayed.test | 43 +++++++++++++++++++++++++++++++++++++ mysys/thr_lock.c | 9 +++++--- sql/sql_insert.cc | 5 ++++- 5 files changed, 81 insertions(+), 5 deletions(-) diff --git a/include/thr_lock.h b/include/thr_lock.h index c7754ada299..e409df30972 100644 --- a/include/thr_lock.h +++ b/include/thr_lock.h @@ -159,7 +159,8 @@ void thr_multi_unlock(THR_LOCK_DATA **data,uint count); void thr_abort_locks(THR_LOCK *lock, my_bool upgrade_lock); my_bool thr_abort_locks_for_thread(THR_LOCK *lock, my_thread_id thread); void thr_print_locks(void); /* For debugging */ -my_bool thr_upgrade_write_delay_lock(THR_LOCK_DATA *data); +my_bool thr_upgrade_write_delay_lock(THR_LOCK_DATA *data, + enum thr_lock_type new_lock_type); void thr_downgrade_write_lock(THR_LOCK_DATA *data, enum thr_lock_type new_lock_type); my_bool thr_reschedule_write_lock(THR_LOCK_DATA *data); diff --git a/mysql-test/r/delayed.result b/mysql-test/r/delayed.result index bcda6ddb6ab..4d5d656f3ce 100644 --- a/mysql-test/r/delayed.result +++ b/mysql-test/r/delayed.result @@ -284,4 +284,30 @@ ERROR 22007: Incorrect date value: '0000-00-00' for column 'f1' at row 1 INSERT DELAYED INTO t2 VALUES (0,'2007-00-00'); ERROR 22007: Incorrect date value: '2007-00-00' for column 'f1' at row 1 DROP TABLE t1,t2; +set @old_delayed_updates = @@global.low_priority_updates; +set global low_priority_updates = 1; +select @@global.low_priority_updates; +@@global.low_priority_updates +1 +drop table if exists t1; +create table t1 (a int, b int); +insert into t1 values (1,1); +lock table t1 read; +connection: update +insert delayed into t1 values (2,2);; +connection: select +select * from t1; +a b +1 1 +connection: default +select * from t1; +a b +1 1 +unlock tables; +select * from t1; +a b +1 1 +2 2 +drop table t1; +set global low_priority_updates = @old_delayed_updates; End of 5.1 tests diff --git a/mysql-test/t/delayed.test b/mysql-test/t/delayed.test index ce57645bd4b..94ad22b80d0 100644 --- a/mysql-test/t/delayed.test +++ b/mysql-test/t/delayed.test @@ -285,4 +285,47 @@ INSERT DELAYED INTO t2 VALUES (0,'0000-00-00'); INSERT DELAYED INTO t2 VALUES (0,'2007-00-00'); DROP TABLE t1,t2; +# +# Bug#40536: SELECT is blocked by INSERT DELAYED waiting on upgrading lock, +# even with low_priority_updates +# + +set @old_delayed_updates = @@global.low_priority_updates; +set global low_priority_updates = 1; +select @@global.low_priority_updates; + +--disable_warnings +drop table if exists t1; +--enable_warnings +create table t1 (a int, b int); +insert into t1 values (1,1); +lock table t1 read; +connect (update,localhost,root,,); +connection update; +--echo connection: update +--send insert delayed into t1 values (2,2); +connection default; +let $wait_condition= + select count(*) = 1 from information_schema.processlist + where command = "Delayed insert" and state = "upgrading lock"; +--source include/wait_condition.inc +connect (select,localhost,root,,); +--echo connection: select +select * from t1; +connection default; +--echo connection: default +select * from t1; +connection default; +disconnect update; +disconnect select; +unlock tables; +let $wait_condition= + select count(*) = 1 from information_schema.processlist + where command = "Delayed insert" and state = "Waiting for INSERT"; +--source include/wait_condition.inc +select * from t1; +drop table t1; + +set global low_priority_updates = @old_delayed_updates; + --echo End of 5.1 tests diff --git a/mysys/thr_lock.c b/mysys/thr_lock.c index b13e8411771..31638ecee9a 100644 --- a/mysys/thr_lock.c +++ b/mysys/thr_lock.c @@ -1359,7 +1359,8 @@ void thr_downgrade_write_lock(THR_LOCK_DATA *in_data, /* Upgrade a WRITE_DELAY lock to a WRITE_LOCK */ -my_bool thr_upgrade_write_delay_lock(THR_LOCK_DATA *data) +my_bool thr_upgrade_write_delay_lock(THR_LOCK_DATA *data, + enum thr_lock_type new_lock_type) { THR_LOCK *lock=data->lock; DBUG_ENTER("thr_upgrade_write_delay_lock"); @@ -1372,7 +1373,7 @@ my_bool thr_upgrade_write_delay_lock(THR_LOCK_DATA *data) } check_locks(lock,"before upgrading lock",0); /* TODO: Upgrade to TL_WRITE_CONCURRENT_INSERT in some cases */ - data->type=TL_WRITE; /* Upgrade lock */ + data->type= new_lock_type; /* Upgrade lock */ /* Check if someone has given us the lock */ if (!data->cond) @@ -1411,6 +1412,7 @@ my_bool thr_upgrade_write_delay_lock(THR_LOCK_DATA *data) my_bool thr_reschedule_write_lock(THR_LOCK_DATA *data) { THR_LOCK *lock=data->lock; + enum thr_lock_type write_lock_type; DBUG_ENTER("thr_reschedule_write_lock"); pthread_mutex_lock(&lock->mutex); @@ -1420,6 +1422,7 @@ my_bool thr_reschedule_write_lock(THR_LOCK_DATA *data) DBUG_RETURN(0); } + write_lock_type= data->type; data->type=TL_WRITE_DELAYED; if (lock->update_status) (*lock->update_status)(data->status_param); @@ -1438,7 +1441,7 @@ my_bool thr_reschedule_write_lock(THR_LOCK_DATA *data) free_all_read_locks(lock,0); pthread_mutex_unlock(&lock->mutex); - DBUG_RETURN(thr_upgrade_write_delay_lock(data)); + DBUG_RETURN(thr_upgrade_write_delay_lock(data, write_lock_type)); } diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index fb437bed3fa..fcf86edeaa9 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -1690,6 +1690,7 @@ public: class Delayed_insert :public ilink { uint locks_in_memory; + thr_lock_type delayed_lock; public: THD thd; TABLE *table; @@ -1731,6 +1732,8 @@ public: pthread_cond_init(&cond_client,NULL); VOID(pthread_mutex_lock(&LOCK_thread_count)); delayed_insert_threads++; + delayed_lock= global_system_variables.low_priority_updates ? + TL_WRITE_LOW_PRIORITY : TL_WRITE; VOID(pthread_mutex_unlock(&LOCK_thread_count)); } ~Delayed_insert() @@ -2540,7 +2543,7 @@ bool Delayed_insert::handle_inserts(void) table->use_all_columns(); thd_proc_info(&thd, "upgrading lock"); - if (thr_upgrade_write_delay_lock(*thd.lock->locks)) + if (thr_upgrade_write_delay_lock(*thd.lock->locks, delayed_lock)) { /* This can happen if thread is killed either by a shutdown From dfbba6e7fda2286a2c021a025fa82926551e01f9 Mon Sep 17 00:00:00 2001 From: Alexey Kopytov Date: Tue, 3 Feb 2009 20:19:01 +0300 Subject: [PATCH 020/219] Fix for bug #41868: crash or memory overrun with concat + upper, date_format functions String::realloc() did not check whether the existing string data fits in the newly allocated buffer for cases when reallocating a String object with external buffer (i.e.alloced == FALSE). This could lead to memory overruns in some cases. mysql-test/r/func_str.result: Added a test case for bug #41868. mysql-test/t/func_str.test: Added a test case for bug #41868. sql/sql_class.cc: After each call to Item::send() in select_send::send_data() reset buffer to its original state to reduce unnecessary malloc() calls. See comments for bug #41868 for detailed analysis. sql/sql_string.cc: Fixed String::realloc() to check whether the existing string data fits in the newly allocated buffer for cases when reallocating a String object with external buffer. --- client/sql_string.cc | 20 ++++++++++---------- mysql-test/r/func_str.result | 6 ++++++ mysql-test/t/func_str.test | 9 +++++++++ sql/sql_class.cc | 5 +++++ sql/sql_string.cc | 20 ++++++++++---------- 5 files changed, 40 insertions(+), 20 deletions(-) diff --git a/client/sql_string.cc b/client/sql_string.cc index 9d887ff031c..eb80e29ed49 100644 --- a/client/sql_string.cc +++ b/client/sql_string.cc @@ -72,26 +72,26 @@ bool String::realloc(uint32 alloc_length) if (alloced) { if ((new_ptr= (char*) my_realloc(Ptr,len,MYF(MY_WME)))) - { - Ptr=new_ptr; - Alloced_length=len; - } + new_ptr[alloc_length]= 0; else - return TRUE; // Signal error + return TRUE; // Signal error } else if ((new_ptr= (char*) my_malloc(len,MYF(MY_WME)))) { + if (str_length > len - 1) + str_length= 0; if (str_length) // Avoid bugs in memcpy on AIX - memcpy(new_ptr,Ptr,str_length); - new_ptr[str_length]=0; - Ptr=new_ptr; - Alloced_length=len; + memcpy(new_ptr, Ptr, str_length); + new_ptr[str_length]= 0; alloced=1; } else return TRUE; // Signal error + Ptr= new_ptr; + Alloced_length= len; } - Ptr[alloc_length]=0; // This make other funcs shorter + else + Ptr[alloc_length]= 0; return FALSE; } diff --git a/mysql-test/r/func_str.result b/mysql-test/r/func_str.result index c121c8937d7..d7fd8c5c887 100644 --- a/mysql-test/r/func_str.result +++ b/mysql-test/r/func_str.result @@ -2181,4 +2181,10 @@ def format(a, 2) 253 20 4 Y 0 2 8 format(a, 2) 1.33 drop table t1; +CREATE TABLE t1 (c DATE, aa VARCHAR(30)); +INSERT INTO t1 VALUES ('2008-12-31','aaaaaa'); +SELECT DATE_FORMAT(c, GET_FORMAT(DATE, 'eur')) h, CONCAT(UPPER(aa),', ', aa) i FROM t1; +h i +31.12.2008 AAAAAA, aaaaaa +DROP TABLE t1; End of 5.0 tests diff --git a/mysql-test/t/func_str.test b/mysql-test/t/func_str.test index 8298a50c277..389538c4cc0 100644 --- a/mysql-test/t/func_str.test +++ b/mysql-test/t/func_str.test @@ -1159,4 +1159,13 @@ select format(a, 2) from t1; --disable_metadata drop table t1; +# +# Bug #41868: crash or memory overrun with concat + upper, date_format functions +# + +CREATE TABLE t1 (c DATE, aa VARCHAR(30)); +INSERT INTO t1 VALUES ('2008-12-31','aaaaaa'); +SELECT DATE_FORMAT(c, GET_FORMAT(DATE, 'eur')) h, CONCAT(UPPER(aa),', ', aa) i FROM t1; +DROP TABLE t1; + --echo End of 5.0 tests diff --git a/sql/sql_class.cc b/sql/sql_class.cc index 91c0aa66761..9ff602bb62e 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -1047,6 +1047,11 @@ bool select_send::send_data(List &items) my_message(ER_OUT_OF_RESOURCES, ER(ER_OUT_OF_RESOURCES), MYF(0)); break; } + /* + Reset buffer to its original state, as it may have been altered in + Item::send(). + */ + buffer.set(buff, sizeof(buff), &my_charset_bin); } thd->sent_row_count++; if (!thd->vio_ok()) diff --git a/sql/sql_string.cc b/sql/sql_string.cc index 75e47dd0c8e..b6ce4d8dc8d 100644 --- a/sql/sql_string.cc +++ b/sql/sql_string.cc @@ -72,26 +72,26 @@ bool String::realloc(uint32 alloc_length) if (alloced) { if ((new_ptr= (char*) my_realloc(Ptr,len,MYF(MY_WME)))) - { - Ptr=new_ptr; - Alloced_length=len; - } + new_ptr[alloc_length]= 0; else - return TRUE; // Signal error + return TRUE; // Signal error } else if ((new_ptr= (char*) my_malloc(len,MYF(MY_WME)))) { + if (str_length > len - 1) + str_length= 0; if (str_length) // Avoid bugs in memcpy on AIX - memcpy(new_ptr,Ptr,str_length); - new_ptr[str_length]=0; - Ptr=new_ptr; - Alloced_length=len; + memcpy(new_ptr, Ptr, str_length); + new_ptr[str_length]= 0; alloced=1; } else return TRUE; // Signal error + Ptr= new_ptr; + Alloced_length= len; } - Ptr[alloc_length]=0; // This make other funcs shorter + else + Ptr[alloc_length]= 0; return FALSE; } From 1b557a2ce73942a06da0e36480802f0e5ae98b17 Mon Sep 17 00:00:00 2001 From: Timothy Smith Date: Wed, 4 Feb 2009 04:20:42 +0100 Subject: [PATCH 021/219] The nwbootstrap script depended on BitKeeper, and was fairly complicated. It's much simpler to just use the source .tar.gz to do a build. So the script has been renamed to nwbuild, and simplified. --- netware/BUILD/nwbootstrap | 191 -------------------------------------- netware/BUILD/nwbuild | 86 +++++++++++++++++ 2 files changed, 86 insertions(+), 191 deletions(-) delete mode 100755 netware/BUILD/nwbootstrap create mode 100755 netware/BUILD/nwbuild diff --git a/netware/BUILD/nwbootstrap b/netware/BUILD/nwbootstrap deleted file mode 100755 index 7ea8b9fc4b8..00000000000 --- a/netware/BUILD/nwbootstrap +++ /dev/null @@ -1,191 +0,0 @@ -#! /bin/sh - -# debug -#set -x - -# stop on errors -set -e - -path=`dirname $0` - -# repository direcotry -repo_dir=`pwd` - -# build directory -build_dir="$HOME/mydev" -wine_build_dir="F:/mydev" - -# doc directory -doc_dir="$repo_dir/../mysqldoc" - -# init -target_dir="" -temp_dir="" -revision="" -rev="" -build="" -suffix="" -#obsolete mwenv="" - -# show usage -show_usage() -{ - cat << EOF - -usage: nwbootstrap [options] - -Exports a revision of the BitKeeper tree (nwbootstrap must be run inside a -directory of the BitKeeper tree to be used). Creates the ChangeLog file. -Adds the latest manual.texi from the mysqldoc BitKeeper tree. Builds the -Linux tools required for cross-platform builds. Optionally, builds the -binary distributions for NetWare. - -options: - ---build= Build the binary distributions for NetWare, - where is "standard", "debug", or "all" - (default is to not build a binary distribution) - ---build-dir= Export the BitKeeper tree to the directroy - (default is "$build_dir") - ---doc-dir= Use the mysqldoc BitKeeper tree located in the - directory - (default is parallel to current BitKeeper tree) - ---help Show this help information - ---revision= Export the BitKeeper tree as of revision - (default is the latest revision) - ---wine-build-dir= Use the WINE directory , which should - correspond to the --build-dir directory - (default is "$wine_build_dir") - -examples: - - nwbootstrap - - nwbootstrap --revision=1.1594 --build=all - - nwbootstrap --build-dir=/home/jdoe/dev --wine-build-dir=F:/dev - - -EOF - exit 0; -} - -# parse arguments -for arg do - case "$arg" in - --build-dir=*) build_dir=`echo "$arg" | sed -e "s;--build-dir=;;"` ;; - --wine-build-dir=*) wine_build_dir=`echo "$arg" | sed -e "s;--wine-build-dir=;;"` ;; - --revision=*) revision=`echo "$arg" | sed -e "s;--revision=;;"` ;; - --build=*) build=`echo "$arg" | sed -e "s;--build=;;"` ;; - --suffix=*) suffix=`echo "$arg" | sed -e "s;--suffix=;;"` ;; - --doc-dir=*) doc_dir=`echo "$arg" | sed -e "s;--doc-dir=;;"` ;; - *) show_usage ;; - esac -done - -echo "starting build..." - -# check for bk and repo_dir -bzr help > /dev/null -repo_dir=`bzr root $repo_dir` -cd $repo_dir -doc_dir="$repo_dir/../mysqldoc" - -# build temporary directory -temp_dir="$build_dir/mysql-$$.tmp" - -# export the bk tree -command="bzr export"; -if test $revision; then command="$command -r$revision"; fi -command="$command $temp_dir" -echo "exporting $repo_dir..." -$command - -# determine version -version=`grep -e "AM_INIT_AUTOMAKE(mysql, .*)" < $temp_dir/configure.in | sed -e "s/AM_INIT_AUTOMAKE(mysql, \(.*\))/\1/"` -echo "version: $version" - -# build target directory -target_dir="$build_dir/mysql-$version" - -# add suffix -if test $suffix -then - target_dir="$target_dir-$suffix" -fi - -# delete any old target -if test -d $target_dir.old; then rm -rf $target_dir.old; fi - -# rename old target -if test -d $target_dir; then mv -f $target_dir $target_dir.old; fi - -# rename directory to use version -mv $temp_dir $target_dir - -# create ChangeLog -if test $revision -then - rev=`bk changes -r..$revision -t -d':REV:' -n | head -2 | tail -1` -else - rev=`bk changes -t -d':REV:' -n | head -1` -fi - -echo "creating ChangeLog..." -bk changes -v -r$rev..$revision > $target_dir/ChangeLog - -# add the latest manual -if test -d $doc_dir -then - echo "adding the latest manual..." - install -m 644 $doc_dir/Docs/{manual,reservedwords}.texi $target_dir/Docs/ -fi - -# make files writeable -echo "making files writable..." -cd $target_dir -chmod -R u+rw,g+rw . - -#obsolete # edit the mvenv file -#obsolete echo "updating the mwenv environment file..." -#obsolete mwenv="./netware/BUILD/mwenv" -#obsolete mv -f $mwenv $mwenv.org -#obsolete sed -e "s;WINE_BUILD_DIR;$wine_build_dir;g" \ -#obsolete -e "s;BUILD_DIR;$build_dir;g" \ -#obsolete -e "s;VERSION;$version;g" $mwenv.org > $mwenv -#obsolete chmod +rwx $mwenv - -# edit the def file versions -echo "updating *.def file versions..." -nlm_version=`echo "$version" | sed -e "s;\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\).*;\1, \2, \3;"` - -for file in ./netware/*.def -do - mv -f $file $file.org - sed -e "s;VERSION.*;VERSION $nlm_version;g" $file.org > $file - rm $file.org -done - -# create the libmysql.imp file in netware folder from libmysql/libmysql.def -# file -echo "generating llibmysql.imp file..." -awk 'BEGIN{x=0;} END{printf("\n");} x==1 {printf(" %s",$1); x++; next} x>1 {printf(",\n %s", $1);next} /EXPORTS/{x=1}' libmysql/libmysql.def > netware/libmysql.imp -# build linux tools -echo "compiling linux tools..." -./netware/BUILD/compile-linux-tools -test -f ./netware/init_db.sql # this must exist -test -f ./netware/test_db.sql # this must exist - -# compile -if test $build -then - echo "compiling $build..." - ./netware/BUILD/compile-netware-$build -fi - -echo "done" diff --git a/netware/BUILD/nwbuild b/netware/BUILD/nwbuild new file mode 100755 index 00000000000..d431f70add8 --- /dev/null +++ b/netware/BUILD/nwbuild @@ -0,0 +1,86 @@ +#! /bin/sh + +# This script builds a Netware binary from a MySQL source tarball + +# debug +#set -x + +# stop on errors +set -e + +# init +build="" + +# show usage +show_usage() +{ + cat << EOF + +usage: nwbuild [options] + +Build Netware binary from source .tar.gz + +options: + +--build= Build the binary distributions for NetWare, + where is "standard", "debug", or "all" + (default is to not build a binary distribution) + +--help Show this help information + +Examples: + + ./netware/BUILD/nwbuild --build=debug + ./netware/BUILD/nwbuild --build=standard + +EOF +} + +# parse arguments +for arg do + case "$arg" in + --build=*) build=`echo "$arg" | sed -e "s;--build=;;"` ;; + --help) show_usage; exit 0 ;; + *) show_usage >&2; exit 1 ;; + esac +done + +# determine version +version=`grep -e "AM_INIT_AUTOMAKE(mysql, .*)" < configure.in | sed -e "s/AM_INIT_AUTOMAKE(mysql, \(.*\))/\1/"` +echo "version: $version" + +# make files writeable +echo "making files writable..." +chmod -R u+rw,g+rw . + +# edit the def file versions +nlm_version=`echo "$version" | sed -e "s;\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\).*;\1, \2, \3;"` +echo "updating *.def file versions to $nlm_version..." + +for file in ./netware/*.def +do + mv -f $file $file.org + sed -e "s;VERSION.*;VERSION $nlm_version;g" $file.org > $file + rm $file.org +done + +# create the libmysql.imp file in netware folder from libmysql/libmysql.def +# file +echo "generating libmysql.imp file..." +awk 'BEGIN{x=0;} END{printf("\n");} x==1 {printf(" %s",$1); x++; next} x>1 {printf(",\n %s", $1);next} /EXPORTS/{x=1}' libmysql/libmysql.def > netware/libmysql.imp +# build linux tools +echo "compiling linux tools..." +./netware/BUILD/compile-linux-tools +test -f ./netware/init_db.sql # this must exist +test -f ./netware/test_db.sql # this must exist + +# compile +if test $build +then + echo "compiling $build..." + ./netware/BUILD/compile-netware-$build +else + echo "Preparation complete. Use ./netware/BUILD/compile-netware-* to build MySQL." +fi + +echo "done" From 4561831bf7a526e1535f5d08bfa5eb6520773894 Mon Sep 17 00:00:00 2001 From: Magnus Svensson Date: Wed, 4 Feb 2009 10:49:52 +0100 Subject: [PATCH 022/219] Bug#42588 system_mysql_db_fix30020 fails when run from bin dist with mtr2 - Properly set --bindir=$path_client_bindir and --basedir=$basedir by adding %s format specifier --- mysql-test/mysql-test-run.pl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl index 30eab135b24..3c02f8803af 100755 --- a/mysql-test/mysql-test-run.pl +++ b/mysql-test/mysql-test-run.pl @@ -1528,8 +1528,8 @@ sub mysql_fix_arguments () { mtr_init_args(\$args); mtr_add_arg($args, "--defaults-file=%s", $path_config_file); - mtr_add_arg($args, "--basedir=", $basedir); - mtr_add_arg($args, "--bindir=", $path_client_bindir); + mtr_add_arg($args, "--basedir=%s", $basedir); + mtr_add_arg($args, "--bindir=%s", $path_client_bindir); mtr_add_arg($args, "--verbose"); return mtr_args2str($exe, @$args); } From 9b11bc02ae792d5154efd08852e0120690c323e8 Mon Sep 17 00:00:00 2001 From: Andrei Elkin Date: Wed, 4 Feb 2009 12:13:54 +0200 Subject: [PATCH 023/219] Bug #41183 rpl_ndb_circular, rpl_ndb_circular_simplex need maintenance, crash The bug happened because filtering-out a STMT_END_F-flagged event so that the transaction COMMIT finds traces of incomplete statement commit. Such situation is only possible with ndb circular replication. The filtered-out rows event is one that immediately preceeds the COMMIT query event. Fixed with deploying an the rows-log-event statement commit at executing of the transaction COMMIT event. Resources that were allocated by other than STMT_END_F-flagged event of the last statement are clean up prior execution of the commit logics. mysql-test/suite/rpl_ndb/t/disabled.def: re-enabling two tests. sql/log_event.cc: Adding the statement cleanup to execute at the transaction commit time. The statement might not be ended with execution of STMT_END_F-flagged event because of the event was filtered out by SERVER_ID rules. Small refactoring for Rows_log_event::do_update_pos() to be split on two parts: the statement commit that releases its execution time allocated resources, and the relay log update. --- mysql-test/suite/rpl_ndb/t/disabled.def | 3 - sql/log_event.cc | 88 +++++++++++++++++++++---- 2 files changed, 75 insertions(+), 16 deletions(-) diff --git a/mysql-test/suite/rpl_ndb/t/disabled.def b/mysql-test/suite/rpl_ndb/t/disabled.def index 694f7098980..6908269d014 100644 --- a/mysql-test/suite/rpl_ndb/t/disabled.def +++ b/mysql-test/suite/rpl_ndb/t/disabled.def @@ -10,7 +10,4 @@ # ############################################################################## -rpl_ndb_circular : Bug#41183 rpl_ndb_circular, rpl_ndb_circular_simplex need maintenance, crash -rpl_ndb_circular_simplex : Bug#41183 rpl_ndb_circular, rpl_ndb_circular_simplex need maintenance, crash - # the below testcase have been reworked to avoid the bug, test contains comment, keep bug open diff --git a/sql/log_event.cc b/sql/log_event.cc index 0f980f1808d..850b03589a1 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -51,6 +51,7 @@ */ #define FMT_G_BUFSIZE(PREC) (3 + (PREC) + 5 + 1) +static int rows_event_stmt_cleanup(Relay_log_info const *rli, THD* thd); #if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION) static const char *HA_ERR(int i) @@ -2894,7 +2895,37 @@ int Query_log_event::do_apply_event(Relay_log_info const *rli, DBUG_PRINT("info", ("log_pos: %lu", (ulong) log_pos)); clear_all_errors(thd, const_cast(rli)); - const_cast(rli)->clear_tables_to_lock(); + if (strcmp("COMMIT", query) == 0 && rli->tables_to_lock) + { + /* + Cleaning-up the last statement context: + the terminal event of the current statement flagged with + STMT_END_F got filtered out in ndb circular replication. + */ + int error; + char llbuff[22]; + if ((error= rows_event_stmt_cleanup(const_cast(rli), thd))) + { + const_cast(rli)->report(ERROR_LEVEL, error, + "Error in cleaning up after an event preceeding the commit; " + "the group log file/position: %s %s", + const_cast(rli)->group_master_log_name, + llstr(const_cast(rli)->group_master_log_pos, + llbuff)); + } + /* + Executing a part of rli->stmt_done() logics that does not deal + with group position change. The part is redundant now but is + future-change-proof addon, e.g if COMMIT handling will start checking + invariants like IN_STMT flag must be off at committing the transaction. + */ + const_cast(rli)->inc_event_relay_log_pos(); + const_cast(rli)->clear_flag(Relay_log_info::IN_STMT); + } + else + { + const_cast(rli)->clear_tables_to_lock(); + } /* Note: We do not need to execute reset_one_shot_variables() if this @@ -7403,16 +7434,20 @@ Rows_log_event::do_shall_skip(Relay_log_info *rli) return Log_event::do_shall_skip(rli); } -int -Rows_log_event::do_update_pos(Relay_log_info *rli) +/** + The function is called at Rows_log_event statement commit time, + normally from Rows_log_event::do_update_pos() and possibly from + Query_log_event::do_apply_event() of the COMMIT. + The function commits the last statement for engines, binlog and + releases resources have been allocated for the statement. + + @retval 0 Ok. + @retval non-zero Error at the commit. + */ + +static int rows_event_stmt_cleanup(Relay_log_info const *rli, THD * thd) { - DBUG_ENTER("Rows_log_event::do_update_pos"); - int error= 0; - - DBUG_PRINT("info", ("flags: %s", - get_flags(STMT_END_F) ? "STMT_END_F " : "")); - - if (get_flags(STMT_END_F)) + int error; { /* This is the end of a statement or transaction, so close (and @@ -7454,14 +7489,39 @@ Rows_log_event::do_update_pos(Relay_log_info *rli) thd->reset_current_stmt_binlog_row_based(); - rli->cleanup_context(thd, 0); - if (error == 0) + const_cast(rli)->cleanup_context(thd, 0); + } + return error; +} + +/** + The method either increments the relay log position or + commits the current statement and increments the master group + possition if the event is STMT_END_F flagged and + the statement corresponds to the autocommit query (i.e replicated + without wrapping in BEGIN/COMMIT) + + @retval 0 Success + @retval non-zero Error in the statement commit + */ +int +Rows_log_event::do_update_pos(Relay_log_info *rli) +{ + DBUG_ENTER("Rows_log_event::do_update_pos"); + int error= 0; + + DBUG_PRINT("info", ("flags: %s", + get_flags(STMT_END_F) ? "STMT_END_F " : "")); + + if (get_flags(STMT_END_F)) + { + if ((error= rows_event_stmt_cleanup(rli, thd)) == 0) { /* Indicate that a statement is finished. Step the group log position if we are not in a transaction, otherwise increase the event log position. - */ + */ rli->stmt_done(log_pos, when); /* @@ -7475,11 +7535,13 @@ Rows_log_event::do_update_pos(Relay_log_info *rli) thd->clear_error(); } else + { rli->report(ERROR_LEVEL, error, "Error in %s event: commit of row events failed, " "table `%s`.`%s`", get_type_str(), m_table->s->db.str, m_table->s->table_name.str); + } } else { From 5aef51b5d31d405488d7cda8e8001f4ac201fa19 Mon Sep 17 00:00:00 2001 From: Andrei Elkin Date: Wed, 4 Feb 2009 13:08:27 +0200 Subject: [PATCH 024/219] Bug #41183 rpl_ndb_circular, rpl_ndb_circular_simplex need maintenance, crash fixing build issue, caused by the previous push. sql/log_event.cc: moving a new declaration out of mysqlbinlog compilation scope. --- sql/log_event.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sql/log_event.cc b/sql/log_event.cc index 850b03589a1..0e400ac2705 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -51,9 +51,10 @@ */ #define FMT_G_BUFSIZE(PREC) (3 + (PREC) + 5 + 1) -static int rows_event_stmt_cleanup(Relay_log_info const *rli, THD* thd); #if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION) +static int rows_event_stmt_cleanup(Relay_log_info const *rli, THD* thd); + static const char *HA_ERR(int i) { switch (i) { From 1d09ec6208010830e20970531fcb8d7ff6f733d8 Mon Sep 17 00:00:00 2001 From: Sergey Glukhov Date: Wed, 4 Feb 2009 15:40:12 +0400 Subject: [PATCH 025/219] Bug#42495 updatexml: Assertion failed: xpath->context, file .\item_xmlfunc.cc, line 2507 Problem: RelativeLocationPath can appear only after a node-set expression in the third and the fourth branches of this rule: PathExpr :: = LocationPath | FilterExpr | FilterExpr '/' RelativeLocationPath | FilterExpr '//' RelativeLocationPath XPatch code didn't check the type of FilterExpr and crashed. Fix: If FilterExpr is a scalar expression (variable reference, literal, number, scalar function call) return error. mysql-test/r/xml.result: test result mysql-test/t/xml.test: test case sql/item_xmlfunc.cc: Problem: RelativeLocationPath can appear only after a node-set expression in the third and the fourth branches of this rule: PathExpr :: = LocationPath | FilterExpr | FilterExpr '/' RelativeLocationPath | FilterExpr '//' RelativeLocationPath XPatch code didn't check the type of FilterExpr and crashed. Fix: If FilterExpr is a scalar expression (variable reference, literal, number, scalar function call) return error. --- mysql-test/r/xml.result | 11 +++++++++++ mysql-test/t/xml.test | 14 ++++++++++++++ sql/item_xmlfunc.cc | 8 +++++++- 3 files changed, 32 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/xml.result b/mysql-test/r/xml.result index 41c0d6bee21..404b0dc3789 100644 --- a/mysql-test/r/xml.result +++ b/mysql-test/r/xml.result @@ -1053,4 +1053,15 @@ ExtractValue('CharData', '/xml') NULL Warnings: Warning 1525 Incorrect XML value: 'parse error at line 1 pos 17: STRING unexpected ('>' wanted)' +set @x=10; +select extractvalue('','$@x/a'); +ERROR HY000: XPATH syntax error: '/a' +select extractvalue('','round(123.4)/a'); +ERROR HY000: XPATH syntax error: '/a' +select extractvalue('','1/a'); +ERROR HY000: XPATH syntax error: '/a' +select extractvalue('','"b"/a'); +ERROR HY000: XPATH syntax error: '/a' +select extractvalue('','(1)/a'); +ERROR HY000: XPATH syntax error: '/a' End of 5.1 tests diff --git a/mysql-test/t/xml.test b/mysql-test/t/xml.test index d840e14ba5f..74bce8dc962 100644 --- a/mysql-test/t/xml.test +++ b/mysql-test/t/xml.test @@ -575,5 +575,19 @@ SELECT ExtractValue(@xml, 'html/body'); SELECT ExtractValue('CharData', '/xml'); SELECT ExtractValue('CharData', '/xml'); +# +# Bug#42495 updatexml: Assertion failed: xpath->context, file .\item_xmlfunc.cc, line 2507 +# +set @x=10; +--error ER_UNKNOWN_ERROR +select extractvalue('','$@x/a'); +--error ER_UNKNOWN_ERROR +select extractvalue('','round(123.4)/a'); +--error ER_UNKNOWN_ERROR +select extractvalue('','1/a'); +--error ER_UNKNOWN_ERROR +select extractvalue('','"b"/a'); +--error ER_UNKNOWN_ERROR +select extractvalue('','(1)/a'); --echo End of 5.1 tests diff --git a/sql/item_xmlfunc.cc b/sql/item_xmlfunc.cc index 68d85418324..5601a2b18c6 100644 --- a/sql/item_xmlfunc.cc +++ b/sql/item_xmlfunc.cc @@ -1969,6 +1969,13 @@ my_xpath_parse_FilterExpr_opt_slashes_RelativeLocationPath(MY_XPATH *xpath) if (!my_xpath_parse_term(xpath, MY_XPATH_LEX_SLASH)) return 1; + if (xpath->item->type() != Item::XPATH_NODESET) + { + xpath->lasttok= xpath->prevtok; + xpath->error= 1; + return 0; + } + my_xpath_parse_term(xpath, MY_XPATH_LEX_SLASH); return my_xpath_parse_RelativeLocationPath(xpath); } @@ -1976,7 +1983,6 @@ static int my_xpath_parse_PathExpr(MY_XPATH *xpath) { return my_xpath_parse_LocationPath(xpath) || my_xpath_parse_FilterExpr_opt_slashes_RelativeLocationPath(xpath); - } From 97bd763544bbaf882a083b1952b47901bc9a335b Mon Sep 17 00:00:00 2001 From: Sergey Vojtovich Date: Wed, 4 Feb 2009 15:46:23 +0400 Subject: [PATCH 026/219] BUG#32047 - 'Spurious' errors while opening MERGE tables Accessing well defined MERGE table may return an error stating that the merge table is incorrectly defined. This happens if MERGE child tables were accessed before and we failed to open another incorrectly defined MERGE table in this connection. myrg_open() internally used my_errno as a variable for determining failure, and thus could be tricked into a wrong decision by other uses of my_errno. With this fix we use function local boolean flag instead of my_errno to determine failure. myisammrg/myrg_open.c: There are two requirement for accessing/setting my_errno variable, which were not followed by myrg_open(): - it must be checked immediately after a function returned an error. There must be no calls to other functions that may change it's value between. - my_errno value must be set right before a function is going to return an error. There must be no calls to other functions that may change it's value between (that's why we have these tricks with save_errno at the bottom of myrg_open()). myrg_open() internally used my_errno as a variable for determining failure, and thus could be tricked into a wrong decision by other uses of my_errno. mysql-test/r/merge.result: A test case for BUG#32047. mysql-test/t/merge.test: A test case for BUG#32047. --- myisammrg/myrg_open.c | 17 ++++++++++------- mysql-test/r/merge.result | 11 +++++++++++ mysql-test/t/merge.test | 13 +++++++++++++ 3 files changed, 34 insertions(+), 7 deletions(-) diff --git a/myisammrg/myrg_open.c b/myisammrg/myrg_open.c index 0e82e429afd..4e61f42efce 100644 --- a/myisammrg/myrg_open.c +++ b/myisammrg/myrg_open.c @@ -40,6 +40,7 @@ MYRG_INFO *myrg_open(const char *name, int mode, int handle_locking) IO_CACHE file; MI_INFO *isam=0; uint found_merge_insert_method= 0; + my_bool bad_children= FALSE; DBUG_ENTER("myrg_open"); LINT_INIT(key_parts); @@ -89,13 +90,13 @@ MYRG_INFO *myrg_open(const char *name, int mode, int handle_locking) fn_format(buff, buff, "", "", 0); if (!(isam=mi_open(buff,mode,(handle_locking?HA_OPEN_WAIT_IF_LOCKED:0)))) { - my_errno= HA_ERR_WRONG_MRG_TABLE_DEF; if (handle_locking & HA_OPEN_FOR_REPAIR) { myrg_print_wrong_table(buff); + bad_children= TRUE; continue; } - goto err; + goto bad_children; } if (!m_info) /* First file */ { @@ -122,13 +123,13 @@ MYRG_INFO *myrg_open(const char *name, int mode, int handle_locking) files++; if (m_info->reclength != isam->s->base.reclength) { - my_errno=HA_ERR_WRONG_MRG_TABLE_DEF; if (handle_locking & HA_OPEN_FOR_REPAIR) { myrg_print_wrong_table(buff); + bad_children= TRUE; continue; } - goto err; + goto bad_children; } m_info->options|= isam->s->options; m_info->records+= isam->state->records; @@ -141,8 +142,8 @@ MYRG_INFO *myrg_open(const char *name, int mode, int handle_locking) m_info->tables); } - if (my_errno == HA_ERR_WRONG_MRG_TABLE_DEF) - goto err; + if (bad_children) + goto bad_children; if (!m_info && !(m_info= (MYRG_INFO*) my_malloc(sizeof(MYRG_INFO), MYF(MY_WME | MY_ZEROFILL)))) goto err; @@ -170,12 +171,14 @@ MYRG_INFO *myrg_open(const char *name, int mode, int handle_locking) pthread_mutex_unlock(&THR_LOCK_open); DBUG_RETURN(m_info); +bad_children: + my_errno= HA_ERR_WRONG_MRG_TABLE_DEF; err: save_errno=my_errno; switch (errpos) { case 3: while (files) - mi_close(m_info->open_tables[--files].table); + (void) mi_close(m_info->open_tables[--files].table); my_free((char*) m_info,MYF(0)); /* Fall through */ case 2: diff --git a/mysql-test/r/merge.result b/mysql-test/r/merge.result index f8ef4f23180..3f2ac3e08ec 100644 --- a/mysql-test/r/merge.result +++ b/mysql-test/r/merge.result @@ -940,4 +940,15 @@ m1 CREATE TABLE `m1` ( `a` int(11) default NULL ) ENGINE=MRG_MyISAM DEFAULT CHARSET=latin1 DROP TABLE t1, m1; +CREATE TABLE t1(a INT); +CREATE TABLE t2(a VARCHAR(10)); +CREATE TABLE m1(a INT) ENGINE=MERGE UNION=(t1, t2); +CREATE TABLE m2(a INT) ENGINE=MERGE UNION=(t1); +SELECT * FROM t1; +a +SELECT * FROM m1; +ERROR HY000: Unable to open underlying table which is differently defined or of non-MyISAM type or doesn't exist +SELECT * FROM m2; +a +DROP TABLE t1, t2, m1, m2; End of 5.0 tests diff --git a/mysql-test/t/merge.test b/mysql-test/t/merge.test index e5cc4d703f2..341296dbe8e 100644 --- a/mysql-test/t/merge.test +++ b/mysql-test/t/merge.test @@ -556,4 +556,17 @@ ALTER TABLE m1 UNION=(); SHOW CREATE TABLE m1; DROP TABLE t1, m1; +# +# BUG#32047 - 'Spurious' errors while opening MERGE tables +# +CREATE TABLE t1(a INT); +CREATE TABLE t2(a VARCHAR(10)); +CREATE TABLE m1(a INT) ENGINE=MERGE UNION=(t1, t2); +CREATE TABLE m2(a INT) ENGINE=MERGE UNION=(t1); +SELECT * FROM t1; +--error ER_WRONG_MRG_TABLE +SELECT * FROM m1; +SELECT * FROM m2; +DROP TABLE t1, t2, m1, m2; + --echo End of 5.0 tests From 9036f1aa97ad0a46a338b70673327dd3d8192eee Mon Sep 17 00:00:00 2001 From: Alexey Botchkov Date: Thu, 5 Feb 2009 10:16:00 +0400 Subject: [PATCH 027/219] Bug#37995 Error message truncation in test "innodb" in embedded mode. code backported from 6.0 per-file messages: include/my_global.h Remove SC_MAXWIDTH. This is unused and irrelevant nowadays. include/my_sys.h Remove errbuf declaration and unused definitions. mysys/my_error.c Remove errbuf definition and move and adjust ERRMSGSIZE. mysys/my_init.c Declare buffer on the stack and use my_snprintf. mysys/safemalloc.c Use size explicitly. It's more than enough for the message at hand. sql/sql_error.cc Use size explicitly. It's more than enough for the message at hand. sql/sql_parse.cc Declare buffer on the stack. Use my_snprintf as it will result in less stack space being used than by a system provided sprintf -- this allows us to put the buffer on the stack without causing much trouble. Also, the use of errbuff here was not thread-safe as the function can be entered concurrently from multiple threads. sql/sql_table.cc Use MYSQL_ERRMSG_SIZE. Extra space is not needed as my_snprintf will nul terminate strings. storage/myisam/ha_myisam.cc Use MYSQL_ERRMSG_SIZE. sql/share/errmsg.txt Error message truncation in test "innodb" in embedded mode filename in the error message can safely take up to 210 symbols. --- include/my_global.h | 1 - include/my_sys.h | 3 --- mysys/my_error.c | 10 ++++---- mysys/my_init.c | 8 ++++--- mysys/safemalloc.c | 2 +- sql/share/errmsg.txt | 48 ++++++++++++++++++------------------- sql/sql_error.cc | 2 +- sql/sql_parse.cc | 7 +++--- sql/sql_table.cc | 17 ++++++------- storage/myisam/ha_myisam.cc | 4 ++-- 10 files changed, 52 insertions(+), 50 deletions(-) diff --git a/include/my_global.h b/include/my_global.h index ac49d48e78d..4581dd6785c 100644 --- a/include/my_global.h +++ b/include/my_global.h @@ -724,7 +724,6 @@ typedef SOCKET_SIZE_TYPE size_socket; #define UNSINT32 /* unsigned int32 */ /* General constants */ -#define SC_MAXWIDTH 256 /* Max width of screen (for error messages) */ #define FN_LEN 256 /* Max file name len */ #define FN_HEADLEN 253 /* Max length of filepart of file name */ #define FN_EXTLEN 20 /* Max length of extension (part of FN_LEN) */ diff --git a/include/my_sys.h b/include/my_sys.h index 60122eab94e..5335b65822f 100644 --- a/include/my_sys.h +++ b/include/my_sys.h @@ -39,8 +39,6 @@ extern int NEAR my_errno; /* Last error in mysys */ #define MYSYS_PROGRAM_DONT_USE_CURSES() { error_handler_hook = my_message_no_curses; mysys_uses_curses=0;} #define MY_INIT(name); { my_progname= name; my_init(); } -#define ERRMSGSIZE (SC_MAXWIDTH) /* Max length of a error message */ -#define NRERRBUFFS (2) /* Buffers for parameters */ #define MY_FILE_ERROR ((size_t) -1) /* General bitmaps for my_func's */ @@ -208,7 +206,6 @@ extern void my_large_free(uchar * ptr, myf my_flags); extern int errno; /* declare errno */ #endif #endif /* #ifndef errno */ -extern char NEAR errbuff[NRERRBUFFS][ERRMSGSIZE]; extern char *home_dir; /* Home directory for user */ extern const char *my_progname; /* program-name (printed in errors) */ extern char NEAR curr_dir[]; /* Current directory for user */ diff --git a/mysys/my_error.c b/mysys/my_error.c index 75701536dd3..07656dda979 100644 --- a/mysys/my_error.c +++ b/mysys/my_error.c @@ -19,6 +19,10 @@ #include #include +/* Max length of a error message. Should be kept in sync with MYSQL_ERRMSG_SIZE. */ +#define ERRMSGSIZE (512) + + /* Define some external variables for error handling */ /* @@ -30,8 +34,6 @@ my_printf_error(ER_CODE, format, MYF(N), ...) */ -char NEAR errbuff[NRERRBUFFS][ERRMSGSIZE]; - /* Message texts are registered into a linked list of 'my_err_head' structs. Each struct contains (1.) an array of pointers to C character strings with @@ -75,7 +77,7 @@ int my_error(int nr, myf MyFlags, ...) const char *format; struct my_err_head *meh_p; va_list args; - char ebuff[ERRMSGSIZE + 20]; + char ebuff[ERRMSGSIZE]; DBUG_ENTER("my_error"); DBUG_PRINT("my", ("nr: %d MyFlags: %d errno: %d", nr, MyFlags, errno)); @@ -112,7 +114,7 @@ int my_error(int nr, myf MyFlags, ...) int my_printf_error(uint error, const char *format, myf MyFlags, ...) { va_list args; - char ebuff[ERRMSGSIZE+20]; + char ebuff[ERRMSGSIZE]; DBUG_ENTER("my_printf_error"); DBUG_PRINT("my", ("nr: %d MyFlags: %d errno: %d Format: %s", error, MyFlags, errno, format)); diff --git a/mysys/my_init.c b/mysys/my_init.c index edc37a3c96f..b330ffac65a 100644 --- a/mysys/my_init.c +++ b/mysys/my_init.c @@ -153,9 +153,11 @@ void my_end(int infoflag) { /* Test if some file is left open */ if (my_file_opened | my_stream_opened) { - sprintf(errbuff[0],EE(EE_OPEN_WARNING),my_file_opened,my_stream_opened); - (void) my_message_no_curses(EE_OPEN_WARNING,errbuff[0],ME_BELL); - DBUG_PRINT("error",("%s",errbuff[0])); + char ebuff[512]; + my_snprintf(ebuff, sizeof(ebuff), EE(EE_OPEN_WARNING), + my_file_opened, my_stream_opened); + my_message_no_curses(EE_OPEN_WARNING, ebuff, ME_BELL); + DBUG_PRINT("error", ("%s", ebuff)); my_print_open_files(); } } diff --git a/mysys/safemalloc.c b/mysys/safemalloc.c index 905733524e3..c484f1d4c54 100644 --- a/mysys/safemalloc.c +++ b/mysys/safemalloc.c @@ -147,7 +147,7 @@ void *_mymalloc(size_t size, const char *filename, uint lineno, myf MyFlags) error_handler_hook=fatal_error_handler_hook; if (MyFlags & (MY_FAE+MY_WME)) { - char buff[SC_MAXWIDTH]; + char buff[256]; my_errno=errno; sprintf(buff,"Out of memory at line %d, '%s'", lineno, filename); my_message(EE_OUTOFMEMORY, buff, MYF(ME_BELL+ME_WAITTANG+ME_NOREFRESH)); diff --git a/sql/share/errmsg.txt b/sql/share/errmsg.txt index fd75fee9737..befd064e3e3 100644 --- a/sql/share/errmsg.txt +++ b/sql/share/errmsg.txt @@ -571,30 +571,30 @@ ER_ERROR_ON_READ swe "Fick fel vid läsning av '%-.200s' (Felkod %d)" ukr "îÅ ÍÏÖÕ ÐÒÏÞÉÔÁÔÉ ÆÁÊÌ '%-.200s' (ÐÏÍÉÌËÁ: %d)" ER_ERROR_ON_RENAME - cze "Chyba p-Bøi pøejmenování '%-.150s' na '%-.150s' (chybový kód: %d)" - dan "Fejl ved omdøbning af '%-.150s' til '%-.150s' (Fejlkode: %d)" - nla "Fout bij het hernoemen van '%-.150s' naar '%-.150s' (Errcode: %d)" - eng "Error on rename of '%-.150s' to '%-.150s' (errno: %d)" - jps "'%-.150s' ‚ð '%-.150s' ‚É rename ‚Å‚«‚Ü‚¹‚ñ (errno: %d)", - est "Viga faili '%-.150s' ümbernimetamisel '%-.150s'-ks (veakood: %d)" - fre "Erreur en renommant '%-.150s' en '%-.150s' (Errcode: %d)" - ger "Fehler beim Umbenennen von '%-.150s' in '%-.150s' (Fehler: %d)" - greek "Ðñüâëçìá êáôÜ ôçí ìåôïíïìáóßá ôïõ áñ÷åßïõ '%-.150s' to '%-.150s' (êùäéêüò ëÜèïõò: %d)" - hun "Hiba a '%-.150s' file atnevezesekor '%-.150s'. (hibakod: %d)" - ita "Errore durante la rinominazione da '%-.150s' a '%-.150s' (errno: %d)" - jpn "'%-.150s' ¤ò '%-.150s' ¤Ë rename ¤Ç¤­¤Þ¤»¤ó (errno: %d)" - kor "'%-.150s'¸¦ '%-.150s'·Î À̸§ º¯°æÁß ¿¡·¯ (¿¡·¯¹øÈ£: %d)" - nor "Feil ved omdøping av '%-.150s' til '%-.150s' (Feilkode: %d)" - norwegian-ny "Feil ved omdøyping av '%-.150s' til '%-.150s' (Feilkode: %d)" - pol "B³?d podczas zmieniania nazwy '%-.150s' na '%-.150s' (Kod b³êdu: %d)" - por "Erro ao renomear '%-.150s' para '%-.150s' (erro no. %d)" - rum "Eroare incercind sa renumesc '%-.150s' in '%-.150s' (errno: %d)" - rus "ïÛÉÂËÁ ÐÒÉ ÐÅÒÅÉÍÅÎÏ×ÁÎÉÉ '%-.150s' × '%-.150s' (ÏÛÉÂËÁ: %d)" - serbian "Greška pri promeni imena '%-.150s' na '%-.150s' (errno: %d)" - slo "Chyba pri premenovávaní '%-.150s' na '%-.150s' (chybový kód: %d)" - spa "Error en el renombrado de '%-.150s' a '%-.150s' (Error: %d)" - swe "Kan inte byta namn från '%-.150s' till '%-.150s' (Felkod: %d)" - ukr "îÅ ÍÏÖÕ ÐÅÒÅÊÍÅÎÕ×ÁÔÉ '%-.150s' Õ '%-.150s' (ÐÏÍÉÌËÁ: %d)" + cze "Chyba p-Bøi pøejmenování '%-.210s' na '%-.210s' (chybový kód: %d)" + dan "Fejl ved omdøbning af '%-.210s' til '%-.210s' (Fejlkode: %d)" + nla "Fout bij het hernoemen van '%-.210s' naar '%-.210s' (Errcode: %d)" + eng "Error on rename of '%-.210s' to '%-.210s' (errno: %d)" + jps "'%-.210s' ‚ð '%-.210s' ‚É rename ‚Å‚«‚Ü‚¹‚ñ (errno: %d)", + est "Viga faili '%-.210s' ümbernimetamisel '%-.210s'-ks (veakood: %d)" + fre "Erreur en renommant '%-.210s' en '%-.210s' (Errcode: %d)" + ger "Fehler beim Umbenennen von '%-.210s' in '%-.210s' (Fehler: %d)" + greek "Ðñüâëçìá êáôÜ ôçí ìåôïíïìáóßá ôïõ áñ÷åßïõ '%-.210s' to '%-.210s' (êùäéêüò ëÜèïõò: %d)" + hun "Hiba a '%-.210s' file atnevezesekor '%-.210s'. (hibakod: %d)" + ita "Errore durante la rinominazione da '%-.210s' a '%-.210s' (errno: %d)" + jpn "'%-.210s' ¤ò '%-.210s' ¤Ë rename ¤Ç¤­¤Þ¤»¤ó (errno: %d)" + kor "'%-.210s'¸¦ '%-.210s'·Î À̸§ º¯°æÁß ¿¡·¯ (¿¡·¯¹øÈ£: %d)" + nor "Feil ved omdøping av '%-.210s' til '%-.210s' (Feilkode: %d)" + norwegian-ny "Feil ved omdøyping av '%-.210s' til '%-.210s' (Feilkode: %d)" + pol "B³?d podczas zmieniania nazwy '%-.210s' na '%-.210s' (Kod b³êdu: %d)" + por "Erro ao renomear '%-.210s' para '%-.210s' (erro no. %d)" + rum "Eroare incercind sa renumesc '%-.210s' in '%-.210s' (errno: %d)" + rus "ïÛÉÂËÁ ÐÒÉ ÐÅÒÅÉÍÅÎÏ×ÁÎÉÉ '%-.210s' × '%-.210s' (ÏÛÉÂËÁ: %d)" + serbian "Greška pri promeni imena '%-.210s' na '%-.210s' (errno: %d)" + slo "Chyba pri premenovávaní '%-.210s' na '%-.210s' (chybový kód: %d)" + spa "Error en el renombrado de '%-.210s' a '%-.210s' (Error: %d)" + swe "Kan inte byta namn från '%-.210s' till '%-.210s' (Felkod: %d)" + ukr "îÅ ÍÏÖÕ ÐÅÒÅÊÍÅÎÕ×ÁÔÉ '%-.210s' Õ '%-.210s' (ÐÏÍÉÌËÁ: %d)" ER_ERROR_ON_WRITE cze "Chyba p-Bøi zápisu do souboru '%-.200s' (chybový kód: %d)" dan "Fejl ved skriving av filen '%-.200s' (Fejlkode: %d)" diff --git a/sql/sql_error.cc b/sql/sql_error.cc index 79da1936eb9..bd8f9469571 100644 --- a/sql/sql_error.cc +++ b/sql/sql_error.cc @@ -177,7 +177,7 @@ void push_warning_printf(THD *thd, MYSQL_ERROR::enum_warning_level level, uint code, const char *format, ...) { va_list args; - char warning[ERRMSGSIZE+20]; + char warning[MYSQL_ERRMSG_SIZE]; DBUG_ENTER("push_warning_printf"); DBUG_PRINT("enter",("warning: %u", code)); diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 99b131c3aef..592dbe9f43b 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -5454,9 +5454,10 @@ bool check_stack_overrun(THD *thd, long margin, if ((stack_used=used_stack(thd->thread_stack,(char*) &stack_used)) >= (long) (my_thread_stack_size - margin)) { - sprintf(errbuff[0],ER(ER_STACK_OVERRUN_NEED_MORE), - stack_used,my_thread_stack_size,margin); - my_message(ER_STACK_OVERRUN_NEED_MORE,errbuff[0],MYF(0)); + char ebuff[MYSQL_ERRMSG_SIZE]; + my_snprintf(ebuff, sizeof(ebuff), ER(ER_STACK_OVERRUN_NEED_MORE), + stack_used, my_thread_stack_size, margin); + my_message(ER_STACK_OVERRUN_NEED_MORE, ebuff, MYF(ME_FATALERROR)); thd->fatal_error(); return 1; } diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 4827810334f..aa2a5739f17 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -4435,8 +4435,8 @@ send_result_message: switch (result_code) { case HA_ADMIN_NOT_IMPLEMENTED: { - char buf[ERRMSGSIZE+20]; - uint length=my_snprintf(buf, ERRMSGSIZE, + char buf[MYSQL_ERRMSG_SIZE]; + uint length=my_snprintf(buf, sizeof(buf), ER(ER_CHECK_NOT_IMPLEMENTED), operator_name); protocol->store(STRING_WITH_LEN("note"), system_charset_info); protocol->store(buf, length, system_charset_info); @@ -4445,8 +4445,8 @@ send_result_message: case HA_ADMIN_NOT_BASE_TABLE: { - char buf[ERRMSGSIZE+20]; - uint length= my_snprintf(buf, ERRMSGSIZE, + char buf[MYSQL_ERRMSG_SIZE]; + uint length= my_snprintf(buf, sizeof(buf), ER(ER_BAD_TABLE_ERROR), table_name); protocol->store(STRING_WITH_LEN("note"), system_charset_info); protocol->store(buf, length, system_charset_info); @@ -4573,11 +4573,12 @@ send_result_message: case HA_ADMIN_NEEDS_UPGRADE: case HA_ADMIN_NEEDS_ALTER: { - char buf[ERRMSGSIZE]; + char buf[MYSQL_ERRMSG_SIZE]; uint length; protocol->store(STRING_WITH_LEN("error"), system_charset_info); - length=my_snprintf(buf, ERRMSGSIZE, ER(ER_TABLE_NEEDS_UPGRADE), table->table_name); + length=my_snprintf(buf, sizeof(buf), ER(ER_TABLE_NEEDS_UPGRADE), + table->table_name); protocol->store(buf, length, system_charset_info); fatal_error=1; break; @@ -4585,8 +4586,8 @@ send_result_message: default: // Probably HA_ADMIN_INTERNAL_ERROR { - char buf[ERRMSGSIZE+20]; - uint length=my_snprintf(buf, ERRMSGSIZE, + char buf[MYSQL_ERRMSG_SIZE]; + uint length=my_snprintf(buf, sizeof(buf), "Unknown - internal error %d during operation", result_code); protocol->store(STRING_WITH_LEN("error"), system_charset_info); diff --git a/storage/myisam/ha_myisam.cc b/storage/myisam/ha_myisam.cc index b8d5a9af8d2..4073044bf63 100644 --- a/storage/myisam/ha_myisam.cc +++ b/storage/myisam/ha_myisam.cc @@ -1257,7 +1257,7 @@ int ha_myisam::preload_keys(THD* thd, HA_CHECK_OPT *check_opt) ulonglong map; TABLE_LIST *table_list= table->pos_in_table_list; my_bool ignore_leaves= table_list->ignore_leaves; - char buf[ERRMSGSIZE+20]; + char buf[MYSQL_ERRMSG_SIZE]; DBUG_ENTER("ha_myisam::preload_keys"); @@ -1285,7 +1285,7 @@ int ha_myisam::preload_keys(THD* thd, HA_CHECK_OPT *check_opt) errmsg= "Failed to allocate buffer"; break; default: - my_snprintf(buf, ERRMSGSIZE, + my_snprintf(buf, sizeof(buf), "Failed to read from index file (errno: %d)", my_errno); errmsg= buf; } From 31d908d70ba6e0240dd85712e474fbc30b95dbd7 Mon Sep 17 00:00:00 2001 From: Ramil Kalimullin Date: Thu, 5 Feb 2009 11:43:39 +0400 Subject: [PATCH 028/219] Fix for bug#42014: Crash, name_const with collate Problem: some queries using NAME_CONST(.. COLLATE ...) lead to server crash due to failed type cast. Fix: return the underlying item's type in case of NAME_CONST(.. COLLATE ...) to avoid wrong casting. mysql-test/r/func_misc.result: Fix for bug#42014: Crash, name_const with coll - test result. mysql-test/t/func_misc.test: Fix for bug#42014: Crash, name_const with coll - test case. sql/item.cc: Fix for bug#42014: Crash, name_const with coll - in case of NAME_CONST('name', 'value' COLLATE collation) Item_name_const::type() returns type of 'value' argument to awoid wrong type casting of the Item_name_const items. --- mysql-test/r/func_misc.result | 5 +++++ mysql-test/t/func_misc.test | 9 +++++++++ sql/item.cc | 25 +++++++++++++++++++------ 3 files changed, 33 insertions(+), 6 deletions(-) diff --git a/mysql-test/r/func_misc.result b/mysql-test/r/func_misc.result index ce177b511b9..e57d46c006a 100644 --- a/mysql-test/r/func_misc.result +++ b/mysql-test/r/func_misc.result @@ -319,4 +319,9 @@ select @my_uuid_date - @my_uuid_synthetic; @my_uuid_date - @my_uuid_synthetic 0 set @@session.time_zone=@save_tz; +CREATE TABLE t1 (a DATE); +SELECT * FROM t1 WHERE a = NAME_CONST('reportDate', +_binary'2009-01-09' COLLATE 'binary'); +a +DROP TABLE t1; End of 5.0 tests diff --git a/mysql-test/t/func_misc.test b/mysql-test/t/func_misc.test index 93fe94ec94f..c8075c42fc7 100644 --- a/mysql-test/t/func_misc.test +++ b/mysql-test/t/func_misc.test @@ -436,5 +436,14 @@ select @my_uuid_date - @my_uuid_synthetic; set @@session.time_zone=@save_tz; + +# +# Bug#42014: Crash, name_const with collate +# +CREATE TABLE t1 (a DATE); +SELECT * FROM t1 WHERE a = NAME_CONST('reportDate', + _binary'2009-01-09' COLLATE 'binary'); +DROP TABLE t1; + --echo End of 5.0 tests diff --git a/sql/item.cc b/sql/item.cc index fc5ee3d4d6a..bc1ae683e93 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -1243,13 +1243,26 @@ Item::Type Item_name_const::type() const valid_args guarantees value_item->basic_const_item(); if type is FUNC_ITEM, then we have a fudged item_func_neg() on our hands and return the underlying type. + For Item_func_set_collation() + e.g. NAME_CONST('name', 'value' COLLATE collation) we return its + 'value' argument type. */ - return valid_args ? - (((value_item->type() == FUNC_ITEM) && - (((Item_func *) value_item)->functype() == Item_func::NEG_FUNC)) ? - ((Item_func *) value_item)->key_item()->type() : - value_item->type()) : - NULL_ITEM; + if (!valid_args) + return NULL_ITEM; + Item::Type value_type= value_item->type(); + if (value_type == FUNC_ITEM) + { + /* + The second argument of NAME_CONST('name', 'value') must be + a simple constant item or a NEG_FUNC/COLLATE_FUNC. + */ + DBUG_ASSERT(((Item_func *) value_item)->functype() == + Item_func::NEG_FUNC || + ((Item_func *) value_item)->functype() == + Item_func::COLLATE_FUNC); + return ((Item_func *) value_item)->key_item()->type(); + } + return value_type; } From 061bf717e0a0b46b2b05567b569bcfe53bbfc12f Mon Sep 17 00:00:00 2001 From: Gleb Shchepa Date: Thu, 5 Feb 2009 13:30:39 +0400 Subject: [PATCH 029/219] Bug #42037: Queries containing a subquery with DISTINCT and ORDER BY could cause a server crash Dependent subqueries like SELECT COUNT(*) FROM t1, t2 WHERE t2.b IN (SELECT DISTINCT t2.b FROM t2 WHERE t2.b = t1.a) caused a memory leak proportional to the number of outer rows. The make_simple_join() function has been modified to JOIN class method to store join_tab_reexec and table_reexec values in the parent join only (make_simple_join of tmp_join may access these values via 'this' pointer of the parent JOIN). NOTE: this patch doesn't include standard test case (this is "out of memory" bug). See bug #42037 page for test cases. sql/sql_select.cc: Bug #42037: Queries containing a subquery with DISTINCT and ORDER BY could cause a server crash The make_simple_join() function has been modified to JOIN class method to store join_tab_reexec and table_reexec values in the parent join only. sql/sql_select.h: Bug #42037: Queries containing a subquery with DISTINCT and ORDER BY could cause a server crash 1. The make_simple_join() function has been modified to JOIN class method. 2. Type of JOIN::table_reexec field has been changed from TABLE** to TABLE *table_reexec[1]: this field always was NULL or a pointer to one-element array of pointers, so a pointer to a pointer has been replaced with one pointer and unnecessary memory allocation has been eliminated. --- sql/sql_select.cc | 71 +++++++++++++++++++++-------------------------- sql/sql_select.h | 9 ++++-- 2 files changed, 39 insertions(+), 41 deletions(-) diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 74d1158d8b7..a341cf5e0e9 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -78,7 +78,6 @@ static store_key *get_store_key(THD *thd, KEYUSE *keyuse, table_map used_tables, KEY_PART_INFO *key_part, char *key_buff, uint maybe_null); -static bool make_simple_join(JOIN *join,TABLE *tmp_table); static void make_outerjoin_info(JOIN *join); static bool make_join_select(JOIN *join,SQL_SELECT *select,COND *item); static void make_join_readinfo(JOIN *join, ulonglong options); @@ -1809,7 +1808,7 @@ JOIN::exec() /* Free first data from old join */ curr_join->join_free(); - if (make_simple_join(curr_join, curr_tmp_table)) + if (curr_join->make_simple_join(this, curr_tmp_table)) DBUG_VOID_RETURN; calc_group_buffer(curr_join, group_list); count_field_types(select_lex, &curr_join->tmp_table_param, @@ -1929,7 +1928,7 @@ JOIN::exec() curr_join->select_distinct=0; } curr_tmp_table->reginfo.lock_type= TL_UNLOCK; - if (make_simple_join(curr_join, curr_tmp_table)) + if (curr_join->make_simple_join(this, curr_tmp_table)) DBUG_VOID_RETURN; calc_group_buffer(curr_join, curr_join->group_list); count_field_types(select_lex, &curr_join->tmp_table_param, @@ -5431,48 +5430,42 @@ store_val_in_field(Field *field, Item *item, enum_check_fields check_flag) } -static bool -make_simple_join(JOIN *join,TABLE *tmp_table) +/** + @details Initialize a JOIN as a query execution plan + that accesses a single table via a table scan. + + @param parent contains JOIN_TAB and TABLE object buffers for this join + @param tmp_table temporary table + + @retval FALSE success + @retval TRUE error occurred +*/ +bool +JOIN::make_simple_join(JOIN *parent, TABLE *tmp_table) { - TABLE **tableptr; - JOIN_TAB *join_tab; - DBUG_ENTER("make_simple_join"); + DBUG_ENTER("JOIN::make_simple_join"); /* Reuse TABLE * and JOIN_TAB if already allocated by a previous call to this function through JOIN::exec (may happen for sub-queries). */ - if (!join->table_reexec) - { - if (!(join->table_reexec= (TABLE**) join->thd->alloc(sizeof(TABLE*)))) - DBUG_RETURN(TRUE); /* purecov: inspected */ - if (join->tmp_join) - join->tmp_join->table_reexec= join->table_reexec; - } - if (!join->join_tab_reexec) - { - if (!(join->join_tab_reexec= - (JOIN_TAB*) join->thd->alloc(sizeof(JOIN_TAB)))) - DBUG_RETURN(TRUE); /* purecov: inspected */ - if (join->tmp_join) - join->tmp_join->join_tab_reexec= join->join_tab_reexec; - } - tableptr= join->table_reexec; - join_tab= join->join_tab_reexec; + if (!parent->join_tab_reexec && + !(parent->join_tab_reexec= (JOIN_TAB*) thd->alloc(sizeof(JOIN_TAB)))) + DBUG_RETURN(TRUE); /* purecov: inspected */ - join->join_tab=join_tab; - join->table=tableptr; tableptr[0]=tmp_table; - join->tables=1; - join->const_tables=0; - join->const_table_map=0; - join->tmp_table_param.field_count= join->tmp_table_param.sum_func_count= - join->tmp_table_param.func_count=0; - join->tmp_table_param.copy_field=join->tmp_table_param.copy_field_end=0; - join->first_record=join->sort_and_group=0; - join->send_records=(ha_rows) 0; - join->group=0; - join->row_limit=join->unit->select_limit_cnt; - join->do_send_rows = (join->row_limit) ? 1 : 0; + join_tab= parent->join_tab_reexec; + table= &parent->table_reexec[0]; parent->table_reexec[0]= tmp_table; + tables= 1; + const_tables= 0; + const_table_map= 0; + tmp_table_param.field_count= tmp_table_param.sum_func_count= + tmp_table_param.func_count= 0; + tmp_table_param.copy_field= tmp_table_param.copy_field_end=0; + first_record= sort_and_group=0; + send_records= (ha_rows) 0; + group= 0; + row_limit= unit->select_limit_cnt; + do_send_rows= row_limit ? 1 : 0; join_tab->cache.buff=0; /* No caching */ join_tab->table=tmp_table; @@ -5489,7 +5482,7 @@ make_simple_join(JOIN *join,TABLE *tmp_table) join_tab->ref.key = -1; join_tab->not_used_in_distinct=0; join_tab->read_first_record= join_init_read_record; - join_tab->join=join; + join_tab->join= this; join_tab->ref.key_parts= 0; bzero((char*) &join_tab->read_record,sizeof(join_tab->read_record)); tmp_table->status=0; diff --git a/sql/sql_select.h b/sql/sql_select.h index 8ece01d3286..75a905043d2 100644 --- a/sql/sql_select.h +++ b/sql/sql_select.h @@ -352,9 +352,12 @@ public: cleared only at the end of the execution of the whole query and not caching allocations that occur in repetition at execution time will result in excessive memory usage. + Note: make_simple_join always creates an execution plan that accesses + a single table, thus it is sufficient to have a one-element array for + table_reexec. */ SORT_FIELD *sortorder; // make_unireg_sortorder() - TABLE **table_reexec; // make_simple_join() + TABLE *table_reexec[1]; // make_simple_join() JOIN_TAB *join_tab_reexec; // make_simple_join() /* end of allocation caching storage */ @@ -384,7 +387,7 @@ public: exec_tmp_table1= 0; exec_tmp_table2= 0; sortorder= 0; - table_reexec= 0; + table_reexec[0]= 0; join_tab_reexec= 0; thd= thd_arg; sum_funcs= sum_funcs2= 0; @@ -476,6 +479,8 @@ public: return (unit == &thd->lex->unit && (unit->fake_select_lex == 0 || select_lex == unit->fake_select_lex)); } +private: + bool make_simple_join(JOIN *join, TABLE *tmp_table); }; From b9d02d4669ad45444f5082979e37908125eea3de Mon Sep 17 00:00:00 2001 From: Gleb Shchepa Date: Thu, 5 Feb 2009 13:49:32 +0400 Subject: [PATCH 030/219] Bug #39265: fix for the bug 33699 should be reverted Documented behaviour was broken by the patch for bug 33699 that actually is not a bug. This fix reverts patch for bug 33699 and reverts the UPDATE of NOT NULL field with NULL query to old behavior. mysql-test/extra/rpl_tests/rpl_extraMaster_Col.test: Bug #39265: fix for the bug 33699 should be reverted mysql-test/include/ps_modify.inc: Bug #39265: fix for the bug 33699 should be reverted mysql-test/r/auto_increment.result: Bug #39265: fix for the bug 33699 should be reverted mysql-test/r/csv_not_null.result: Bug #39265: fix for the bug 33699 should be reverted mysql-test/r/null.result: Bug #39265: fix for the bug 33699 should be reverted mysql-test/r/ps_2myisam.result: Bug #39265: fix for the bug 33699 should be reverted mysql-test/r/ps_3innodb.result: Bug #39265: fix for the bug 33699 should be reverted mysql-test/r/ps_4heap.result: Bug #39265: fix for the bug 33699 should be reverted mysql-test/r/ps_5merge.result: Bug #39265: fix for the bug 33699 should be reverted mysql-test/r/warnings.result: Bug #39265: fix for the bug 33699 should be reverted mysql-test/suite/ndb/r/ps_7ndb.result: Bug #39265: fix for the bug 33699 should be reverted mysql-test/suite/rpl/r/rpl_extraColmaster_innodb.result: Bug #39265: fix for the bug 33699 should be reverted mysql-test/suite/rpl/r/rpl_extraColmaster_myisam.result: Bug #39265: fix for the bug 33699 should be reverted mysql-test/suite/rpl/t/rpl_err_ignoredtable.test: Bug #39265: fix for the bug 33699 should be reverted mysql-test/t/auto_increment.test: Bug #39265: fix for the bug 33699 should be reverted mysql-test/t/csv_not_null.test: Bug #39265: fix for the bug 33699 should be reverted mysql-test/t/null.test: Bug #39265: fix for the bug 33699 should be reverted mysql-test/t/warnings.test: Bug #39265: fix for the bug 33699 should be reverted sql/sql_update.cc: Bug #39265: fix for the bug 33699 should be reverted --- mysql-test/extra/rpl_tests/rpl_extraMaster_Col.test | 2 +- mysql-test/include/ps_modify.inc | 1 - mysql-test/r/auto_increment.result | 12 ++++++------ mysql-test/r/csv_not_null.result | 5 +++-- mysql-test/r/null.result | 8 +++++--- mysql-test/r/ps_2myisam.result | 5 +++-- mysql-test/r/ps_3innodb.result | 5 +++-- mysql-test/r/ps_4heap.result | 5 +++-- mysql-test/r/ps_5merge.result | 10 ++++++---- mysql-test/r/warnings.result | 3 ++- mysql-test/suite/ndb/r/ps_7ndb.result | 5 +++-- .../suite/rpl/r/rpl_extraColmaster_innodb.result | 12 +++++++++--- .../suite/rpl/r/rpl_extraColmaster_myisam.result | 12 +++++++++--- mysql-test/suite/rpl/t/rpl_err_ignoredtable.test | 2 +- mysql-test/t/auto_increment.test | 2 -- mysql-test/t/csv_not_null.test | 1 - mysql-test/t/null.test | 2 -- mysql-test/t/warnings.test | 1 - sql/sql_update.cc | 8 +++++--- 19 files changed, 59 insertions(+), 42 deletions(-) diff --git a/mysql-test/extra/rpl_tests/rpl_extraMaster_Col.test b/mysql-test/extra/rpl_tests/rpl_extraMaster_Col.test index df0d6cf5045..c426ac1fae8 100644 --- a/mysql-test/extra/rpl_tests/rpl_extraMaster_Col.test +++ b/mysql-test/extra/rpl_tests/rpl_extraMaster_Col.test @@ -419,7 +419,7 @@ connection master; update t31 set f5=555555555555555 where f3=6; update t31 set f2=2 where f3=2; update t31 set f1=NULL where f3=1; - update t31 set f3=0, f27=NULL, f35='f35 new value' where f3=3; + update t31 set f3=NULL, f27=NULL, f35='f35 new value' where f3=3; --echo --echo ** Delete from Master ** diff --git a/mysql-test/include/ps_modify.inc b/mysql-test/include/ps_modify.inc index 4cde18b97d1..f66f888261d 100644 --- a/mysql-test/include/ps_modify.inc +++ b/mysql-test/include/ps_modify.inc @@ -108,7 +108,6 @@ execute stmt1 using @arg00, @arg01; select a,b from t1 where a=@arg00; set @arg00=NULL; set @arg01=2; ---error 1048 execute stmt1 using @arg00, @arg01; select a,b from t1 order by a; set @arg00=0; diff --git a/mysql-test/r/auto_increment.result b/mysql-test/r/auto_increment.result index a39b424827c..21e6347cb47 100644 --- a/mysql-test/r/auto_increment.result +++ b/mysql-test/r/auto_increment.result @@ -231,7 +231,8 @@ a b 204 7 delete from t1 where a=0; update t1 set a=NULL where b=6; -ERROR 23000: Column 'a' cannot be null +Warnings: +Warning 1048 Column 'a' cannot be null update t1 set a=300 where b=7; SET SQL_MODE=''; insert into t1(a,b)values(NULL,8); @@ -246,7 +247,7 @@ a b 1 1 200 2 201 4 -203 6 +0 6 300 7 301 8 400 9 @@ -262,7 +263,6 @@ a b 1 1 200 2 201 4 -203 6 300 7 301 8 400 9 @@ -273,20 +273,20 @@ a b 405 14 delete from t1 where a=0; update t1 set a=NULL where b=13; -ERROR 23000: Column 'a' cannot be null +Warnings: +Warning 1048 Column 'a' cannot be null update t1 set a=500 where b=14; select * from t1 order by b; a b 1 1 200 2 201 4 -203 6 300 7 301 8 400 9 401 10 402 11 -404 13 +0 13 500 14 drop table t1; create table t1 (a bigint); diff --git a/mysql-test/r/csv_not_null.result b/mysql-test/r/csv_not_null.result index 77026b8f056..af583a36837 100644 --- a/mysql-test/r/csv_not_null.result +++ b/mysql-test/r/csv_not_null.result @@ -46,8 +46,9 @@ SELECT * FROM t1; a b 0 new_value UPDATE t1 set b = NULL where b = 'new_value'; -ERROR 23000: Column 'b' cannot be null +Warnings: +Warning 1048 Column 'b' cannot be null SELECT * FROM t1; a b -0 new_value +0 DROP TABLE t1; diff --git a/mysql-test/r/null.result b/mysql-test/r/null.result index 64b8aa74af3..1cdc48e6552 100644 --- a/mysql-test/r/null.result +++ b/mysql-test/r/null.result @@ -93,9 +93,11 @@ INSERT INTO t1 SET a = "", d= "2003-01-14 03:54:55"; Warnings: Warning 1265 Data truncated for column 'd' at row 1 UPDATE t1 SET d=1/NULL; -ERROR 23000: Column 'd' cannot be null +Warnings: +Warning 1265 Data truncated for column 'd' at row 1 UPDATE t1 SET d=NULL; -ERROR 23000: Column 'd' cannot be null +Warnings: +Warning 1048 Column 'd' cannot be null INSERT INTO t1 (a) values (null); ERROR 23000: Column 'a' cannot be null INSERT INTO t1 (a) values (1/null); @@ -130,7 +132,7 @@ Warning 1048 Column 'd' cannot be null Warning 1048 Column 'd' cannot be null select * from t1; a b c d - 0 0000-00-00 00:00:00 2003 + 0 0000-00-00 00:00:00 0 0 0000-00-00 00:00:00 0 0 0000-00-00 00:00:00 0 0 0000-00-00 00:00:00 0 diff --git a/mysql-test/r/ps_2myisam.result b/mysql-test/r/ps_2myisam.result index 0888b78618f..a91d13d11a1 100644 --- a/mysql-test/r/ps_2myisam.result +++ b/mysql-test/r/ps_2myisam.result @@ -1303,11 +1303,12 @@ a b set @arg00=NULL; set @arg01=2; execute stmt1 using @arg00, @arg01; -ERROR 23000: Column 'a' cannot be null +Warnings: +Warning 1048 Column 'a' cannot be null select a,b from t1 order by a; a b +0 two 1 one -2 two 3 three 4 four set @arg00=0; diff --git a/mysql-test/r/ps_3innodb.result b/mysql-test/r/ps_3innodb.result index e5a57131b01..50c94d6cc4e 100644 --- a/mysql-test/r/ps_3innodb.result +++ b/mysql-test/r/ps_3innodb.result @@ -1286,11 +1286,12 @@ a b set @arg00=NULL; set @arg01=2; execute stmt1 using @arg00, @arg01; -ERROR 23000: Column 'a' cannot be null +Warnings: +Warning 1048 Column 'a' cannot be null select a,b from t1 order by a; a b +0 two 1 one -2 two 3 three 4 four set @arg00=0; diff --git a/mysql-test/r/ps_4heap.result b/mysql-test/r/ps_4heap.result index 2c83916e952..a85809d3800 100644 --- a/mysql-test/r/ps_4heap.result +++ b/mysql-test/r/ps_4heap.result @@ -1287,11 +1287,12 @@ a b set @arg00=NULL; set @arg01=2; execute stmt1 using @arg00, @arg01; -ERROR 23000: Column 'a' cannot be null +Warnings: +Warning 1048 Column 'a' cannot be null select a,b from t1 order by a; a b +0 two 1 one -2 two 3 three 4 four set @arg00=0; diff --git a/mysql-test/r/ps_5merge.result b/mysql-test/r/ps_5merge.result index 0348d100393..fd1b69c0ffd 100644 --- a/mysql-test/r/ps_5merge.result +++ b/mysql-test/r/ps_5merge.result @@ -1329,11 +1329,12 @@ a b set @arg00=NULL; set @arg01=2; execute stmt1 using @arg00, @arg01; -ERROR 23000: Column 'a' cannot be null +Warnings: +Warning 1048 Column 'a' cannot be null select a,b from t1 order by a; a b +0 two 1 one -2 two 3 three 4 four set @arg00=0; @@ -4350,11 +4351,12 @@ a b set @arg00=NULL; set @arg01=2; execute stmt1 using @arg00, @arg01; -ERROR 23000: Column 'a' cannot be null +Warnings: +Warning 1048 Column 'a' cannot be null select a,b from t1 order by a; a b +0 two 1 one -2 two 3 three 4 four set @arg00=0; diff --git a/mysql-test/r/warnings.result b/mysql-test/r/warnings.result index 7629a1d79a3..19d95acd5c1 100644 --- a/mysql-test/r/warnings.result +++ b/mysql-test/r/warnings.result @@ -98,7 +98,8 @@ Warning 1265 Data truncated for column 'c' at row 1 Warning 1265 Data truncated for column 'c' at row 2 alter table t1 add d char(2); update t1 set a=NULL where a=10; -ERROR 23000: Column 'a' cannot be null +Warnings: +Warning 1048 Column 'a' cannot be null update t1 set c='mysql ab' where c='test'; Warnings: Warning 1265 Data truncated for column 'c' at row 4 diff --git a/mysql-test/suite/ndb/r/ps_7ndb.result b/mysql-test/suite/ndb/r/ps_7ndb.result index 7ebadfa3685..73a2e0c1dda 100644 --- a/mysql-test/suite/ndb/r/ps_7ndb.result +++ b/mysql-test/suite/ndb/r/ps_7ndb.result @@ -1286,11 +1286,12 @@ a b set @arg00=NULL; set @arg01=2; execute stmt1 using @arg00, @arg01; -ERROR 23000: Column 'a' cannot be null +Warnings: +Warning 1048 Column 'a' cannot be null select a,b from t1 order by a; a b +0 two 1 one -2 two 3 three 4 four set @arg00=0; diff --git a/mysql-test/suite/rpl/r/rpl_extraColmaster_innodb.result b/mysql-test/suite/rpl/r/rpl_extraColmaster_innodb.result index 86648ba12c3..ad67f96db71 100644 --- a/mysql-test/suite/rpl/r/rpl_extraColmaster_innodb.result +++ b/mysql-test/suite/rpl/r/rpl_extraColmaster_innodb.result @@ -454,7 +454,9 @@ f1 f2 f3 f4 update t31 set f5=555555555555555 where f3=6; update t31 set f2=2 where f3=2; update t31 set f1=NULL where f3=1; -update t31 set f3=0, f27=NULL, f35='f35 new value' where f3=3; +update t31 set f3=NULL, f27=NULL, f35='f35 new value' where f3=3; +Warnings: +Warning 1048 Column 'f3' cannot be null ** Delete from Master ** @@ -1593,7 +1595,9 @@ f1 f2 f3 f4 update t31 set f5=555555555555555 where f3=6; update t31 set f2=2 where f3=2; update t31 set f1=NULL where f3=1; -update t31 set f3=0, f27=NULL, f35='f35 new value' where f3=3; +update t31 set f3=NULL, f27=NULL, f35='f35 new value' where f3=3; +Warnings: +Warning 1048 Column 'f3' cannot be null ** Delete from Master ** @@ -2732,7 +2736,9 @@ f1 f2 f3 f4 update t31 set f5=555555555555555 where f3=6; update t31 set f2=2 where f3=2; update t31 set f1=NULL where f3=1; -update t31 set f3=0, f27=NULL, f35='f35 new value' where f3=3; +update t31 set f3=NULL, f27=NULL, f35='f35 new value' where f3=3; +Warnings: +Warning 1048 Column 'f3' cannot be null ** Delete from Master ** diff --git a/mysql-test/suite/rpl/r/rpl_extraColmaster_myisam.result b/mysql-test/suite/rpl/r/rpl_extraColmaster_myisam.result index 96d4ca237d1..8859a8e24e3 100644 --- a/mysql-test/suite/rpl/r/rpl_extraColmaster_myisam.result +++ b/mysql-test/suite/rpl/r/rpl_extraColmaster_myisam.result @@ -454,7 +454,9 @@ f1 f2 f3 f4 update t31 set f5=555555555555555 where f3=6; update t31 set f2=2 where f3=2; update t31 set f1=NULL where f3=1; -update t31 set f3=0, f27=NULL, f35='f35 new value' where f3=3; +update t31 set f3=NULL, f27=NULL, f35='f35 new value' where f3=3; +Warnings: +Warning 1048 Column 'f3' cannot be null ** Delete from Master ** @@ -1593,7 +1595,9 @@ f1 f2 f3 f4 update t31 set f5=555555555555555 where f3=6; update t31 set f2=2 where f3=2; update t31 set f1=NULL where f3=1; -update t31 set f3=0, f27=NULL, f35='f35 new value' where f3=3; +update t31 set f3=NULL, f27=NULL, f35='f35 new value' where f3=3; +Warnings: +Warning 1048 Column 'f3' cannot be null ** Delete from Master ** @@ -2732,7 +2736,9 @@ f1 f2 f3 f4 update t31 set f5=555555555555555 where f3=6; update t31 set f2=2 where f3=2; update t31 set f1=NULL where f3=1; -update t31 set f3=0, f27=NULL, f35='f35 new value' where f3=3; +update t31 set f3=NULL, f27=NULL, f35='f35 new value' where f3=3; +Warnings: +Warning 1048 Column 'f3' cannot be null ** Delete from Master ** diff --git a/mysql-test/suite/rpl/t/rpl_err_ignoredtable.test b/mysql-test/suite/rpl/t/rpl_err_ignoredtable.test index e26e240b5ab..b9ab66165cc 100644 --- a/mysql-test/suite/rpl/t/rpl_err_ignoredtable.test +++ b/mysql-test/suite/rpl/t/rpl_err_ignoredtable.test @@ -50,7 +50,7 @@ kill @id; drop table t2,t3; insert into t4 values (3),(4); connection master; ---error 0,1053,2013,1048 +--error 0,1053,2013 reap; connection master1; save_master_pos; diff --git a/mysql-test/t/auto_increment.test b/mysql-test/t/auto_increment.test index 47458c1f054..32f065171f2 100644 --- a/mysql-test/t/auto_increment.test +++ b/mysql-test/t/auto_increment.test @@ -149,7 +149,6 @@ delete from t1 where a=0; update t1 set a=0 where b=5; select * from t1 order by b; delete from t1 where a=0; ---error 1048 update t1 set a=NULL where b=6; update t1 set a=300 where b=7; SET SQL_MODE=''; @@ -165,7 +164,6 @@ delete from t1 where a=0; update t1 set a=0 where b=12; select * from t1 order by b; delete from t1 where a=0; ---error 1048 update t1 set a=NULL where b=13; update t1 set a=500 where b=14; select * from t1 order by b; diff --git a/mysql-test/t/csv_not_null.test b/mysql-test/t/csv_not_null.test index bb7b412aa49..03ed566fb22 100644 --- a/mysql-test/t/csv_not_null.test +++ b/mysql-test/t/csv_not_null.test @@ -93,7 +93,6 @@ SELECT * FROM t1; UPDATE t1 set b = 'new_value' where a = 0; --enable_warnings SELECT * FROM t1; ---error ER_BAD_NULL_ERROR UPDATE t1 set b = NULL where b = 'new_value'; SELECT * FROM t1; diff --git a/mysql-test/t/null.test b/mysql-test/t/null.test index ddf6b8870fa..2878b54c357 100644 --- a/mysql-test/t/null.test +++ b/mysql-test/t/null.test @@ -61,9 +61,7 @@ drop table t1; # CREATE TABLE t1 (a varchar(16) NOT NULL default '', b smallint(6) NOT NULL default 0, c datetime NOT NULL default '0000-00-00 00:00:00', d smallint(6) NOT NULL default 0); INSERT INTO t1 SET a = "", d= "2003-01-14 03:54:55"; ---error 1048 UPDATE t1 SET d=1/NULL; ---error 1048 UPDATE t1 SET d=NULL; --error 1048 INSERT INTO t1 (a) values (null); diff --git a/mysql-test/t/warnings.test b/mysql-test/t/warnings.test index 4074317f38a..12421170eba 100644 --- a/mysql-test/t/warnings.test +++ b/mysql-test/t/warnings.test @@ -65,7 +65,6 @@ create table t1(a tinyint NOT NULL, b tinyint unsigned, c char(5)); insert into t1 values(NULL,100,'mysql'),(10,-1,'mysql ab'),(500,256,'open source'),(20,NULL,'test'); alter table t1 modify c char(4); alter table t1 add d char(2); ---error 1048 update t1 set a=NULL where a=10; update t1 set c='mysql ab' where c='test'; update t1 set d=c; diff --git a/sql/sql_update.cc b/sql/sql_update.cc index f448fb7ab50..b3bd5d0bc57 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -526,9 +526,11 @@ int mysql_update(THD *thd, init_read_record(&info, thd, table, select, 0, 1, FALSE); updated= found= 0; - /* Generate an error when trying to set a NOT NULL field to NULL. */ - thd->count_cuted_fields= ignore ? CHECK_FIELD_WARN - : CHECK_FIELD_ERROR_FOR_NULL; + /* + Generate an error (in TRADITIONAL mode) or warning + when trying to set a NOT NULL field to NULL. + */ + thd->count_cuted_fields= CHECK_FIELD_WARN; thd->cuted_fields=0L; thd_proc_info(thd, "Updating"); From 071cfc03b7fb706b9262b58a794c6a8871592c3e Mon Sep 17 00:00:00 2001 From: Sergey Vojtovich Date: Thu, 5 Feb 2009 17:03:47 +0400 Subject: [PATCH 031/219] BUG#39185 - Cardinality for merge tables calculated incorrectly. Every subsequent query to a merge table with indexes was lowering down cardinality. The problem was that key statistics was not cleared when merge children were detached. Causing next attach children perform incremental key statistics calculation. Fixed by clearing key statistics when attaching first child. mysql-test/r/merge.result: A test case for BUG#39185. mysql-test/t/merge.test: A test case for BUG#39185. storage/myisammrg/myrg_open.c: Clear key statistics when we're attaching first child, even if it's buffer was allocated before. This is needed because detach_children() doesn't clear statistics, causing incremental statistics calculation. --- mysql-test/r/merge.result | 19 +++++++++++++++++++ mysql-test/t/merge.test | 13 +++++++++++++ storage/myisammrg/myrg_open.c | 3 ++- 3 files changed, 34 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/merge.result b/mysql-test/r/merge.result index 9ab982a6688..b3d73f1225f 100644 --- a/mysql-test/r/merge.result +++ b/mysql-test/r/merge.result @@ -2041,4 +2041,23 @@ EXPLAIN SELECT COUNT(*) FROM t4; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Select tables optimized away DROP TABLE t1, t2, t3, t4; +CREATE TABLE t1(a INT, KEY(a)); +INSERT INTO t1 VALUES(0),(1),(2),(3),(4); +ANALYZE TABLE t1; +Table Op Msg_type Msg_text +test.t1 analyze status OK +CREATE TABLE m1(a INT, KEY(a)) ENGINE=MERGE UNION=(t1); +SELECT CARDINALITY FROM INFORMATION_SCHEMA.STATISTICS WHERE TABLE_SCHEMA='test' AND TABLE_NAME='m1'; +CARDINALITY +5 +SELECT CARDINALITY FROM INFORMATION_SCHEMA.STATISTICS WHERE TABLE_SCHEMA='test' AND TABLE_NAME='m1'; +CARDINALITY +5 +SELECT CARDINALITY FROM INFORMATION_SCHEMA.STATISTICS WHERE TABLE_SCHEMA='test' AND TABLE_NAME='m1'; +CARDINALITY +5 +SELECT CARDINALITY FROM INFORMATION_SCHEMA.STATISTICS WHERE TABLE_SCHEMA='test' AND TABLE_NAME='m1'; +CARDINALITY +5 +DROP TABLE t1, m1; End of 5.1 tests diff --git a/mysql-test/t/merge.test b/mysql-test/t/merge.test index 118f8771f91..e8c514f3804 100644 --- a/mysql-test/t/merge.test +++ b/mysql-test/t/merge.test @@ -1435,4 +1435,17 @@ EXPLAIN SELECT COUNT(*) FROM t1; EXPLAIN SELECT COUNT(*) FROM t4; DROP TABLE t1, t2, t3, t4; +# +# BUG#39185 - Cardinality for merge tables calculated incorrectly. +# +CREATE TABLE t1(a INT, KEY(a)); +INSERT INTO t1 VALUES(0),(1),(2),(3),(4); +ANALYZE TABLE t1; +CREATE TABLE m1(a INT, KEY(a)) ENGINE=MERGE UNION=(t1); +SELECT CARDINALITY FROM INFORMATION_SCHEMA.STATISTICS WHERE TABLE_SCHEMA='test' AND TABLE_NAME='m1'; +SELECT CARDINALITY FROM INFORMATION_SCHEMA.STATISTICS WHERE TABLE_SCHEMA='test' AND TABLE_NAME='m1'; +SELECT CARDINALITY FROM INFORMATION_SCHEMA.STATISTICS WHERE TABLE_SCHEMA='test' AND TABLE_NAME='m1'; +SELECT CARDINALITY FROM INFORMATION_SCHEMA.STATISTICS WHERE TABLE_SCHEMA='test' AND TABLE_NAME='m1'; +DROP TABLE t1, m1; + --echo End of 5.1 tests diff --git a/storage/myisammrg/myrg_open.c b/storage/myisammrg/myrg_open.c index 64b4be2b7ca..69d2d2d0608 100644 --- a/storage/myisammrg/myrg_open.c +++ b/storage/myisammrg/myrg_open.c @@ -428,10 +428,11 @@ int myrg_attach_children(MYRG_INFO *m_info, int handle_locking, if (!m_info->rec_per_key_part) { if(!(m_info->rec_per_key_part= (ulong*) - my_malloc(key_parts * sizeof(long), MYF(MY_WME|MY_ZEROFILL)))) + my_malloc(key_parts * sizeof(long), MYF(MY_WME)))) goto err; /* purecov: inspected */ errpos= 1; } + bzero((char*) m_info->rec_per_key_part, key_parts * sizeof(long)); } /* Add MyISAM table info. */ From a7435ddf49d28526fc45f3e52324514e71ffdd30 Mon Sep 17 00:00:00 2001 From: Gleb Shchepa Date: Thu, 5 Feb 2009 17:51:00 +0400 Subject: [PATCH 032/219] after-push test update (bug #39265) --- mysql-test/suite/funcs_1/r/innodb_trig_09.result | 3 ++- mysql-test/suite/funcs_1/r/memory_trig_09.result | 3 ++- mysql-test/suite/funcs_1/r/myisam_trig_09.result | 3 ++- mysql-test/suite/funcs_1/r/ndb_trig_09.result | 3 ++- mysql-test/suite/funcs_1/triggers/triggers_09.inc | 1 - 5 files changed, 8 insertions(+), 5 deletions(-) diff --git a/mysql-test/suite/funcs_1/r/innodb_trig_09.result b/mysql-test/suite/funcs_1/r/innodb_trig_09.result index b2ed4321a8f..986506b4e71 100644 --- a/mysql-test/suite/funcs_1/r/innodb_trig_09.result +++ b/mysql-test/suite/funcs_1/r/innodb_trig_09.result @@ -187,7 +187,8 @@ a NULL Test 3.5.9.4 7 999 995.240000000000000000000000000000 0 0 0 0 0 0 Update tb3 Set f122='Test 3.5.9.4-trig', f136=NULL, f151=DEFAULT, f163=NULL where f122='Test 3.5.9.4'; -ERROR 23000: Column 'f136' cannot be null +Warnings: +Warning 1048 Column 'f136' cannot be null Update tb3 Set f122='Test 3.5.9.4-trig', f136=0, f151=DEFAULT, f163=NULL where f122='Test 3.5.9.4'; select f118, f121, f122, f136, f151, f163 from tb3 diff --git a/mysql-test/suite/funcs_1/r/memory_trig_09.result b/mysql-test/suite/funcs_1/r/memory_trig_09.result index aa9d93403dd..0795c3be36f 100644 --- a/mysql-test/suite/funcs_1/r/memory_trig_09.result +++ b/mysql-test/suite/funcs_1/r/memory_trig_09.result @@ -188,7 +188,8 @@ a NULL Test 3.5.9.4 7 999 995.240000000000000000000000000000 0 0 0 0 0 0 Update tb3 Set f122='Test 3.5.9.4-trig', f136=NULL, f151=DEFAULT, f163=NULL where f122='Test 3.5.9.4'; -ERROR 23000: Column 'f136' cannot be null +Warnings: +Warning 1048 Column 'f136' cannot be null Update tb3 Set f122='Test 3.5.9.4-trig', f136=0, f151=DEFAULT, f163=NULL where f122='Test 3.5.9.4'; select f118, f121, f122, f136, f151, f163 from tb3 diff --git a/mysql-test/suite/funcs_1/r/myisam_trig_09.result b/mysql-test/suite/funcs_1/r/myisam_trig_09.result index aa9d93403dd..0795c3be36f 100644 --- a/mysql-test/suite/funcs_1/r/myisam_trig_09.result +++ b/mysql-test/suite/funcs_1/r/myisam_trig_09.result @@ -188,7 +188,8 @@ a NULL Test 3.5.9.4 7 999 995.240000000000000000000000000000 0 0 0 0 0 0 Update tb3 Set f122='Test 3.5.9.4-trig', f136=NULL, f151=DEFAULT, f163=NULL where f122='Test 3.5.9.4'; -ERROR 23000: Column 'f136' cannot be null +Warnings: +Warning 1048 Column 'f136' cannot be null Update tb3 Set f122='Test 3.5.9.4-trig', f136=0, f151=DEFAULT, f163=NULL where f122='Test 3.5.9.4'; select f118, f121, f122, f136, f151, f163 from tb3 diff --git a/mysql-test/suite/funcs_1/r/ndb_trig_09.result b/mysql-test/suite/funcs_1/r/ndb_trig_09.result index b2ed4321a8f..986506b4e71 100644 --- a/mysql-test/suite/funcs_1/r/ndb_trig_09.result +++ b/mysql-test/suite/funcs_1/r/ndb_trig_09.result @@ -187,7 +187,8 @@ a NULL Test 3.5.9.4 7 999 995.240000000000000000000000000000 0 0 0 0 0 0 Update tb3 Set f122='Test 3.5.9.4-trig', f136=NULL, f151=DEFAULT, f163=NULL where f122='Test 3.5.9.4'; -ERROR 23000: Column 'f136' cannot be null +Warnings: +Warning 1048 Column 'f136' cannot be null Update tb3 Set f122='Test 3.5.9.4-trig', f136=0, f151=DEFAULT, f163=NULL where f122='Test 3.5.9.4'; select f118, f121, f122, f136, f151, f163 from tb3 diff --git a/mysql-test/suite/funcs_1/triggers/triggers_09.inc b/mysql-test/suite/funcs_1/triggers/triggers_09.inc index c20553a9435..47277afb63c 100644 --- a/mysql-test/suite/funcs_1/triggers/triggers_09.inc +++ b/mysql-test/suite/funcs_1/triggers/triggers_09.inc @@ -183,7 +183,6 @@ let $message= Testcase 3.5.9.4:; @tr_var_af_136, @tr_var_af_151, @tr_var_af_163; --enable_query_log ---error ER_BAD_NULL_ERROR Update tb3 Set f122='Test 3.5.9.4-trig', f136=NULL, f151=DEFAULT, f163=NULL where f122='Test 3.5.9.4'; From 09387431c180af5a719c923b81149792204b749d Mon Sep 17 00:00:00 2001 From: Matthias Leich Date: Thu, 5 Feb 2009 17:48:47 +0100 Subject: [PATCH 033/219] Fix for Bug#42602 main.status: random failures + minor improvements --- mysql-test/r/status.result | 2 +- mysql-test/t/status.test | 29 +++++++++++++++++++---------- 2 files changed, 20 insertions(+), 11 deletions(-) diff --git a/mysql-test/r/status.result b/mysql-test/r/status.result index b76109a3d0e..ca815540c29 100644 --- a/mysql-test/r/status.result +++ b/mysql-test/r/status.result @@ -196,7 +196,7 @@ create table db37908.t1(f1 int); insert into db37908.t1 values(1); grant usage,execute on test.* to mysqltest_1@localhost; create procedure proc37908() begin select 1; end | -create function func37908() returns int sql security invoker +create function func37908() returns int sql security invoker return (select * from db37908.t1 limit 1)| select * from db37908.t1; ERROR 42000: SELECT command denied to user 'mysqltest_1'@'localhost' for table 't1' diff --git a/mysql-test/t/status.test b/mysql-test/t/status.test index f487f0695a3..69ae56ff9a2 100644 --- a/mysql-test/t/status.test +++ b/mysql-test/t/status.test @@ -4,6 +4,9 @@ # embedded server causes different stat -- source include/not_embedded.inc +# Save the initial number of concurrent sessions +--source include/count_sessions.inc + # Disable concurrent inserts to avoid sporadic test failures as it might # affect the the value of variables used throughout the test case. set @old_concurrent_insert= @@global.concurrent_insert; @@ -88,7 +91,7 @@ show status like 'last_query_cost'; drop table t1; # -# Test for Bug #15933 max_used_connections is wrong after FLUSH STATUS +# Test for Bug#15933 max_used_connections is wrong after FLUSH STATUS # if connections are cached # # @@ -188,7 +191,7 @@ disconnect con1; # -# Bug #30377: EXPLAIN loses last_query_cost when used with UNION +# Bug#30377 EXPLAIN loses last_query_cost when used with UNION # CREATE TABLE t1 ( a INT ); @@ -241,7 +244,7 @@ eval select substring_index('$rnd_next2',0x9,-1)-substring_index('$rnd_next',0x9 disconnect con1; connection default; -# +# # Bug#30252 Com_create_function is not incremented. # flush status; @@ -261,7 +264,7 @@ drop function f1; show status like 'Com%function'; # -# Bug#37908: Skipped access right check caused server crash. +# Bug#37908 Skipped access right check caused server crash. # connect (root, localhost, root,,test); connection root; @@ -273,20 +276,20 @@ insert into db37908.t1 values(1); grant usage,execute on test.* to mysqltest_1@localhost; delimiter |; create procedure proc37908() begin select 1; end | -create function func37908() returns int sql security invoker +create function func37908() returns int sql security invoker return (select * from db37908.t1 limit 1)| delimiter ;| - + connect (user1,localhost,mysqltest_1,,test); connection user1; ---error 1142 +--error ER_TABLEACCESS_DENIED_ERROR select * from db37908.t1; ---error 1142 +--error ER_TABLEACCESS_DENIED_ERROR show status where variable_name ='uptime' and 2 in (select * from db37908.t1); ---error 1142 +--error ER_TABLEACCESS_DENIED_ERROR show procedure status where name ='proc37908' and 1 in (select f1 from db37908.t1); ---error 1142 +--error ER_TABLEACCESS_DENIED_ERROR show function status where name ='func37908' and 1 in (select func37908()); connection default; @@ -297,6 +300,8 @@ drop procedure proc37908; drop function func37908; REVOKE ALL PRIVILEGES, GRANT OPTION FROM mysqltest_1@localhost; DROP USER mysqltest_1@localhost; +# Wait till we reached the initial number of concurrent sessions +--source include/wait_until_count_sessions.inc # # Bug#41131 "Questions" fails to increment - ignores statements instead stored procs @@ -339,3 +344,7 @@ DROP FUNCTION f1; # Restore global concurrent_insert value. Keep in the end of the test file. --connection default set @@global.concurrent_insert= @old_concurrent_insert; + +# Wait till we reached the initial number of concurrent sessions +--source include/wait_until_count_sessions.inc + From 798f19e4631893ac80fd9fd9460bba4553f119f7 Mon Sep 17 00:00:00 2001 From: Gleb Shchepa Date: Thu, 5 Feb 2009 21:47:24 +0400 Subject: [PATCH 034/219] after-after-push testcase update (bug #39265) --- .../suite/parts/inc/partition_auto_increment.inc | 10 ---------- .../parts/r/partition_auto_increment_blackhole.result | 2 -- .../parts/r/partition_auto_increment_innodb.result | 8 ++++++-- .../parts/r/partition_auto_increment_memory.result | 8 ++++++-- .../parts/r/partition_auto_increment_myisam.result | 8 ++++++-- .../suite/parts/r/partition_auto_increment_ndb.result | 8 ++++++-- 6 files changed, 24 insertions(+), 20 deletions(-) diff --git a/mysql-test/suite/parts/inc/partition_auto_increment.inc b/mysql-test/suite/parts/inc/partition_auto_increment.inc index 5e9ad47aa2e..26375c72c0c 100644 --- a/mysql-test/suite/parts/inc/partition_auto_increment.inc +++ b/mysql-test/suite/parts/inc/partition_auto_increment.inc @@ -50,12 +50,7 @@ if (!$skip_update) UPDATE t1 SET c1 = 40 WHERE c1 = 50; SELECT AUTO_INCREMENT FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA='test' AND TABLE_NAME='t1'; - -- error 0, ER_BAD_NULL_ERROR UPDATE t1 SET c1 = NULL WHERE c1 = 4; -if (!$mysql_errno) -{ - echo # ERROR (only OK if Blackhole) should give ER_DUP_KEY or ER_DUP_ENTRY; -} INSERT INTO t1 VALUES (NULL); INSERT INTO t1 VALUES (NULL); } @@ -203,12 +198,7 @@ if (!$skip_update) UPDATE t1 SET c1 = 140 WHERE c1 = 150; SELECT AUTO_INCREMENT FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA='test' AND TABLE_NAME='t1'; - -- error 0, ER_BAD_NULL_ERROR UPDATE t1 SET c1 = NULL WHERE c1 = 4; -if (!$mysql_errno) -{ - echo # ERROR (only OK if Blackhole) should give ER_DUP_KEY or ER_DUP_ENTRY; -} INSERT INTO t1 VALUES (NULL); INSERT INTO t1 VALUES (NULL); } diff --git a/mysql-test/suite/parts/r/partition_auto_increment_blackhole.result b/mysql-test/suite/parts/r/partition_auto_increment_blackhole.result index 1946ebbf978..ac39d038c56 100644 --- a/mysql-test/suite/parts/r/partition_auto_increment_blackhole.result +++ b/mysql-test/suite/parts/r/partition_auto_increment_blackhole.result @@ -43,7 +43,6 @@ SELECT AUTO_INCREMENT FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA='test' AUTO_INCREMENT 1 UPDATE t1 SET c1 = NULL WHERE c1 = 4; -# ERROR (only OK if Blackhole) should give ER_DUP_KEY or ER_DUP_ENTRY INSERT INTO t1 VALUES (NULL); INSERT INTO t1 VALUES (NULL); SELECT * FROM t1 ORDER BY c1; @@ -192,7 +191,6 @@ SELECT AUTO_INCREMENT FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA='test' AUTO_INCREMENT 1 UPDATE t1 SET c1 = NULL WHERE c1 = 4; -# ERROR (only OK if Blackhole) should give ER_DUP_KEY or ER_DUP_ENTRY INSERT INTO t1 VALUES (NULL); INSERT INTO t1 VALUES (NULL); SELECT * FROM t1 ORDER BY c1; diff --git a/mysql-test/suite/parts/r/partition_auto_increment_innodb.result b/mysql-test/suite/parts/r/partition_auto_increment_innodb.result index a30dfbcbe72..9a23cd4364e 100644 --- a/mysql-test/suite/parts/r/partition_auto_increment_innodb.result +++ b/mysql-test/suite/parts/r/partition_auto_increment_innodb.result @@ -42,12 +42,14 @@ SELECT AUTO_INCREMENT FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA='test' AUTO_INCREMENT 31 UPDATE t1 SET c1 = NULL WHERE c1 = 4; +Warnings: +Warning 1048 Column 'c1' cannot be null INSERT INTO t1 VALUES (NULL); INSERT INTO t1 VALUES (NULL); SELECT * FROM t1 ORDER BY c1; c1 +0 2 -4 5 6 10 @@ -215,12 +217,14 @@ SELECT AUTO_INCREMENT FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA='test' AUTO_INCREMENT 141 UPDATE t1 SET c1 = NULL WHERE c1 = 4; +Warnings: +Warning 1048 Column 'c1' cannot be null INSERT INTO t1 VALUES (NULL); INSERT INTO t1 VALUES (NULL); SELECT * FROM t1 ORDER BY c1; c1 +0 2 -4 5 6 9 diff --git a/mysql-test/suite/parts/r/partition_auto_increment_memory.result b/mysql-test/suite/parts/r/partition_auto_increment_memory.result index 96925d206f6..77bab79f020 100644 --- a/mysql-test/suite/parts/r/partition_auto_increment_memory.result +++ b/mysql-test/suite/parts/r/partition_auto_increment_memory.result @@ -42,12 +42,14 @@ SELECT AUTO_INCREMENT FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA='test' AUTO_INCREMENT 52 UPDATE t1 SET c1 = NULL WHERE c1 = 4; +Warnings: +Warning 1048 Column 'c1' cannot be null INSERT INTO t1 VALUES (NULL); INSERT INTO t1 VALUES (NULL); SELECT * FROM t1 ORDER BY c1; c1 +0 2 -4 5 6 10 @@ -214,12 +216,14 @@ SELECT AUTO_INCREMENT FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA='test' AUTO_INCREMENT 152 UPDATE t1 SET c1 = NULL WHERE c1 = 4; +Warnings: +Warning 1048 Column 'c1' cannot be null INSERT INTO t1 VALUES (NULL); INSERT INTO t1 VALUES (NULL); SELECT * FROM t1 ORDER BY c1; c1 +0 2 -4 5 6 9 diff --git a/mysql-test/suite/parts/r/partition_auto_increment_myisam.result b/mysql-test/suite/parts/r/partition_auto_increment_myisam.result index 204c241cfa8..b5b001ec17a 100644 --- a/mysql-test/suite/parts/r/partition_auto_increment_myisam.result +++ b/mysql-test/suite/parts/r/partition_auto_increment_myisam.result @@ -42,12 +42,14 @@ SELECT AUTO_INCREMENT FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA='test' AUTO_INCREMENT 52 UPDATE t1 SET c1 = NULL WHERE c1 = 4; +Warnings: +Warning 1048 Column 'c1' cannot be null INSERT INTO t1 VALUES (NULL); INSERT INTO t1 VALUES (NULL); SELECT * FROM t1 ORDER BY c1; c1 +0 2 -4 5 6 10 @@ -214,12 +216,14 @@ SELECT AUTO_INCREMENT FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA='test' AUTO_INCREMENT 152 UPDATE t1 SET c1 = NULL WHERE c1 = 4; +Warnings: +Warning 1048 Column 'c1' cannot be null INSERT INTO t1 VALUES (NULL); INSERT INTO t1 VALUES (NULL); SELECT * FROM t1 ORDER BY c1; c1 +0 2 -4 5 6 9 diff --git a/mysql-test/suite/parts/r/partition_auto_increment_ndb.result b/mysql-test/suite/parts/r/partition_auto_increment_ndb.result index 85e226b749b..408f32cce78 100644 --- a/mysql-test/suite/parts/r/partition_auto_increment_ndb.result +++ b/mysql-test/suite/parts/r/partition_auto_increment_ndb.result @@ -43,12 +43,14 @@ SELECT AUTO_INCREMENT FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA='test' AUTO_INCREMENT 52 UPDATE t1 SET c1 = NULL WHERE c1 = 4; +Warnings: +Warning 1048 Column 'c1' cannot be null INSERT INTO t1 VALUES (NULL); INSERT INTO t1 VALUES (NULL); SELECT * FROM t1 ORDER BY c1; c1 +0 2 -4 5 6 10 @@ -215,12 +217,14 @@ SELECT AUTO_INCREMENT FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA='test' AUTO_INCREMENT 152 UPDATE t1 SET c1 = NULL WHERE c1 = 4; +Warnings: +Warning 1048 Column 'c1' cannot be null INSERT INTO t1 VALUES (NULL); INSERT INTO t1 VALUES (NULL); SELECT * FROM t1 ORDER BY c1; c1 +0 2 -4 5 6 9 From 41e6a1f89c943083e46fba9f548333629eefbbd9 Mon Sep 17 00:00:00 2001 From: Matthias Leich Date: Thu, 5 Feb 2009 21:47:23 +0100 Subject: [PATCH 035/219] 2. Slice of fix for Bug#42003 tests missing the disconnect of connections <> default - If missing: add "disconnect " - If physical disconnect of non "default" sessions is not finished at test end: add routine which waits till this happened + additional improvements - remove superfluous files created by the test - replace error numbers by error names - remove trailing spaces, replace tabs by spaces - unify writing of bugs within comments - correct comments - minor changes of formatting Fixed tests: backup check compress grant information_schema multi_update overflow packet query_cache_not_embedded sp-threads subselect synchronization timezone_grant --- mysql-test/r/backup.result | 2 +- mysql-test/r/check.result | 3 +- mysql-test/r/grant.result | 32 +- mysql-test/r/information_schema.result | 22 +- mysql-test/r/multi_update.result | 10 +- mysql-test/r/packet.result | 4 + mysql-test/r/query_cache_notembedded.result | 16 + mysql-test/r/subselect.result | 218 ++++---- mysql-test/r/synchronization.result | 44 +- mysql-test/t/backup.test | 15 +- mysql-test/t/check.test | 24 +- mysql-test/t/compress.test | 11 + mysql-test/t/grant.test | 179 +++---- mysql-test/t/information_schema.test | 144 ++--- mysql-test/t/multi_update.test | 55 +- mysql-test/t/overflow.test | 10 +- mysql-test/t/packet.test | 20 +- mysql-test/t/query_cache_notembedded.test | 47 +- mysql-test/t/sp-threads.test | 29 +- mysql-test/t/subselect.test | 555 +++++++++++--------- mysql-test/t/synchronization.test | 22 +- mysql-test/t/timezone_grant.test | 41 +- 22 files changed, 867 insertions(+), 636 deletions(-) diff --git a/mysql-test/r/backup.result b/mysql-test/r/backup.result index 14313ba490f..f5a649d27a5 100644 --- a/mysql-test/r/backup.result +++ b/mysql-test/r/backup.result @@ -1,5 +1,5 @@ set SQL_LOG_BIN=0; -drop table if exists t1, t2, t3; +drop table if exists t1, t2, t3, t4; create table t4(n int); backup table t4 to '../bogus'; Table Op Msg_type Msg_text diff --git a/mysql-test/r/check.result b/mysql-test/r/check.result index 03219d0977e..0bff34dba20 100644 --- a/mysql-test/r/check.result +++ b/mysql-test/r/check.result @@ -1,4 +1,5 @@ -drop table if exists t1; +drop table if exists t1,t2; +drop view if exists v1; create table t1(n int not null, key(n), key(n), key(n), key(n)); check table t1 extended; insert into t1 values (200000); diff --git a/mysql-test/r/grant.result b/mysql-test/r/grant.result index ee328d461ac..97945a702d8 100644 --- a/mysql-test/r/grant.result +++ b/mysql-test/r/grant.result @@ -162,7 +162,7 @@ Warnings: Warning 1364 Field 'ssl_cipher' doesn't have a default value Warning 1364 Field 'x509_issuer' doesn't have a default value Warning 1364 Field 'x509_subject' doesn't have a default value -insert into mysql.db (host, db, user, select_priv) values +insert into mysql.db (host, db, user, select_priv) values ('localhost', 'a%', 'test11', 'Y'), ('localhost', 'ab%', 'test11', 'Y'); alter table mysql.db order by db asc; flush privileges; @@ -262,7 +262,7 @@ drop user mysqltest_1@localhost; SET NAMES koi8r; CREATE DATABASE ÂÄ; USE ÂÄ; -CREATE TABLE ÔÁ (ËÏÌ int); +CREATE TABLE ÔÁ (ËÏÌ INT); GRANT SELECT ON ÂÄ.* TO ÀÚÅÒ@localhost; SHOW GRANTS FOR ÀÚÅÒ@localhost; Grants for ÀÚÅÒ@localhost @@ -381,21 +381,21 @@ grant update (a) on mysqltest_1.t1 to mysqltest_3@localhost; grant select (b) on mysqltest_1.t2 to mysqltest_3@localhost; grant select (c) on mysqltest_2.t1 to mysqltest_3@localhost; grant update (d) on mysqltest_2.t2 to mysqltest_3@localhost; -SELECT * FROM INFORMATION_SCHEMA.COLUMN_PRIVILEGES -WHERE GRANTEE = '''mysqltest_3''@''localhost''' -ORDER BY TABLE_NAME,COLUMN_NAME,PRIVILEGE_TYPE; +SELECT * FROM INFORMATION_SCHEMA.COLUMN_PRIVILEGES +WHERE GRANTEE = '''mysqltest_3''@''localhost''' + ORDER BY TABLE_NAME,COLUMN_NAME,PRIVILEGE_TYPE; GRANTEE TABLE_CATALOG TABLE_SCHEMA TABLE_NAME COLUMN_NAME PRIVILEGE_TYPE IS_GRANTABLE 'mysqltest_3'@'localhost' NULL mysqltest_1 t1 a UPDATE NO 'mysqltest_3'@'localhost' NULL mysqltest_2 t1 c SELECT NO 'mysqltest_3'@'localhost' NULL mysqltest_1 t2 b SELECT NO 'mysqltest_3'@'localhost' NULL mysqltest_2 t2 d UPDATE NO SELECT * FROM INFORMATION_SCHEMA.TABLE_PRIVILEGES -WHERE GRANTEE = '''mysqltest_3''@''localhost''' -ORDER BY TABLE_NAME,PRIVILEGE_TYPE; +WHERE GRANTEE = '''mysqltest_3''@''localhost''' + ORDER BY TABLE_NAME,PRIVILEGE_TYPE; GRANTEE TABLE_CATALOG TABLE_SCHEMA TABLE_NAME PRIVILEGE_TYPE IS_GRANTABLE SELECT * from INFORMATION_SCHEMA.SCHEMA_PRIVILEGES -WHERE GRANTEE = '''mysqltest_3''@''localhost''' -ORDER BY TABLE_SCHEMA,PRIVILEGE_TYPE; +WHERE GRANTEE = '''mysqltest_3''@''localhost''' + ORDER BY TABLE_SCHEMA,PRIVILEGE_TYPE; GRANTEE TABLE_CATALOG TABLE_SCHEMA PRIVILEGE_TYPE IS_GRANTABLE SELECT * from INFORMATION_SCHEMA.USER_PRIVILEGES WHERE GRANTEE = '''mysqltest_3''@''localhost''' @@ -880,11 +880,11 @@ flush privileges; drop table t2; drop table t1; CREATE DATABASE mysqltest3; -use mysqltest3; +USE mysqltest3; CREATE TABLE t_nn (c1 INT); CREATE VIEW v_nn AS SELECT * FROM t_nn; CREATE DATABASE mysqltest2; -use mysqltest2; +USE mysqltest2; CREATE TABLE t_nn (c1 INT); CREATE VIEW v_nn AS SELECT * FROM t_nn; CREATE VIEW v_yn AS SELECT * FROM t_nn; @@ -954,7 +954,7 @@ DROP TABLE mysqltest3.t_nn; DROP DATABASE mysqltest3; REVOKE ALL PRIVILEGES, GRANT OPTION FROM 'mysqltest_1'@'localhost'; DROP USER 'mysqltest_1'@'localhost'; -use test; +USE test; create user mysqltest1_thisisreallytoolong; ERROR HY000: String 'mysqltest1_thisisreallytoolong' is too long for user name (should be no longer than 16) GRANT CREATE ON mysqltest.* TO 1234567890abcdefGHIKL@localhost; @@ -1106,16 +1106,16 @@ DROP DATABASE mysqltest1; DROP DATABASE mysqltest2; DROP USER mysqltest_1@localhost; DROP USER mysqltest_2@localhost; -use test; +USE test; CREATE TABLE t1 (f1 int, f2 int); INSERT INTO t1 VALUES(1,1), (2,2); CREATE DATABASE db27878; GRANT UPDATE(f1) ON t1 TO 'mysqltest_1'@'localhost'; GRANT SELECT ON `test`.* TO 'mysqltest_1'@'localhost'; GRANT ALL ON db27878.* TO 'mysqltest_1'@'localhost'; -use db27878; +USE db27878; CREATE SQL SECURITY INVOKER VIEW db27878.v1 AS SELECT * FROM test.t1; -use db27878; +USE db27878; UPDATE v1 SET f2 = 4; ERROR HY000: View 'db27878.v1' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them SELECT * FROM test.t1; @@ -1127,7 +1127,7 @@ REVOKE SELECT ON `test`.* FROM 'mysqltest_1'@'localhost'; REVOKE ALL ON db27878.* FROM 'mysqltest_1'@'localhost'; DROP USER mysqltest_1@localhost; DROP DATABASE db27878; -use test; +USE test; DROP TABLE t1; drop table if exists test; Warnings: diff --git a/mysql-test/r/information_schema.result b/mysql-test/r/information_schema.result index d7ff87bd1eb..38c8d748870 100644 --- a/mysql-test/r/information_schema.result +++ b/mysql-test/r/information_schema.result @@ -75,7 +75,7 @@ t2 t3 t5 v1 -select c,table_name from v1 +select c,table_name from v1 inner join information_schema.TABLES v2 on (v1.c=v2.table_name) where v1.c like "t%"; c table_name @@ -94,7 +94,7 @@ t4 t4 t2 t2 t3 t3 t5 t5 -select c,table_name from v1 +select c,table_name from v1 left join information_schema.TABLES v2 on (v1.c=v2.table_name) where v1.c like "t%"; c table_name @@ -173,7 +173,7 @@ a int(11) YES NULL create view mysqltest.v1 (c) as select a from mysqltest.t1; grant select (a) on mysqltest.t1 to mysqltest_2@localhost; grant select on mysqltest.v1 to mysqltest_3; -select table_name, column_name, privileges from information_schema.columns +select table_name, column_name, privileges from information_schema.columns where table_schema = 'mysqltest' and table_name = 't1'; table_name column_name privileges t1 a select @@ -249,7 +249,7 @@ begin select * from t1; select * from t2; end| -select parameter_style, sql_data_access, dtd_identifier +select parameter_style, sql_data_access, dtd_identifier from information_schema.routines; parameter_style sql_data_access dtd_identifier SQL CONTAINS SQL NULL @@ -280,7 +280,7 @@ sub1 sub1 select count(*) from information_schema.ROUTINES; count(*) 2 -create view v1 as select routine_schema, routine_name from information_schema.routines +create view v1 as select routine_schema, routine_name from information_schema.routines order by routine_schema, routine_name; select * from v1; routine_schema routine_name @@ -532,7 +532,7 @@ drop view v1; create table t1(a NUMERIC(5,3), b NUMERIC(5,1), c float(5,2), d NUMERIC(6,4), e float, f DECIMAL(6,3), g int(11), h DOUBLE(10,3), i DOUBLE); -select COLUMN_NAME,COLUMN_TYPE, CHARACTER_MAXIMUM_LENGTH, +select COLUMN_NAME,COLUMN_TYPE, CHARACTER_MAXIMUM_LENGTH, CHARACTER_OCTET_LENGTH, NUMERIC_PRECISION, NUMERIC_SCALE from information_schema.columns where table_name= 't1'; COLUMN_NAME COLUMN_TYPE CHARACTER_MAXIMUM_LENGTH CHARACTER_OCTET_LENGTH NUMERIC_PRECISION NUMERIC_SCALE @@ -589,7 +589,7 @@ TABLE_NAME= "vo"; CONSTRAINT_CATALOG CONSTRAINT_SCHEMA CONSTRAINT_NAME TABLE_CATALOG TABLE_SCHEMA TABLE_NAME COLUMN_NAME ORDINAL_POSITION POSITION_IN_UNIQUE_CONSTRAINT REFERENCED_TABLE_SCHEMA REFERENCED_TABLE_NAME REFERENCED_COLUMN_NAME drop view vo; select TABLE_NAME,TABLE_TYPE,ENGINE -from information_schema.tables +from information_schema.tables where table_schema='information_schema' limit 2; TABLE_NAME TABLE_TYPE ENGINE CHARACTER_SETS SYSTEM VIEW MEMORY @@ -700,7 +700,7 @@ where table_schema="information_schema" and table_name="COLUMNS" and column_type varchar(64) varchar(64) -select TABLE_ROWS from information_schema.tables where +select TABLE_ROWS from information_schema.tables where table_schema="information_schema" and table_name="COLUMNS"; TABLE_ROWS NULL @@ -733,7 +733,7 @@ count(*) drop view a2, a1; drop table t_crashme; select table_schema,table_name, column_name from -information_schema.columns +information_schema.columns where data_type = 'longtext'; table_schema table_name column_name information_schema COLUMNS COLUMN_DEFAULT @@ -755,7 +755,7 @@ TABLES UPDATE_TIME datetime TABLES CHECK_TIME datetime TRIGGERS CREATED datetime SELECT COUNT(*) FROM INFORMATION_SCHEMA.TABLES A -WHERE NOT EXISTS +WHERE NOT EXISTS (SELECT * FROM INFORMATION_SCHEMA.COLUMNS B WHERE A.TABLE_SCHEMA = B.TABLE_SCHEMA AND A.TABLE_NAME = B.TABLE_NAME); @@ -784,7 +784,7 @@ x_float NULL NULL x_double_precision NULL NULL drop table t1; grant select on test.* to mysqltest_4@localhost; -SELECT TABLE_NAME, COLUMN_NAME, PRIVILEGES FROM INFORMATION_SCHEMA.COLUMNS +SELECT TABLE_NAME, COLUMN_NAME, PRIVILEGES FROM INFORMATION_SCHEMA.COLUMNS where COLUMN_NAME='TABLE_NAME'; TABLE_NAME COLUMN_NAME PRIVILEGES COLUMNS TABLE_NAME select diff --git a/mysql-test/r/multi_update.result b/mysql-test/r/multi_update.result index b85fb559e8c..f6dbac31c2a 100644 --- a/mysql-test/r/multi_update.result +++ b/mysql-test/r/multi_update.result @@ -375,7 +375,7 @@ update t2, t1 set t2.field=t1.field where t1.id1=t2.id2 and 0=1; delete t1, t2 from t2 inner join t1 on t1.id1=t2.id2 where 0=1; -delete t1, t2 from t2,t1 +delete t1, t2 from t2,t1 where t1.id1=t2.id2 and 0=1; drop table t1,t2; CREATE TABLE t1 ( a int ); @@ -443,12 +443,12 @@ delete t1 from t1,t2 where t1.col1 < (select max(col1) from t1) and t1.col1 = t2 ERROR HY000: You can't specify target table 't1' for update in FROM clause drop table t1,t2; create table t1 ( -aclid bigint not null primary key, -status tinyint(1) not null +aclid bigint not null primary key, +status tinyint(1) not null ) engine = innodb; create table t2 ( -refid bigint not null primary key, -aclid bigint, index idx_acl(aclid) +refid bigint not null primary key, +aclid bigint, index idx_acl(aclid) ) engine = innodb; insert into t2 values(1,null); delete t2, t1 from t2 left join t1 on (t2.aclid=t1.aclid) where t2.refid='1'; diff --git a/mysql-test/r/packet.result b/mysql-test/r/packet.result index df0d9ff9adc..5cc63c4690d 100644 --- a/mysql-test/r/packet.result +++ b/mysql-test/r/packet.result @@ -1,3 +1,5 @@ +set @max_allowed_packet=@@global.max_allowed_packet; +set @net_buffer_length=@@global.net_buffer_length; set global max_allowed_packet=100; Warnings: Warning 1292 Truncated incorrect max_allowed_packet value: '100' @@ -33,3 +35,5 @@ len select length(repeat('a',2000)); length(repeat('a',2000)) 2000 +set global max_allowed_packet=@max_allowed_packet; +set global net_buffer_length=@net_buffer_length; diff --git a/mysql-test/r/query_cache_notembedded.result b/mysql-test/r/query_cache_notembedded.result index 8e5df012cfb..bf582bfaec6 100644 --- a/mysql-test/r/query_cache_notembedded.result +++ b/mysql-test/r/query_cache_notembedded.result @@ -345,3 +345,19 @@ id drop table t1; drop function f1; set GLOBAL query_cache_size=0; +DROP TABLE IF EXISTS t1; +FLUSH STATUS; +SET GLOBAL query_cache_size=1048576; +CREATE TABLE t1 (a INT); +INSERT INTO t1 VALUES (1),(2),(3),(4),(5); +SHOW STATUS LIKE 'Qcache_queries_in_cache'; +Variable_name Value +Qcache_queries_in_cache 0 +LOCK TABLES t1 WRITE; +SELECT * FROM t1; +UNLOCK TABLES; +SHOW STATUS LIKE 'Qcache_queries_in_cache'; +Variable_name Value +Qcache_queries_in_cache 0 +DROP TABLE t1; +SET GLOBAL query_cache_size= default; diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result index 8830ea11f97..671e5d8f532 100644 --- a/mysql-test/r/subselect.result +++ b/mysql-test/r/subselect.result @@ -192,11 +192,11 @@ select (select a from t3 where a1) as tt; (select t3.a from t3 where a<8 order by 1 desc limit 1) a 7 2 -explain extended select (select t3.a from t3 where a<8 order by 1 desc limit 1), a from +explain extended select (select t3.a from t3 where a<8 order by 1 desc limit 1), a from (select * from t2 where a>1) as tt; id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY system NULL NULL NULL NULL 1 @@ -2303,20 +2303,20 @@ drop table t1,t2; CREATE TABLE t1 ( a int, b int ); CREATE TABLE t2 ( c int, d int ); INSERT INTO t1 VALUES (1,2), (2,3), (3,4); -SELECT a AS abc, b FROM t1 outr WHERE b = +SELECT a AS abc, b FROM t1 outr WHERE b = (SELECT MIN(b) FROM t1 WHERE a=outr.a); abc b 1 2 2 3 3 4 -INSERT INTO t2 SELECT a AS abc, b FROM t1 outr WHERE b = +INSERT INTO t2 SELECT a AS abc, b FROM t1 outr WHERE b = (SELECT MIN(b) FROM t1 WHERE a=outr.a); select * from t2; c d 1 2 2 3 3 4 -CREATE TABLE t3 SELECT a AS abc, b FROM t1 outr WHERE b = +CREATE TABLE t3 SELECT a AS abc, b FROM t1 outr WHERE b = (SELECT MIN(b) FROM t1 WHERE a=outr.a); select * from t3; abc b @@ -2517,8 +2517,8 @@ INSERT INTO t1 VALUES ('ASM','American Samoa','Oceania','Polynesia',199.00,0,680 INSERT INTO t1 VALUES ('ATF','French Southern territories','Antarctica','Antarctica',7780.00,0,0,NULL,0.00,NULL,'Terres australes françaises','Nonmetropolitan Territory of France','Jacques Chirac',NULL,'TF'); INSERT INTO t1 VALUES ('UMI','United States Minor Outlying Islands','Oceania','Micronesia/Caribbean',16.00,0,0,NULL,0.00,NULL,'United States Minor Outlying Islands','Dependent Territory of the US','George W. Bush',NULL,'UM'); /*!40000 ALTER TABLE t1 ENABLE KEYS */; -SELECT DISTINCT Continent AS c FROM t1 outr WHERE -Code <> SOME ( SELECT Code FROM t1 WHERE Continent = outr.Continent AND +SELECT DISTINCT Continent AS c FROM t1 outr WHERE +Code <> SOME ( SELECT Code FROM t1 WHERE Continent = outr.Continent AND Population < 200); c Oceania @@ -2628,32 +2628,32 @@ select count(distinct t2.userid) pass, groupstuff.*, count(t2.courseid) crse, -t1.categoryid, +t1.categoryid, t2.courseid, date_format(date, '%b%y') as colhead -from t2 -join t1 on t2.courseid=t1.courseid +from t2 +join t1 on t2.courseid=t1.courseid join ( -select -t5.userid, -parentid, -parentgroup, -childid, -groupname, -grouptypeid -from t5 -join +select +t5.userid, +parentid, +parentgroup, +childid, +groupname, +grouptypeid +from t5 +join ( -select t4.id as parentid, -t4.name as parentgroup, -t4.id as childid, -t4.name as groupname, -t4.grouptypeid -from t4 -) as gin on t5.groupid=gin.childid -) as groupstuff on t2.userid = groupstuff.userid -group by +select t4.id as parentid, +t4.name as parentgroup, +t4.id as childid, +t4.name as groupname, +t4.grouptypeid +from t4 +) as gin on t5.groupid=gin.childid +) as groupstuff on t2.userid = groupstuff.userid +group by groupstuff.groupname, colhead , t2.courseid; pass userid parentid parentgroup childid groupname grouptypeid crse categoryid courseid colhead 1 5141 12 group2 12 group2 5 1 5 12 Aug04 @@ -2929,9 +2929,9 @@ INSERT INTO t1 VALUES("0037", "1", "2005-12-06 12:18:56"); INSERT INTO t1 VALUES("0037", "2", "2006-01-06 12:25:53"); INSERT INTO t1 VALUES("0048", "1", "2006-01-06 12:37:50"); INSERT INTO t1 VALUES("0059", "1", "2006-01-06 12:37:50"); -select * from t1 r1 -where (r1.retailerID,(r1.changed)) in -(SELECT r2.retailerId,(max(changed)) from t1 r2 +select * from t1 r1 +where (r1.retailerID,(r1.changed)) in +(SELECT r2.retailerId,(max(changed)) from t1 r2 group by r2.retailerId); retailerID statusID changed 0026 2 2006-01-06 12:25:53 @@ -2943,41 +2943,41 @@ create table t1(a int, primary key (a)); insert into t1 values (10); create table t2 (a int primary key, b varchar(32), c int, unique key b(c, b)); insert into t2(a, c, b) values (1,10,'359'), (2,10,'35988'), (3,10,'35989'); -explain SELECT sql_no_cache t1.a, r.a, r.b FROM t1 LEFT JOIN t2 r -ON r.a = (SELECT t2.a FROM t2 WHERE t2.c = t1.a AND t2.b <= '359899' -ORDER BY t2.c DESC, t2.b DESC LIMIT 1) WHERE t1.a = 10; +explain SELECT sql_no_cache t1.a, r.a, r.b FROM t1 LEFT JOIN t2 r +ON r.a = (SELECT t2.a FROM t2 WHERE t2.c = t1.a AND t2.b <= '359899' + ORDER BY t2.c DESC, t2.b DESC LIMIT 1) WHERE t1.a = 10; id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY t1 system PRIMARY NULL NULL NULL 1 1 PRIMARY r const PRIMARY PRIMARY 4 const 1 2 DEPENDENT SUBQUERY t2 range b b 40 NULL 2 Using where -SELECT sql_no_cache t1.a, r.a, r.b FROM t1 LEFT JOIN t2 r -ON r.a = (SELECT t2.a FROM t2 WHERE t2.c = t1.a AND t2.b <= '359899' -ORDER BY t2.c DESC, t2.b DESC LIMIT 1) WHERE t1.a = 10; +SELECT sql_no_cache t1.a, r.a, r.b FROM t1 LEFT JOIN t2 r +ON r.a = (SELECT t2.a FROM t2 WHERE t2.c = t1.a AND t2.b <= '359899' + ORDER BY t2.c DESC, t2.b DESC LIMIT 1) WHERE t1.a = 10; a a b 10 3 35989 -explain SELECT sql_no_cache t1.a, r.a, r.b FROM t1 LEFT JOIN t2 r -ON r.a = (SELECT t2.a FROM t2 WHERE t2.c = t1.a AND t2.b <= '359899' -ORDER BY t2.c, t2.b LIMIT 1) WHERE t1.a = 10; +explain SELECT sql_no_cache t1.a, r.a, r.b FROM t1 LEFT JOIN t2 r +ON r.a = (SELECT t2.a FROM t2 WHERE t2.c = t1.a AND t2.b <= '359899' + ORDER BY t2.c, t2.b LIMIT 1) WHERE t1.a = 10; id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY t1 system PRIMARY NULL NULL NULL 1 1 PRIMARY r const PRIMARY PRIMARY 4 const 1 2 DEPENDENT SUBQUERY t2 range b b 40 NULL 2 Using where -SELECT sql_no_cache t1.a, r.a, r.b FROM t1 LEFT JOIN t2 r -ON r.a = (SELECT t2.a FROM t2 WHERE t2.c = t1.a AND t2.b <= '359899' -ORDER BY t2.c, t2.b LIMIT 1) WHERE t1.a = 10; +SELECT sql_no_cache t1.a, r.a, r.b FROM t1 LEFT JOIN t2 r +ON r.a = (SELECT t2.a FROM t2 WHERE t2.c = t1.a AND t2.b <= '359899' + ORDER BY t2.c, t2.b LIMIT 1) WHERE t1.a = 10; a a b 10 1 359 drop table t1,t2; -CREATE TABLE t1 ( -field1 int NOT NULL, -field2 int NOT NULL, -field3 int NOT NULL, -PRIMARY KEY (field1,field2,field3) +CREATE TABLE t1 ( +field1 int NOT NULL, +field2 int NOT NULL, +field3 int NOT NULL, +PRIMARY KEY (field1,field2,field3) ); -CREATE TABLE t2 ( -fieldA int NOT NULL, -fieldB int NOT NULL, -PRIMARY KEY (fieldA,fieldB) +CREATE TABLE t2 ( +fieldA int NOT NULL, +fieldB int NOT NULL, +PRIMARY KEY (fieldA,fieldB) ); INSERT INTO t1 VALUES (1,1,1), (1,1,2), (1,2,1), (1,2,2), (1,2,3), (1,3,1); @@ -2991,14 +2991,14 @@ field1 field2 COUNT(*) SELECT field1, field2 FROM t1 GROUP BY field1, field2 -HAVING COUNT(*) >= ALL (SELECT fieldB +HAVING COUNT(*) >= ALL (SELECT fieldB FROM t2 WHERE fieldA = field1); field1 field2 1 2 SELECT field1, field2 FROM t1 GROUP BY field1, field2 -HAVING COUNT(*) < ANY (SELECT fieldB +HAVING COUNT(*) < ANY (SELECT fieldB FROM t2 WHERE fieldA = field1); field1 field2 1 1 @@ -3021,8 +3021,8 @@ a a IN (SELECT a FROM t1) DROP TABLE t1,t2; CREATE TABLE t1 (a DATETIME); INSERT INTO t1 VALUES ('1998-09-23'), ('2003-03-25'); -CREATE TABLE t2 AS SELECT -(SELECT a FROM t1 WHERE a < '2000-01-01') AS sub_a +CREATE TABLE t2 AS SELECT +(SELECT a FROM t1 WHERE a < '2000-01-01') AS sub_a FROM t1 WHERE a > '2000-01-01'; SHOW CREATE TABLE t2; Table Create Table @@ -3188,7 +3188,7 @@ INSERT INTO t2 VALUES ( 6 ); CREATE TABLE t3 ( c3 integer ); INSERT INTO t3 VALUES ( 7 ); INSERT INTO t3 VALUES ( 8 ); -SELECT c1,c2 FROM t1 LEFT JOIN t2 ON c1 = c2 +SELECT c1,c2 FROM t1 LEFT JOIN t2 ON c1 = c2 WHERE EXISTS (SELECT c3 FROM t3 WHERE c2 IS NULL ); c1 c2 2 NULL @@ -3231,20 +3231,20 @@ E1 DROP TABLE t1,t2; CREATE TABLE t1(select_id BIGINT, values_id BIGINT); INSERT INTO t1 VALUES (1, 1); -CREATE TABLE t2 (select_id BIGINT, values_id BIGINT, +CREATE TABLE t2 (select_id BIGINT, values_id BIGINT, PRIMARY KEY(select_id,values_id)); INSERT INTO t2 VALUES (0, 1), (0, 2), (0, 3), (1, 5); -SELECT values_id FROM t1 +SELECT values_id FROM t1 WHERE values_id IN (SELECT values_id FROM t2 WHERE select_id IN (1, 0)); values_id 1 -SELECT values_id FROM t1 +SELECT values_id FROM t1 WHERE values_id IN (SELECT values_id FROM t2 WHERE select_id BETWEEN 0 AND 1); values_id 1 -SELECT values_id FROM t1 +SELECT values_id FROM t1 WHERE values_id IN (SELECT values_id FROM t2 WHERE select_id = 0 OR select_id = 1); values_id @@ -3259,7 +3259,7 @@ drop table t1; CREATE TABLE t1 (a int, b int); CREATE TABLE t2 (c int, d int); CREATE TABLE t3 (e int); -INSERT INTO t1 VALUES +INSERT INTO t1 VALUES (1,10), (2,10), (1,20), (2,20), (3,20), (2,30), (4,40); INSERT INTO t2 VALUES (2,10), (2,20), (4,10), (5,10), (3,20), (2,40); @@ -3322,7 +3322,7 @@ a 2 SELECT a FROM t1 GROUP BY a HAVING a IN (SELECT c FROM t2 -WHERE MIN(b) < d AND +WHERE MIN(b) < d AND EXISTS(SELECT e FROM t3 WHERE MAX(b)=e AND e <= d)); a 2 @@ -3373,7 +3373,7 @@ a 4 SELECT t1.a FROM t1 GROUP BY t1.a HAVING t1.a > ALL(SELECT t2.c FROM t2 -WHERE EXISTS(SELECT t3.e FROM t3 +WHERE EXISTS(SELECT t3.e FROM t3 WHERE SUM(t1.a+t2.c) < t3.e/4)); ERROR HY000: Invalid use of group function SELECT t1.a from t1 GROUP BY t1.a HAVING AVG(SUM(t1.b)) > 20; @@ -3486,7 +3486,7 @@ mid bigint(20) unsigned NOT NULL, date date NOT NULL, PRIMARY KEY (id) ); -INSERT INTO t2 VALUES +INSERT INTO t2 VALUES (1, 1, '2006-03-30'), (2, 2, '2006-04-06'), (3, 3, '2006-04-13'), (4, 2, '2006-04-20'), (5, 1, '2006-05-01'); SELECT *, @@ -3524,7 +3524,7 @@ i2 int(11) NOT NULL default '0', t datetime NOT NULL default '0000-00-00 00:00:00', PRIMARY KEY (i1,i2,t) ); -INSERT INTO t1 VALUES +INSERT INTO t1 VALUES (24,1,'2005-03-03 16:31:31'),(24,1,'2005-05-27 12:40:07'), (24,1,'2005-05-27 12:40:08'),(24,1,'2005-05-27 12:40:10'), (24,1,'2005-05-27 12:40:25'),(24,1,'2005-05-27 12:40:30'), @@ -3540,7 +3540,7 @@ PRIMARY KEY (i1) INSERT INTO t2 VALUES (24,1,'2006-06-20 12:29:40'); EXPLAIN SELECT * FROM t1,t2 -WHERE t1.t = (SELECT t1.t FROM t1 +WHERE t1.t = (SELECT t1.t FROM t1 WHERE t1.t < t2.t AND t1.i2=1 AND t2.i1=t1.i1 ORDER BY t1.t DESC LIMIT 1); id select_type table type possible_keys key key_len ref rows Extra @@ -3548,7 +3548,7 @@ id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY t1 index NULL PRIMARY 16 NULL 11 Using where; Using index 2 DEPENDENT SUBQUERY t1 range PRIMARY PRIMARY 16 NULL 5 Using where; Using index SELECT * FROM t1,t2 -WHERE t1.t = (SELECT t1.t FROM t1 +WHERE t1.t = (SELECT t1.t FROM t1 WHERE t1.t < t2.t AND t1.i2=1 AND t2.i1=t1.i1 ORDER BY t1.t DESC LIMIT 1); i1 i2 t i1 i2 t @@ -3557,22 +3557,22 @@ DROP TABLE t1, t2; CREATE TABLE t1 (i INT); (SELECT i FROM t1) UNION (SELECT i FROM t1); i -SELECT sql_no_cache * FROM t1 WHERE NOT EXISTS +SELECT sql_no_cache * FROM t1 WHERE NOT EXISTS ( -(SELECT i FROM t1) UNION +(SELECT i FROM t1) UNION (SELECT i FROM t1) ); -ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'UNION +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'UNION (SELECT i FROM t1) )' at line 3 -SELECT * FROM t1 +SELECT * FROM t1 WHERE NOT EXISTS (((SELECT i FROM t1) UNION (SELECT i FROM t1))); ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'UNION (SELECT i FROM t1)))' at line 2 explain select ((select t11.i from t1 t11) union (select t12.i from t1 t12)) from t1; ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'union (select t12.i from t1 t12)) from t1' at line 1 -explain select * from t1 where not exists +explain select * from t1 where not exists ((select t11.i from t1 t11) union (select t12.i from t1 t12)); ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'union (select t12.i from t1 t12))' at line 2 DROP TABLE t1; @@ -3591,9 +3591,9 @@ insert into t1 (a) select FLOOR(rand() * 100) from t1; insert into t1 (a) select FLOOR(rand() * 100) from t1; insert into t1 (a) select FLOOR(rand() * 100) from t1; insert into t1 (a) select FLOOR(rand() * 100) from t1; -SELECT a, -(SELECT REPEAT(' ',250) FROM t1 i1 -WHERE i1.b=t1.a ORDER BY RAND() LIMIT 1) AS a +SELECT a, +(SELECT REPEAT(' ',250) FROM t1 i1 +WHERE i1.b=t1.a ORDER BY RAND() LIMIT 1) AS a FROM t1 ORDER BY a LIMIT 5; a a 0 NULL @@ -3622,7 +3622,7 @@ COUNT(DISTINCT t1.b) (SELECT COUNT(DISTINCT t1.b)) 2 2 1 1 1 1 -SELECT COUNT(DISTINCT t1.b), +SELECT COUNT(DISTINCT t1.b), (SELECT COUNT(DISTINCT t1.b) union select 1 from DUAL where 12 < 3) FROM t1 GROUP BY t1.a; COUNT(DISTINCT t1.b) (SELECT COUNT(DISTINCT t1.b) union select 1 from DUAL where 12 < 3) @@ -3633,7 +3633,7 @@ SELECT ( SELECT ( SELECT COUNT(DISTINCT t1.b) ) -) +) FROM t1 GROUP BY t1.a; ( SELECT ( @@ -3648,8 +3648,8 @@ SELECT ( SELECT ( SELECT COUNT(DISTINCT t1.b) ) -) -FROM t1 GROUP BY t1.a LIMIT 1) +) +FROM t1 GROUP BY t1.a LIMIT 1) FROM t1 t2 GROUP BY t2.a; ( @@ -3657,7 +3657,7 @@ SELECT ( SELECT ( SELECT COUNT(DISTINCT t1.b) ) -) +) FROM t1 GROUP BY t1.a LIMIT 1) 2 2 @@ -3669,13 +3669,13 @@ PRIMARY KEY (x), FOREIGN KEY (y) REFERENCES t1 (b)); SET SESSION sort_buffer_size = 32 * 1024; Warnings: Warning 1292 Truncated incorrect sort_buffer_size value: '32768' -SELECT SQL_NO_CACHE COUNT(*) +SELECT SQL_NO_CACHE COUNT(*) FROM (SELECT a, b, (SELECT x FROM t2 WHERE y=b ORDER BY z DESC LIMIT 1) c FROM t1) t; COUNT(*) 3000 SET SESSION sort_buffer_size = 8 * 1024 * 1024; -SELECT SQL_NO_CACHE COUNT(*) +SELECT SQL_NO_CACHE COUNT(*) FROM (SELECT a, b, (SELECT x FROM t2 WHERE y=b ORDER BY z DESC LIMIT 1) c FROM t1) t; COUNT(*) @@ -3736,7 +3736,7 @@ sq 2 4 DEALLOCATE PREPARE stmt1; -SELECT f2, AVG(f21), +SELECT f2, AVG(f21), (SELECT t.f3 FROM t2 AS t WHERE t2.f2=t.f2 AND t.f3=MAX(t2.f3)) AS test FROM t2 GROUP BY f2; f2 AVG(f21) test @@ -3744,12 +3744,12 @@ f2 AVG(f21) test 2 2.0000 2004-02-29 11:11:11 DROP TABLE t1,t2; CREATE TABLE t1 (a int, b INT, c CHAR(10) NOT NULL); -INSERT INTO t1 VALUES -(1,1,'a'), (1,2,'b'), (1,3,'c'), (1,4,'d'), (1,5,'e'), -(2,1,'f'), (2,2,'g'), (2,3,'h'), (3,4,'i'), (3,3,'j'), +INSERT INTO t1 VALUES +(1,1,'a'), (1,2,'b'), (1,3,'c'), (1,4,'d'), (1,5,'e'), +(2,1,'f'), (2,2,'g'), (2,3,'h'), (3,4,'i'), (3,3,'j'), (3,2,'k'), (3,1,'l'), (1,9,'m'); -SELECT a, MAX(b), -(SELECT t.c FROM t1 AS t WHERE t1.a=t.a AND t.b=MAX(t1.b)) AS test +SELECT a, MAX(b), +(SELECT t.c FROM t1 AS t WHERE t1.a=t.a AND t.b=MAX(t1.b)) AS test FROM t1 GROUP BY a; a MAX(b) test 1 9 m @@ -3900,7 +3900,7 @@ COUNT(*) a (SELECT MIN(m) FROM t2 WHERE m = count(*)) 2 2 2 3 3 3 1 4 1 -SELECT COUNT(*), a +SELECT COUNT(*), a FROM t1 GROUP BY a HAVING (SELECT MIN(m) FROM t2 WHERE m = count(*)) > 1; COUNT(*) a @@ -3931,7 +3931,7 @@ INSERT INTO t1 VALUES (1,1,0,'a'), (1,2,0,'b'), (1,3,0,'c'), (1,4,0,'d'), (1,5,0,'e'), (2,1,0,'f'), (2,2,0,'g'), (2,3,0,'h'), (3,4,0,'i'), (3,3,0,'j'), (3,2,0,'k'), (3,1,0,'l'), (1,9,0,'m'), (1,0,10,'n'), (2,0,5,'o'), (3,0,7,'p'); SELECT a, MAX(b), -(SELECT t.c FROM t1 AS t WHERE t1.a=t.a AND t.b=MAX(t1.b + 0)) as test +(SELECT t.c FROM t1 AS t WHERE t1.a=t.a AND t.b=MAX(t1.b + 0)) as test FROM t1 GROUP BY a; a MAX(b) test 1 9 m @@ -3953,7 +3953,7 @@ a AVG(b) test 3 2.5000 NULL SELECT tt.a, (SELECT (SELECT c FROM t1 as t WHERE t1.a=t.a AND t.d=MAX(t1.b + tt.a) -LIMIT 1) FROM t1 WHERE t1.a=tt.a GROUP BY a LIMIT 1) as test +LIMIT 1) FROM t1 WHERE t1.a=tt.a GROUP BY a LIMIT 1) as test FROM t1 as tt; a test 1 n @@ -3975,7 +3975,7 @@ a test SELECT tt.a, (SELECT (SELECT t.c FROM t1 AS t WHERE t1.a=t.a AND t.d=MAX(t1.b + tt.a) LIMIT 1) -FROM t1 WHERE t1.a=tt.a GROUP BY a LIMIT 1) as test +FROM t1 WHERE t1.a=tt.a GROUP BY a LIMIT 1) as test FROM t1 as tt GROUP BY tt.a; a test 1 n @@ -3984,7 +3984,7 @@ a test SELECT tt.a, MAX( (SELECT (SELECT t.c FROM t1 AS t WHERE t1.a=t.a AND t.d=MAX(t1.b + tt.a) LIMIT 1) -FROM t1 WHERE t1.a=tt.a GROUP BY a LIMIT 1)) as test +FROM t1 WHERE t1.a=tt.a GROUP BY a LIMIT 1)) as test FROM t1 as tt GROUP BY tt.a; a test 1 n @@ -4027,11 +4027,11 @@ COUNT(1) 1 SELECT SUM( (SELECT AVG( (SELECT t1.a FROM t2) ) FROM DUAL) ) FROM t1; ERROR HY000: Invalid use of group function -SELECT +SELECT SUM( (SELECT AVG( (SELECT COUNT(*) FROM t1 t HAVING t1.a < 12) ) FROM t2) ) FROM t1; ERROR HY000: Invalid use of group function -SELECT t1.a as XXA, +SELECT t1.a as XXA, SUM( (SELECT AVG( (SELECT COUNT(*) FROM t1 t HAVING XXA < 12) ) FROM t2) ) FROM t1; ERROR HY000: Invalid use of group function @@ -4048,25 +4048,25 @@ INSERT INTO t1 VALUES (3,'FL'), (2,'GA'), (4,'FL'), (1,'GA'), (5,'NY'), (7,'FL'), (6,'NY'); CREATE TABLE t2 (id int NOT NULL, INDEX idx(id)); INSERT INTO t2 VALUES (7), (5), (1), (3); -SELECT id, st FROM t1 +SELECT id, st FROM t1 WHERE st IN ('GA','FL') AND EXISTS(SELECT 1 FROM t2 WHERE t2.id=t1.id); id st 3 FL 1 GA 7 FL -SELECT id, st FROM t1 +SELECT id, st FROM t1 WHERE st IN ('GA','FL') AND EXISTS(SELECT 1 FROM t2 WHERE t2.id=t1.id) GROUP BY id; id st 1 GA 3 FL 7 FL -SELECT id, st FROM t1 +SELECT id, st FROM t1 WHERE st IN ('GA','FL') AND NOT EXISTS(SELECT 1 FROM t2 WHERE t2.id=t1.id); id st 2 GA 4 FL -SELECT id, st FROM t1 +SELECT id, st FROM t1 WHERE st IN ('GA','FL') AND NOT EXISTS(SELECT 1 FROM t2 WHERE t2.id=t1.id) GROUP BY id; id st @@ -4272,7 +4272,7 @@ a b DROP TABLE t1,t2; CREATE TABLE t1(a INT, b INT); INSERT INTO t1 VALUES (1,1), (1,2), (2,3), (2,4); -EXPLAIN +EXPLAIN SELECT a AS out_a, MIN(b) FROM t1 WHERE b > (SELECT MIN(b) FROM t1 WHERE a = out_a) GROUP BY a; @@ -4281,7 +4281,7 @@ SELECT a AS out_a, MIN(b) FROM t1 WHERE b > (SELECT MIN(b) FROM t1 WHERE a = out_a) GROUP BY a; ERROR 42S22: Unknown column 'out_a' in 'where clause' -EXPLAIN +EXPLAIN SELECT a AS out_a, MIN(b) FROM t1 t1_outer WHERE b > (SELECT MIN(b) FROM t1 WHERE a = t1_outer.a) GROUP BY a; @@ -4312,16 +4312,16 @@ Warnings: Note 1276 Field or reference 'test.t1.a' of SELECT #2 was resolved in SELECT #1 Note 1003 select 2 AS `2` from `test`.`t1` where exists(select 1 AS `1` from `test`.`t2` where (`test`.`t1`.`a` = `test`.`t2`.`a`)) EXPLAIN EXTENDED -SELECT 2 FROM t1 WHERE EXISTS ((SELECT 1 FROM t2 WHERE t1.a=t2.a) UNION +SELECT 2 FROM t1 WHERE EXISTS ((SELECT 1 FROM t2 WHERE t1.a=t2.a) UNION (SELECT 1 FROM t2 WHERE t1.a = t2.a)); -ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'UNION +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'UNION (SELECT 1 FROM t2 WHERE t1.a = t2.a))' at line 2 DROP TABLE t1,t2; create table t1(f11 int, f12 int); create table t2(f21 int unsigned not null, f22 int, f23 varchar(10)); insert into t1 values(1,1),(2,2), (3, 3); set session sort_buffer_size= 33*1024; -select count(*) from t1 where f12 = +select count(*) from t1 where f12 = (select f22 from t2 where f22 = f12 order by f21 desc, f22, f23 limit 1); count(*) 3 @@ -4362,12 +4362,12 @@ IF( FROM t2 VPC, t4 a2, t2 a3 WHERE VPC.f4 = a2.f10 AND a3.f2 = a4 -LIMIT 1) IS NULL, -0, +LIMIT 1) IS NULL, +0, t3.f5 ) ) AS a6 -FROM +FROM t2, t3, t1 JOIN t2 a1 ON t1.f9 = a1.f4 GROUP BY a4; a4 f3 a6 @@ -4376,7 +4376,7 @@ a4 f3 a6 DROP TABLE t1, t2, t3, t4; create table t1 (a float(5,4) zerofill); create table t2 (a float(5,4),b float(2,0)); -select t1.a from t1 where +select t1.a from t1 where t1.a= (select b from t2 limit 1) and not t1.a= (select a from t2 limit 1) ; a diff --git a/mysql-test/r/synchronization.result b/mysql-test/r/synchronization.result index 29557b6cfd4..44edfb1e535 100644 --- a/mysql-test/r/synchronization.result +++ b/mysql-test/r/synchronization.result @@ -1,6 +1,6 @@ -drop table if exists t1; -CREATE TABLE t1 (x1 int); -ALTER TABLE t1 CHANGE x1 x2 int; +DROP TABLE IF EXISTS t1,t2; +CREATE TABLE t1 (x1 INT); +ALTER TABLE t1 CHANGE x1 x2 INT; CREATE TABLE t2 LIKE t1; SHOW CREATE TABLE t2; Table Create Table @@ -8,7 +8,7 @@ t2 CREATE TABLE `t2` ( `xx` int(11) default NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 DROP TABLE t2; -ALTER TABLE t1 CHANGE x2 x1 int; +ALTER TABLE t1 CHANGE x2 x1 INT; CREATE TABLE t2 LIKE t1; SHOW CREATE TABLE t2; Table Create Table @@ -16,7 +16,7 @@ t2 CREATE TABLE `t2` ( `xx` int(11) default NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 DROP TABLE t2; -ALTER TABLE t1 CHANGE x1 x2 int; +ALTER TABLE t1 CHANGE x1 x2 INT; CREATE TABLE t2 LIKE t1; SHOW CREATE TABLE t2; Table Create Table @@ -24,7 +24,7 @@ t2 CREATE TABLE `t2` ( `xx` int(11) default NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 DROP TABLE t2; -ALTER TABLE t1 CHANGE x2 x1 int; +ALTER TABLE t1 CHANGE x2 x1 INT; CREATE TABLE t2 LIKE t1; SHOW CREATE TABLE t2; Table Create Table @@ -32,7 +32,7 @@ t2 CREATE TABLE `t2` ( `xx` int(11) default NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 DROP TABLE t2; -ALTER TABLE t1 CHANGE x1 x2 int; +ALTER TABLE t1 CHANGE x1 x2 INT; CREATE TABLE t2 LIKE t1; SHOW CREATE TABLE t2; Table Create Table @@ -40,7 +40,7 @@ t2 CREATE TABLE `t2` ( `xx` int(11) default NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 DROP TABLE t2; -ALTER TABLE t1 CHANGE x2 x1 int; +ALTER TABLE t1 CHANGE x2 x1 INT; CREATE TABLE t2 LIKE t1; SHOW CREATE TABLE t2; Table Create Table @@ -48,7 +48,7 @@ t2 CREATE TABLE `t2` ( `xx` int(11) default NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 DROP TABLE t2; -ALTER TABLE t1 CHANGE x1 x2 int; +ALTER TABLE t1 CHANGE x1 x2 INT; CREATE TABLE t2 LIKE t1; SHOW CREATE TABLE t2; Table Create Table @@ -56,7 +56,7 @@ t2 CREATE TABLE `t2` ( `xx` int(11) default NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 DROP TABLE t2; -ALTER TABLE t1 CHANGE x2 x1 int; +ALTER TABLE t1 CHANGE x2 x1 INT; CREATE TABLE t2 LIKE t1; SHOW CREATE TABLE t2; Table Create Table @@ -64,7 +64,7 @@ t2 CREATE TABLE `t2` ( `xx` int(11) default NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 DROP TABLE t2; -ALTER TABLE t1 CHANGE x1 x2 int; +ALTER TABLE t1 CHANGE x1 x2 INT; CREATE TABLE t2 LIKE t1; SHOW CREATE TABLE t2; Table Create Table @@ -72,7 +72,7 @@ t2 CREATE TABLE `t2` ( `xx` int(11) default NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 DROP TABLE t2; -ALTER TABLE t1 CHANGE x2 x1 int; +ALTER TABLE t1 CHANGE x2 x1 INT; CREATE TABLE t2 LIKE t1; SHOW CREATE TABLE t2; Table Create Table @@ -80,7 +80,7 @@ t2 CREATE TABLE `t2` ( `xx` int(11) default NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 DROP TABLE t2; -ALTER TABLE t1 CHANGE x1 x2 int; +ALTER TABLE t1 CHANGE x1 x2 INT; CREATE TABLE t2 LIKE t1; SHOW CREATE TABLE t2; Table Create Table @@ -88,7 +88,7 @@ t2 CREATE TABLE `t2` ( `xx` int(11) default NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 DROP TABLE t2; -ALTER TABLE t1 CHANGE x2 x1 int; +ALTER TABLE t1 CHANGE x2 x1 INT; CREATE TABLE t2 LIKE t1; SHOW CREATE TABLE t2; Table Create Table @@ -96,7 +96,7 @@ t2 CREATE TABLE `t2` ( `xx` int(11) default NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 DROP TABLE t2; -ALTER TABLE t1 CHANGE x1 x2 int; +ALTER TABLE t1 CHANGE x1 x2 INT; CREATE TABLE t2 LIKE t1; SHOW CREATE TABLE t2; Table Create Table @@ -104,7 +104,7 @@ t2 CREATE TABLE `t2` ( `xx` int(11) default NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 DROP TABLE t2; -ALTER TABLE t1 CHANGE x2 x1 int; +ALTER TABLE t1 CHANGE x2 x1 INT; CREATE TABLE t2 LIKE t1; SHOW CREATE TABLE t2; Table Create Table @@ -112,7 +112,7 @@ t2 CREATE TABLE `t2` ( `xx` int(11) default NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 DROP TABLE t2; -ALTER TABLE t1 CHANGE x1 x2 int; +ALTER TABLE t1 CHANGE x1 x2 INT; CREATE TABLE t2 LIKE t1; SHOW CREATE TABLE t2; Table Create Table @@ -120,7 +120,7 @@ t2 CREATE TABLE `t2` ( `xx` int(11) default NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 DROP TABLE t2; -ALTER TABLE t1 CHANGE x2 x1 int; +ALTER TABLE t1 CHANGE x2 x1 INT; CREATE TABLE t2 LIKE t1; SHOW CREATE TABLE t2; Table Create Table @@ -128,7 +128,7 @@ t2 CREATE TABLE `t2` ( `xx` int(11) default NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 DROP TABLE t2; -ALTER TABLE t1 CHANGE x1 x2 int; +ALTER TABLE t1 CHANGE x1 x2 INT; CREATE TABLE t2 LIKE t1; SHOW CREATE TABLE t2; Table Create Table @@ -136,7 +136,7 @@ t2 CREATE TABLE `t2` ( `xx` int(11) default NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 DROP TABLE t2; -ALTER TABLE t1 CHANGE x2 x1 int; +ALTER TABLE t1 CHANGE x2 x1 INT; CREATE TABLE t2 LIKE t1; SHOW CREATE TABLE t2; Table Create Table @@ -144,7 +144,7 @@ t2 CREATE TABLE `t2` ( `xx` int(11) default NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 DROP TABLE t2; -ALTER TABLE t1 CHANGE x1 x2 int; +ALTER TABLE t1 CHANGE x1 x2 INT; CREATE TABLE t2 LIKE t1; SHOW CREATE TABLE t2; Table Create Table @@ -152,7 +152,7 @@ t2 CREATE TABLE `t2` ( `xx` int(11) default NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 DROP TABLE t2; -ALTER TABLE t1 CHANGE x2 x1 int; +ALTER TABLE t1 CHANGE x2 x1 INT; CREATE TABLE t2 LIKE t1; SHOW CREATE TABLE t2; Table Create Table diff --git a/mysql-test/t/backup.test b/mysql-test/t/backup.test index b05eef6a3ad..34982b391ac 100644 --- a/mysql-test/t/backup.test +++ b/mysql-test/t/backup.test @@ -1,7 +1,10 @@ # The server need to be started in $MYSQLTEST_VARDIR since it # uses ../std_data_ln/ --- source include/uses_vardir.inc +--source include/uses_vardir.inc + +# Save the initial number of concurrent sessions +--source include/count_sessions.inc # # This test is a bit tricky as we can't use backup table to overwrite an old @@ -12,7 +15,7 @@ connect (con2,localhost,root,,); connection con1; set SQL_LOG_BIN=0; --disable_warnings -drop table if exists t1, t2, t3; +drop table if exists t1, t2, t3, t4; --enable_warnings create table t4(n int); --replace_result ": 1" ": X" ": 2" ": X" ": 22" ": X" ": 23" ": X" $MYSQLTEST_VARDIR MYSQLTEST_VARDIR @@ -57,6 +60,9 @@ unlock tables; connection con1; reap; drop table t5; +connection default; +disconnect con1; +disconnect con2; remove_file $MYSQLTEST_VARDIR/tmp/t1.MYD; remove_file $MYSQLTEST_VARDIR/tmp/t2.MYD; remove_file $MYSQLTEST_VARDIR/tmp/t3.MYD; @@ -68,4 +74,9 @@ remove_file $MYSQLTEST_VARDIR/tmp/t3.frm; remove_file $MYSQLTEST_VARDIR/tmp/t4.frm; remove_file $MYSQLTEST_VARDIR/tmp/t5.frm; + # End of 4.1 tests + +# Wait till all disconnects are completed +--source include/wait_until_count_sessions.inc + diff --git a/mysql-test/t/check.test b/mysql-test/t/check.test index 698f6538529..ff23b352b5a 100644 --- a/mysql-test/t/check.test +++ b/mysql-test/t/check.test @@ -1,8 +1,12 @@ +# Save the initial number of concurrent sessions +--source include/count_sessions.inc + connect (con1,localhost,root,,); connect (con2,localhost,root,,); connection con1; --disable_warnings -drop table if exists t1; +drop table if exists t1,t2; +drop view if exists v1; --enable_warnings # Add a lot of keys to slow down check @@ -20,16 +24,18 @@ connection con2; insert into t1 values (200000); connection con1; reap; +connection default; +disconnect con1; +disconnect con2; drop table t1; + # End of 4.1 tests # -# Bug #9897 Views: 'Check Table' crashes MySQL, with a view and a table -# in the statement +# Bug#9897 Views: 'Check Table' crashes MySQL, with a view and a table +# in the statement # - -connection default; Create table t1(f1 int); Create table t2(f1 int); Create view v1 as Select * from t1; @@ -37,11 +43,15 @@ Check Table v1,t2; drop view v1; drop table t1, t2; + # -# BUG#26325 - TEMPORARY TABLE "corrupt" after first read, according to CHECK -# TABLE +# Bug#26325 TEMPORARY TABLE "corrupt" after first read, according to CHECK TABLE # CREATE TEMPORARY TABLE t1(a INT); CHECK TABLE t1; REPAIR TABLE t1; DROP TABLE t1; + + +# Wait till we reached the initial number of concurrent sessions +--source include/wait_until_count_sessions.inc diff --git a/mysql-test/t/compress.test b/mysql-test/t/compress.test index 3f1892b5dec..8e12ab46f06 100644 --- a/mysql-test/t/compress.test +++ b/mysql-test/t/compress.test @@ -6,6 +6,10 @@ -- source include/have_compress.inc +# Save the initial number of concurrent sessions +--source include/count_sessions.inc + + connect (comp_con,localhost,root,,,,,COMPRESS); # Check compression turned on @@ -16,3 +20,10 @@ SHOW STATUS LIKE 'Compression'; # Check compression turned on SHOW STATUS LIKE 'Compression'; + +connection default; +disconnect comp_con; + +# Wait till all disconnects are completed +--source include/wait_until_count_sessions.inc + diff --git a/mysql-test/t/grant.test b/mysql-test/t/grant.test index 14c5879d007..6f6e8753004 100644 --- a/mysql-test/t/grant.test +++ b/mysql-test/t/grant.test @@ -3,6 +3,9 @@ # Grant tests not performed with embedded server -- source include/not_embedded.inc +# Save the initial number of concurrent sessions +--source include/count_sessions.inc + # Cleanup --disable_warnings drop table if exists t1; @@ -78,7 +81,7 @@ delete from mysql.db where user='mysqltest_1'; delete from mysql.tables_priv where user='mysqltest_1'; delete from mysql.columns_priv where user='mysqltest_1'; flush privileges; ---error 1141 +--error ER_NONEXISTING_GRANT show grants for mysqltest_1@localhost; # @@ -116,15 +119,15 @@ drop table t1; # # Test some error conditions # ---error 1221 +--error ER_WRONG_USAGE GRANT FILE on mysqltest.* to mysqltest_1@localhost; -select 1; # To test that the previous command didn't cause problems +select 1; # To test that the previous command didn't cause problems # -# Bug #4898: User privileges depending on ORDER BY Settings of table db +# Bug#4898 User privileges depending on ORDER BY Settings of table db # insert into mysql.user (host, user) values ('localhost', 'test11'); -insert into mysql.db (host, db, user, select_priv) values +insert into mysql.db (host, db, user, select_priv) values ('localhost', 'a%', 'test11', 'Y'), ('localhost', 'ab%', 'test11', 'Y'); alter table mysql.db order by db asc; flush privileges; @@ -136,7 +139,7 @@ delete from mysql.user where user='test11'; delete from mysql.db where user='test11'; # -# Bug#6123: GRANT USAGE inserts useless Db row +# Bug#6123 GRANT USAGE inserts useless Db row # create database mysqltest1; grant usage on mysqltest1.* to test6123 identified by 'magic123'; @@ -145,7 +148,7 @@ delete from mysql.user where user='test6123'; drop database mysqltest1; # -# Test for 'drop user', 'revoke privileges, grant' +# Test for 'drop user', 'revoke privileges, grant' # create table t1 (a int); @@ -160,7 +163,7 @@ grant select(a) on test.t1 to drop_user@localhost; show grants for drop_user@localhost; # -# Bug3086 +# Bug#3086 SHOW GRANTS doesn't follow ANSI_QUOTES # set sql_mode=ansi_quotes; show grants for drop_user@localhost; @@ -178,7 +181,7 @@ show grants for drop_user@localhost; revoke all privileges, grant option from drop_user@localhost; show grants for drop_user@localhost; drop user drop_user@localhost; ---error 1269 +--error ER_REVOKE_GRANTS revoke all privileges, grant option from drop_user@localhost; grant select(a) on test.t1 to drop_user1@localhost; @@ -188,10 +191,10 @@ grant select on *.* to drop_user4@localhost; # Drop user now implicitly revokes all privileges. drop user drop_user1@localhost, drop_user2@localhost, drop_user3@localhost, drop_user4@localhost; ---error 1269 +--error ER_REVOKE_GRANTS revoke all privileges, grant option from drop_user1@localhost, drop_user2@localhost, drop_user3@localhost, drop_user4@localhost; ---error 1396 +--error ER_CANNOT_USER drop user drop_user1@localhost, drop_user2@localhost, drop_user3@localhost, drop_user4@localhost; drop table t1; @@ -201,12 +204,12 @@ show grants for mysqltest_1@localhost; drop user mysqltest_1@localhost; # -# Bug #3403 Wrong encodin in SHOW GRANTS output +# Bug#3403 Wrong encoding in SHOW GRANTS, EPLAIN SELECT output # SET NAMES koi8r; CREATE DATABASE ÂÄ; USE ÂÄ; -CREATE TABLE ÔÁ (ËÏÌ int); +CREATE TABLE ÔÁ (ËÏÌ INT); GRANT SELECT ON ÂÄ.* TO ÀÚÅÒ@localhost; SHOW GRANTS FOR ÀÚÅÒ@localhost; @@ -227,7 +230,7 @@ DROP DATABASE SET NAMES latin1; # -# Bug #5831: REVOKE ALL PRIVILEGES, GRANT OPTION does not revoke everything +# Bug#5831 REVOKE ALL PRIVILEGES, GRANT OPTION does not revoke everything # USE test; CREATE TABLE t1 (a int ); @@ -296,7 +299,7 @@ DROP DATABASE testdb9; DROP DATABASE testdb10; # -# Bug #6932: a problem with 'revoke ALL PRIVILEGES' +# Bug#6932 a problem with 'revoke ALL PRIVILEGES' # create table t1(a int, b int, c int, d int); @@ -310,7 +313,7 @@ drop user grant_user@localhost; drop table t1; # -# Bug#7391: Cross-database multi-table UPDATE security problem +# Bug#7391 Cross-database multi-table UPDATE security problem # create database mysqltest_1; create database mysqltest_2; @@ -319,36 +322,36 @@ create table mysqltest_1.t2 select 1 b, 2 r; create table mysqltest_2.t1 select 1 c, 2 s; create table mysqltest_2.t2 select 1 d, 2 t; -#test the column privileges +# test the column privileges grant update (a) on mysqltest_1.t1 to mysqltest_3@localhost; grant select (b) on mysqltest_1.t2 to mysqltest_3@localhost; grant select (c) on mysqltest_2.t1 to mysqltest_3@localhost; grant update (d) on mysqltest_2.t2 to mysqltest_3@localhost; connect (conn1,localhost,mysqltest_3,,); connection conn1; -SELECT * FROM INFORMATION_SCHEMA.COLUMN_PRIVILEGES - WHERE GRANTEE = '''mysqltest_3''@''localhost''' +SELECT * FROM INFORMATION_SCHEMA.COLUMN_PRIVILEGES + WHERE GRANTEE = '''mysqltest_3''@''localhost''' ORDER BY TABLE_NAME,COLUMN_NAME,PRIVILEGE_TYPE; SELECT * FROM INFORMATION_SCHEMA.TABLE_PRIVILEGES - WHERE GRANTEE = '''mysqltest_3''@''localhost''' + WHERE GRANTEE = '''mysqltest_3''@''localhost''' ORDER BY TABLE_NAME,PRIVILEGE_TYPE; SELECT * from INFORMATION_SCHEMA.SCHEMA_PRIVILEGES - WHERE GRANTEE = '''mysqltest_3''@''localhost''' + WHERE GRANTEE = '''mysqltest_3''@''localhost''' ORDER BY TABLE_SCHEMA,PRIVILEGE_TYPE; SELECT * from INFORMATION_SCHEMA.USER_PRIVILEGES WHERE GRANTEE = '''mysqltest_3''@''localhost''' ORDER BY TABLE_CATALOG,PRIVILEGE_TYPE; ---error 1143 +--error ER_COLUMNACCESS_DENIED_ERROR update mysqltest_1.t1, mysqltest_1.t2 set q=10 where b=1; ---error 1143 +--error ER_COLUMNACCESS_DENIED_ERROR update mysqltest_1.t2, mysqltest_2.t2 set d=20 where d=1; ---error 1142 +--error ER_TABLEACCESS_DENIED_ERROR update mysqltest_1.t1, mysqltest_2.t2 set d=20 where d=1; ---error 1142 +--error ER_TABLEACCESS_DENIED_ERROR update mysqltest_2.t1, mysqltest_1.t2 set c=20 where b=1; ---error 1143 +--error ER_COLUMNACCESS_DENIED_ERROR update mysqltest_2.t1, mysqltest_2.t2 set d=10 where s=2; -#the following two should work +# the following two should work update mysqltest_1.t1, mysqltest_2.t2 set a=10,d=10; update mysqltest_1.t1, mysqltest_2.t1 set a=20 where c=20; connection master; @@ -359,7 +362,7 @@ revoke all on mysqltest_1.t2 from mysqltest_3@localhost; revoke all on mysqltest_2.t1 from mysqltest_3@localhost; revoke all on mysqltest_2.t2 from mysqltest_3@localhost; -#test the db/table level privileges +# test the db/table level privileges grant all on mysqltest_2.* to mysqltest_3@localhost; grant select on *.* to mysqltest_3@localhost; # Next grant is needed to trigger bug#7391. Do not optimize! @@ -371,15 +374,15 @@ connection conn2; use mysqltest_1; update mysqltest_2.t1, mysqltest_2.t2 set c=500,d=600; # the following failed before, should fail now. ---error 1142 +--error ER_TABLEACCESS_DENIED_ERROR update mysqltest_1.t1, mysqltest_1.t2 set a=100,b=200; use mysqltest_2; -#the following used to succeed, it must fail now. ---error 1142 +# the following used to succeed, it must fail now. +--error ER_TABLEACCESS_DENIED_ERROR update mysqltest_1.t1, mysqltest_1.t2 set a=100,b=200; ---error 1142 +--error ER_TABLEACCESS_DENIED_ERROR update mysqltest_2.t1, mysqltest_1.t2 set c=100,b=200; ---error 1142 +--error ER_TABLEACCESS_DENIED_ERROR update mysqltest_1.t1, mysqltest_2.t2 set a=100,d=200; #lets see the result connection master; @@ -393,6 +396,7 @@ delete from mysql.columns_priv where user="mysqltest_3"; flush privileges; drop database mysqltest_1; drop database mysqltest_2; +disconnect conn2; # # just SHOW PRIVILEGES test @@ -400,7 +404,7 @@ drop database mysqltest_2; SHOW PRIVILEGES; # -# Rights for renaming test (Bug #3270) +# Rights for renaming test (Bug#3270) # connect (root,localhost,root,,test,$MASTER_MYPORT,$MASTER_MYSOCK); connection root; @@ -411,16 +415,18 @@ create table mysqltest.t1 (a int,b int,c int); grant all on mysqltest.t1 to mysqltest_1@localhost; connect (user1,localhost,mysqltest_1,,mysqltest,$MASTER_MYPORT,$MASTER_MYSOCK); connection user1; --- error 1142 +-- error ER_TABLEACCESS_DENIED_ERROR alter table t1 rename t2; disconnect user1; connection root; revoke all privileges on mysqltest.t1 from mysqltest_1@localhost; delete from mysql.user where user=_binary'mysqltest_1'; drop database mysqltest; +connection default; +disconnect root; # -# check all new table priveleges +# check all new table privileges # CREATE USER dummy@localhost; CREATE DATABASE mysqltest; @@ -485,7 +491,7 @@ REVOKE ALL PRIVILEGES, GRANT OPTION FROM dummy@localhost; DROP USER dummy@localhost; DROP DATABASE mysqltest; # -# Bug #11330: Entry in tables_priv with host = '' causes crash +# Bug#11330 Entry in tables_priv with host = '' causes crash # connection default; use mysql; @@ -496,7 +502,7 @@ flush privileges; use test; # -# Bug #10892 user variables not auto cast for comparisons +# Bug#10892 user variables not auto cast for comparisons # Check that we don't get illegal mix of collations # set @user123="non-existent"; @@ -515,18 +521,18 @@ show grants for root@localhost; set names latin1; # -# Bug #15598 Server crashes in specific case during setting new password +# Bug#15598 Server crashes in specific case during setting new password # - Caused by a user with host '' # create user mysqltest_7@; set password for mysqltest_7@ = password('systpass'); show grants for mysqltest_7@; drop user mysqltest_7@; ---error 1141 +--error ER_NONEXISTING_GRANT show grants for mysqltest_7@; # -# Bug#14385: GRANT and mapping to correct user account problems +# Bug#14385 GRANT and mapping to correct user account problems # create database mysqltest; use mysqltest; @@ -542,7 +548,7 @@ flush privileges; drop database mysqltest; # -# Bug #27515: DROP previlege is not required for RENAME TABLE +# Bug#27515 DROP previlege is not required for RENAME TABLE # connection master; create database db27515; @@ -553,7 +559,7 @@ grant insert, create on db27515.t2 to user27515@localhost; connect (conn27515, localhost, user27515, , db27515); connection conn27515; ---error 1142 +--error ER_TABLEACCESS_DENIED_ERROR rename table t1 to t2; disconnect conn27515; @@ -565,7 +571,7 @@ drop database db27515; --echo End of 4.1 tests # -# Bug #16297 In memory grant tables not flushed when users's hostname is "" +# Bug#16297 In memory grant tables not flushed when users's hostname is "" # use test; create table t1 (a int); @@ -582,11 +588,11 @@ create user mysqltest_8; create user mysqltest_8@host8; # Try to create them again ---error 1396 +--error ER_CANNOT_USER create user mysqltest_8@''; ---error 1396 +--error ER_CANNOT_USER create user mysqltest_8; ---error 1396 +--error ER_CANNOT_USER create user mysqltest_8@host8; select user, QUOTE(host) from mysql.user where user="mysqltest_8"; @@ -681,44 +687,43 @@ flush privileges; show grants for mysqltest_8@''; show grants for mysqltest_8; drop user mysqltest_8@''; ---error 1141 +--error ER_NONEXISTING_GRANT show grants for mysqltest_8@''; show grants for mysqltest_8; select * from information_schema.user_privileges where grantee like "'mysqltest_8'%"; drop user mysqltest_8; --replace_result $MASTER_MYSOCK MASTER_SOCKET $MASTER_MYPORT MASTER_PORT ---error 1045 +--error ER_ACCESS_DENIED_ERROR connect (conn6,localhost,mysqltest_8,,); connection master; ---error 1141 +--error ER_NONEXISTING_GRANT show grants for mysqltest_8; drop user mysqltest_8@host8; ---error 1141 +--error ER_NONEXISTING_GRANT show grants for mysqltest_8@host8; # Restore the anonymous users. insert into mysql.user select * from t2; flush privileges; drop table t2; - drop table t1; # -# Bug#20214: Incorrect error when user calls SHOW CREATE VIEW on non -# privileged view +# Bug#20214 Incorrect error when user calls SHOW CREATE VIEW on non +# privileged view # connection master; CREATE DATABASE mysqltest3; -use mysqltest3; +USE mysqltest3; CREATE TABLE t_nn (c1 INT); CREATE VIEW v_nn AS SELECT * FROM t_nn; CREATE DATABASE mysqltest2; -use mysqltest2; +USE mysqltest2; CREATE TABLE t_nn (c1 INT); CREATE VIEW v_nn AS SELECT * FROM t_nn; @@ -740,24 +745,18 @@ SHOW CREATE VIEW mysqltest2.v_nn; --error ER_TABLEACCESS_DENIED_ERROR SHOW CREATE TABLE mysqltest2.v_nn; - - # fail because of missing SHOW VIEW --error ER_TABLEACCESS_DENIED_ERROR SHOW CREATE VIEW mysqltest2.v_yn; --error ER_TABLEACCESS_DENIED_ERROR SHOW CREATE TABLE mysqltest2.v_yn; - - # succeed (despite of missing SELECT, having SHOW VIEW bails us out) SHOW CREATE TABLE mysqltest2.v_ny; # succeed (despite of missing SELECT, having SHOW VIEW bails us out) SHOW CREATE VIEW mysqltest2.v_ny; - - # fail because of missing (specific or generic) SELECT --error ER_TABLEACCESS_DENIED_ERROR SHOW CREATE TABLE mysqltest3.t_nn; @@ -766,16 +765,12 @@ SHOW CREATE TABLE mysqltest3.t_nn; --error ER_TABLEACCESS_DENIED_ERROR SHOW CREATE VIEW mysqltest3.t_nn; - - # fail because of missing missing (specific or generic) SELECT (and SHOW VIEW) --error ER_TABLEACCESS_DENIED_ERROR SHOW CREATE VIEW mysqltest3.v_nn; --error ER_TABLEACCESS_DENIED_ERROR SHOW CREATE TABLE mysqltest3.v_nn; - - # succeed thanks to generic SELECT SHOW CREATE TABLE mysqltest2.t_nn; @@ -783,8 +778,6 @@ SHOW CREATE TABLE mysqltest2.t_nn; --error ER_WRONG_OBJECT SHOW CREATE VIEW mysqltest2.t_nn; - - # succeed, have SELECT and SHOW VIEW SHOW CREATE VIEW mysqltest2.v_yy; @@ -792,8 +785,7 @@ SHOW CREATE VIEW mysqltest2.v_yy; SHOW CREATE TABLE mysqltest2.v_yy; - -#clean-up +# clean-up connection master; # succeed, we're root @@ -806,38 +798,30 @@ SHOW CREATE TABLE mysqltest2.t_nn; --error ER_WRONG_OBJECT SHOW CREATE VIEW mysqltest2.t_nn; - - DROP VIEW mysqltest2.v_nn; DROP VIEW mysqltest2.v_yn; DROP VIEW mysqltest2.v_ny; DROP VIEW mysqltest2.v_yy; - DROP TABLE mysqltest2.t_nn; - DROP DATABASE mysqltest2; - - - DROP VIEW mysqltest3.v_nn; DROP TABLE mysqltest3.t_nn; - DROP DATABASE mysqltest3; - +disconnect mysqltest_1; REVOKE ALL PRIVILEGES, GRANT OPTION FROM 'mysqltest_1'@'localhost'; DROP USER 'mysqltest_1'@'localhost'; # restore the original database -use test; +USE test; # -# Bug #10668: CREATE USER does not enforce username length limit +# Bug#10668 CREATE USER does not enforce username length limit # --error ER_WRONG_STRING_LENGTH create user mysqltest1_thisisreallytoolong; # -# Test for BUG#16899: Possible buffer overflow in handling of DEFINER-clause. +# Test for Bug#16899 Possible buffer overflow in handling of DEFINER-clause. # # These checks are intended to ensure that appropriate errors are risen when # illegal user name or hostname is specified in user-clause of GRANT/REVOKE @@ -887,7 +871,7 @@ REVOKE EXECUTE ON PROCEDURE p1 FROM 1234567890abcdefGHIKL@localhost; REVOKE EXECUTE ON PROCEDURE t1 FROM some_user_name@1234567890abcdefghij1234567890abcdefghij1234567890abcdefghijQWERTY; # -# Bug #6774: Replication fails with Wrong usage of DB GRANT and GLOBAL PRIVILEGES +# Bug#6774 Replication fails with Wrong usage of DB GRANT and GLOBAL PRIVILEGES # # Check if GRANT ... ON * ... fails when no database is selected connect (con1, localhost, root,,*NO-ONE*); @@ -899,7 +883,7 @@ connection default; # -# BUG#9504: Stored procedures: execute privilege doesn't make 'use database' +# Bug#9504 Stored procedures: execute privilege doesn't make 'use database' # okay. # @@ -924,8 +908,8 @@ CREATE PROCEDURE mysqltest2.p_inv() SQL SECURITY INVOKER SELECT 1; CREATE FUNCTION mysqltest3.f_def() RETURNS INT SQL SECURITY DEFINER - RETURN 1; - + RETURN 1; + CREATE FUNCTION mysqltest4.f_inv() RETURNS INT SQL SECURITY INVOKER RETURN 1; @@ -981,7 +965,7 @@ DROP USER mysqltest_1@localhost; # -# BUG#27337: Privileges are not restored properly. +# Bug#27337 Privileges are not restored properly. # # Actually, the patch for this bugs fixes two problems. So, here are two test # cases. @@ -1043,7 +1027,7 @@ DROP DATABASE mysqltest2; DROP USER mysqltest_1@localhost; -# Test case 2: priveleges are not checked properly for prepared statements. +# Test case 2: privileges are not checked properly for prepared statements. # Prepare. @@ -1116,6 +1100,7 @@ EXECUTE stmt2; --echo --echo ---> connection: default +--disconnect bug27337_con1 --disconnect bug27337_con2 DROP DATABASE mysqltest1; @@ -1125,21 +1110,21 @@ DROP USER mysqltest_1@localhost; DROP USER mysqltest_2@localhost; # -# Bug#27878: Unchecked privileges on a view referring to a table from another -# database. +# Bug#27878 Unchecked privileges on a view referring to a table from another +# database. # -use test; +USE test; CREATE TABLE t1 (f1 int, f2 int); INSERT INTO t1 VALUES(1,1), (2,2); CREATE DATABASE db27878; GRANT UPDATE(f1) ON t1 TO 'mysqltest_1'@'localhost'; GRANT SELECT ON `test`.* TO 'mysqltest_1'@'localhost'; GRANT ALL ON db27878.* TO 'mysqltest_1'@'localhost'; -use db27878; +USE db27878; CREATE SQL SECURITY INVOKER VIEW db27878.v1 AS SELECT * FROM test.t1; connect (user1,localhost,mysqltest_1,,test); connection user1; -use db27878; +USE db27878; --error 1356 UPDATE v1 SET f2 = 4; SELECT * FROM test.t1; @@ -1150,11 +1135,11 @@ REVOKE SELECT ON `test`.* FROM 'mysqltest_1'@'localhost'; REVOKE ALL ON db27878.* FROM 'mysqltest_1'@'localhost'; DROP USER mysqltest_1@localhost; DROP DATABASE db27878; -use test; +USE test; DROP TABLE t1; # -# Bug #33201 Crash occurs when granting update privilege on one column of a view +# Bug#33201 Crash occurs when granting update privilege on one column of a view # drop table if exists test; drop function if exists test_function; @@ -1183,3 +1168,7 @@ SET PASSWORD FOR CURRENT_USER() = PASSWORD("admin"); SET PASSWORD FOR CURRENT_USER() = PASSWORD(""); --echo End of 5.0 tests + +disconnect master; +# Wait till we reached the initial number of concurrent sessions +--source include/wait_until_count_sessions.inc diff --git a/mysql-test/t/information_schema.test b/mysql-test/t/information_schema.test index caf38945cbc..5873347eae0 100644 --- a/mysql-test/t/information_schema.test +++ b/mysql-test/t/information_schema.test @@ -36,11 +36,11 @@ insert into t5 values (10); create view v1 (c) as select table_name from information_schema.TABLES; select * from v1; -select c,table_name from v1 +select c,table_name from v1 inner join information_schema.TABLES v2 on (v1.c=v2.table_name) where v1.c like "t%"; -select c,table_name from v1 +select c,table_name from v1 left join information_schema.TABLES v2 on (v1.c=v2.table_name) where v1.c like "t%"; @@ -69,7 +69,7 @@ grant select (a) on mysqltest.t1 to mysqltest_2@localhost; grant select on mysqltest.v1 to mysqltest_3; connect (user3,localhost,mysqltest_2,,); connection user3; -select table_name, column_name, privileges from information_schema.columns +select table_name, column_name, privileges from information_schema.columns where table_schema = 'mysqltest' and table_name = 't1'; show columns from mysqltest.t1; connect (user4,localhost,mysqltest_3,,mysqltest); @@ -77,6 +77,7 @@ connection user4; select table_name, column_name, privileges from information_schema.columns where table_schema = 'mysqltest' and table_name = 'v1'; connection default; +disconnect user4; drop view v1, mysqltest.v1; drop tables mysqltest.t4, mysqltest.t1, t2, t3, t5; @@ -126,7 +127,7 @@ delimiter ;| # # Bug#7222 information_schema: errors in "routines" # -select parameter_style, sql_data_access, dtd_identifier +select parameter_style, sql_data_access, dtd_identifier from information_schema.routines; --replace_column 5 # 6 # @@ -145,7 +146,7 @@ select a.ROUTINE_NAME, b.name from information_schema.ROUTINES a, mysql.proc b where a.ROUTINE_NAME = convert(b.name using utf8) order by 1; select count(*) from information_schema.ROUTINES; -create view v1 as select routine_schema, routine_name from information_schema.routines +create view v1 as select routine_schema, routine_name from information_schema.routines order by routine_schema, routine_name; select * from v1; drop view v1; @@ -153,7 +154,7 @@ drop view v1; connect (user1,localhost,mysqltest_1,,); connection user1; select ROUTINE_NAME, ROUTINE_DEFINITION from information_schema.ROUTINES; ---error 1305 +--error ER_SP_DOES_NOT_EXIST show create function sub1; connection user3; select ROUTINE_NAME, ROUTINE_DEFINITION from information_schema.ROUTINES; @@ -172,6 +173,7 @@ show create function sub2; show function status like "sub2"; connection default; disconnect user1; +disconnect user3; drop function sub2; show create procedure sel2; @@ -311,7 +313,7 @@ drop view v1; create table t1(a NUMERIC(5,3), b NUMERIC(5,1), c float(5,2), d NUMERIC(6,4), e float, f DECIMAL(6,3), g int(11), h DOUBLE(10,3), i DOUBLE); -select COLUMN_NAME,COLUMN_TYPE, CHARACTER_MAXIMUM_LENGTH, +select COLUMN_NAME,COLUMN_TYPE, CHARACTER_MAXIMUM_LENGTH, CHARACTER_OCTET_LENGTH, NUMERIC_PRECISION, NUMERIC_SCALE from information_schema.columns where table_name= 't1'; drop table t1; @@ -324,7 +326,7 @@ drop table t115; delimiter //; create procedure p108 () begin declare c cursor for select data_type from information_schema.columns; open c; open c; end;// ---error 1325 +--error ER_SP_CURSOR_ALREADY_OPEN call p108()// delimiter ;// drop procedure p108; @@ -334,24 +336,24 @@ where table_name= "user"; select * from v1; drop view v1; -create view vo as select 'a' union select 'a'; +create view vo as select 'a' union select 'a'; show index from vo; select * from information_schema.TABLE_CONSTRAINTS where TABLE_NAME= "vo"; select * from information_schema.KEY_COLUMN_USAGE where -TABLE_NAME= "vo"; +TABLE_NAME= "vo"; drop view vo; select TABLE_NAME,TABLE_TYPE,ENGINE -from information_schema.tables +from information_schema.tables where table_schema='information_schema' limit 2; show tables from information_schema like "T%"; ---error 1044 +--error ER_DBACCESS_DENIED_ERROR create database information_schema; use information_schema; show full tables like "T%"; ---error 1109 +--error ER_UNKNOWN_TABLE create table t1(a int); use test; show tables; @@ -359,15 +361,15 @@ use information_schema; show tables like "T%"; # -# Bug#7210: information_schema: can't access when table-name = reserved word +# Bug#7210 information_schema: can't access when table-name = reserved word # select table_name from tables where table_name='user'; select column_name, privileges from columns where table_name='user' and column_name like '%o%'; # -# Bug#7212: information_schema: "Can't find file" errors if storage engine gone -# Bug#7211: information_schema: crash if bad view +# Bug#7212 information_schema: "Can't find file" errors if storage engine gone +# Bug#7211 information_schema: crash if bad view # use test; create function sub1(i int) returns int @@ -394,9 +396,9 @@ drop view v3; drop table t4; # -# Bug#7213: information_schema: redundant non-standard TABLE_NAMES table +# Bug#7213 information_schema: redundant non-standard TABLE_NAMES table # ---error 1109 +--error ER_UNKNOWN_TABLE select * from information_schema.table_names; # @@ -409,7 +411,7 @@ where table_schema="information_schema" and table_name="COLUMNS" and # # Bug#2718 information_schema: errors in "tables" # -select TABLE_ROWS from information_schema.tables where +select TABLE_ROWS from information_schema.tables where table_schema="information_schema" and table_name="COLUMNS"; select table_type from information_schema.tables where table_schema="mysql" and table_name="user"; @@ -422,14 +424,14 @@ show status where variable_name like "%database%"; show variables where variable_name like "skip_show_databas"; # -# Bug #7981:SHOW GLOBAL STATUS crashes server +# Bug#7981 SHOW GLOBAL STATUS crashes server # # We don't actually care about the value, just that it doesn't crash. --replace_column 2 # show global status like "Threads_running"; # -# Bug #7915 crash,JOIN VIEW, subquery, +# Bug#7915 crash,JOIN VIEW, subquery, # SELECT .. FROM INFORMATION_SCHEMA.COLUMNS # create table t1(f1 int); @@ -440,7 +442,7 @@ drop view v1; drop table t1, t2; # -# Bug #7476: crash on SELECT * FROM INFORMATION_SCHEMA.TABLES +# Bug#7476 crash on SELECT * FROM INFORMATION_SCHEMA.TABLES # CREATE TABLE t_crashme ( f1 BIGINT); @@ -468,26 +470,26 @@ drop view a2, a1; drop table t_crashme; # -# Bug #7215 information_schema: columns are longtext instead of varchar -# Bug #7217 information_schema: columns are varbinary() instead of timestamp +# Bug#7215 information_schema: columns are longtext instead of varchar +# Bug#7217 information_schema: columns are varbinary() instead of timestamp # select table_schema,table_name, column_name from -information_schema.columns +information_schema.columns where data_type = 'longtext'; select table_name, column_name, data_type from information_schema.columns where data_type = 'datetime'; # -# Bug #8164 subquery with INFORMATION_SCHEMA.COLUMNS, 100 % CPU +# Bug#8164 subquery with INFORMATION_SCHEMA.COLUMNS, 100 % CPU # SELECT COUNT(*) FROM INFORMATION_SCHEMA.TABLES A -WHERE NOT EXISTS +WHERE NOT EXISTS (SELECT * FROM INFORMATION_SCHEMA.COLUMNS B WHERE A.TABLE_SCHEMA = B.TABLE_SCHEMA AND A.TABLE_NAME = B.TABLE_NAME); # -# Bug #9344 INFORMATION_SCHEMA, wrong content, numeric columns +# Bug#9344 INFORMATION_SCHEMA, wrong content, numeric columns # create table t1 @@ -505,21 +507,22 @@ WHERE TABLE_NAME= 't1'; drop table t1; # -# Bug#10261 INFORMATION_SCHEMA.COLUMNS, incomplete result for non root user +# Bug#10261 INFORMATION_SCHEMA.COLUMNS, incomplete result for non root user # grant select on test.* to mysqltest_4@localhost; connect (user10261,localhost,mysqltest_4,,); connection user10261; -SELECT TABLE_NAME, COLUMN_NAME, PRIVILEGES FROM INFORMATION_SCHEMA.COLUMNS +SELECT TABLE_NAME, COLUMN_NAME, PRIVILEGES FROM INFORMATION_SCHEMA.COLUMNS where COLUMN_NAME='TABLE_NAME'; connection default; +disconnect user10261; delete from mysql.user where user='mysqltest_4'; delete from mysql.db where user='mysqltest_4'; flush privileges; # -# Bug #9404 information_schema: Weird error messages +# Bug#9404 information_schema: Weird error messages # with SELECT SUM() ... GROUP BY queries # SELECT table_schema, count(*) FROM information_schema.TABLES GROUP BY TABLE_SCHEMA; @@ -560,7 +563,7 @@ drop table t1; # -# Bug #10964 Information Schema:Authorization check on privilege tables is improper +# Bug#10964 Information Schema:Authorization check on privilege tables is improper # create database mysqltest; @@ -604,12 +607,16 @@ select * from information_schema.user_privileges where grantee like '%user%' order by grantee; show grants; connection default; +disconnect con1; +disconnect con2; +disconnect con3; +disconnect con4; drop user user1@localhost, user2@localhost, user3@localhost, user4@localhost; use test; drop database mysqltest; # -# Bug #11055 information_schema: routines.sql_data_access has wrong value +# Bug#11055 information_schema: routines.sql_data_access has wrong value # --disable_warnings drop procedure if exists p1; @@ -624,13 +631,13 @@ drop procedure p1; drop procedure p2; # -# Bug #9434 SHOW CREATE DATABASE information_schema; +# Bug#9434 SHOW CREATE DATABASE information_schema; # show create database information_schema; # -# Bug #11057 information_schema: columns table has some questionable contents -# Bug #12301 information_schema: NUMERIC_SCALE must be 0 for integer columns +# Bug#11057 information_schema: columns table has some questionable contents +# Bug#12301 information_schema: NUMERIC_SCALE must be 0 for integer columns # create table t1(f1 LONGBLOB, f2 LONGTEXT); select column_name,data_type,CHARACTER_OCTET_LENGTH, @@ -646,7 +653,7 @@ where table_name='t1'; drop table t1; # -# Bug #12127 triggers do not show in info_schema before they are used if set to the database +# Bug#12127 triggers do not show in info_schema before they are used if set to the database # create table t1 (f1 integer); create trigger tr1 after insert on t1 for each row set @test_var=42; @@ -668,7 +675,7 @@ show columns from t1; drop table t1; # -# Bug #12636: SHOW TABLE STATUS with where condition containing a subquery +# Bug#12636 SHOW TABLE STATUS with where condition containing a subquery # over information schema # @@ -683,7 +690,7 @@ SHOW TABLE STATUS FROM test DROP TABLE t1,t2; # -# Bug #12905 show fields from view behaving erratically with current database +# Bug#12905 show fields from view behaving erratically with current database # create table t1(f1 int); create view v1 (c) as select f1 from t1; @@ -691,28 +698,29 @@ connect (con5,localhost,root,,*NO-ONE*); select database(); show fields from test.v1; connection default; +disconnect con5; drop view v1; drop table t1; # -# Bug #9846 Inappropriate error displayed while dropping table from 'INFORMATION_SCHEMA' +# Bug#9846 Inappropriate error displayed while dropping table from 'INFORMATION_SCHEMA' # --error ER_PARSE_ERROR alter database information_schema; ---error 1044 +--error ER_DBACCESS_DENIED_ERROR drop database information_schema; ---error 1044 +--error ER_DBACCESS_DENIED_ERROR drop table information_schema.tables; ---error 1044 +--error ER_DBACCESS_DENIED_ERROR alter table information_schema.tables; # -# Bug #9683 INFORMATION_SCH: Creation of temporary table allowed in Information_schema DB +# Bug#9683 INFORMATION_SCH: Creation of temporary table allowed in Information_schema DB # use information_schema; ---error 1044 +--error ER_DBACCESS_DENIED_ERROR create temporary table schemata(f1 char(10)); # -# Bug #10708 SP's can use INFORMATION_SCHEMA as ROUTINE_SCHEMA +# Bug#10708 SP's can use INFORMATION_SCHEMA as ROUTINE_SCHEMA # delimiter |; --error ER_BAD_DB_ERROR @@ -723,11 +731,11 @@ END | delimiter ;| select ROUTINE_NAME from routines; # -# Bug #10734 Grant of privileges other than 'select' and 'create view' should fail on schema +# Bug#10734 Grant of privileges other than 'select' and 'create view' should fail on schema # ---error 1044 +--error ER_DBACCESS_DENIED_ERROR grant all on information_schema.* to 'user1'@'localhost'; ---error 1044 +--error ER_DBACCESS_DENIED_ERROR grant select on information_schema.* to 'user1'@'localhost'; # @@ -753,9 +761,9 @@ where table_name="v1"; drop view v1; # -# Bug #14387 SHOW COLUMNS doesn't work on temporary tables -# Bug #15224 SHOW INDEX from temporary table doesn't work -# Bug #12770 DESC cannot display the info. about temporary table +# Bug#14387 SHOW COLUMNS doesn't work on temporary tables +# Bug#15224 SHOW INDEX from temporary table doesn't work +# Bug#12770 DESC cannot display the info. about temporary table # create temporary table t1(f1 int, index(f1)); show columns from t1; @@ -839,6 +847,7 @@ connection con16681; select * from information_schema.views where table_name='v1' or table_name='v2'; connection default; +disconnect con16681; drop view v1, v2; drop table t1; drop user mysqltest_1@localhost; @@ -855,7 +864,7 @@ drop table t1,t2; # -# Bug#20230: routine_definition is not null +# Bug#20230 routine_definition is not null # --disable_warnings DROP PROCEDURE IF EXISTS p1; @@ -888,7 +897,7 @@ DROP PROCEDURE p1; DROP USER mysql_bug20230@localhost; # -# Bug#18925: subqueries with MIN/MAX functions on INFORMARTION_SCHEMA +# Bug#18925 subqueries with MIN/MAX functions on INFORMARTION_SCHEMA # SELECT t.table_name, c1.column_name @@ -921,8 +930,8 @@ SELECT t.table_name, c1.column_name ); # -# Bug#21231: query with a simple non-correlated subquery over -# INFORMARTION_SCHEMA.TABLES +# Bug#2123 query with a simple non-correlated subquery over +# INFORMARTION_SCHEMA.TABLES # SELECT MAX(table_name) FROM information_schema.tables; @@ -931,7 +940,7 @@ SELECT table_name from information_schema.tables FROM information_schema.tables); # -# Bug #23037: Bug in field "Default" of query "SHOW COLUMNS FROM table" +# Bug#23037 Bug in field "Default" of query "SHOW COLUMNS FROM table" # # Note, MyISAM/InnoDB can't take more that 65532 chars, because the row # size is limited to 65535 bytes (BLOBs not counted) @@ -975,7 +984,7 @@ DROP FUNCTION get_value; # -# Bug#22413: EXPLAIN SELECT FROM view with ORDER BY yield server crash +# Bug#22413 EXPLAIN SELECT FROM view with ORDER BY yield server crash # create view v1 as select table_schema as object_schema, @@ -1001,7 +1010,7 @@ drop table t1,t2; # -# Bug#24630 Subselect query crashes mysqld +# Bug#24630 Subselect query crashes mysqld # select 1 as f1 from information_schema.tables where "CHARACTER_SETS"= (select cast(table_name as char) from information_schema.tables @@ -1028,8 +1037,8 @@ group by t.table_name order by num1, t.table_name; # create table t1(f1 int); create view v1 as select f1+1 as a from t1; -create table t2 (f1 int, f2 int); -create view v2 as select f1+1 as a, f2 as b from t2; +create table t2 (f1 int, f2 int); +create view v2 as select f1+1 as a, f2 as b from t2; select table_name, is_updatable from information_schema.views; # # Note: we can perform 'delete' for non updatable view. @@ -1039,7 +1048,7 @@ drop view v1,v2; drop table t1,t2; # -# Bug#25859 ALTER DATABASE works w/o parameters +# Bug#25859 ALTER DATABASE works w/o parameters # --error ER_PARSE_ERROR alter database; @@ -1068,6 +1077,7 @@ show triggers; select trigger_name from information_schema.triggers where event_object_table='t1'; connection default; +disconnect con27629; drop user mysqltest_1@localhost; drop database mysqltest; @@ -1111,13 +1121,13 @@ select * from `information_schema`.`VIEWS` where `TABLE_NAME` = NULL; # # Bug#30079 A check for "hidden" I_S tables is flawed # ---error 1109 +--error ER_UNKNOWN_TABLE show fields from information_schema.table_names; ---error 1109 +--error ER_UNKNOWN_TABLE show keys from information_schema.table_names; # -# Bug#34529: Crash on complex Falcon I_S select after ALTER .. PARTITION BY +# Bug#34529 Crash on complex Falcon I_S select after ALTER .. PARTITION BY # USE information_schema; SET max_heap_table_size = 16384; @@ -1126,9 +1136,9 @@ CREATE TABLE test.t1( a INT ); # What we need to create here is a bit of a corner case: # We need a star query with information_schema tables, where the first -# branch of the star join produces zero rows, so that reading of the +# branch of the star join produces zero rows, so that reading of the # second branch never happens. At the same time we have to make sure -# that data for at least the last table is swapped from MEMORY/HEAP to +# that data for at least the last table is swapped from MEMORY/HEAP to # MyISAM. This and only this triggers the bug. SELECT * FROM tables ta diff --git a/mysql-test/t/multi_update.test b/mysql-test/t/multi_update.test index 2bb3b17340c..9f493189e6d 100644 --- a/mysql-test/t/multi_update.test +++ b/mysql-test/t/multi_update.test @@ -24,17 +24,17 @@ let $1 = 100; while ($1) { let $2 = 5; - eval insert into t1(t) values ('$1'); + eval insert into t1(t) values ('$1'); while ($2) { - eval insert into t2(id2,t) values ($1,'$2'); + eval insert into t2(id2,t) values ($1,'$2'); let $3 = 10; while ($3) { - eval insert into t3(id3,t) values ($1,'$2'); + eval insert into t3(id3,t) values ($1,'$2'); dec $3; } - dec $2; + dec $2; } dec $1; } @@ -79,11 +79,11 @@ let $1 = 1000; while ($1) { let $2 = 5; - eval insert into t1 values ($1,'aaaaaaaaaaaaaaaaaaaa'); + eval insert into t1 values ($1,'aaaaaaaaaaaaaaaaaaaa'); while ($2) { - eval insert into t2(id2,t) values ($1,'bbbbbbbbbbbbbbbbb'); - dec $2; + eval insert into t2(id2,t) values ($1,'bbbbbbbbbbbbbbbbb'); + dec $2; } dec $1; } @@ -317,7 +317,7 @@ update t2, t1 set t2.field=t1.field delete t1, t2 from t2 inner join t1 on t1.id1=t2.id2 where 0=1; -delete t1, t2 from t2,t1 +delete t1, t2 from t2,t1 where t1.id1=t2.id2 and 0=1; drop table t1,t2; @@ -351,7 +351,7 @@ create table `t2` (`c2_id` int(10) unsigned NULL auto_increment, `c2_p_id` int(1 insert into t1 values (0,'A01-Comp',1); insert into t1 values (0,'B01-Comp',1); insert into t2 values (0,1,'A Note',1); -update t1 left join t2 on p_id = c2_p_id set c2_note = 'asdf-1' where p_id = 2; +update t1 left join t2 on p_id = c2_p_id set c2_note = 'asdf-1' where p_id = 2; select * from t1; select * from t2; drop table t1, t2; @@ -379,6 +379,9 @@ revoke all privileges on mysqltest.t1 from mysqltest_1@localhost; revoke all privileges on mysqltest.* from mysqltest_1@localhost; delete from mysql.user where user=_binary'mysqltest_1'; drop database mysqltest; +connection default; +disconnect user1; +disconnect root; # # multi delete wrong table check @@ -393,7 +396,7 @@ drop table t1, t2, t3; # # multi* unique updating table check # -create table t1 (col1 int); +create table t1 (col1 int); create table t2 (col1 int); -- error ER_UPDATE_TABLE_USED update t1,t2 set t1.col1 = (select max(col1) from t1) where t1.col1 = t2.col1; @@ -401,16 +404,16 @@ update t1,t2 set t1.col1 = (select max(col1) from t1) where t1.col1 = t2.col1; delete t1 from t1,t2 where t1.col1 < (select max(col1) from t1) and t1.col1 = t2.col1; drop table t1,t2; -# Test for BUG#5837 - delete with outer join and const tables +# Test for Bug#5837 delete with outer join and const tables --disable_warnings create table t1 ( - aclid bigint not null primary key, - status tinyint(1) not null + aclid bigint not null primary key, + status tinyint(1) not null ) engine = innodb; create table t2 ( - refid bigint not null primary key, - aclid bigint, index idx_acl(aclid) + refid bigint not null primary key, + aclid bigint, index idx_acl(aclid) ) engine = innodb; --enable_warnings insert into t2 values(1,null); @@ -418,7 +421,7 @@ delete t2, t1 from t2 left join t1 on (t2.aclid=t1.aclid) where t2.refid='1'; drop table t1, t2; # -# Bug#19225: unchecked error leads to server crash +# Bug#19225 unchecked error leads to server crash # create table t1(a int); create table t2(a int); @@ -428,7 +431,7 @@ drop table t1, t2; # End of 4.1 tests # -# Test for bug #1980. +# Test for Bug#1980. # --disable_warnings create table t1 ( c char(8) not null ) engine=innodb; @@ -484,9 +487,12 @@ send alter table t1 add column c int default 100 after a; connect (updater,localhost,root,,test); connection updater; +# Wait till "alter table t1 ..." is in work. +sleep 2; send update t1, v1 set t1.b=t1.a+t1.b+v1.b where t1.a=v1.a; connection locker; +# Wait till "update t1, v1 ..." is in work. sleep 2; unlock tables; @@ -500,8 +506,14 @@ select * from t2; drop view v1; drop table t1, t2; +connection default; +disconnect locker; +disconnect changer; +disconnect updater; + + # -# Bug#27716 multi-update did partially and has not binlogged +# Bug#27716 multi-update did partially and has not binlogged # CREATE TABLE `t1` ( @@ -536,11 +548,12 @@ reset master; UPDATE t2,t1 SET t2.a=t2.b where t2.a=t1.a; show master status /* there must be the UPDATE query event */; -# cleanup bug#27716 +# cleanup drop table t1, t2; + # -# Bug #29136 erred multi-delete on trans table does not rollback +# Bug#29136 erred multi-delete on trans table does not rollback # # prepare @@ -569,7 +582,7 @@ select count(*) from t3 /* must be 1 */; # the query must be in binlog (no surprise though) source include/show_binlog_events.inc; -# cleanup bug#29136 +# cleanup drop table t1, t2, t3; diff --git a/mysql-test/t/overflow.test b/mysql-test/t/overflow.test index a62ef9c4cd2..774c43be658 100644 --- a/mysql-test/t/overflow.test +++ b/mysql-test/t/overflow.test @@ -1,6 +1,14 @@ +# Save the initial number of concurrent sessions +--source include/count_sessions.inc + connect (con1,localhost,root,,); connection con1; --- error 1064,1102,1280 +--error ER_PARSE_ERROR,ER_WRONG_DB_NAME,ER_WRONG_NAME_FOR_INDEX drop database AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA; +connection default; +disconnect con1; # End of 4.1 tests + +# Wait till we reached the initial number of concurrent sessions +--source include/wait_until_count_sessions.inc diff --git a/mysql-test/t/packet.test b/mysql-test/t/packet.test index 4de284b7824..6210e9986ad 100644 --- a/mysql-test/t/packet.test +++ b/mysql-test/t/packet.test @@ -4,12 +4,18 @@ # swallowing them and returning an error --source include/not_windows.inc +# Save the initial number of concurrent sessions +--source include/count_sessions.inc + + # # Check protocol handling # -connect (con1,localhost,root,,); +set @max_allowed_packet=@@global.max_allowed_packet; +set @net_buffer_length=@@global.net_buffer_length; +connect (con1,localhost,root,,); connection con1; set global max_allowed_packet=100; set max_allowed_packet=100; @@ -19,6 +25,8 @@ set net_buffer_length=100; SELECT length("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa") as len; # Should return NULL as 2000 is bigger than max_allowed_packet select repeat('a',2000); +connection default; +disconnect con1; # # Connection 2 should get error for too big packets @@ -26,7 +34,7 @@ select repeat('a',2000); connect (con2,localhost,root,,); connection con2; select @@net_buffer_length, @@max_allowed_packet; ---error 1153 +--error ER_NET_PACKET_TOO_LARGE SELECT length("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa") as len; set global max_allowed_packet=default; set max_allowed_packet=default; @@ -34,5 +42,13 @@ set global net_buffer_length=default; set net_buffer_length=default; SELECT length("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa") as len; select length(repeat('a',2000)); +connection default; +disconnect con2; + +set global max_allowed_packet=@max_allowed_packet; +set global net_buffer_length=@net_buffer_length; # End of 4.1 tests + +# Wait till we reached the initial number of concurrent sessions +--source include/wait_until_count_sessions.inc diff --git a/mysql-test/t/query_cache_notembedded.test b/mysql-test/t/query_cache_notembedded.test index 421ec913e5d..b8b223ecd8c 100644 --- a/mysql-test/t/query_cache_notembedded.test +++ b/mysql-test/t/query_cache_notembedded.test @@ -1,6 +1,10 @@ -- source include/have_query_cache.inc -- source include/not_embedded.inc +# Save the initial number of concurrent sessions +--source include/count_sessions.inc + + # # Tests with query cache # @@ -79,7 +83,7 @@ show status like "Qcache_free_blocks"; drop table t1, t2, t3, t11, t21; # -# do not use QC if tables locked (BUG#12385) +# do not use QC if tables locked (Bug#12385) # connect (root,localhost,root,,test,$MASTER_MYPORT,$MASTER_MYSOCK); connection root; @@ -96,10 +100,13 @@ SELECT * FROM t1; connection root; SELECT * FROM t1; drop table t1; +connection default; +disconnect root; +disconnect root2; # -# query in QC from normal execution and SP (BUG#6897) -# improved to also test BUG#3583 and BUG#12990 +# query in QC from normal execution and SP (Bug#6897) +# improved to also test Bug#3583 and Bug#12990 # flush query cache; reset query cache; @@ -181,7 +188,7 @@ drop procedure f4; drop table t1; # -# bug#14767: INSERT in SF + concurrent SELECT with query cache +# Bug#14767 INSERT in SF + concurrent SELECT with query cache # reset query cache; --disable_warnings @@ -223,4 +230,36 @@ connection default; set GLOBAL query_cache_size=0; +# +# Bug#40264: Aborted cached query causes query to hang indefinitely on next cache hit +# + +--disable_warnings +DROP TABLE IF EXISTS t1; +--enable_warnings + +FLUSH STATUS; +SET GLOBAL query_cache_size=1048576; +CREATE TABLE t1 (a INT); +INSERT INTO t1 VALUES (1),(2),(3),(4),(5); +SHOW STATUS LIKE 'Qcache_queries_in_cache'; +LOCK TABLES t1 WRITE; +connect(con1,localhost,root,,); +--send SELECT * FROM t1 +connection default; +let $show_type= open tables where `table`='t1' and in_use=2; +let $show_pattern= '%t1%2%'; +--source include/wait_show_pattern.inc +dirty_close con1; +UNLOCK TABLES; +let $show_type= open tables where `table`='t1' and in_use=0; +let $show_pattern= '%t1%0%'; +--source include/wait_show_pattern.inc +SHOW STATUS LIKE 'Qcache_queries_in_cache'; +DROP TABLE t1; +SET GLOBAL query_cache_size= default; + # End of 5.0 tests + +# Wait till we reached the initial number of concurrent sessions +#--source include/wait_until_count_sessions.inc diff --git a/mysql-test/t/sp-threads.test b/mysql-test/t/sp-threads.test index d8a8ce5dae7..e1012e2b72d 100644 --- a/mysql-test/t/sp-threads.test +++ b/mysql-test/t/sp-threads.test @@ -5,6 +5,9 @@ # except security/privilege tests, they go to sp-security.test # +# Save the initial number of concurrent sessions +--source include/count_sessions.inc + connect (con1root,localhost,root,,); connect (con2root,localhost,root,,); connect (con3root,localhost,root,,); @@ -17,7 +20,7 @@ drop table if exists t1; --enable_warnings create table t1 (s1 int, s2 int, s3 int); -delimiter //; +delimiter //; create procedure bug4934() begin insert into t1 values (1,0,1); @@ -38,7 +41,7 @@ drop table t1; create table t1 (s1 int, s2 int, s3 int); drop procedure bug4934; -delimiter //; +delimiter //; create procedure bug4934() begin end// @@ -58,7 +61,7 @@ drop procedure bug4934; # -# BUG #9486 "Can't perform multi-update in stored procedure" +# Bug#9486 Can't perform multi-update in stored procedure # --disable_warnings drop procedure if exists bug9486; @@ -87,8 +90,9 @@ reap; drop procedure bug9486; drop table t1, t2; + # -# BUG#11158: Can't perform multi-delete in stored procedure +# Bug#11158 Can't perform multi-delete in stored procedure # --disable_warnings drop procedure if exists bug11158; @@ -114,8 +118,9 @@ connection con1root; drop procedure bug11158; drop table t1, t2; + # -# BUG#11554: Server crashes on statement indirectly using non-cached function +# Bug#11554 Server crashes on statement indirectly using non-cached function # --disable_warnings drop function if exists bug11554; @@ -134,7 +139,7 @@ drop table t1; drop view v1; -# BUG#12228 +# Bug#12228 Crash happens during calling specific SP in multithread environment --disable_warnings drop procedure if exists p1; drop procedure if exists p2; @@ -168,18 +173,26 @@ connection con2root; unlock tables; connection con1root; -# Crash will be here if we hit BUG#12228 +# Crash will be here if we hit Bug#12228 reap; drop procedure p1; drop procedure p2; drop table t1; + # -# BUG#NNNN: New bug synopsis +# Bug#NNNN New bug synopsis # #--disable_warnings #drop procedure if exists bugNNNN; #--enable_warnings #create procedure bugNNNN... +connection default; +disconnect con1root; +disconnect con2root; +disconnect con3root; + +# Wait till we reached the initial number of concurrent sessions +--source include/wait_until_count_sessions.inc diff --git a/mysql-test/t/subselect.test b/mysql-test/t/subselect.test index ea911e4912d..57aaa00e643 100644 --- a/mysql-test/t/subselect.test +++ b/mysql-test/t/subselect.test @@ -78,9 +78,9 @@ select * from t2 where t2.b=(select a from t3 order by 1 desc limit 1); (select * from t2 where t2.b=(select a from t3 order by 1 desc limit 1)) union (select * from t4 where t4.b=(select max(t2.a)*4 from t2) order by a); explain extended (select * from t2 where t2.b=(select a from t3 order by 1 desc limit 1)) union (select * from t4 where t4.b=(select max(t2.a)*4 from t2) order by a); select (select a from t3 where a1) as tt; -explain extended select (select t3.a from t3 where a<8 order by 1 desc limit 1), a from +explain extended select (select t3.a from t3 where a<8 order by 1 desc limit 1), a from (select * from t2 where a>1) as tt; select * from t1 where t1.a=(select t2.a from t2 where t2.b=(select max(a) from t3) order by 1 desc limit 1); select * from t1 where t1.a=(select t2.a from t2 where t2.b=(select max(a) from t3 where t3.a > t1.a) order by 1 desc limit 1); @@ -536,7 +536,7 @@ do (SELECT a from t1); -- error ER_NO_SUCH_TABLE set @a:=(SELECT a from t1); -CREATE TABLE t1 (a int, KEY(a)); +CREATE TABLE t1 (a int, KEY(a)); HANDLER t1 OPEN; -- error ER_PARSE_ERROR HANDLER t1 READ a=((SELECT 1)); @@ -678,7 +678,7 @@ CREATE TABLE t2 ( INSERT INTO t2 VALUES ('AUS','Australia','Oceania','Australia and New Zealand',7741220.00,1901,18886000,79.8,351182.00,392911.00,'Australia','Constitutional Monarchy, Federation','Elisabeth II',135,'AU'); INSERT INTO t2 VALUES ('AZE','Azerbaijan','Asia','Middle East',86600.00,1991,7734000,62.9,4127.00,4100.00,'Azärbaycan','Federal Republic','Heydär Äliyev',144,'AZ'); -select t2.Continent, t1.Name, t1.Population from t2 LEFT JOIN t1 ON t2.Code = t1.t2 where t1.Population IN (select max(t1.Population) AS Population from t1, t2 where t1.t2 = t2.Code group by Continent); +select t2.Continent, t1.Name, t1.Population from t2 LEFT JOIN t1 ON t2.Code = t1.t2 where t1.Population IN (select max(t1.Population) AS Population from t1, t2 where t1.t2 = t2.Code group by Continent); drop table t1, t2; @@ -732,9 +732,9 @@ drop table t1,t2; # # correct NULL in IN (SELECT ...) # -create table t1 (a int, unique index indexa (a)); -insert into t1 values (-1), (-4), (-2), (NULL); -select -10 IN (select a from t1 FORCE INDEX (indexa)); +create table t1 (a int, unique index indexa (a)); +insert into t1 values (-1), (-4), (-2), (NULL); +select -10 IN (select a from t1 FORCE INDEX (indexa)); drop table t1; # @@ -816,7 +816,7 @@ disable_query_log; let $1 = 10000; while ($1) { - eval insert into t1 values (rand()*100000+200,rand()*100000); + eval insert into t1 values (rand()*100000+200,rand()*100000); dec $1; } enable_query_log; @@ -842,7 +842,7 @@ create table t2 (a int, b int); create table t3 (a int, b int); insert into t1 values (0,100),(1,2), (1,3), (2,2), (2,7), (2,-1), (3,10); insert into t2 values (0,0), (1,1), (2,1), (3,1), (4,1); -insert into t3 values (3,3), (2,2), (1,1); +insert into t3 values (3,3), (2,2), (1,1); select a,(select count(distinct t1.b) as sum from t1,t2 where t1.a=t2.a and t2.b > 0 and t1.a <= t3.b group by t1.a order by sum limit 1) from t3; drop table t1,t2,t3; @@ -1010,7 +1010,7 @@ drop table t1, t2; # # unresolved field error # -create table t1 (s1 int); +create table t1 (s1 int); create table t2 (s1 int); -- error ER_BAD_FIELD_ERROR select * from t1 where (select count(*) from t2 where t1.s2) = 1; @@ -1035,11 +1035,12 @@ INSERT INTO t1 VALUES (1),(1),(1),(1),(1),(2),(3),(4),(5); SELECT DISTINCT (SELECT a) FROM t1 LIMIT 100; DROP TABLE t1; + # -# Bug 2198 +# Bug#2198 SELECT INTO OUTFILE (with Sub-Select) Problem # -create table t1 (a int, b decimal(13, 3)); +create table t1 (a int, b decimal(13, 3)); insert into t1 values (1, 0.123); let $outfile = $MYSQLTEST_VARDIR/master-data/test/subselect.out.file.1; --error 0,1 @@ -1051,8 +1052,9 @@ load data infile "subselect.out.file.1" into table t1; select * from t1; drop table t1; + # -# Bug 2479 +# Bug#2479 dependant subquery with limit crash # CREATE TABLE `t1` ( @@ -1090,8 +1092,9 @@ select 2 in (select * from t1); SET SQL_SELECT_LIMIT=default; drop table t1; + # -# Bug #3118: subselect + order by +# Bug#3118 subselect + order by # CREATE TABLE t1 (a int, b int, INDEX (a)); @@ -1130,8 +1133,9 @@ insert into t1 values (1); explain select benchmark(1000, (select a from t1 where a=sha(rand()))); drop table t1; + # -# bug 3188 +# Bug#3188 Ambiguous Column in Subselect crashes server # create table t1(id int); create table t2(id int); @@ -1140,8 +1144,9 @@ create table t3(flag int); select (select * from t3 where id not null) from t1, t2; drop table t1,t2,t3; + # -# aggregate functions (Bug #3505) +# aggregate functions (Bug#3505 Wrong results on use of ORDER BY with subqueries) # CREATE TABLE t1 (id INT); CREATE TABLE t2 (id INT); @@ -1332,8 +1337,9 @@ select * from t1 up where exists (select * from t1 where t1.a=up.a); explain extended select * from t1 up where exists (select * from t1 where t1.a=up.a); drop table t1; + # -# Bug #4102: subselect in HAVING +# Bug#4102 subselect in HAVING # CREATE TABLE t1 (t1_a int); @@ -1344,8 +1350,10 @@ SELECT * FROM t1, t2 table2 WHERE t1_a = 1 AND table2.t2_a = 1 HAVING table2.t2_b = (SELECT MAX(t2_b) FROM t2 WHERE t2_a = table2.t2_a); DROP TABLE t1, t2; + # -# Test problem with NULL and derived tables (Bug #4097) +# Test problem with NULL and derived tables +# (Bug#4097 JOIN with subquery causes entire column to report NULL) # CREATE TABLE t1 (id int(11) default NULL,name varchar(10) default NULL); @@ -1355,18 +1363,19 @@ INSERT INTO t2 VALUES (1,'Fido'),(2,'Spot'),(3,'Felix'); SELECT a.*, b.* FROM (SELECT * FROM t1) AS a JOIN t2 as b on a.id=b.id; drop table t1,t2; + # # outer fields resolving in INSERT/REPLACE and CRETE with SELECT # CREATE TABLE t1 ( a int, b int ); CREATE TABLE t2 ( c int, d int ); INSERT INTO t1 VALUES (1,2), (2,3), (3,4); -SELECT a AS abc, b FROM t1 outr WHERE b = +SELECT a AS abc, b FROM t1 outr WHERE b = (SELECT MIN(b) FROM t1 WHERE a=outr.a); -INSERT INTO t2 SELECT a AS abc, b FROM t1 outr WHERE b = +INSERT INTO t2 SELECT a AS abc, b FROM t1 outr WHERE b = (SELECT MIN(b) FROM t1 WHERE a=outr.a); select * from t2; -CREATE TABLE t3 SELECT a AS abc, b FROM t1 outr WHERE b = +CREATE TABLE t3 SELECT a AS abc, b FROM t1 outr WHERE b = (SELECT MIN(b) FROM t1 WHERE a=outr.a); select * from t3; prepare stmt1 from "INSERT INTO t2 SELECT a AS abc, b FROM t1 outr WHERE b = (SELECT MIN(b) FROM t1 WHERE a=outr.a);"; @@ -1390,19 +1399,21 @@ insert into t2 values (1,2); select t000.a, count(*) `C` FROM t1 t000 GROUP BY t000.a HAVING count(*) > ALL (SELECT count(*) FROM t2 t001 WHERE t001.a=1); drop table t1,t2; -# -# BUG#4769 - fulltext in subselect -# -create table t1 (a int not null auto_increment primary key, b varchar(40), fulltext(b)); -insert into t1 (b) values ('ball'),('ball games'), ('games'), ('foo'), ('foobar'), ('Serg'), ('Sergei'),('Georg'), ('Patrik'),('Hakan'); -create table t2 (a int); -insert into t2 values (1),(3),(2),(7); -select a,b from t1 where match(b) against ('Ball') > 0; -select a from t2 where a in (select a from t1 where match(b) against ('Ball') > 0); -drop table t1,t2; # -# BUG#5003 - like in subselect +# Bug#4769 - fulltext in subselect +# +create table t1 (a int not null auto_increment primary key, b varchar(40), fulltext(b)); +insert into t1 (b) values ('ball'),('ball games'), ('games'), ('foo'), ('foobar'), ('Serg'), ('Sergei'),('Georg'), ('Patrik'),('Hakan'); +create table t2 (a int); +insert into t2 values (1),(3),(2),(7); +select a,b from t1 where match(b) against ('Ball') > 0; +select a from t2 where a in (select a from t1 where match(b) against ('Ball') > 0); +drop table t1,t2; + + +# +# Bug#5003 - like in subselect # CREATE TABLE t1(`IZAVORGANG_ID` VARCHAR(11) CHARACTER SET latin1 COLLATE latin1_bin,`KUERZEL` VARCHAR(10) CHARACTER SET latin1 COLLATE latin1_bin,`IZAANALYSEART_ID` VARCHAR(11) CHARACTER SET latin1 COLLATE latin1_bin,`IZAPMKZ_ID` VARCHAR(11) CHARACTER SET latin1 COLLATE latin1_bin); CREATE INDEX AK01IZAVORGANG ON t1(izaAnalyseart_id,Kuerzel); @@ -1459,10 +1470,10 @@ SELECT b.sc FROM (SELECT (SELECT a.access FROM t1 a WHERE a.map = op.map AND a.s SELECT b.ac FROM (SELECT (SELECT a.access FROM t1 a WHERE a.map = op.map AND a.slave = op.pid AND a.master = 1) ac FROM t2 op WHERE op.id = 12 AND op.map = 0) b; drop tables t1,t2; + # -# Test for bug #6462. "Same request on same data returns different -# results." a.k.a. "Proper cleanup of subqueries is missing for -# SET and DO statements". +# Test for Bug#6462 Same request on same data returns different results +# a.k.a. "Proper cleanup of subqueries is missing for SET and DO statements". # create table t1 (a int not null, b int not null, c int, primary key (a,b)); insert into t1 values (1,1,1), (2,2,2), (3,3,3); @@ -1484,9 +1495,11 @@ drop table t1; connect (root,localhost,root,,test,$MASTER_MYPORT,$MASTER_MYSOCK); connection root; set @got_val= (SELECT 1 FROM (SELECT 'A' as my_col) as T1 ) ; +connection default; +disconnect root; # -# primary query with temporary table and subquery with groupping +# primary query with temporary table and subquery with grouping # create table t1 (a int, b int); create table t2 (a int, b int); @@ -1547,14 +1560,15 @@ INSERT INTO t1 VALUES ('ASM','American Samoa','Oceania','Polynesia',199.00,0,680 INSERT INTO t1 VALUES ('ATF','French Southern territories','Antarctica','Antarctica',7780.00,0,0,NULL,0.00,NULL,'Terres australes françaises','Nonmetropolitan Territory of France','Jacques Chirac',NULL,'TF'); INSERT INTO t1 VALUES ('UMI','United States Minor Outlying Islands','Oceania','Micronesia/Caribbean',16.00,0,0,NULL,0.00,NULL,'United States Minor Outlying Islands','Dependent Territory of the US','George W. Bush',NULL,'UM'); /*!40000 ALTER TABLE t1 ENABLE KEYS */; -SELECT DISTINCT Continent AS c FROM t1 outr WHERE - Code <> SOME ( SELECT Code FROM t1 WHERE Continent = outr.Continent AND +SELECT DISTINCT Continent AS c FROM t1 outr WHERE + Code <> SOME ( SELECT Code FROM t1 WHERE Continent = outr.Continent AND Population < 200); drop table t1; + # -# Test for BUG#7885: Server crash when 'any' subselect compared to -# non-existant field. +# Test for Bug#7885 Server crash when 'any' subselect compared to +# non-existant field. # create table t1 (a1 int); create table t2 (b1 int); @@ -1603,8 +1617,9 @@ select 1 = ALL (select 1 from t1 where 1 = xx ), 1 as xx; select 1 = ALL (select 1 from t1 where 1 = xx ), 1 as xx from DUAL; drop table t1; + # -# Test for BUG#8218 +# Test for Bug#8218 Join does not pass string from right table # CREATE TABLE t1 ( categoryId int(11) NOT NULL, @@ -1674,38 +1689,39 @@ select count(distinct t2.userid) pass, groupstuff.*, count(t2.courseid) crse, - t1.categoryid, + t1.categoryid, t2.courseid, date_format(date, '%b%y') as colhead -from t2 -join t1 on t2.courseid=t1.courseid +from t2 +join t1 on t2.courseid=t1.courseid join ( - select - t5.userid, - parentid, - parentgroup, - childid, - groupname, - grouptypeid - from t5 - join + select + t5.userid, + parentid, + parentgroup, + childid, + groupname, + grouptypeid + from t5 + join ( - select t4.id as parentid, - t4.name as parentgroup, - t4.id as childid, - t4.name as groupname, - t4.grouptypeid - from t4 - ) as gin on t5.groupid=gin.childid -) as groupstuff on t2.userid = groupstuff.userid -group by + select t4.id as parentid, + t4.name as parentgroup, + t4.id as childid, + t4.name as groupname, + t4.grouptypeid + from t4 + ) as gin on t5.groupid=gin.childid +) as groupstuff on t2.userid = groupstuff.userid +group by groupstuff.groupname, colhead , t2.courseid; drop table t1, t2, t3, t4, t5; + # -# Transformation in left expression of subquery (BUG#8888) +# Transformation in left expression of subquery (Bug#8888) # create table t1 (a int); insert into t1 values (1), (2), (3); @@ -1750,8 +1766,9 @@ select (1,2,3) = (select * from t1); select (select * from t1) = (1,2,3); drop table t1; + # -# Item_int_with_ref check (BUG#10020) +# Item_int_with_ref check (Bug#10020) # CREATE TABLE `t1` ( `itemid` bigint(20) unsigned NOT NULL auto_increment, @@ -1774,15 +1791,16 @@ INSERT INTO `t2` VALUES (1, 1, 1, '10.10.10.1'); SELECT s.ip, count( e.itemid ) FROM `t1` e JOIN t2 s ON s.sessionid = e.sessionid WHERE e.sessionid = ( SELECT sessionid FROM t2 ORDER BY sessionid DESC LIMIT 1 ) GROUP BY s.ip HAVING count( e.itemid ) >0 LIMIT 0 , 30; drop tables t1,t2; -# BUG#11821 : Select from subselect using aggregate function on an enum -# segfaults: + +# Bug#11821 Select from subselect using aggregate function on an enum segfaults create table t1 (fld enum('0','1')); insert into t1 values ('1'); select * from (select max(fld) from t1) as foo; drop table t1; + # -# Bug #11867: queries with ROW(,elems>) IN (SELECT DISTINCT FROM ...) +# Bug#11867 queries with ROW(,elems>) IN (SELECT DISTINCT FROM ...) # CREATE TABLE t1 (one int, two int, flag char(1)); @@ -1812,8 +1830,9 @@ explain extended SELECT one,two from t1 where ROW(one,two) IN (SELECT one,two FR explain extended SELECT one,two,ROW(one,two) IN (SELECT one,two FROM t2 WHERE flag = '0' group by one,two) as 'test' from t1; DROP TABLE t1,t2; + # -# Bug #12392: where cond with IN predicate for rows and NULL values in table +# Bug#12392 where cond with IN predicate for rows and NULL values in table # CREATE TABLE t1 (a char(5), b char(5)); @@ -1823,8 +1842,9 @@ SELECT * FROM t1 WHERE (a,b) IN (('aaa','aaa'), ('aaa','bbb')); DROP TABLE t1; + # -# Bug #11479: subquery over left join with an empty inner table +# Bug#11479 subquery over left join with an empty inner table # CREATE TABLE t1 (a int); @@ -1841,9 +1861,10 @@ SELECT * FROM t1 DROP TABLE t1,t2,t3; + # -# Bug#18503: Queries with a quantified subquery returning empty set may -# return a wrong result. +# Bug#18503 Queries with a quantified subquery returning empty set may +# return a wrong result. # CREATE TABLE t1 (f1 INT); CREATE TABLE t2 (f2 INT); @@ -1855,8 +1876,9 @@ INSERT INTO t2 VALUES (2); SELECT * FROM t1 WHERE f1 > ALL (SELECT f2 FROM t2 WHERE f2=0); DROP TABLE t1, t2; + # -# Bug#16302: Quantified subquery without any tables gives wrong results +# Bug#16302 Quantified subquery without any tables gives wrong results # select 1 from dual where 1 < any (select 2); select 1 from dual where 1 < all (select 2); @@ -1865,7 +1887,8 @@ select 1 from dual where 2 > all (select 1); select 1 from dual where 1 < any (select 2 from dual); select 1 from dual where 1 < all (select 2 from dual where 1!=1); -# BUG#20975 Wrong query results for subqueries within NOT + +# Bug#20975 Wrong query results for subqueries within NOT create table t1 (s1 char); insert into t1 values (1),(2); @@ -1882,8 +1905,9 @@ select * from t1 where (s1 = ALL (select s1/s1 from t1)); select * from t1 where NOT(s1 = ALL (select s1/s1 from t1)); drop table t1; + # -# Bug #16255: Subquery in where +# Bug#16255 Subquery in where # create table t1 ( retailerID varchar(8) NOT NULL, @@ -1899,15 +1923,16 @@ INSERT INTO t1 VALUES("0037", "2", "2006-01-06 12:25:53"); INSERT INTO t1 VALUES("0048", "1", "2006-01-06 12:37:50"); INSERT INTO t1 VALUES("0059", "1", "2006-01-06 12:37:50"); -select * from t1 r1 - where (r1.retailerID,(r1.changed)) in - (SELECT r2.retailerId,(max(changed)) from t1 r2 +select * from t1 r1 + where (r1.retailerID,(r1.changed)) in + (SELECT r2.retailerId,(max(changed)) from t1 r2 group by r2.retailerId); drop table t1; + # -# Bug #21180: Subselect with index for both WHERE and ORDER BY -# produces empty result +# Bug#21180 Subselect with index for both WHERE and ORDER BY +# produces empty result # create table t1(a int, primary key (a)); insert into t1 values (10); @@ -1915,38 +1940,39 @@ insert into t1 values (10); create table t2 (a int primary key, b varchar(32), c int, unique key b(c, b)); insert into t2(a, c, b) values (1,10,'359'), (2,10,'35988'), (3,10,'35989'); -explain SELECT sql_no_cache t1.a, r.a, r.b FROM t1 LEFT JOIN t2 r - ON r.a = (SELECT t2.a FROM t2 WHERE t2.c = t1.a AND t2.b <= '359899' +explain SELECT sql_no_cache t1.a, r.a, r.b FROM t1 LEFT JOIN t2 r + ON r.a = (SELECT t2.a FROM t2 WHERE t2.c = t1.a AND t2.b <= '359899' ORDER BY t2.c DESC, t2.b DESC LIMIT 1) WHERE t1.a = 10; -SELECT sql_no_cache t1.a, r.a, r.b FROM t1 LEFT JOIN t2 r - ON r.a = (SELECT t2.a FROM t2 WHERE t2.c = t1.a AND t2.b <= '359899' +SELECT sql_no_cache t1.a, r.a, r.b FROM t1 LEFT JOIN t2 r + ON r.a = (SELECT t2.a FROM t2 WHERE t2.c = t1.a AND t2.b <= '359899' ORDER BY t2.c DESC, t2.b DESC LIMIT 1) WHERE t1.a = 10; -explain SELECT sql_no_cache t1.a, r.a, r.b FROM t1 LEFT JOIN t2 r - ON r.a = (SELECT t2.a FROM t2 WHERE t2.c = t1.a AND t2.b <= '359899' +explain SELECT sql_no_cache t1.a, r.a, r.b FROM t1 LEFT JOIN t2 r + ON r.a = (SELECT t2.a FROM t2 WHERE t2.c = t1.a AND t2.b <= '359899' ORDER BY t2.c, t2.b LIMIT 1) WHERE t1.a = 10; -SELECT sql_no_cache t1.a, r.a, r.b FROM t1 LEFT JOIN t2 r - ON r.a = (SELECT t2.a FROM t2 WHERE t2.c = t1.a AND t2.b <= '359899' +SELECT sql_no_cache t1.a, r.a, r.b FROM t1 LEFT JOIN t2 r + ON r.a = (SELECT t2.a FROM t2 WHERE t2.c = t1.a AND t2.b <= '359899' ORDER BY t2.c, t2.b LIMIT 1) WHERE t1.a = 10; drop table t1,t2; + # -# Bug #21853: assert failure for a grouping query with -# an ALL/ANY quantified subquery in HAVING +# Bug#21853 assert failure for a grouping query with +# an ALL/ANY quantified subquery in HAVING # -CREATE TABLE t1 ( - field1 int NOT NULL, - field2 int NOT NULL, - field3 int NOT NULL, - PRIMARY KEY (field1,field2,field3) +CREATE TABLE t1 ( + field1 int NOT NULL, + field2 int NOT NULL, + field3 int NOT NULL, + PRIMARY KEY (field1,field2,field3) +); +CREATE TABLE t2 ( + fieldA int NOT NULL, + fieldB int NOT NULL, + PRIMARY KEY (fieldA,fieldB) ); -CREATE TABLE t2 ( - fieldA int NOT NULL, - fieldB int NOT NULL, - PRIMARY KEY (fieldA,fieldB) -); INSERT INTO t1 VALUES (1,1,1), (1,1,2), (1,2,1), (1,2,2), (1,2,3), (1,3,1); @@ -1958,19 +1984,20 @@ SELECT field1, field2, COUNT(*) SELECT field1, field2 FROM t1 GROUP BY field1, field2 - HAVING COUNT(*) >= ALL (SELECT fieldB + HAVING COUNT(*) >= ALL (SELECT fieldB FROM t2 WHERE fieldA = field1); SELECT field1, field2 FROM t1 GROUP BY field1, field2 - HAVING COUNT(*) < ANY (SELECT fieldB + HAVING COUNT(*) < ANY (SELECT fieldB FROM t2 WHERE fieldA = field1); DROP TABLE t1, t2; + # -# Bug #23478: not top-level IN subquery returning a non-empty result set -# with possible NULL values by index access from the outer query +# Bug#23478 not top-level IN subquery returning a non-empty result set +# with possible NULL values by index access from the outer query # CREATE TABLE t1(a int, INDEX (a)); @@ -1985,24 +2012,26 @@ SELECT a, a IN (SELECT a FROM t1) FROM t2; DROP TABLE t1,t2; + # -# Bug #11302: getObject() returns a String for a sub-query of type datetime +# Bug#11302 getObject() returns a String for a sub-query of type datetime # CREATE TABLE t1 (a DATETIME); INSERT INTO t1 VALUES ('1998-09-23'), ('2003-03-25'); -CREATE TABLE t2 AS SELECT - (SELECT a FROM t1 WHERE a < '2000-01-01') AS sub_a +CREATE TABLE t2 AS SELECT + (SELECT a FROM t1 WHERE a < '2000-01-01') AS sub_a FROM t1 WHERE a > '2000-01-01'; SHOW CREATE TABLE t2; -CREATE TABLE t3 AS (SELECT a FROM t1 WHERE a < '2000-01-01') UNION (SELECT a FROM t1 WHERE a > '2000-01-01'); +CREATE TABLE t3 AS (SELECT a FROM t1 WHERE a < '2000-01-01') UNION (SELECT a FROM t1 WHERE a > '2000-01-01'); SHOW CREATE TABLE t3; DROP TABLE t1,t2,t3; + # -# Bug 24670: subquery witout tables but with a WHERE clause +# Bug24670 subquery witout tables but with a WHERE clause # CREATE TABLE t1 (a int); @@ -2014,9 +2043,10 @@ EXPLAIN SELECT a FROM t1 WHERE (SELECT 1 FROM DUAL WHERE 1=0) IS NULL; DROP TABLE t1; + # -# Bug 24653: sorting by expressions containing subselects -# that return more than one row +# Bug#24653 sorting by expressions containing subselects +# that return more than one row # CREATE TABLE t1 (a int); @@ -2099,8 +2129,9 @@ select * from t1; select min(a) from t1 group by grp; drop table t1; + # -# Test for bug #9338: lame substitution of c1 instead of c2 +# Test for Bug#9338 lame substitution of c1 instead of c2 # CREATE table t1 ( c1 integer ); @@ -2120,15 +2151,16 @@ SELECT * FROM t1 LEFT JOIN t2 ON c1 = c2 DROP TABLE t1,t2; + # -# Test for bug #9516: wrong evaluation of not_null_tables attribute in SQ +# Test for Bug#9516 wrong evaluation of not_null_tables attribute in SQ # CREATE TABLE t1 ( c1 integer ); INSERT INTO t1 VALUES ( 1 ); INSERT INTO t1 VALUES ( 2 ); INSERT INTO t1 VALUES ( 3 ); -INSERT INTO t1 VALUES ( 6 ); - +INSERT INTO t1 VALUES ( 6 ); + CREATE TABLE t2 ( c2 integer ); INSERT INTO t2 VALUES ( 1 ); INSERT INTO t2 VALUES ( 4 ); @@ -2139,13 +2171,14 @@ CREATE TABLE t3 ( c3 integer ); INSERT INTO t3 VALUES ( 7 ); INSERT INTO t3 VALUES ( 8 ); -SELECT c1,c2 FROM t1 LEFT JOIN t2 ON c1 = c2 +SELECT c1,c2 FROM t1 LEFT JOIN t2 ON c1 = c2 WHERE EXISTS (SELECT c3 FROM t3 WHERE c2 IS NULL ); DROP TABLE t1,t2,t3; + # -# Item_int_with_ref check (BUG#10020) +# Item_int_with_ref check (Bug#10020) # CREATE TABLE `t1` ( `itemid` bigint(20) unsigned NOT NULL auto_increment, @@ -2168,9 +2201,10 @@ INSERT INTO `t2` VALUES (1, 1, 1, '10.10.10.1'); SELECT s.ip, count( e.itemid ) FROM `t1` e JOIN t2 s ON s.sessionid = e.sessionid WHERE e.sessionid = ( SELECT sessionid FROM t2 ORDER BY sessionid DESC LIMIT 1 ) GROUP BY s.ip HAVING count( e.itemid ) >0 LIMIT 0 , 30; drop tables t1,t2; + # # Correct building of equal fields list (do not include outer -# fields) (BUG#6384) +# fields) (Bug#6384) # CREATE TABLE t1 (EMPNUM CHAR(3)); CREATE TABLE t2 (EMPNUM CHAR(3) ); @@ -2184,44 +2218,46 @@ WHERE t1.EMPNUM NOT IN select * from t1; DROP TABLE t1,t2; + # -# Test for bug #11487: range access in a subquery +# Test for Bug#11487 range access in a subquery # CREATE TABLE t1(select_id BIGINT, values_id BIGINT); INSERT INTO t1 VALUES (1, 1); -CREATE TABLE t2 (select_id BIGINT, values_id BIGINT, +CREATE TABLE t2 (select_id BIGINT, values_id BIGINT, PRIMARY KEY(select_id,values_id)); INSERT INTO t2 VALUES (0, 1), (0, 2), (0, 3), (1, 5); -SELECT values_id FROM t1 +SELECT values_id FROM t1 WHERE values_id IN (SELECT values_id FROM t2 WHERE select_id IN (1, 0)); -SELECT values_id FROM t1 +SELECT values_id FROM t1 WHERE values_id IN (SELECT values_id FROM t2 WHERE select_id BETWEEN 0 AND 1); -SELECT values_id FROM t1 +SELECT values_id FROM t1 WHERE values_id IN (SELECT values_id FROM t2 WHERE select_id = 0 OR select_id = 1); DROP TABLE t1, t2; -# BUG#11821 : Select from subselect using aggregate function on an enum -# segfaults: + +# Bug#11821 Select from subselect using aggregate function on an enum segfaults create table t1 (fld enum('0','1')); insert into t1 values ('1'); select * from (select max(fld) from t1) as foo; drop table t1; + # -# Test for bug #11762: subquery with an aggregate function in HAVING +# Test for Bug#11762 subquery with an aggregate function in HAVING # CREATE TABLE t1 (a int, b int); CREATE TABLE t2 (c int, d int); CREATE TABLE t3 (e int); -INSERT INTO t1 VALUES +INSERT INTO t1 VALUES (1,10), (2,10), (1,20), (2,20), (3,20), (2,30), (4,40); INSERT INTO t2 VALUES (2,10), (2,20), (4,10), (5,10), (3,20), (2,40); @@ -2251,7 +2287,7 @@ SELECT a FROM t1 GROUP BY a WHERE EXISTS(SELECT e FROM t3 WHERE MAX(b)=e AND e < d)); SELECT a FROM t1 GROUP BY a HAVING a IN (SELECT c FROM t2 - WHERE MIN(b) < d AND + WHERE MIN(b) < d AND EXISTS(SELECT e FROM t3 WHERE MAX(b)=e AND e <= d)); SELECT a, SUM(a) FROM t1 GROUP BY a; @@ -2279,9 +2315,9 @@ SELECT t1.a FROM t1 GROUP BY t1.a -- error ER_INVALID_GROUP_FUNC_USE SELECT t1.a FROM t1 GROUP BY t1.a HAVING t1.a > ALL(SELECT t2.c FROM t2 - WHERE EXISTS(SELECT t3.e FROM t3 + WHERE EXISTS(SELECT t3.e FROM t3 WHERE SUM(t1.a+t2.c) < t3.e/4)); --- error ER_INVALID_GROUP_FUNC_USE +-- error ER_INVALID_GROUP_FUNC_USE SELECT t1.a from t1 GROUP BY t1.a HAVING AVG(SUM(t1.b)) > 20; SELECT t1.a FROM t1 GROUP BY t1.a @@ -2297,9 +2333,10 @@ SELECT t1.a, SUM(b) AS sum FROM t1 GROUP BY t1.a DROP TABLE t1,t2,t3; + # -# Test for bug #16603: GROUP BY in a row subquery with a quantifier -# when an index is defined on the grouping field +# Test for Bug#16603 GROUP BY in a row subquery with a quantifier +# when an index is defined on the grouping field CREATE TABLE t1 (a varchar(5), b varchar(10)); INSERT INTO t1 VALUES @@ -2318,27 +2355,30 @@ SELECT * FROM t1 WHERE (a,b) = ANY (SELECT a, max(b) FROM t1 GROUP BY a); DROP TABLE t1; + # -# Bug#17366: Unchecked Item_int results in server crash +# Bug#17366 Unchecked Item_int results in server crash # create table t1( f1 int,f2 int); insert into t1 values (1,1),(2,2); select tt.t from (select 'crash1' as t, f2 from t1) as tt left join t1 on tt.t = 'crash2' and tt.f2 = t1.f2 where tt.t = 'crash1'; drop table t1; + # -# Bug #18306: server crash on delete using subquery. +# Bug#18306 server crash on delete using subquery. # -create table t1 (c int, key(c)); +create table t1 (c int, key(c)); insert into t1 values (1142477582), (1142455969); create table t2 (a int, b int); insert into t2 values (2, 1), (1, 0); delete from t1 where c <= 1140006215 and (select b from t2 where a = 2) = 1; drop table t1, t2; + # -# Bug #7549: Missing error message for invalid view selection with subquery +# Bug#7549 Missing error message for invalid view selection with subquery # CREATE TABLE t1 (a INT); @@ -2352,16 +2392,18 @@ SELECT * FROM t1 WHERE no_such_column = ANY (SELECT 1); DROP TABLE t1; + # -# Bug#19077: A nested materialized derived table is used before being populated. +# Bug#19077 A nested materialized derived table is used before being populated. # create table t1 (i int, j bigint); insert into t1 values (1, 2), (2, 2), (3, 2); select * from (select min(i) from t1 where j=(select * from (select min(j) from t1) t2)) t3; drop table t1; -# -# Bug#19700: subselect returning BIGINT always returned it as SIGNED + +# +# Bug#19700 subselect returning BIGINT always returned it as SIGNED # CREATE TABLE t1 (i BIGINT UNSIGNED); INSERT INTO t1 VALUES (10000000000000000000); # > MAX SIGNED BIGINT 9323372036854775807 @@ -2383,8 +2425,9 @@ SELECT t1.i FROM t1 WHERE t1.i = CAST((SELECT MAX(i) FROM t2) AS UNSIGNED); DROP TABLE t1; DROP TABLE t2; -# -# Bug#20519: subselect with LIMIT M, N + +# +# Bug#20519 subselect with LIMIT M, N # CREATE TABLE t1 ( @@ -2401,7 +2444,7 @@ CREATE TABLE t2 ( date date NOT NULL, PRIMARY KEY (id) ); -INSERT INTO t2 VALUES +INSERT INTO t2 VALUES (1, 1, '2006-03-30'), (2, 2, '2006-04-06'), (3, 3, '2006-04-13'), (4, 2, '2006-04-20'), (5, 1, '2006-05-01'); @@ -2423,8 +2466,9 @@ SELECT *, FROM t1; DROP TABLE t1,t2; + # -# Bug#20869: subselect with range access by DESC +# Bug#20869 subselect with range access by DESC # CREATE TABLE t1 ( @@ -2433,7 +2477,7 @@ CREATE TABLE t1 ( t datetime NOT NULL default '0000-00-00 00:00:00', PRIMARY KEY (i1,i2,t) ); -INSERT INTO t1 VALUES +INSERT INTO t1 VALUES (24,1,'2005-03-03 16:31:31'),(24,1,'2005-05-27 12:40:07'), (24,1,'2005-05-27 12:40:08'),(24,1,'2005-05-27 12:40:10'), (24,1,'2005-05-27 12:40:25'),(24,1,'2005-05-27 12:40:30'), @@ -2451,34 +2495,34 @@ INSERT INTO t2 VALUES (24,1,'2006-06-20 12:29:40'); EXPLAIN SELECT * FROM t1,t2 - WHERE t1.t = (SELECT t1.t FROM t1 + WHERE t1.t = (SELECT t1.t FROM t1 WHERE t1.t < t2.t AND t1.i2=1 AND t2.i1=t1.i1 ORDER BY t1.t DESC LIMIT 1); SELECT * FROM t1,t2 - WHERE t1.t = (SELECT t1.t FROM t1 + WHERE t1.t = (SELECT t1.t FROM t1 WHERE t1.t < t2.t AND t1.i2=1 AND t2.i1=t1.i1 ORDER BY t1.t DESC LIMIT 1); DROP TABLE t1, t2; + # -# Bug#14654 : Cannot select from the same table twice within a UNION -# statement +# Bug#14654 Cannot select from the same table twice within a UNION statement # CREATE TABLE t1 (i INT); (SELECT i FROM t1) UNION (SELECT i FROM t1); #TODO:not supported --error ER_PARSE_ERROR -SELECT sql_no_cache * FROM t1 WHERE NOT EXISTS +SELECT sql_no_cache * FROM t1 WHERE NOT EXISTS ( - (SELECT i FROM t1) UNION + (SELECT i FROM t1) UNION (SELECT i FROM t1) ); #TODO:not supported --error ER_PARSE_ERROR -SELECT * FROM t1 +SELECT * FROM t1 WHERE NOT EXISTS (((SELECT i FROM t1) UNION (SELECT i FROM t1))); #TODO:not supported @@ -2488,14 +2532,15 @@ explain select ((select t11.i from t1 t11) union (select t12.i from t1 t12)) #TODO:not supported --error ER_PARSE_ERROR -explain select * from t1 where not exists +explain select * from t1 where not exists ((select t11.i from t1 t11) union (select t12.i from t1 t12)); DROP TABLE t1; + # -# Bug#21798: memory leak during query execution with subquery in column -# list using a function +# Bug#21798 memory leak during query execution with subquery in column +# list using a function # CREATE TABLE t1 (a VARCHAR(250), b INT auto_increment, PRIMARY KEY (b)); insert into t1 (a) values (FLOOR(rand() * 100)); @@ -2513,14 +2558,15 @@ insert into t1 (a) select FLOOR(rand() * 100) from t1; insert into t1 (a) select FLOOR(rand() * 100) from t1; insert into t1 (a) select FLOOR(rand() * 100) from t1; -SELECT a, - (SELECT REPEAT(' ',250) FROM t1 i1 - WHERE i1.b=t1.a ORDER BY RAND() LIMIT 1) AS a +SELECT a, + (SELECT REPEAT(' ',250) FROM t1 i1 + WHERE i1.b=t1.a ORDER BY RAND() LIMIT 1) AS a FROM t1 ORDER BY a LIMIT 5; DROP TABLE t1; + # -# Bug #21540: Subqueries with no from and aggregate functions return +# Bug#21540 Subqueries with no from and aggregate functions return # wrong results CREATE TABLE t1 (a INT, b INT); CREATE TABLE t2 (a INT); @@ -2530,29 +2576,30 @@ SELECT (SELECT COUNT(DISTINCT t1.b) from t2) FROM t1 GROUP BY t1.a; SELECT (SELECT COUNT(DISTINCT t1.b) from t2 union select 1 from t2 where 12 < 3) FROM t1 GROUP BY t1.a; SELECT COUNT(DISTINCT t1.b), (SELECT COUNT(DISTINCT t1.b)) FROM t1 GROUP BY t1.a; -SELECT COUNT(DISTINCT t1.b), +SELECT COUNT(DISTINCT t1.b), (SELECT COUNT(DISTINCT t1.b) union select 1 from DUAL where 12 < 3) FROM t1 GROUP BY t1.a; SELECT ( SELECT ( SELECT COUNT(DISTINCT t1.b) ) -) +) FROM t1 GROUP BY t1.a; SELECT ( SELECT ( SELECT ( SELECT COUNT(DISTINCT t1.b) ) - ) - FROM t1 GROUP BY t1.a LIMIT 1) + ) + FROM t1 GROUP BY t1.a LIMIT 1) FROM t1 t2 GROUP BY t2.a; -DROP TABLE t1,t2; +DROP TABLE t1,t2; + # -# Bug #21727: Correlated subquery that requires filesort: -# slow with big sort_buffer_size +# Bug#21727 Correlated subquery that requires filesort: +# slow with big sort_buffer_size # CREATE TABLE t1 (a int, b int auto_increment, PRIMARY KEY (b)); @@ -2570,26 +2617,27 @@ while ($1) { eval INSERT INTO t2(y,z) VALUES(@id,RAND()*1000); dec $2; - } + } dec $1; } enable_query_log; SET SESSION sort_buffer_size = 32 * 1024; -SELECT SQL_NO_CACHE COUNT(*) +SELECT SQL_NO_CACHE COUNT(*) FROM (SELECT a, b, (SELECT x FROM t2 WHERE y=b ORDER BY z DESC LIMIT 1) c FROM t1) t; SET SESSION sort_buffer_size = 8 * 1024 * 1024; -SELECT SQL_NO_CACHE COUNT(*) +SELECT SQL_NO_CACHE COUNT(*) FROM (SELECT a, b, (SELECT x FROM t2 WHERE y=b ORDER BY z DESC LIMIT 1) c FROM t1) t; DROP TABLE t1,t2; + # -# Bug #25219: EXIST subquery with UNION over a mix of -# correlated and uncorrelated selects +# Bug#25219 EXIST subquery with UNION over a mix of +# correlated and uncorrelated selects # CREATE TABLE t1 (id char(4) PRIMARY KEY, c int); @@ -2621,10 +2669,11 @@ SELECT * FROM t1 DROP TABLE t1,t2,t3; -# -# Bug#23800: Outer fields in correlated subqueries is used in a temporary -# table created for sorting. -# + +# +# Bug#23800 Outer fields in correlated subqueries is used in a temporary +# table created for sorting. +# CREATE TABLE t1(f1 int); CREATE TABLE t2(f2 int, f21 int, f3 timestamp); INSERT INTO t1 VALUES (1),(1),(2),(2); @@ -2635,19 +2684,20 @@ PREPARE stmt1 FROM 'SELECT ((SELECT f2 FROM t2 WHERE f21=f1 LIMIT 1) * COUNT(f1) EXECUTE stmt1; EXECUTE stmt1; DEALLOCATE PREPARE stmt1; -SELECT f2, AVG(f21), +SELECT f2, AVG(f21), (SELECT t.f3 FROM t2 AS t WHERE t2.f2=t.f2 AND t.f3=MAX(t2.f3)) AS test FROM t2 GROUP BY f2; -DROP TABLE t1,t2; -CREATE TABLE t1 (a int, b INT, c CHAR(10) NOT NULL); -INSERT INTO t1 VALUES - (1,1,'a'), (1,2,'b'), (1,3,'c'), (1,4,'d'), (1,5,'e'), - (2,1,'f'), (2,2,'g'), (2,3,'h'), (3,4,'i'), (3,3,'j'), - (3,2,'k'), (3,1,'l'), (1,9,'m'); -SELECT a, MAX(b), - (SELECT t.c FROM t1 AS t WHERE t1.a=t.a AND t.b=MAX(t1.b)) AS test - FROM t1 GROUP BY a; -DROP TABLE t1; +DROP TABLE t1,t2; +CREATE TABLE t1 (a int, b INT, c CHAR(10) NOT NULL); +INSERT INTO t1 VALUES + (1,1,'a'), (1,2,'b'), (1,3,'c'), (1,4,'d'), (1,5,'e'), + (2,1,'f'), (2,2,'g'), (2,3,'h'), (3,4,'i'), (3,3,'j'), + (3,2,'k'), (3,1,'l'), (1,9,'m'); +SELECT a, MAX(b), + (SELECT t.c FROM t1 AS t WHERE t1.a=t.a AND t.b=MAX(t1.b)) AS test + FROM t1 GROUP BY a; +DROP TABLE t1; + # # Bug#21904 (parser problem when using IN with a double "(())") @@ -2748,21 +2798,23 @@ DROP TABLE t1; DROP TABLE t2; DROP TABLE t1xt2; + +# +# Bug#26728 derived table with concatanation of literals in select list # -# Bug #26728: derived table with concatanation of literals in select list -# CREATE TABLE t1 (a int); -INSERT INTO t1 VALUES (3), (1), (2); +INSERT INTO t1 VALUES (3), (1), (2); SELECT 'this is ' 'a test.' AS col1, a AS col2 FROM t1; SELECT * FROM (SELECT 'this is ' 'a test.' AS col1, a AS t2 FROM t1) t; DROP table t1; + +# +# Bug#27257 COUNT(*) aggregated in outer query # -# Bug #27257: COUNT(*) aggregated in outer query -# CREATE TABLE t1 (a int, b int); CREATE TABLE t2 (m int, n int); @@ -2777,15 +2829,16 @@ SELECT COUNT(*), a, (SELECT MIN(m) FROM t2 WHERE m = count(*)) FROM t1 GROUP BY a; -SELECT COUNT(*), a +SELECT COUNT(*), a FROM t1 GROUP BY a HAVING (SELECT MIN(m) FROM t2 WHERE m = count(*)) > 1; DROP TABLE t1,t2; + +# +# Bug#27229 GROUP_CONCAT in subselect with COUNT() as an argument # -# Bug #27229: GROUP_CONCAT in subselect with COUNT() as an argument -# CREATE TABLE t1 (a int, b int); CREATE TABLE t2 (m int, n int); @@ -2802,8 +2855,9 @@ SELECT COUNT(*) c, a, DROP table t1,t2; + # -# Bug#27321: Wrong subquery result in a grouping select +# Bug#27321 Wrong subquery result in a grouping select # CREATE TABLE t1 (a int, b INT, d INT, c CHAR(10) NOT NULL, PRIMARY KEY (a, b)); INSERT INTO t1 VALUES (1,1,0,'a'), (1,2,0,'b'), (1,3,0,'c'), (1,4,0,'d'), @@ -2811,7 +2865,7 @@ INSERT INTO t1 VALUES (1,1,0,'a'), (1,2,0,'b'), (1,3,0,'c'), (1,4,0,'d'), (3,2,0,'k'), (3,1,0,'l'), (1,9,0,'m'), (1,0,10,'n'), (2,0,5,'o'), (3,0,7,'p'); SELECT a, MAX(b), - (SELECT t.c FROM t1 AS t WHERE t1.a=t.a AND t.b=MAX(t1.b + 0)) as test + (SELECT t.c FROM t1 AS t WHERE t1.a=t.a AND t.b=MAX(t1.b + 0)) as test FROM t1 GROUP BY a; SELECT a x, MAX(b), (SELECT t.c FROM t1 AS t WHERE x=t.a AND t.b=MAX(t1.b + 0)) as test @@ -2822,25 +2876,27 @@ SELECT a, AVG(b), SELECT tt.a, (SELECT (SELECT c FROM t1 as t WHERE t1.a=t.a AND t.d=MAX(t1.b + tt.a) - LIMIT 1) FROM t1 WHERE t1.a=tt.a GROUP BY a LIMIT 1) as test + LIMIT 1) FROM t1 WHERE t1.a=tt.a GROUP BY a LIMIT 1) as test FROM t1 as tt; SELECT tt.a, (SELECT (SELECT t.c FROM t1 AS t WHERE t1.a=t.a AND t.d=MAX(t1.b + tt.a) LIMIT 1) - FROM t1 WHERE t1.a=tt.a GROUP BY a LIMIT 1) as test + FROM t1 WHERE t1.a=tt.a GROUP BY a LIMIT 1) as test FROM t1 as tt GROUP BY tt.a; SELECT tt.a, MAX( (SELECT (SELECT t.c FROM t1 AS t WHERE t1.a=t.a AND t.d=MAX(t1.b + tt.a) LIMIT 1) - FROM t1 WHERE t1.a=tt.a GROUP BY a LIMIT 1)) as test + FROM t1 WHERE t1.a=tt.a GROUP BY a LIMIT 1)) as test FROM t1 as tt GROUP BY tt.a; DROP TABLE t1; + + +# +# Bug#27348 SET FUNCTION used in a subquery from WHERE condition # -# Bug #27348: SET FUNCTION used in a subquery from WHERE condition -# CREATE TABLE t1 (a int, b int); INSERT INTO t1 VALUES (2,22),(1,11),(2,22); @@ -2865,9 +2921,9 @@ SET @@sql_mode=default; DROP TABLE t1; + # -# Bug #27363: nested aggregates in outer, subquery / sum(select -# count(outer)) +# Bug#27363 nested aggregates in outer, subquery / sum(select count(outer)) # CREATE TABLE t1 (a INT); INSERT INTO t1 values (1),(1),(1),(1); CREATE TABLE t2 (x INT); INSERT INTO t1 values (1000),(1001),(1002); @@ -2882,28 +2938,30 @@ SELECT COUNT(1) FROM DUAL; SELECT SUM( (SELECT AVG( (SELECT t1.a FROM t2) ) FROM DUAL) ) FROM t1; --error ER_INVALID_GROUP_FUNC_USE -SELECT +SELECT SUM( (SELECT AVG( (SELECT COUNT(*) FROM t1 t HAVING t1.a < 12) ) FROM t2) ) FROM t1; --error ER_INVALID_GROUP_FUNC_USE -SELECT t1.a as XXA, +SELECT t1.a as XXA, SUM( (SELECT AVG( (SELECT COUNT(*) FROM t1 t HAVING XXA < 12) ) FROM t2) ) FROM t1; DROP TABLE t1,t2; + # -# Bug #27807: Server crash when executing subquery with EXPLAIN -# -CREATE TABLE t1 (a int, b int, KEY (a)); +# Bug#27807 Server crash when executing subquery with EXPLAIN +# +CREATE TABLE t1 (a int, b int, KEY (a)); INSERT INTO t1 VALUES (1,1),(2,1); EXPLAIN SELECT 1 FROM t1 WHERE a = (SELECT COUNT(*) FROM t1 GROUP BY b); DROP TABLE t1; + +# +# Bug#28377 grouping query with a correlated subquery in WHERE condition # -# Bug #28377: grouping query with a correlated subquery in WHERE condition -# CREATE TABLE t1 (id int NOT NULL, st CHAR(2), INDEX idx(id)); INSERT INTO t1 VALUES @@ -2911,24 +2969,25 @@ INSERT INTO t1 VALUES CREATE TABLE t2 (id int NOT NULL, INDEX idx(id)); INSERT INTO t2 VALUES (7), (5), (1), (3); -SELECT id, st FROM t1 +SELECT id, st FROM t1 WHERE st IN ('GA','FL') AND EXISTS(SELECT 1 FROM t2 WHERE t2.id=t1.id); -SELECT id, st FROM t1 +SELECT id, st FROM t1 WHERE st IN ('GA','FL') AND EXISTS(SELECT 1 FROM t2 WHERE t2.id=t1.id) GROUP BY id; -SELECT id, st FROM t1 +SELECT id, st FROM t1 WHERE st IN ('GA','FL') AND NOT EXISTS(SELECT 1 FROM t2 WHERE t2.id=t1.id); -SELECT id, st FROM t1 +SELECT id, st FROM t1 WHERE st IN ('GA','FL') AND NOT EXISTS(SELECT 1 FROM t2 WHERE t2.id=t1.id) GROUP BY id; DROP TABLE t1,t2; + +# +# Bug#28728 crash with EXPLAIN EXTENDED for a query with a derived table +# over a grouping subselect # -# Bug #28728: crash with EXPLAIN EXTENDED for a query with a derived table -# over a grouping subselect -# CREATE TABLE t1 (a int); @@ -2939,10 +2998,11 @@ SELECT * FROM (SELECT count(*) FROM t1 GROUP BY a) as res; DROP TABLE t1; + # -# Bug #28811: crash for query containing subquery with ORDER BY and LIMIT 1 +# Bug#28811 crash for query containing subquery with ORDER BY and LIMIT 1 # - + CREATE TABLE t1 ( a varchar(255) default NULL, b timestamp NOT NULL default CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP, @@ -2973,8 +3033,8 @@ DROP TABLE t1,t2; # -# Bug #27333: subquery grouped for aggregate of outer query / no aggregate -# of subquery +# Bug#27333 subquery grouped for aggregate of outer query / no aggregate +# of subquery # CREATE TABLE t1 (a INTEGER, b INTEGER); CREATE TABLE t2 (x INTEGER); @@ -3013,8 +3073,9 @@ SELECT (SELECT SUM(t1.a) FROM t2 WHERE a!=0) FROM t1; SELECT (SELECT SUM(t1.a) FROM t2 WHERE a=1) FROM t1; DROP TABLE t1,t2; + # -# Bug31048: Many nested subqueries may cause server crash. +# Bug31048 Many nested subqueries may cause server crash. # create table t1(a int,b int,key(a),key(b)); insert into t1(a,b) values (1,2),(2,1),(2,3),(3,4),(5,4),(5,5), @@ -3059,8 +3120,9 @@ while ($nesting) --enable_query_log drop table t1; + # -# Bug #31884: Assertion + crash in subquery in the SELECT clause. +# Bug#31884 Assertion + crash in subquery in the SELECT clause. # CREATE TABLE t1 (a1 INT, a2 INT); @@ -3075,7 +3137,7 @@ SELECT ((a1,a2) IN (SELECT * FROM t2 WHERE b2 > 0)) IS NULL FROM t1; DROP TABLE t1, t2; # -# Bug #28076: inconsistent binary/varbinary comparison +# Bug#28076 inconsistent binary/varbinary comparison # CREATE TABLE t1 (s1 BINARY(5), s2 VARBINARY(5)); @@ -3116,8 +3178,9 @@ SELECT LEFT(t1.a1,1) FROM t1,t3 WHERE t1.b1=t3.a3; SELECT a2 FROM t2 WHERE t2.a2 IN (SELECT t1.a1 FROM t1,t3 WHERE t1.b1=t3.a3); DROP TABLE t1, t2, t3; + # -# Bug #30788: Inconsistent retrieval of char/varchar +# Bug#30788 Inconsistent retrieval of char/varchar # CREATE TABLE t1 (a CHAR(1), b VARCHAR(10)); @@ -3141,16 +3204,16 @@ SELECT a,b FROM t1 WHERE b IN (SELECT a FROM t1 WHERE LENGTH(a)<500); DROP TABLE t1,t2; + # -# Bug #32400: Complex SELECT query returns correct result only on some -# occasions +# Bug#32400 Complex SELECT query returns correct result only on some occasions # CREATE TABLE t1(a INT, b INT); INSERT INTO t1 VALUES (1,1), (1,2), (2,3), (2,4); --error ER_BAD_FIELD_ERROR -EXPLAIN +EXPLAIN SELECT a AS out_a, MIN(b) FROM t1 WHERE b > (SELECT MIN(b) FROM t1 WHERE a = out_a) GROUP BY a; @@ -3160,7 +3223,7 @@ SELECT a AS out_a, MIN(b) FROM t1 WHERE b > (SELECT MIN(b) FROM t1 WHERE a = out_a) GROUP BY a; -EXPLAIN +EXPLAIN SELECT a AS out_a, MIN(b) FROM t1 t1_outer WHERE b > (SELECT MIN(b) FROM t1 WHERE a = t1_outer.a) GROUP BY a; @@ -3171,8 +3234,9 @@ GROUP BY a; DROP TABLE t1; + # -# Bug #32036: EXISTS within a WHERE clause with a UNION crashes MySQL 5.122 +# Bug#32036 EXISTS within a WHERE clause with a UNION crashes MySQL 5.122 # CREATE TABLE t1 (a INT); @@ -3189,15 +3253,15 @@ SELECT 2 FROM t1 WHERE EXISTS ((SELECT 1 FROM t2 WHERE t1.a=t2.a)); #TODO:not supported --error ER_PARSE_ERROR EXPLAIN EXTENDED -SELECT 2 FROM t1 WHERE EXISTS ((SELECT 1 FROM t2 WHERE t1.a=t2.a) UNION +SELECT 2 FROM t1 WHERE EXISTS ((SELECT 1 FROM t2 WHERE t1.a=t2.a) UNION (SELECT 1 FROM t2 WHERE t1.a = t2.a)); DROP TABLE t1,t2; # -# Bug#33675: Usage of an uninitialized memory by filesort in a subquery -# caused server crash. +# Bug#33675 Usage of an uninitialized memory by filesort in a subquery +# caused server crash. # create table t1(f11 int, f12 int); create table t2(f21 int unsigned not null, f22 int, f23 varchar(10)); @@ -3213,13 +3277,14 @@ while ($i) --enable_warnings --enable_query_log set session sort_buffer_size= 33*1024; -select count(*) from t1 where f12 = +select count(*) from t1 where f12 = (select f22 from t2 where f22 = f12 order by f21 desc, f22, f23 limit 1); drop table t1,t2; + # -# BUG#33794 "MySQL crashes executing specific query on specific dump" +# Bug#33794 "MySQL crashes executing specific query on specific dump" # CREATE TABLE t4 ( f7 varchar(32) collate utf8_bin NOT NULL default '', @@ -3261,32 +3326,34 @@ SELECT FROM t2 VPC, t4 a2, t2 a3 WHERE VPC.f4 = a2.f10 AND a3.f2 = a4 - LIMIT 1) IS NULL, - 0, + LIMIT 1) IS NULL, + 0, t3.f5 ) ) AS a6 -FROM +FROM t2, t3, t1 JOIN t2 a1 ON t1.f9 = a1.f4 GROUP BY a4; DROP TABLE t1, t2, t3, t4; + # -# BUG#36139 "float, zerofill, crash with subquery" +# Bug#36139 "float, zerofill, crash with subquery" # create table t1 (a float(5,4) zerofill); create table t2 (a float(5,4),b float(2,0)); -select t1.a from t1 where +select t1.a from t1 where t1.a= (select b from t2 limit 1) and not t1.a= (select a from t2 limit 1) ; drop table t1, t2; + # -# Bug #36011: Server crash with explain extended on query with dependent -# subqueries +# Bug#36011 Server crash with explain extended on query with dependent +# subqueries # CREATE TABLE t1 (a INT); @@ -3295,8 +3362,9 @@ EXPLAIN EXTENDED SELECT 1 FROM t1 WHERE 1 IN (SELECT 1 FROM t1 GROUP BY a); EXPLAIN EXTENDED SELECT 1 FROM t1 WHERE 1 IN (SELECT 1 FROM t1 WHERE a > 3 GROUP BY a); DROP TABLE t1; + # -# Bug #38191: Server crash with subquery containing DISTINCT and ORDER BY +# Bug#38191 Server crash with subquery containing DISTINCT and ORDER BY # CREATE TABLE t1(pk int PRIMARY KEY, a int, INDEX idx(a)); @@ -3307,6 +3375,7 @@ SELECT * FROM t1 WHERE EXISTS (SELECT DISTINCT a FROM t2 WHERE t1.a < t2.a ORDER BY b); DROP TABLE t1,t2; + # # Bug#20835 (literal string with =any values) # @@ -3315,6 +3384,7 @@ INSERT INTO t1 VALUES ('a'); SELECT * FROM t1 WHERE _utf8'a' = ANY (SELECT s1 FROM t1); DROP TABLE t1; + # # Bug#40519 Subselect query using bigint fails # @@ -3325,6 +3395,7 @@ INSERT INTO t2 VALUES (2,1),(3,1); SELECT * FROM t1 i WHERE 1 IN (SELECT l.id2 FROM t2 l WHERE i.id=l.id1); DROP TABLE t1, t2; + # # Bug#37460 Assertion failed: # !table->file || table->file->inited == handler::NONE @@ -3346,7 +3417,7 @@ CREATE VIEW v2 (a,b) AS SELECT t2.id, t2.c AS c FROM t1, t2 WHERE t1.id=t2.id AND 1 IN (SELECT id FROM t1) WITH CHECK OPTION; ---error 1369 +--error ER_VIEW_CHECK_FAILED INSERT INTO v2(a,b) VALUES (2,2); INSERT INTO v2(a,b) VALUES (1,2); SELECT * FROM v1; diff --git a/mysql-test/t/synchronization.test b/mysql-test/t/synchronization.test index c7696195ee0..aef06245717 100644 --- a/mysql-test/t/synchronization.test +++ b/mysql-test/t/synchronization.test @@ -1,10 +1,13 @@ +# Save the initial number of concurrent sessions +--source include/count_sessions.inc + # -# Test for Bug #2385 CREATE TABLE LIKE lacks locking on source and destination -# table +# Test for Bug#2385 CREATE TABLE LIKE lacks locking on source and destination +# table # --disable_warnings -drop table if exists t1; +DROP TABLE IF EXISTS t1,t2; --enable_warnings connect (con1,localhost,root,,); @@ -12,12 +15,12 @@ connect (con2,localhost,root,,); # locking of source: -CREATE TABLE t1 (x1 int); +CREATE TABLE t1 (x1 INT); let $1= 10; while ($1) { connection con1; - send ALTER TABLE t1 CHANGE x1 x2 int; + send ALTER TABLE t1 CHANGE x1 x2 INT; connection con2; CREATE TABLE t2 LIKE t1; replace_result x1 xx x2 xx; @@ -25,7 +28,7 @@ while ($1) DROP TABLE t2; connection con1; reap; - send ALTER TABLE t1 CHANGE x2 x1 int; + send ALTER TABLE t1 CHANGE x2 x1 INT; connection con2; CREATE TABLE t2 LIKE t1; replace_result x1 xx x2 xx; @@ -37,4 +40,11 @@ while ($1) } DROP TABLE t1; +connection default; +disconnect con1; +disconnect con2; + # End of 4.1 tests + +# Wait till we reached the initial number of concurrent sessions +--source include/wait_until_count_sessions.inc diff --git a/mysql-test/t/timezone_grant.test b/mysql-test/t/timezone_grant.test index 450c1edc47e..8013f2b04ce 100644 --- a/mysql-test/t/timezone_grant.test +++ b/mysql-test/t/timezone_grant.test @@ -1,15 +1,18 @@ # Embedded server testing does not support grants -- source include/not_embedded.inc +# Save the initial number of concurrent sessions +--source include/count_sessions.inc + --disable_warnings drop tables if exists t1, t2; drop view if exists v1; --enable_warnings # -# Test for bug #6116 "SET time_zone := ... requires access to mysql.time_zone -# tables". We should allow implicit access to time zone description tables -# even for unprivileged users. +# Test for Bug#6116 SET time_zone := ... requires access to mysql.time_zone tables +# We should allow implicit access to time zone description tables even for +# unprivileged users. # # Let us prepare playground @@ -33,18 +36,20 @@ select convert_tz(b, 'Europe/Moscow', 'UTC') from t1; update t1, t2 set t1.b = convert_tz('2004-10-21 19:00:00', 'Europe/Moscow', 'UTC') where t1.a = t2.c and t2.d = (select max(d) from t2); # But still these two statements should not work: ---error 1142 +--error ER_TABLEACCESS_DENIED_ERROR select * from mysql.time_zone_name; ---error 1142 +--error ER_TABLEACCESS_DENIED_ERROR select Name, convert_tz('2004-10-21 19:00:00', Name, 'UTC') from mysql.time_zone_name; +connection default; +disconnect tzuser; + # -# Test for bug #6765 "Implicit access to time zone description tables -# requires privileges for them if some table or column level grants -# present" +# Bug#6765 Implicit access to time zone description tables requires privileges +# for them if some table or column level grants present # connection default; -# Let use some table-level grants instead of db-level +# Let use some table-level grants instead of db-level # to make life more interesting delete from mysql.db where user like 'mysqltest\_%'; flush privileges; @@ -61,14 +66,14 @@ select convert_tz(b, 'Europe/Moscow', 'UTC') from t1; update t1, t2 set t1.b = convert_tz('2004-11-30 12:00:00', 'Europe/Moscow', 'UTC') where t1.a = t2.c and t2.d = (select max(d) from t2); # Again these two statements should not work (but with different errors): ---error 1142 +--error ER_TABLEACCESS_DENIED_ERROR select * from mysql.time_zone_name; ---error 1142 +--error ER_TABLEACCESS_DENIED_ERROR select Name, convert_tz('2004-11-30 12:00:00', Name, 'UTC') from mysql.time_zone_name; # -# Bug #9979: Use of CONVERT_TZ in multiple-table UPDATE causes bogus -# privilege error +# Bug#9979 Use of CONVERT_TZ in multiple-table UPDATE causes bogus +# privilege error # drop table t1, t2; create table t1 (a int, b datetime); @@ -80,6 +85,7 @@ update t1 join t2 on (t1.a = t2.a) set t1.b = convert_tz('2005-01-01 10:00','UTC # Clean-up connection default; +disconnect tzuser2; delete from mysql.user where user like 'mysqltest\_%'; delete from mysql.db where user like 'mysqltest\_%'; delete from mysql.tables_priv where user like 'mysqltest\_%'; @@ -89,10 +95,9 @@ drop table t1, t2; # End of 4.1 tests # -# Additional test for bug #15153: CONVERT_TZ() is not allowed in all -# places in views. +# Additional test for Bug#15153 CONVERT_TZ() is not allowed in all places in views. # -# Let us check that usage of CONVERT_TZ() function in view does not +# Let us check that usage of CONVERT_TZ() function in view does not # require additional privileges. # Let us rely on that previous tests done proper cleanups @@ -109,7 +114,11 @@ drop view v1; --error ER_TABLEACCESS_DENIED_ERROR create view v1 as select a, convert_tz(b, 'UTC', 'Europe/Moscow') as lb from t1, mysql.time_zone; connection default; +disconnect tzuser3; drop table t1; drop user mysqltest_1@localhost; # End of 5.0 tests + +# Wait till we reached the initial number of concurrent sessions +--source include/wait_until_count_sessions.inc From aca7ca6bbaf7e86b0999da53bc33be265ba6243c Mon Sep 17 00:00:00 2001 From: Magnus Svensson Date: Fri, 6 Feb 2009 08:38:24 +0100 Subject: [PATCH 036/219] Bug#42641 mtr.pl fails to run within JobObject - Allow the new process to break away from any job that this process is part of so that it can be assigned to the new JobObject we just created. This is safe since the new JobObject is created with the JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE flag, making sure it will be terminated when the last handle to it is closed(which is owned by this process). --- mysql-test/lib/My/SafeProcess/safe_process_win.cc | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/mysql-test/lib/My/SafeProcess/safe_process_win.cc b/mysql-test/lib/My/SafeProcess/safe_process_win.cc index 8aa603a8793..640254875c9 100755 --- a/mysql-test/lib/My/SafeProcess/safe_process_win.cc +++ b/mysql-test/lib/My/SafeProcess/safe_process_win.cc @@ -237,12 +237,19 @@ int main(int argc, const char** argv ) /* Create the process suspended to make sure it's assigned to the Job before it creates any process of it's own + + Allow the new process to break away from any job that this + process is part of so that it can be assigned to the new JobObject + we just created. This is safe since the new JobObject is created with + the JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE flag, making sure it will be + terminated when the last handle to it is closed(which is owned by + this process). */ if (CreateProcess(NULL, (LPSTR)child_args, NULL, NULL, TRUE, /* inherit handles */ - CREATE_SUSPENDED, + CREATE_SUSPENDED | CREATE_BREAKAWAY_FROM_JOB, NULL, NULL, &si, From b30239bc1a3e73f4ad4f1ecac9cc1e193f7a0b61 Mon Sep 17 00:00:00 2001 From: Alexey Kopytov Date: Fri, 6 Feb 2009 12:51:11 +0300 Subject: [PATCH 037/219] Temporarily reverted patch for bug #41868 as it was causing problems in PB. --- client/sql_string.cc | 20 ++++++++++---------- mysql-test/r/func_str.result | 6 ------ mysql-test/t/func_str.test | 9 --------- sql/sql_class.cc | 5 ----- sql/sql_string.cc | 20 ++++++++++---------- 5 files changed, 20 insertions(+), 40 deletions(-) diff --git a/client/sql_string.cc b/client/sql_string.cc index eb80e29ed49..9d887ff031c 100644 --- a/client/sql_string.cc +++ b/client/sql_string.cc @@ -72,26 +72,26 @@ bool String::realloc(uint32 alloc_length) if (alloced) { if ((new_ptr= (char*) my_realloc(Ptr,len,MYF(MY_WME)))) - new_ptr[alloc_length]= 0; + { + Ptr=new_ptr; + Alloced_length=len; + } else - return TRUE; // Signal error + return TRUE; // Signal error } else if ((new_ptr= (char*) my_malloc(len,MYF(MY_WME)))) { - if (str_length > len - 1) - str_length= 0; if (str_length) // Avoid bugs in memcpy on AIX - memcpy(new_ptr, Ptr, str_length); - new_ptr[str_length]= 0; + memcpy(new_ptr,Ptr,str_length); + new_ptr[str_length]=0; + Ptr=new_ptr; + Alloced_length=len; alloced=1; } else return TRUE; // Signal error - Ptr= new_ptr; - Alloced_length= len; } - else - Ptr[alloc_length]= 0; + Ptr[alloc_length]=0; // This make other funcs shorter return FALSE; } diff --git a/mysql-test/r/func_str.result b/mysql-test/r/func_str.result index d7fd8c5c887..c121c8937d7 100644 --- a/mysql-test/r/func_str.result +++ b/mysql-test/r/func_str.result @@ -2181,10 +2181,4 @@ def format(a, 2) 253 20 4 Y 0 2 8 format(a, 2) 1.33 drop table t1; -CREATE TABLE t1 (c DATE, aa VARCHAR(30)); -INSERT INTO t1 VALUES ('2008-12-31','aaaaaa'); -SELECT DATE_FORMAT(c, GET_FORMAT(DATE, 'eur')) h, CONCAT(UPPER(aa),', ', aa) i FROM t1; -h i -31.12.2008 AAAAAA, aaaaaa -DROP TABLE t1; End of 5.0 tests diff --git a/mysql-test/t/func_str.test b/mysql-test/t/func_str.test index 389538c4cc0..8298a50c277 100644 --- a/mysql-test/t/func_str.test +++ b/mysql-test/t/func_str.test @@ -1159,13 +1159,4 @@ select format(a, 2) from t1; --disable_metadata drop table t1; -# -# Bug #41868: crash or memory overrun with concat + upper, date_format functions -# - -CREATE TABLE t1 (c DATE, aa VARCHAR(30)); -INSERT INTO t1 VALUES ('2008-12-31','aaaaaa'); -SELECT DATE_FORMAT(c, GET_FORMAT(DATE, 'eur')) h, CONCAT(UPPER(aa),', ', aa) i FROM t1; -DROP TABLE t1; - --echo End of 5.0 tests diff --git a/sql/sql_class.cc b/sql/sql_class.cc index 9ff602bb62e..91c0aa66761 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -1047,11 +1047,6 @@ bool select_send::send_data(List &items) my_message(ER_OUT_OF_RESOURCES, ER(ER_OUT_OF_RESOURCES), MYF(0)); break; } - /* - Reset buffer to its original state, as it may have been altered in - Item::send(). - */ - buffer.set(buff, sizeof(buff), &my_charset_bin); } thd->sent_row_count++; if (!thd->vio_ok()) diff --git a/sql/sql_string.cc b/sql/sql_string.cc index b6ce4d8dc8d..75e47dd0c8e 100644 --- a/sql/sql_string.cc +++ b/sql/sql_string.cc @@ -72,26 +72,26 @@ bool String::realloc(uint32 alloc_length) if (alloced) { if ((new_ptr= (char*) my_realloc(Ptr,len,MYF(MY_WME)))) - new_ptr[alloc_length]= 0; + { + Ptr=new_ptr; + Alloced_length=len; + } else - return TRUE; // Signal error + return TRUE; // Signal error } else if ((new_ptr= (char*) my_malloc(len,MYF(MY_WME)))) { - if (str_length > len - 1) - str_length= 0; if (str_length) // Avoid bugs in memcpy on AIX - memcpy(new_ptr, Ptr, str_length); - new_ptr[str_length]= 0; + memcpy(new_ptr,Ptr,str_length); + new_ptr[str_length]=0; + Ptr=new_ptr; + Alloced_length=len; alloced=1; } else return TRUE; // Signal error - Ptr= new_ptr; - Alloced_length= len; } - else - Ptr[alloc_length]= 0; + Ptr[alloc_length]=0; // This make other funcs shorter return FALSE; } From ec849b19bd861dbf93fd2f334b3a25e92eeedbf0 Mon Sep 17 00:00:00 2001 From: Davi Arnaut Date: Fri, 6 Feb 2009 09:00:09 -0200 Subject: [PATCH 038/219] Bug#42524: Function pthread_setschedprio() is defined but seems broken on i5/OS PASE The problem is that MySQL use of pthread_setschedprio is not supported by i5/OS and the default system behavior for unsupported calls is to emit a SIGILL signal which causes the server to abort. The solution is to treat the pthread_setschedprio as inexistent when compiling binaries for i5/OS. This also does not invalidate the fix for bug 38477 as the only supported dispatch class is SCHED_OTHER (which is passed to pthread_setschedparam). configure.in: Skip pthread_setschedprio check on i5/OS. --- configure.in | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/configure.in b/configure.in index 16d229a84e3..b5beb7a24f5 100644 --- a/configure.in +++ b/configure.in @@ -2048,7 +2048,7 @@ AC_CHECK_FUNCS(alarm bcmp bfill bmove bsearch bzero \ mkstemp mlockall perror poll pread pthread_attr_create mmap mmap64 getpagesize \ pthread_attr_getstacksize pthread_attr_setprio pthread_attr_setschedparam \ pthread_attr_setstacksize pthread_condattr_create pthread_getsequence_np \ - pthread_key_delete pthread_rwlock_rdlock pthread_setprio pthread_setschedprio \ + pthread_key_delete pthread_rwlock_rdlock pthread_setprio \ pthread_setprio_np pthread_setschedparam pthread_sigmask readlink \ realpath rename rint rwlock_init setupterm \ shmget shmat shmdt shmctl sigaction sigemptyset sigaddset \ @@ -2071,6 +2071,15 @@ case "$target" in ;; esac +case "$mysql_cv_sys_os" in + OS400) # i5/OS (OS/400) emits a SIGILL (Function not implemented) when + # unsupported priority values are passed to pthread_setschedprio. + # Since the only supported value is 1, treat it as inexistent. + ;; + *) AC_CHECK_FUNCS(pthread_setschedprio) + ;; +esac + # Check that isinf() is available in math.h and can be used in both C and C++ # code AC_MSG_CHECKING(for isinf in ) From 44ee0c107d76d43538f58e4c38d3a41b974460e5 Mon Sep 17 00:00:00 2001 From: Timothy Smith Date: Fri, 6 Feb 2009 15:07:45 +0100 Subject: [PATCH 039/219] Handle renamed nwbootstrap -> nwbuild --- netware/Makefile.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/netware/Makefile.am b/netware/Makefile.am index 7ad045d433d..0f11ee85eb0 100644 --- a/netware/Makefile.am +++ b/netware/Makefile.am @@ -90,7 +90,7 @@ EXTRA_DIST= $(BUILT_SOURCES) comp_err.def install_test_db.ncf \ BUILD/compile-netware-standard BUILD/create-patch \ BUILD/cron-build BUILD/crontab BUILD/knetware.imp \ BUILD/mwasmnlm BUILD/mwccnlm BUILD/mwenv BUILD/mwldnlm \ - BUILD/nwbootstrap BUILD/openssl.imp BUILD/save-patch + BUILD/nwbuild BUILD/openssl.imp BUILD/save-patch endif From 0ea110d8585f478249883928d0fe7bfe08fea80b Mon Sep 17 00:00:00 2001 From: Magnus Svensson Date: Fri, 6 Feb 2009 15:09:15 +0100 Subject: [PATCH 040/219] Bug#42366 server-cert.pem expired: "Not After : Jan 27 08:54:13 2009 GMT - remove the disbling of all ssl_* tests now when certs are fixed. --- mysql-test/mysql-test-run.pl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl index 3c02f8803af..511cd4d07ba 100755 --- a/mysql-test/mysql-test-run.pl +++ b/mysql-test/mysql-test-run.pl @@ -132,7 +132,7 @@ our @opt_extra_mysqld_opt; my $opt_compress; my $opt_ssl; -my $opt_skip_ssl = 1; # Until bug#42366 has been fixed +my $opt_skip_ssl; my $opt_ssl_supported; my $opt_ps_protocol; my $opt_sp_protocol; From bd53d21417e2d340758abfeb29f7057221e0da03 Mon Sep 17 00:00:00 2001 From: Mats Kindahl Date: Fri, 6 Feb 2009 17:06:41 +0100 Subject: [PATCH 041/219] Bug #36763 TRUNCATE TABLE fails to replicate when stmt-based binlogging is not supported. There were two separate problems with the code, both of which are fixed with this patch: 1. An error was printed by InnoDB for TRUNCATE TABLE in statement mode when the in isolation levels READ COMMITTED and READ UNCOMMITTED since InnoDB does permit statement-based replication for DML statements. However, the TRUNCATE TABLE is not transactional, but is a DDL, and should therefore be allowed to be replicated as a statement. 2. The statement was not logged in mixed mode because of the error above, but the error was not reported to the client. This patch fixes the problem by treating TRUNCATE TABLE a DDL, that is, it is always logged as a statement and not reporting an error from InnoDB for TRUNCATE TABLE. mysql-test/extra/binlog_tests/binlog_truncate.test: Adding new test to check that TRUNCATE TABLE is written correctly to the binary log. mysql-test/extra/rpl_tests/rpl_truncate.test: Removing redundant testing by eliminating settings of BINLOG_FORMAT. mysql-test/extra/rpl_tests/rpl_truncate_helper.test: Replacing slave and master reset code with include file. Removing settings of BINLOG_FORMAT. Replacing printing of table contents to compare master and slave with diff_tables.inc. mysql-test/suite/binlog/t/binlog_truncate_innodb.test: Adding test for testing that TRUNCATE TABLE is logged correctly for InnoDB in all isolation levels. mysql-test/suite/binlog/t/binlog_truncate_myisam.test: Adding test for testing that TRUNCATE TABLE is logged correctly for MyISAM. mysql-test/suite/binlog/t/disabled.def: Disabling binlog_truncate_innodb since it does not work (yet). sql/sql_base.cc: Correcting setting of capabilities flags to make the comparison with 0 later in the code work correctly. sql/sql_delete.cc: Re-organizing code to ensure that TRUNCATE TABLE is logged in statement format and that row format is not used unless there are rows to log (which there are not when delete_all_rows() is called, so this has to be logged as a statement). --- .../extra/binlog_tests/binlog_truncate.test | 27 ++ mysql-test/extra/rpl_tests/rpl_truncate.test | 23 +- .../extra/rpl_tests/rpl_truncate_helper.test | 51 ++-- .../binlog/r/binlog_truncate_innodb.result | 63 +++++ .../binlog/r/binlog_truncate_myisam.result | 11 + .../t/binlog_truncate_innodb-master.opt | 1 + .../binlog/t/binlog_truncate_innodb.test | 22 ++ .../binlog/t/binlog_truncate_myisam.test | 4 + mysql-test/suite/binlog/t/disabled.def | 2 + .../suite/rpl/r/rpl_truncate_2myisam.result | 234 ++-------------- .../suite/rpl/r/rpl_truncate_3innodb.result | 252 ++---------------- sql/sql_base.cc | 11 +- sql/sql_delete.cc | 22 +- 13 files changed, 219 insertions(+), 504 deletions(-) create mode 100644 mysql-test/extra/binlog_tests/binlog_truncate.test create mode 100644 mysql-test/suite/binlog/r/binlog_truncate_innodb.result create mode 100644 mysql-test/suite/binlog/r/binlog_truncate_myisam.result create mode 100644 mysql-test/suite/binlog/t/binlog_truncate_innodb-master.opt create mode 100644 mysql-test/suite/binlog/t/binlog_truncate_innodb.test create mode 100644 mysql-test/suite/binlog/t/binlog_truncate_myisam.test diff --git a/mysql-test/extra/binlog_tests/binlog_truncate.test b/mysql-test/extra/binlog_tests/binlog_truncate.test new file mode 100644 index 00000000000..dce33b3cef0 --- /dev/null +++ b/mysql-test/extra/binlog_tests/binlog_truncate.test @@ -0,0 +1,27 @@ +# BUG #36763: TRUNCATE TABLE fails to replicate when stmt-based +# binlogging is not supported. + +# This should always be logged as a statement, even when executed as a +# row-by-row deletion. + +# $before_truncate A statement to execute (just) before issuing the +# TRUNCATE TABLE + + +eval CREATE TABLE t1 (a INT) ENGINE=$engine; +eval CREATE TABLE t2 (a INT) ENGINE=$engine; +INSERT INTO t2 VALUES (1),(2),(3); +let $binlog_start = query_get_value("SHOW MASTER STATUS", Position, 1); +if (`select length('$before_truncate') > 0`) { + eval $before_truncate; +} +--echo **** Truncate of empty table shall be logged +TRUNCATE TABLE t1; + +if (`select length('$before_truncate') > 0`) { + eval $before_truncate; +} +TRUNCATE TABLE t2; +source include/show_binlog_events.inc; + +DROP TABLE t1,t2; diff --git a/mysql-test/extra/rpl_tests/rpl_truncate.test b/mysql-test/extra/rpl_tests/rpl_truncate.test index bca53336514..7036ab126e1 100644 --- a/mysql-test/extra/rpl_tests/rpl_truncate.test +++ b/mysql-test/extra/rpl_tests/rpl_truncate.test @@ -9,27 +9,8 @@ --source include/master-slave.inc -let $format = STATEMENT; -let $stmt = TRUNCATE TABLE; +let $trunc_stmt = TRUNCATE TABLE; --source extra/rpl_tests/rpl_truncate_helper.test -let $format = MIXED; -let $stmt = TRUNCATE TABLE; +let $trunc_stmt = DELETE FROM; --source extra/rpl_tests/rpl_truncate_helper.test - -let $format = ROW; -let $stmt = TRUNCATE TABLE; ---source extra/rpl_tests/rpl_truncate_helper.test - -let $format = STATEMENT; -let $stmt = DELETE FROM; ---source extra/rpl_tests/rpl_truncate_helper.test - -let $format = MIXED; -let $stmt = DELETE FROM; ---source extra/rpl_tests/rpl_truncate_helper.test - -let $format = ROW; -let $stmt = DELETE FROM; ---source extra/rpl_tests/rpl_truncate_helper.test - diff --git a/mysql-test/extra/rpl_tests/rpl_truncate_helper.test b/mysql-test/extra/rpl_tests/rpl_truncate_helper.test index 76db74acfa1..cd1ce93177a 100644 --- a/mysql-test/extra/rpl_tests/rpl_truncate_helper.test +++ b/mysql-test/extra/rpl_tests/rpl_truncate_helper.test @@ -1,42 +1,35 @@ -connection slave; -STOP SLAVE; -source include/wait_for_slave_to_stop.inc; -connection master; ---disable_warnings -DROP TABLE IF EXISTS t1; ---enable_warnings -connection slave; ---disable_warnings -DROP TABLE IF EXISTS t1; ---enable_warnings -RESET SLAVE; -START SLAVE; +source include/reset_master_and_slave.inc; --echo **** On Master **** connection master; -eval SET SESSION BINLOG_FORMAT=$format; -eval SET GLOBAL BINLOG_FORMAT=$format; - eval CREATE TABLE t1 (a INT, b LONG) ENGINE=$engine; INSERT INTO t1 VALUES (1,1), (2,2); -SELECT * FROM t1; ---echo **** On Slave **** sync_slave_with_master; -INSERT INTO t1 VALUE (3,3); -SELECT * FROM t1; --echo **** On Master **** connection master; -eval $stmt t1; -SELECT * FROM t1; ---echo **** On Slave **** +eval $trunc_stmt t1; sync_slave_with_master; -# Should be empty -SELECT * FROM t1; + +let $diff_table_1=master:test.t1; +let $diff_table_2=slave:test.t1; +source include/diff_tables.inc; + +--echo ==== Test using a table with delete triggers ==== --echo **** On Master **** connection master; -DROP TABLE t1; -let $SERVER_VERSION=`select version()`; -source include/show_binlog_events.inc; +SET @count := 1; +eval CREATE TABLE t2 (a INT, b LONG) ENGINE=$engine; +CREATE TRIGGER trg1 BEFORE DELETE ON t1 FOR EACH ROW SET @count := @count + 1; +sync_slave_with_master; +--echo **** On Master **** +connection master; +eval $trunc_stmt t1; +sync_slave_with_master; + +let $diff_table_1=master:test.t2; +let $diff_table_2=slave:test.t2; +source include/diff_tables.inc; connection master; -RESET MASTER; +DROP TABLE t1,t2; +sync_slave_with_master; diff --git a/mysql-test/suite/binlog/r/binlog_truncate_innodb.result b/mysql-test/suite/binlog/r/binlog_truncate_innodb.result new file mode 100644 index 00000000000..ab237898a74 --- /dev/null +++ b/mysql-test/suite/binlog/r/binlog_truncate_innodb.result @@ -0,0 +1,63 @@ +CREATE TABLE t1 (a INT) ENGINE=InnoDB; +CREATE TABLE t2 (a INT) ENGINE=InnoDB; +INSERT INTO t2 VALUES (1),(2),(3); +**** Truncate of empty table shall be logged +TRUNCATE TABLE t1; +TRUNCATE TABLE t2; +show binlog events from ; +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query # # use `test`; TRUNCATE TABLE t1 +master-bin.000001 # Query # # use `test`; TRUNCATE TABLE t2 +DROP TABLE t1,t2; +CREATE TABLE t1 (a INT) ENGINE=InnoDB; +CREATE TABLE t2 (a INT) ENGINE=InnoDB; +INSERT INTO t2 VALUES (1),(2),(3); +SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; +**** Truncate of empty table shall be logged +TRUNCATE TABLE t1; +SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; +TRUNCATE TABLE t2; +show binlog events from ; +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query # # use `test`; TRUNCATE TABLE t1 +master-bin.000001 # Query # # use `test`; TRUNCATE TABLE t2 +DROP TABLE t1,t2; +CREATE TABLE t1 (a INT) ENGINE=InnoDB; +CREATE TABLE t2 (a INT) ENGINE=InnoDB; +INSERT INTO t2 VALUES (1),(2),(3); +SET TRANSACTION ISOLATION LEVEL READ COMMITTED; +**** Truncate of empty table shall be logged +TRUNCATE TABLE t1; +SET TRANSACTION ISOLATION LEVEL READ COMMITTED; +TRUNCATE TABLE t2; +show binlog events from ; +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query # # use `test`; TRUNCATE TABLE t1 +master-bin.000001 # Query # # use `test`; TRUNCATE TABLE t2 +DROP TABLE t1,t2; +CREATE TABLE t1 (a INT) ENGINE=InnoDB; +CREATE TABLE t2 (a INT) ENGINE=InnoDB; +INSERT INTO t2 VALUES (1),(2),(3); +SET TRANSACTION ISOLATION LEVEL REPEATABLE READ; +**** Truncate of empty table shall be logged +TRUNCATE TABLE t1; +SET TRANSACTION ISOLATION LEVEL REPEATABLE READ; +TRUNCATE TABLE t2; +show binlog events from ; +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query # # use `test`; TRUNCATE TABLE t1 +master-bin.000001 # Query # # use `test`; TRUNCATE TABLE t2 +DROP TABLE t1,t2; +CREATE TABLE t1 (a INT) ENGINE=InnoDB; +CREATE TABLE t2 (a INT) ENGINE=InnoDB; +INSERT INTO t2 VALUES (1),(2),(3); +SET TRANSACTION ISOLATION LEVEL SERIALIZABLE; +**** Truncate of empty table shall be logged +TRUNCATE TABLE t1; +SET TRANSACTION ISOLATION LEVEL SERIALIZABLE; +TRUNCATE TABLE t2; +show binlog events from ; +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query # # use `test`; TRUNCATE TABLE t1 +master-bin.000001 # Query # # use `test`; TRUNCATE TABLE t2 +DROP TABLE t1,t2; diff --git a/mysql-test/suite/binlog/r/binlog_truncate_myisam.result b/mysql-test/suite/binlog/r/binlog_truncate_myisam.result new file mode 100644 index 00000000000..544882c2c9b --- /dev/null +++ b/mysql-test/suite/binlog/r/binlog_truncate_myisam.result @@ -0,0 +1,11 @@ +CREATE TABLE t1 (a INT) ENGINE=MyISAM; +CREATE TABLE t2 (a INT) ENGINE=MyISAM; +INSERT INTO t2 VALUES (1),(2),(3); +**** Truncate of empty table shall be logged +TRUNCATE TABLE t1; +TRUNCATE TABLE t2; +show binlog events from ; +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query # # use `test`; TRUNCATE TABLE t1 +master-bin.000001 # Query # # use `test`; TRUNCATE TABLE t2 +DROP TABLE t1,t2; diff --git a/mysql-test/suite/binlog/t/binlog_truncate_innodb-master.opt b/mysql-test/suite/binlog/t/binlog_truncate_innodb-master.opt new file mode 100644 index 00000000000..69cc489a969 --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_truncate_innodb-master.opt @@ -0,0 +1 @@ +--loose-innodb \ No newline at end of file diff --git a/mysql-test/suite/binlog/t/binlog_truncate_innodb.test b/mysql-test/suite/binlog/t/binlog_truncate_innodb.test new file mode 100644 index 00000000000..9695710377e --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_truncate_innodb.test @@ -0,0 +1,22 @@ +source include/have_log_bin.inc; +source include/have_innodb.inc; + +let $engine = InnoDB; +source extra/binlog_tests/binlog_truncate.test; + +# Under transaction isolation level READ UNCOMMITTED and READ +# COMMITTED, InnoDB does not permit statement-based replication of +# row-deleting statement. In these cases, TRUNCATE TABLE should still +# be replicated as a statement. + +let $before_truncate = SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; +source extra/binlog_tests/binlog_truncate.test; + +let $before_truncate = SET TRANSACTION ISOLATION LEVEL READ COMMITTED; +source extra/binlog_tests/binlog_truncate.test; + +let $before_truncate = SET TRANSACTION ISOLATION LEVEL REPEATABLE READ; +source extra/binlog_tests/binlog_truncate.test; + +let $before_truncate = SET TRANSACTION ISOLATION LEVEL SERIALIZABLE; +source extra/binlog_tests/binlog_truncate.test; diff --git a/mysql-test/suite/binlog/t/binlog_truncate_myisam.test b/mysql-test/suite/binlog/t/binlog_truncate_myisam.test new file mode 100644 index 00000000000..994647ab78a --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_truncate_myisam.test @@ -0,0 +1,4 @@ +source include/have_log_bin.inc; + +let $engine = MyISAM; +source extra/binlog_tests/binlog_truncate.test; diff --git a/mysql-test/suite/binlog/t/disabled.def b/mysql-test/suite/binlog/t/disabled.def index 888298bbb09..0018387de94 100644 --- a/mysql-test/suite/binlog/t/disabled.def +++ b/mysql-test/suite/binlog/t/disabled.def @@ -9,3 +9,5 @@ # Do not use any TAB characters for whitespace. # ############################################################################## +binlog_truncate_innodb : BUG#42643 2009-02-06 mats Changes to InnoDB requires to complete fix for BUG#36763 + diff --git a/mysql-test/suite/rpl/r/rpl_truncate_2myisam.result b/mysql-test/suite/rpl/r/rpl_truncate_2myisam.result index 1ae98706975..21904fdac51 100644 --- a/mysql-test/suite/rpl/r/rpl_truncate_2myisam.result +++ b/mysql-test/suite/rpl/r/rpl_truncate_2myisam.result @@ -4,241 +4,43 @@ reset master; reset slave; drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; start slave; +**** Resetting master and slave **** STOP SLAVE; -DROP TABLE IF EXISTS t1; -DROP TABLE IF EXISTS t1; RESET SLAVE; +RESET MASTER; START SLAVE; **** On Master **** -SET SESSION BINLOG_FORMAT=STATEMENT; -SET GLOBAL BINLOG_FORMAT=STATEMENT; CREATE TABLE t1 (a INT, b LONG) ENGINE=MyISAM; INSERT INTO t1 VALUES (1,1), (2,2); -SELECT * FROM t1; -a b -1 1 -2 2 -**** On Slave **** -INSERT INTO t1 VALUE (3,3); -SELECT * FROM t1; -a b -1 1 -2 2 -3 3 **** On Master **** TRUNCATE TABLE t1; -SELECT * FROM t1; -a b -**** On Slave **** -SELECT * FROM t1; -a b +Comparing tables master:test.t1 and slave:test.t1 +==== Test using a table with delete triggers ==== **** On Master **** -DROP TABLE t1; -show binlog events from ; -Log_name Pos Event_type Server_id End_log_pos Info -master-bin.000001 # Query # # use `test`; DROP TABLE IF EXISTS t1 -master-bin.000001 # Query # # use `test`; CREATE TABLE t1 (a INT, b LONG) ENGINE=MyISAM -master-bin.000001 # Query # # use `test`; INSERT INTO t1 VALUES (1,1), (2,2) -master-bin.000001 # Query # # use `test`; TRUNCATE TABLE t1 -master-bin.000001 # Query # # use `test`; DROP TABLE t1 -RESET MASTER; -STOP SLAVE; -DROP TABLE IF EXISTS t1; -DROP TABLE IF EXISTS t1; -RESET SLAVE; -START SLAVE; -**** On Master **** -SET SESSION BINLOG_FORMAT=MIXED; -SET GLOBAL BINLOG_FORMAT=MIXED; -CREATE TABLE t1 (a INT, b LONG) ENGINE=MyISAM; -INSERT INTO t1 VALUES (1,1), (2,2); -SELECT * FROM t1; -a b -1 1 -2 2 -**** On Slave **** -INSERT INTO t1 VALUE (3,3); -SELECT * FROM t1; -a b -1 1 -2 2 -3 3 +SET @count := 1; +CREATE TABLE t2 (a INT, b LONG) ENGINE=MyISAM; +CREATE TRIGGER trg1 BEFORE DELETE ON t1 FOR EACH ROW SET @count := @count + 1; **** On Master **** TRUNCATE TABLE t1; -SELECT * FROM t1; -a b -**** On Slave **** -SELECT * FROM t1; -a b -**** On Master **** -DROP TABLE t1; -show binlog events from ; -Log_name Pos Event_type Server_id End_log_pos Info -master-bin.000001 # Query # # use `test`; DROP TABLE IF EXISTS t1 -master-bin.000001 # Query # # use `test`; CREATE TABLE t1 (a INT, b LONG) ENGINE=MyISAM -master-bin.000001 # Query # # use `test`; INSERT INTO t1 VALUES (1,1), (2,2) -master-bin.000001 # Query # # use `test`; TRUNCATE TABLE t1 -master-bin.000001 # Query # # use `test`; DROP TABLE t1 -RESET MASTER; +Comparing tables master:test.t2 and slave:test.t2 +DROP TABLE t1,t2; +**** Resetting master and slave **** STOP SLAVE; -DROP TABLE IF EXISTS t1; -DROP TABLE IF EXISTS t1; RESET SLAVE; +RESET MASTER; START SLAVE; **** On Master **** -SET SESSION BINLOG_FORMAT=ROW; -SET GLOBAL BINLOG_FORMAT=ROW; CREATE TABLE t1 (a INT, b LONG) ENGINE=MyISAM; INSERT INTO t1 VALUES (1,1), (2,2); -SELECT * FROM t1; -a b -1 1 -2 2 -**** On Slave **** -INSERT INTO t1 VALUE (3,3); -SELECT * FROM t1; -a b -1 1 -2 2 -3 3 -**** On Master **** -TRUNCATE TABLE t1; -SELECT * FROM t1; -a b -**** On Slave **** -SELECT * FROM t1; -a b -**** On Master **** -DROP TABLE t1; -show binlog events from ; -Log_name Pos Event_type Server_id End_log_pos Info -master-bin.000001 # Query # # use `test`; DROP TABLE IF EXISTS t1 -master-bin.000001 # Query # # use `test`; CREATE TABLE t1 (a INT, b LONG) ENGINE=MyISAM -master-bin.000001 # Query # # use `test`; BEGIN -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Query # # use `test`; COMMIT -master-bin.000001 # Query # # use `test`; TRUNCATE TABLE t1 -master-bin.000001 # Query # # use `test`; DROP TABLE t1 -RESET MASTER; -STOP SLAVE; -DROP TABLE IF EXISTS t1; -DROP TABLE IF EXISTS t1; -RESET SLAVE; -START SLAVE; -**** On Master **** -SET SESSION BINLOG_FORMAT=STATEMENT; -SET GLOBAL BINLOG_FORMAT=STATEMENT; -CREATE TABLE t1 (a INT, b LONG) ENGINE=MyISAM; -INSERT INTO t1 VALUES (1,1), (2,2); -SELECT * FROM t1; -a b -1 1 -2 2 -**** On Slave **** -INSERT INTO t1 VALUE (3,3); -SELECT * FROM t1; -a b -1 1 -2 2 -3 3 **** On Master **** DELETE FROM t1; -SELECT * FROM t1; -a b -**** On Slave **** -SELECT * FROM t1; -a b +Comparing tables master:test.t1 and slave:test.t1 +==== Test using a table with delete triggers ==== **** On Master **** -DROP TABLE t1; -show binlog events from ; -Log_name Pos Event_type Server_id End_log_pos Info -master-bin.000001 # Query # # use `test`; DROP TABLE IF EXISTS t1 -master-bin.000001 # Query # # use `test`; CREATE TABLE t1 (a INT, b LONG) ENGINE=MyISAM -master-bin.000001 # Query # # use `test`; INSERT INTO t1 VALUES (1,1), (2,2) -master-bin.000001 # Query # # use `test`; DELETE FROM t1 -master-bin.000001 # Query # # use `test`; DROP TABLE t1 -RESET MASTER; -STOP SLAVE; -DROP TABLE IF EXISTS t1; -DROP TABLE IF EXISTS t1; -RESET SLAVE; -START SLAVE; -**** On Master **** -SET SESSION BINLOG_FORMAT=MIXED; -SET GLOBAL BINLOG_FORMAT=MIXED; -CREATE TABLE t1 (a INT, b LONG) ENGINE=MyISAM; -INSERT INTO t1 VALUES (1,1), (2,2); -SELECT * FROM t1; -a b -1 1 -2 2 -**** On Slave **** -INSERT INTO t1 VALUE (3,3); -SELECT * FROM t1; -a b -1 1 -2 2 -3 3 +SET @count := 1; +CREATE TABLE t2 (a INT, b LONG) ENGINE=MyISAM; +CREATE TRIGGER trg1 BEFORE DELETE ON t1 FOR EACH ROW SET @count := @count + 1; **** On Master **** DELETE FROM t1; -SELECT * FROM t1; -a b -**** On Slave **** -SELECT * FROM t1; -a b -**** On Master **** -DROP TABLE t1; -show binlog events from ; -Log_name Pos Event_type Server_id End_log_pos Info -master-bin.000001 # Query # # use `test`; DROP TABLE IF EXISTS t1 -master-bin.000001 # Query # # use `test`; CREATE TABLE t1 (a INT, b LONG) ENGINE=MyISAM -master-bin.000001 # Query # # use `test`; INSERT INTO t1 VALUES (1,1), (2,2) -master-bin.000001 # Query # # use `test`; DELETE FROM t1 -master-bin.000001 # Query # # use `test`; DROP TABLE t1 -RESET MASTER; -STOP SLAVE; -DROP TABLE IF EXISTS t1; -DROP TABLE IF EXISTS t1; -RESET SLAVE; -START SLAVE; -**** On Master **** -SET SESSION BINLOG_FORMAT=ROW; -SET GLOBAL BINLOG_FORMAT=ROW; -CREATE TABLE t1 (a INT, b LONG) ENGINE=MyISAM; -INSERT INTO t1 VALUES (1,1), (2,2); -SELECT * FROM t1; -a b -1 1 -2 2 -**** On Slave **** -INSERT INTO t1 VALUE (3,3); -SELECT * FROM t1; -a b -1 1 -2 2 -3 3 -**** On Master **** -DELETE FROM t1; -SELECT * FROM t1; -a b -**** On Slave **** -SELECT * FROM t1; -a b -3 3 -**** On Master **** -DROP TABLE t1; -show binlog events from ; -Log_name Pos Event_type Server_id End_log_pos Info -master-bin.000001 # Query # # use `test`; DROP TABLE IF EXISTS t1 -master-bin.000001 # Query # # use `test`; CREATE TABLE t1 (a INT, b LONG) ENGINE=MyISAM -master-bin.000001 # Query # # use `test`; BEGIN -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Query # # use `test`; COMMIT -master-bin.000001 # Query # # use `test`; BEGIN -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Delete_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Query # # use `test`; COMMIT -master-bin.000001 # Query # # use `test`; DROP TABLE t1 -RESET MASTER; +Comparing tables master:test.t2 and slave:test.t2 +DROP TABLE t1,t2; diff --git a/mysql-test/suite/rpl/r/rpl_truncate_3innodb.result b/mysql-test/suite/rpl/r/rpl_truncate_3innodb.result index 728b8450314..665d0b153e0 100644 --- a/mysql-test/suite/rpl/r/rpl_truncate_3innodb.result +++ b/mysql-test/suite/rpl/r/rpl_truncate_3innodb.result @@ -4,259 +4,43 @@ reset master; reset slave; drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; start slave; +**** Resetting master and slave **** STOP SLAVE; -DROP TABLE IF EXISTS t1; -DROP TABLE IF EXISTS t1; RESET SLAVE; +RESET MASTER; START SLAVE; **** On Master **** -SET SESSION BINLOG_FORMAT=STATEMENT; -SET GLOBAL BINLOG_FORMAT=STATEMENT; CREATE TABLE t1 (a INT, b LONG) ENGINE=InnoDB; INSERT INTO t1 VALUES (1,1), (2,2); -SELECT * FROM t1; -a b -1 1 -2 2 -**** On Slave **** -INSERT INTO t1 VALUE (3,3); -SELECT * FROM t1; -a b -1 1 -2 2 -3 3 **** On Master **** TRUNCATE TABLE t1; -SELECT * FROM t1; -a b -**** On Slave **** -SELECT * FROM t1; -a b +Comparing tables master:test.t1 and slave:test.t1 +==== Test using a table with delete triggers ==== **** On Master **** -DROP TABLE t1; -show binlog events from ; -Log_name Pos Event_type Server_id End_log_pos Info -master-bin.000001 # Query # # use `test`; DROP TABLE IF EXISTS t1 -master-bin.000001 # Query # # use `test`; CREATE TABLE t1 (a INT, b LONG) ENGINE=InnoDB -master-bin.000001 # Query # # use `test`; BEGIN -master-bin.000001 # Query # # use `test`; INSERT INTO t1 VALUES (1,1), (2,2) -master-bin.000001 # Xid # # COMMIT /* XID */ -master-bin.000001 # Query # # use `test`; BEGIN -master-bin.000001 # Query # # use `test`; TRUNCATE TABLE t1 -master-bin.000001 # Xid # # COMMIT /* XID */ -master-bin.000001 # Query # # use `test`; DROP TABLE t1 -RESET MASTER; -STOP SLAVE; -DROP TABLE IF EXISTS t1; -DROP TABLE IF EXISTS t1; -RESET SLAVE; -START SLAVE; -**** On Master **** -SET SESSION BINLOG_FORMAT=MIXED; -SET GLOBAL BINLOG_FORMAT=MIXED; -CREATE TABLE t1 (a INT, b LONG) ENGINE=InnoDB; -INSERT INTO t1 VALUES (1,1), (2,2); -SELECT * FROM t1; -a b -1 1 -2 2 -**** On Slave **** -INSERT INTO t1 VALUE (3,3); -SELECT * FROM t1; -a b -1 1 -2 2 -3 3 +SET @count := 1; +CREATE TABLE t2 (a INT, b LONG) ENGINE=InnoDB; +CREATE TRIGGER trg1 BEFORE DELETE ON t1 FOR EACH ROW SET @count := @count + 1; **** On Master **** TRUNCATE TABLE t1; -SELECT * FROM t1; -a b -**** On Slave **** -SELECT * FROM t1; -a b -**** On Master **** -DROP TABLE t1; -show binlog events from ; -Log_name Pos Event_type Server_id End_log_pos Info -master-bin.000001 # Query # # use `test`; DROP TABLE IF EXISTS t1 -master-bin.000001 # Query # # use `test`; CREATE TABLE t1 (a INT, b LONG) ENGINE=InnoDB -master-bin.000001 # Query # # use `test`; BEGIN -master-bin.000001 # Query # # use `test`; INSERT INTO t1 VALUES (1,1), (2,2) -master-bin.000001 # Xid # # COMMIT /* XID */ -master-bin.000001 # Query # # use `test`; BEGIN -master-bin.000001 # Query # # use `test`; TRUNCATE TABLE t1 -master-bin.000001 # Xid # # COMMIT /* XID */ -master-bin.000001 # Query # # use `test`; DROP TABLE t1 -RESET MASTER; +Comparing tables master:test.t2 and slave:test.t2 +DROP TABLE t1,t2; +**** Resetting master and slave **** STOP SLAVE; -DROP TABLE IF EXISTS t1; -DROP TABLE IF EXISTS t1; RESET SLAVE; +RESET MASTER; START SLAVE; **** On Master **** -SET SESSION BINLOG_FORMAT=ROW; -SET GLOBAL BINLOG_FORMAT=ROW; CREATE TABLE t1 (a INT, b LONG) ENGINE=InnoDB; INSERT INTO t1 VALUES (1,1), (2,2); -SELECT * FROM t1; -a b -1 1 -2 2 -**** On Slave **** -INSERT INTO t1 VALUE (3,3); -SELECT * FROM t1; -a b -1 1 -2 2 -3 3 -**** On Master **** -TRUNCATE TABLE t1; -SELECT * FROM t1; -a b -**** On Slave **** -SELECT * FROM t1; -a b -**** On Master **** -DROP TABLE t1; -show binlog events from ; -Log_name Pos Event_type Server_id End_log_pos Info -master-bin.000001 # Query # # use `test`; DROP TABLE IF EXISTS t1 -master-bin.000001 # Query # # use `test`; CREATE TABLE t1 (a INT, b LONG) ENGINE=InnoDB -master-bin.000001 # Query # # use `test`; BEGIN -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Xid # # COMMIT /* XID */ -master-bin.000001 # Query # # use `test`; BEGIN -master-bin.000001 # Query # # use `test`; TRUNCATE TABLE t1 -master-bin.000001 # Xid # # COMMIT /* XID */ -master-bin.000001 # Query # # use `test`; DROP TABLE t1 -RESET MASTER; -STOP SLAVE; -DROP TABLE IF EXISTS t1; -DROP TABLE IF EXISTS t1; -RESET SLAVE; -START SLAVE; -**** On Master **** -SET SESSION BINLOG_FORMAT=STATEMENT; -SET GLOBAL BINLOG_FORMAT=STATEMENT; -CREATE TABLE t1 (a INT, b LONG) ENGINE=InnoDB; -INSERT INTO t1 VALUES (1,1), (2,2); -SELECT * FROM t1; -a b -1 1 -2 2 -**** On Slave **** -INSERT INTO t1 VALUE (3,3); -SELECT * FROM t1; -a b -1 1 -2 2 -3 3 **** On Master **** DELETE FROM t1; -SELECT * FROM t1; -a b -**** On Slave **** -SELECT * FROM t1; -a b +Comparing tables master:test.t1 and slave:test.t1 +==== Test using a table with delete triggers ==== **** On Master **** -DROP TABLE t1; -show binlog events from ; -Log_name Pos Event_type Server_id End_log_pos Info -master-bin.000001 # Query # # use `test`; DROP TABLE IF EXISTS t1 -master-bin.000001 # Query # # use `test`; CREATE TABLE t1 (a INT, b LONG) ENGINE=InnoDB -master-bin.000001 # Query # # use `test`; BEGIN -master-bin.000001 # Query # # use `test`; INSERT INTO t1 VALUES (1,1), (2,2) -master-bin.000001 # Xid # # COMMIT /* XID */ -master-bin.000001 # Query # # use `test`; BEGIN -master-bin.000001 # Query # # use `test`; DELETE FROM t1 -master-bin.000001 # Xid # # COMMIT /* XID */ -master-bin.000001 # Query # # use `test`; DROP TABLE t1 -RESET MASTER; -STOP SLAVE; -DROP TABLE IF EXISTS t1; -DROP TABLE IF EXISTS t1; -RESET SLAVE; -START SLAVE; -**** On Master **** -SET SESSION BINLOG_FORMAT=MIXED; -SET GLOBAL BINLOG_FORMAT=MIXED; -CREATE TABLE t1 (a INT, b LONG) ENGINE=InnoDB; -INSERT INTO t1 VALUES (1,1), (2,2); -SELECT * FROM t1; -a b -1 1 -2 2 -**** On Slave **** -INSERT INTO t1 VALUE (3,3); -SELECT * FROM t1; -a b -1 1 -2 2 -3 3 +SET @count := 1; +CREATE TABLE t2 (a INT, b LONG) ENGINE=InnoDB; +CREATE TRIGGER trg1 BEFORE DELETE ON t1 FOR EACH ROW SET @count := @count + 1; **** On Master **** DELETE FROM t1; -SELECT * FROM t1; -a b -**** On Slave **** -SELECT * FROM t1; -a b -**** On Master **** -DROP TABLE t1; -show binlog events from ; -Log_name Pos Event_type Server_id End_log_pos Info -master-bin.000001 # Query # # use `test`; DROP TABLE IF EXISTS t1 -master-bin.000001 # Query # # use `test`; CREATE TABLE t1 (a INT, b LONG) ENGINE=InnoDB -master-bin.000001 # Query # # use `test`; BEGIN -master-bin.000001 # Query # # use `test`; INSERT INTO t1 VALUES (1,1), (2,2) -master-bin.000001 # Xid # # COMMIT /* XID */ -master-bin.000001 # Query # # use `test`; BEGIN -master-bin.000001 # Query # # use `test`; DELETE FROM t1 -master-bin.000001 # Xid # # COMMIT /* XID */ -master-bin.000001 # Query # # use `test`; DROP TABLE t1 -RESET MASTER; -STOP SLAVE; -DROP TABLE IF EXISTS t1; -DROP TABLE IF EXISTS t1; -RESET SLAVE; -START SLAVE; -**** On Master **** -SET SESSION BINLOG_FORMAT=ROW; -SET GLOBAL BINLOG_FORMAT=ROW; -CREATE TABLE t1 (a INT, b LONG) ENGINE=InnoDB; -INSERT INTO t1 VALUES (1,1), (2,2); -SELECT * FROM t1; -a b -1 1 -2 2 -**** On Slave **** -INSERT INTO t1 VALUE (3,3); -SELECT * FROM t1; -a b -1 1 -2 2 -3 3 -**** On Master **** -DELETE FROM t1; -SELECT * FROM t1; -a b -**** On Slave **** -SELECT * FROM t1; -a b -3 3 -**** On Master **** -DROP TABLE t1; -show binlog events from ; -Log_name Pos Event_type Server_id End_log_pos Info -master-bin.000001 # Query # # use `test`; DROP TABLE IF EXISTS t1 -master-bin.000001 # Query # # use `test`; CREATE TABLE t1 (a INT, b LONG) ENGINE=InnoDB -master-bin.000001 # Query # # use `test`; BEGIN -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Xid # # COMMIT /* XID */ -master-bin.000001 # Query # # use `test`; BEGIN -master-bin.000001 # Table_map # # table_id: # (test.t1) -master-bin.000001 # Delete_rows # # table_id: # flags: STMT_END_F -master-bin.000001 # Xid # # COMMIT /* XID */ -master-bin.000001 # Query # # use `test`; DROP TABLE t1 -RESET MASTER; +Comparing tables master:test.t2 and slave:test.t2 +DROP TABLE t1,t2; diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 6db9f1df0f2..d17bf085e3b 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -5103,8 +5103,15 @@ int decide_logging_format(THD *thd, TABLE_LIST *tables) { if (mysql_bin_log.is_open() && (thd->options & OPTION_BIN_LOG)) { - handler::Table_flags flags_some_set= handler::Table_flags(); - handler::Table_flags flags_all_set= ~handler::Table_flags(); + /* + Compute the starting vectors for the computations by creating a + set with all the capabilities bits set and one with no + capabilities bits set. + */ + handler::Table_flags flags_some_set= 0; + handler::Table_flags flags_all_set= + HA_BINLOG_ROW_CAPABLE | HA_BINLOG_STMT_CAPABLE; + my_bool multi_engine= FALSE; void* prev_ht= NULL; for (TABLE_LIST *table= tables; table; table= table->next_global) diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc index b56e042e3d5..b37e2a24895 100644 --- a/sql/sql_delete.cc +++ b/sql/sql_delete.cc @@ -51,6 +51,11 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, THD::killed_state killed_status= THD::NOT_KILLED; DBUG_ENTER("mysql_delete"); + THD::enum_binlog_query_type query_type= + thd->lex->sql_command == SQLCOM_TRUNCATE ? + THD::STMT_QUERY_TYPE : + THD::ROW_QUERY_TYPE; + if (open_and_lock_tables(thd, table_list)) DBUG_RETURN(TRUE); if (!(table= table_list->table)) @@ -135,6 +140,11 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, DBUG_PRINT("debug", ("Trying to use delete_all_rows()")); if (!(error=table->file->ha_delete_all_rows())) { + /* + If delete_all_rows() is used, it is not possible to log the + query in row format, so we have to log it in statement format. + */ + query_type= THD::STMT_QUERY_TYPE; error= -1; // ok deleted= maybe_deleted; goto cleanup; @@ -374,6 +384,11 @@ cleanup: { if (mysql_bin_log.is_open()) { + bool const is_trans= + thd->lex->sql_command == SQLCOM_TRUNCATE ? + FALSE : + transactional_table; + if (error < 0) thd->clear_error(); /* @@ -381,10 +396,13 @@ cleanup: storage engine does not inject the rows itself, we replicate statement-based; otherwise, 'ha_delete_row()' was used to delete specific rows which we might log row-based. + + Note that TRUNCATE TABLE is not transactional and should + therefore be treated as a DDL. */ - int log_result= thd->binlog_query(THD::ROW_QUERY_TYPE, + int log_result= thd->binlog_query(query_type, thd->query, thd->query_length, - transactional_table, FALSE, killed_status); + is_trans, FALSE, killed_status); if (log_result && transactional_table) { From d66dc230652002fabfb539da516e907553024c27 Mon Sep 17 00:00:00 2001 From: "Tatiana A. Nurnberg" Date: Fri, 6 Feb 2009 18:25:08 +0100 Subject: [PATCH 042/219] Bug#42525: TIMEDIFF function In 37553 we declared longlong results for class Item_str_timefunc as per comments/docs, but didn't add a method for that. And the default just wasn't good enough for some cases. Changeset adds dedicated val_int() to class. mysql-test/r/func_sapdb.result: More tests for casts of TIME() / TIMEDIFF() with negative results. mysql-test/t/func_sapdb.test: More tests for casts of TIME() / TIMEDIFF() with negative results. sql/item_timefunc.h: Since we claim to provide longlong results, we should have a suitable function to provide them (the default won't do). This one matches the val_real() variant. --- mysql-test/r/func_sapdb.result | 14 ++++++++++++++ mysql-test/t/func_sapdb.test | 18 ++++++++++++++++++ sql/item_timefunc.h | 1 + 3 files changed, 33 insertions(+) diff --git a/mysql-test/r/func_sapdb.result b/mysql-test/r/func_sapdb.result index a06d7004908..3a8515c8831 100644 --- a/mysql-test/r/func_sapdb.result +++ b/mysql-test/r/func_sapdb.result @@ -268,3 +268,17 @@ timediff('2008-09-29 20:10:10','2008-09-30 20:10:10') Date: Sat, 7 Feb 2009 05:47:21 +0100 Subject: [PATCH 043/219] Raise version number after cloning 5.0.78 --- configure.in | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/configure.in b/configure.in index 12c31b33d1b..9591b5bbc5a 100644 --- a/configure.in +++ b/configure.in @@ -7,7 +7,7 @@ AC_INIT(sql/mysqld.cc) AC_CANONICAL_SYSTEM # The Docs Makefile.am parses this line! # remember to also change ndb version below and update version.c in ndb -AM_INIT_AUTOMAKE(mysql, 5.0.78) +AM_INIT_AUTOMAKE(mysql, 5.0.79) AM_CONFIG_HEADER([include/config.h:config.h.in]) PROTOCOL_VERSION=10 @@ -23,7 +23,7 @@ NDB_SHARED_LIB_VERSION=$NDB_SHARED_LIB_MAJOR_VERSION:0:0 # ndb version NDB_VERSION_MAJOR=5 NDB_VERSION_MINOR=0 -NDB_VERSION_BUILD=78 +NDB_VERSION_BUILD=79 NDB_VERSION_STATUS="" # Set all version vars based on $VERSION. How do we do this more elegant ? From 461cad77b4e068ecc2534150170a029e6f425407 Mon Sep 17 00:00:00 2001 From: Vladislav Vaintroub Date: Mon, 9 Feb 2009 13:10:34 +0100 Subject: [PATCH 044/219] Bug#42427 : MTR v2 fails with "can't write to /tmp/mysql-test-ports.sem" on Windows - /tmp directory is not guaranteed to exist on Windows. Use the value of environment variable TEMP here --- mysql-test/lib/mtr_unique.pm | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/mysql-test/lib/mtr_unique.pm b/mysql-test/lib/mtr_unique.pm index b4093ab1dce..2ac172883a2 100644 --- a/mysql-test/lib/mtr_unique.pm +++ b/mysql-test/lib/mtr_unique.pm @@ -28,7 +28,17 @@ sub msg { # print "### unique($$) - ", join(" ", @_), "\n"; } -my $file= "/tmp/mysql-test-ports"; +my $file; + +if(!IS_WINDOWS) +{ + $file= "/tmp/mysql-test-ports"; +} +else +{ + $file= $ENV{'TEMP'}."/mysql-test-ports"; +} + my %mtr_unique_ids; From 5fc4c37a8050c9457b371cdb368f6cea5b35f48a Mon Sep 17 00:00:00 2001 From: Andrei Elkin Date: Mon, 9 Feb 2009 15:17:04 +0200 Subject: [PATCH 045/219] Bug #42451 setup_fake_relay_log makes an incorrect path on windows Path composition for the relay log file that is stored into the relay index file was not correct for windows. mysql-test language does not provide primitives for portable path composition. Fixed with storing only the basename part of the external "fake" relay log into the relay index file. Safety of removal of the dirname part of the relaylog is provided by logics of `setup_fake_relay_log' that places the fake file into @@datadir directory. mysql-test/include/setup_fake_relay_log.inc: storing only the basename part of the external "fake" relay log into the relay log index. mysql-test/suite/rpl/t/rpl_cross_version.test: restoring test for windows. --- mysql-test/include/setup_fake_relay_log.inc | 4 ++-- mysql-test/suite/rpl/t/rpl_cross_version.test | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/mysql-test/include/setup_fake_relay_log.inc b/mysql-test/include/setup_fake_relay_log.inc index 79ff7429466..f88806e1079 100644 --- a/mysql-test/include/setup_fake_relay_log.inc +++ b/mysql-test/include/setup_fake_relay_log.inc @@ -69,9 +69,9 @@ let $_fake_relay_log_purge= `SELECT @@global.relay_log_purge`; # Create relay log file. copy_file $fake_relay_log $_fake_relay_log; # Create relay log index. ---exec echo $_fake_relay_log > $_fake_relay_index +--exec echo $_fake_filename-fake.000001 > $_fake_relay_index # Setup replication from existing relay log. -eval CHANGE MASTER TO MASTER_HOST='dummy.localdomain', RELAY_LOG_FILE='$_fake_relay_log', RELAY_LOG_POS=4; +eval CHANGE MASTER TO MASTER_HOST='dummy.localdomain', RELAY_LOG_FILE='$_fake_filename-fake.000001', RELAY_LOG_POS=4; --enable_query_log diff --git a/mysql-test/suite/rpl/t/rpl_cross_version.test b/mysql-test/suite/rpl/t/rpl_cross_version.test index adeba7f2b15..bb2ca350152 100644 --- a/mysql-test/suite/rpl/t/rpl_cross_version.test +++ b/mysql-test/suite/rpl/t/rpl_cross_version.test @@ -11,7 +11,7 @@ # --source include/have_log_bin.inc ---source include/not_windows.inc + # # Bug#31240 load data infile replication between (4.0 or 4.1) and 5.1 fails # From 4d0557a2e6e2f79e3662d3f10ea17656cf69ca12 Mon Sep 17 00:00:00 2001 From: Sergey Glukhov Date: Mon, 9 Feb 2009 19:03:52 +0400 Subject: [PATCH 046/219] Bug#42610 Dynamic plugin broken in 5.1.31 added ignore-builtin-innodb option which disabled initialization of builtin InnoDB plugin mysql-test/r/innodb_ignore_builtin.result: test case mysql-test/t/innodb_ignore_builtin-master.opt: test case mysql-test/t/innodb_ignore_builtin.test: test case sql/mysql_priv.h: added ignore-builtin-innodb option which disabled initialization of builtin InnoDB plugin sql/mysqld.cc: added ignore-builtin-innodb option which disabled initialization of builtin InnoDB plugin sql/set_var.cc: added ignore-builtin-innodb option which disabled initialization of builtin InnoDB plugin sql/sql_plugin.cc: added ignore-builtin-innodb option which disabled initialization of builtin InnoDB plugin --- mysql-test/r/innodb_ignore_builtin.result | 9 +++++++++ mysql-test/t/innodb_ignore_builtin-master.opt | 1 + mysql-test/t/innodb_ignore_builtin.test | 8 ++++++++ sql/mysql_priv.h | 1 + sql/mysqld.cc | 12 ++++++++++-- sql/set_var.cc | 5 +++++ sql/sql_plugin.cc | 3 +++ 7 files changed, 37 insertions(+), 2 deletions(-) create mode 100644 mysql-test/r/innodb_ignore_builtin.result create mode 100644 mysql-test/t/innodb_ignore_builtin-master.opt create mode 100644 mysql-test/t/innodb_ignore_builtin.test diff --git a/mysql-test/r/innodb_ignore_builtin.result b/mysql-test/r/innodb_ignore_builtin.result new file mode 100644 index 00000000000..4694a61b20a --- /dev/null +++ b/mysql-test/r/innodb_ignore_builtin.result @@ -0,0 +1,9 @@ +show variables like 'ignore_builtin_innodb'; +Variable_name Value +ignore_builtin_innodb ON +select PLUGIN_NAME from information_schema.plugins +where PLUGIN_NAME = "InnoDb"; +PLUGIN_NAME +select ENGINE from information_schema.engines +where ENGINE = "InnoDB"; +ENGINE diff --git a/mysql-test/t/innodb_ignore_builtin-master.opt b/mysql-test/t/innodb_ignore_builtin-master.opt new file mode 100644 index 00000000000..f7289eed20e --- /dev/null +++ b/mysql-test/t/innodb_ignore_builtin-master.opt @@ -0,0 +1 @@ +--ignore_builtin_innodb diff --git a/mysql-test/t/innodb_ignore_builtin.test b/mysql-test/t/innodb_ignore_builtin.test new file mode 100644 index 00000000000..6f987bcf891 --- /dev/null +++ b/mysql-test/t/innodb_ignore_builtin.test @@ -0,0 +1,8 @@ +# +# Bug #42610: Dynamic plugin broken in 5.1.31 +# +show variables like 'ignore_builtin_innodb'; +select PLUGIN_NAME from information_schema.plugins +where PLUGIN_NAME = "InnoDb"; +select ENGINE from information_schema.engines +where ENGINE = "InnoDB"; diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index 9ce8077249c..015128cda1f 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -1953,6 +1953,7 @@ extern my_bool opt_log, opt_slow_log; extern ulong log_output_options; extern my_bool opt_log_queries_not_using_indexes; extern bool opt_disable_networking, opt_skip_show_db; +extern bool opt_ignore_builtin_innodb; extern my_bool opt_character_set_client_handshake; extern bool volatile abort_loop, shutdown_in_progress; extern uint volatile thread_count, thread_running, global_read_lock; diff --git a/sql/mysqld.cc b/sql/mysqld.cc index a2ccbc42e77..0213eea889b 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -378,7 +378,7 @@ static pthread_cond_t COND_thread_cache, COND_flush_thread_cache; /* Global variables */ -bool opt_update_log, opt_bin_log; +bool opt_update_log, opt_bin_log, opt_ignore_builtin_innodb= 0; my_bool opt_log, opt_slow_log; ulong log_output_options; my_bool opt_log_queries_not_using_indexes= 0; @@ -5585,7 +5585,8 @@ enum options_mysqld OPT_OLD_MODE, OPT_SLAVE_EXEC_MODE, OPT_GENERAL_LOG_FILE, - OPT_SLOW_QUERY_LOG_FILE + OPT_SLOW_QUERY_LOG_FILE, + OPT_IGNORE_BUILTIN_INNODB }; @@ -5791,6 +5792,9 @@ Disable with --skip-large-pages.", (uchar**) &opt_large_pages, (uchar**) &opt_large_pages, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, #endif + {"ignore-builtin-innodb", OPT_IGNORE_BUILTIN_INNODB , + "Disable initialization of builtin InnoDB plugin", + 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, {"init-connect", OPT_INIT_CONNECT, "Command(s) that are executed for each new connection", (uchar**) &opt_init_connect, (uchar**) &opt_init_connect, 0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, @@ -7484,6 +7488,7 @@ static int mysql_init_variables(void) log_output_options= find_bit_type(log_output_str, &log_output_typelib); opt_bin_log= 0; opt_disable_networking= opt_skip_show_db=0; + opt_ignore_builtin_innodb= 0; opt_logname= opt_update_logname= opt_binlog_index_name= opt_slow_logname= 0; opt_tc_log_file= (char *)"tc.log"; // no hostname in tc_log file name ! opt_secure_auth= 0; @@ -7781,6 +7786,9 @@ mysqld_get_one_option(int optid, case (int) OPT_BIG_TABLES: thd_startup_options|=OPTION_BIG_TABLES; break; + case (int) OPT_IGNORE_BUILTIN_INNODB: + opt_ignore_builtin_innodb= 1; + break; case (int) OPT_ISAM_LOG: opt_myisam_log=1; break; diff --git a/sql/set_var.cc b/sql/set_var.cc index 07e1528d483..f14068fcfcb 100644 --- a/sql/set_var.cc +++ b/sql/set_var.cc @@ -275,6 +275,11 @@ static sys_var_const sys_ft_query_expansion_limit(&vars, static sys_var_const sys_ft_stopword_file(&vars, "ft_stopword_file", OPT_GLOBAL, SHOW_CHAR_PTR, (uchar*) &ft_stopword_file); + +static sys_var_const sys_ignore_builtin_innodb(&vars, "ignore_builtin_innodb", + OPT_GLOBAL, SHOW_BOOL, + (uchar*) &opt_ignore_builtin_innodb); + sys_var_str sys_init_connect(&vars, "init_connect", 0, sys_update_init_connect, sys_default_init_connect,0); diff --git a/sql/sql_plugin.cc b/sql/sql_plugin.cc index 0df1631294b..60f205ec8e8 100644 --- a/sql/sql_plugin.cc +++ b/sql/sql_plugin.cc @@ -1138,6 +1138,9 @@ int plugin_init(int *argc, char **argv, int flags) { for (plugin= *builtins; plugin->info; plugin++) { + if (opt_ignore_builtin_innodb && + !my_strcasecmp(&my_charset_latin1, plugin->name, "InnoDB")) + continue; /* by default, ndbcluster and federated are disabled */ def_enabled= my_strcasecmp(&my_charset_latin1, plugin->name, "NDBCLUSTER") != 0 && From bab4ff1ae52762e5eeb828d89cc7cd3b6e94f3aa Mon Sep 17 00:00:00 2001 From: Davi Arnaut Date: Mon, 9 Feb 2009 16:17:58 -0200 Subject: [PATCH 047/219] Bug#42634: % character in query can cause mysqld signal 11 segfault The problem is that a unfiltered user query was being passed as the format string parameter of sql_print_warning which later performs printf-like formatting, leading to crashes if the user query contains formatting instructions (ie: %s). Also, it was using THD::query as the source of the user query, but this variable is not meaningful in some situations -- in a delayed insert, it points to the table name. The solution is to pass the user query as a parameter for the format string and use the function parameter query_arg as the source of the user query. mysql-test/suite/binlog/r/binlog_unsafe.result: Add test case result for Bug#42634 mysql-test/suite/binlog/t/binlog_unsafe.test: Add test case for Bug#42634 sql/sql_class.cc: Don't pass the user query as a format string. --- mysql-test/suite/binlog/r/binlog_unsafe.result | 7 +++++++ mysql-test/suite/binlog/t/binlog_unsafe.test | 14 ++++++++++++++ sql/sql_class.cc | 8 +++----- 3 files changed, 24 insertions(+), 5 deletions(-) diff --git a/mysql-test/suite/binlog/r/binlog_unsafe.result b/mysql-test/suite/binlog/r/binlog_unsafe.result index 1f7b217dc31..7c0980ba77c 100644 --- a/mysql-test/suite/binlog/r/binlog_unsafe.result +++ b/mysql-test/suite/binlog/r/binlog_unsafe.result @@ -220,3 +220,10 @@ Warning 1592 Statement is not safe to log in statement format. Warning 1592 Statement is not safe to log in statement format. DROP PROCEDURE p1; DROP TABLE t1; +DROP TABLE IF EXISTS t1; +CREATE TABLE t1 (a VARCHAR(100), b VARCHAR(100)); +INSERT INTO t1 VALUES ('a','b'); +UPDATE t1 SET b = '%s%s%s%s%s%s%s%s%s%s%s%s%s%s' WHERE a = 'a' LIMIT 1; +Warnings: +Warning 1592 Statement is not safe to log in statement format. +DROP TABLE t1; diff --git a/mysql-test/suite/binlog/t/binlog_unsafe.test b/mysql-test/suite/binlog/t/binlog_unsafe.test index 0d7059bc31f..f58233d4fef 100644 --- a/mysql-test/suite/binlog/t/binlog_unsafe.test +++ b/mysql-test/suite/binlog/t/binlog_unsafe.test @@ -257,3 +257,17 @@ delimiter ;| CALL p1(); DROP PROCEDURE p1; DROP TABLE t1; + +# +# Bug#42634: % character in query can cause mysqld signal 11 segfault +# + +--disable_warnings +DROP TABLE IF EXISTS t1; +--enable_warnings + +CREATE TABLE t1 (a VARCHAR(100), b VARCHAR(100)); +INSERT INTO t1 VALUES ('a','b'); +UPDATE t1 SET b = '%s%s%s%s%s%s%s%s%s%s%s%s%s%s' WHERE a = 'a' LIMIT 1; +DROP TABLE t1; + diff --git a/sql/sql_class.cc b/sql/sql_class.cc index 06f1c644be0..118dc5af68f 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -3660,16 +3660,14 @@ int THD::binlog_query(THD::enum_binlog_query_type qtype, char const *query_arg, if (lex->is_stmt_unsafe() && variables.binlog_format == BINLOG_FORMAT_STMT) { - DBUG_ASSERT(this->query != NULL); push_warning(this, MYSQL_ERROR::WARN_LEVEL_WARN, ER_BINLOG_UNSAFE_STATEMENT, ER(ER_BINLOG_UNSAFE_STATEMENT)); if (!(binlog_flags & BINLOG_FLAG_UNSAFE_STMT_PRINTED)) { - char warn_buf[MYSQL_ERRMSG_SIZE]; - my_snprintf(warn_buf, MYSQL_ERRMSG_SIZE, "%s Statement: %s", - ER(ER_BINLOG_UNSAFE_STATEMENT), this->query); - sql_print_warning(warn_buf); + sql_print_warning("%s Statement: %.*s", + ER(ER_BINLOG_UNSAFE_STATEMENT), + MYSQL_ERRMSG_SIZE, query_arg); binlog_flags|= BINLOG_FLAG_UNSAFE_STMT_PRINTED; } } From 20e5719574a4fa6ce1bc514646d24d3ea63c47cf Mon Sep 17 00:00:00 2001 From: Vladislav Vaintroub Date: Mon, 9 Feb 2009 19:24:48 +0100 Subject: [PATCH 048/219] Bug#42709: safe_process_win.cc does not print correct system error messages. Fix: use FormatMessage() to output system errors , not strerror() --- .../lib/My/SafeProcess/safe_process_win.cc | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/mysql-test/lib/My/SafeProcess/safe_process_win.cc b/mysql-test/lib/My/SafeProcess/safe_process_win.cc index 640254875c9..4fb89f098ed 100755 --- a/mysql-test/lib/My/SafeProcess/safe_process_win.cc +++ b/mysql-test/lib/My/SafeProcess/safe_process_win.cc @@ -77,14 +77,29 @@ static void message(const char* fmt, ...) static void die(const char* fmt, ...) { + DWORD last_err= GetLastError(); va_list args; fprintf(stderr, "%s: FATAL ERROR, ", safe_process_name); va_start(args, fmt); vfprintf(stderr, fmt, args); fprintf(stderr, "\n"); va_end(args); - if (int last_err= GetLastError()) - fprintf(stderr, "error: %d, %s\n", last_err, strerror(last_err)); + if (last_err) + { + char *message_text; + if (FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER + |FORMAT_MESSAGE_IGNORE_INSERTS, NULL, last_err , 0, (LPSTR)&message_text, + 0, NULL)) + { + fprintf(stderr,"error: %d, %s\n",last_err, message_text); + LocalFree(message_text); + } + else + { + /* FormatMessage failed, print error code only */ + fprintf(stderr,"error:%d\n", last_err); + } + } fflush(stderr); exit(1); } From 0fab1a857c12239e8c75e409f2a0c3ba4d021535 Mon Sep 17 00:00:00 2001 From: Matthias Leich Date: Mon, 9 Feb 2009 21:52:40 +0100 Subject: [PATCH 049/219] This belongs to the fix for Bug#42003 tests missing the disconnect of connections <> default second slice Content: 1. wait_until_count_sessions.inc - One PB run of a test using this routine failed because 5 seconds timeout were exceeded. Although I have some doubts if the assigned timeout was really too small, I increase the value to 10. We waste the additional 5 seconds only if the tests fails anyway. - Print the content of the PROCESSLIST if the poll routine fails 2. minor improvements of formatting 3. query_cache_notembedded: Activate the wait_until_count_sessions.inc routine which was unfortunately forgotten in the changeset before. --- .../include/wait_until_count_sessions.inc | 3 ++- mysql-test/r/information_schema.result | 2 +- mysql-test/r/subselect.result | 2 +- mysql-test/t/grant.test | 5 ++--- mysql-test/t/information_schema.test | 7 ++----- mysql-test/t/query_cache_notembedded.test | 2 +- mysql-test/t/subselect.test | 20 +++++++++---------- 7 files changed, 19 insertions(+), 22 deletions(-) diff --git a/mysql-test/include/wait_until_count_sessions.inc b/mysql-test/include/wait_until_count_sessions.inc index 36fa9accafe..41348bee129 100644 --- a/mysql-test/include/wait_until_count_sessions.inc +++ b/mysql-test/include/wait_until_count_sessions.inc @@ -82,7 +82,7 @@ # Created: 2009-01-14 mleich # -let $wait_counter= 50; +let $wait_counter= 100; if ($wait_timeout) { let $wait_counter= `SELECT $wait_timeout * 10`; @@ -108,5 +108,6 @@ if (!$success) { --echo # Timeout in wait_until_count_sessions.inc --echo # Number of sessions expected: $count_sessions found: $current_sessions + SHOW PROCESSLIST; } diff --git a/mysql-test/r/information_schema.result b/mysql-test/r/information_schema.result index 38c8d748870..6ced6bb373a 100644 --- a/mysql-test/r/information_schema.result +++ b/mysql-test/r/information_schema.result @@ -1027,7 +1027,7 @@ BEGIN SELECT 'foo' FROM DUAL; END | ERROR 42000: Unknown database 'information_schema' -select ROUTINE_NAME from routines; +select ROUTINE_NAME from routines; ROUTINE_NAME grant all on information_schema.* to 'user1'@'localhost'; ERROR 42000: Access denied for user 'root'@'localhost' to database 'information_schema' diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result index 671e5d8f532..0c7f9ae959c 100644 --- a/mysql-test/r/subselect.result +++ b/mysql-test/r/subselect.result @@ -4407,7 +4407,7 @@ pk a 3 30 2 20 DROP TABLE t1,t2; -CREATE TABLE t1 (s1 char(1)); +CREATE TABLE t1 (s1 CHAR(1)); INSERT INTO t1 VALUES ('a'); SELECT * FROM t1 WHERE _utf8'a' = ANY (SELECT s1 FROM t1); s1 diff --git a/mysql-test/t/grant.test b/mysql-test/t/grant.test index 6f6e8753004..1b2b8465c83 100644 --- a/mysql-test/t/grant.test +++ b/mysql-test/t/grant.test @@ -204,7 +204,7 @@ show grants for mysqltest_1@localhost; drop user mysqltest_1@localhost; # -# Bug#3403 Wrong encoding in SHOW GRANTS, EPLAIN SELECT output +# Bug#3403 Wrong encoding in SHOW GRANTS, EXPLAIN SELECT output # SET NAMES koi8r; CREATE DATABASE ÂÄ; @@ -384,7 +384,7 @@ update mysqltest_1.t1, mysqltest_1.t2 set a=100,b=200; update mysqltest_2.t1, mysqltest_1.t2 set c=100,b=200; --error ER_TABLEACCESS_DENIED_ERROR update mysqltest_1.t1, mysqltest_2.t2 set a=100,d=200; -#lets see the result +# lets see the result connection master; select t1.*,t2.* from mysqltest_1.t1,mysqltest_1.t2; select t1.*,t2.* from mysqltest_2.t1,mysqltest_2.t2; @@ -784,7 +784,6 @@ SHOW CREATE VIEW mysqltest2.v_yy; # succeed, have SELECT and SHOW VIEW SHOW CREATE TABLE mysqltest2.v_yy; - # clean-up connection master; diff --git a/mysql-test/t/information_schema.test b/mysql-test/t/information_schema.test index 5873347eae0..079f96777bf 100644 --- a/mysql-test/t/information_schema.test +++ b/mysql-test/t/information_schema.test @@ -676,7 +676,7 @@ drop table t1; # # Bug#12636 SHOW TABLE STATUS with where condition containing a subquery -# over information schema +# over information schema # CREATE TABLE t1 (a int); @@ -729,7 +729,7 @@ BEGIN SELECT 'foo' FROM DUAL; END | delimiter ;| -select ROUTINE_NAME from routines; +select ROUTINE_NAME from routines; # # Bug#10734 Grant of privileges other than 'select' and 'create view' should fail on schema # @@ -980,9 +980,6 @@ SELECT COLUMN_NAME, MD5(COLUMN_DEFAULT), LENGTH(COLUMN_DEFAULT), COLUMN_DEFAULT= DROP TABLE bug23037; DROP FUNCTION get_value; - - - # # Bug#22413 EXPLAIN SELECT FROM view with ORDER BY yield server crash # diff --git a/mysql-test/t/query_cache_notembedded.test b/mysql-test/t/query_cache_notembedded.test index b8b223ecd8c..d98ed691c7b 100644 --- a/mysql-test/t/query_cache_notembedded.test +++ b/mysql-test/t/query_cache_notembedded.test @@ -262,4 +262,4 @@ SET GLOBAL query_cache_size= default; # End of 5.0 tests # Wait till we reached the initial number of concurrent sessions -#--source include/wait_until_count_sessions.inc +--source include/wait_until_count_sessions.inc diff --git a/mysql-test/t/subselect.test b/mysql-test/t/subselect.test index 57aaa00e643..26bd7c9e8dd 100644 --- a/mysql-test/t/subselect.test +++ b/mysql-test/t/subselect.test @@ -367,7 +367,7 @@ let $wait_condition= SELECT COUNT(*) <> $row_count_before FROM t1; --source include/wait_condition.inc select * from t1; # -#TODO: should be uncommented after bug 380 fix pushed +#TODO: should be uncommented after Bug#380 fix pushed #INSERT INTO t1 (x) SELECT (SELECT SUM(a)+b FROM t2) from t3; #select * from t1; drop table t1, t2, t3; @@ -2031,7 +2031,7 @@ DROP TABLE t1,t2,t3; # -# Bug24670 subquery witout tables but with a WHERE clause +# Bug#24670 subquery witout tables but with a WHERE clause # CREATE TABLE t1 (a int); @@ -2567,7 +2567,7 @@ DROP TABLE t1; # # Bug#21540 Subqueries with no from and aggregate functions return -# wrong results +# wrong results CREATE TABLE t1 (a INT, b INT); CREATE TABLE t2 (a INT); INSERT INTO t2 values (1); @@ -3379,7 +3379,7 @@ DROP TABLE t1,t2; # # Bug#20835 (literal string with =any values) # -CREATE TABLE t1 (s1 char(1)); +CREATE TABLE t1 (s1 CHAR(1)); INSERT INTO t1 VALUES ('a'); SELECT * FROM t1 WHERE _utf8'a' = ANY (SELECT s1 FROM t1); DROP TABLE t1; @@ -3409,13 +3409,13 @@ INSERT INTO t1 (id) VALUES (1); INSERT INTO t2 (id) VALUES (1); CREATE VIEW v1 AS - SELECT t2.c AS c FROM t1, t2 - WHERE t1.id=t2.id AND 1 IN (SELECT id FROM t1) WITH CHECK OPTION; +SELECT t2.c AS c FROM t1, t2 +WHERE t1.id=t2.id AND 1 IN (SELECT id FROM t1) WITH CHECK OPTION; UPDATE v1 SET c=1; CREATE VIEW v2 (a,b) AS - SELECT t2.id, t2.c AS c FROM t1, t2 - WHERE t1.id=t2.id AND 1 IN (SELECT id FROM t1) WITH CHECK OPTION; +SELECT t2.id, t2.c AS c FROM t1, t2 +WHERE t1.id=t2.id AND 1 IN (SELECT id FROM t1) WITH CHECK OPTION; --error ER_VIEW_CHECK_FAILED INSERT INTO v2(a,b) VALUES (2,2); @@ -3423,8 +3423,8 @@ INSERT INTO v2(a,b) VALUES (1,2); SELECT * FROM v1; CREATE VIEW v3 AS - SELECT t2.c AS c FROM t2 - WHERE 1 IN (SELECT id FROM t1) WITH CHECK OPTION; +SELECT t2.c AS c FROM t2 +WHERE 1 IN (SELECT id FROM t1) WITH CHECK OPTION; DELETE FROM v3; From f6ddcc6d4b8dbfb701ce056d404469209f2916e6 Mon Sep 17 00:00:00 2001 From: Davi Arnaut Date: Tue, 10 Feb 2009 01:00:11 -0200 Subject: [PATCH 050/219] Post-merge fix: Complete reversal of bug 33699. mysql-test/t/null.test: Revert fix for bug 33699. --- mysql-test/t/null.test | 2 -- 1 file changed, 2 deletions(-) diff --git a/mysql-test/t/null.test b/mysql-test/t/null.test index ddf6b8870fa..2878b54c357 100644 --- a/mysql-test/t/null.test +++ b/mysql-test/t/null.test @@ -61,9 +61,7 @@ drop table t1; # CREATE TABLE t1 (a varchar(16) NOT NULL default '', b smallint(6) NOT NULL default 0, c datetime NOT NULL default '0000-00-00 00:00:00', d smallint(6) NOT NULL default 0); INSERT INTO t1 SET a = "", d= "2003-01-14 03:54:55"; ---error 1048 UPDATE t1 SET d=1/NULL; ---error 1048 UPDATE t1 SET d=NULL; --error 1048 INSERT INTO t1 (a) values (null); From 13b564e461096aad0e94faa319c5f5c6d4a96635 Mon Sep 17 00:00:00 2001 From: Ramil Kalimullin Date: Tue, 10 Feb 2009 12:37:27 +0400 Subject: [PATCH 051/219] Fix for bug #40757: Starting server on Windows with innodb_flush_method=wrong_value causes crash Problem: after a failed plugin initialization, incompletely initialized data remained in the plugin and handlerton data structures. These were used later and caused the crash. Fix: clean-up plugin related data if initialization failed. Note: no test case added, hand tested. sql/handler.cc: Fix for bug #40757: Starting server on Windows with innodb_flush_method=wrong_value causes crash - free allocated hton and set plugin->data (pointing to handlerton) to NULL if plugin->init() fails, as we use it as a sign that ha_initialize_handlerton() is failed, which is used in ha_finalize_handlerton(). - do the same if there's no free slot for a plugin in the hton2plugin[] array or there are too many storage engines. - call plugin->deinit() in such cases as we successfully called plugin->init() before. --- sql/handler.cc | 35 +++++++++++++++++++++-------------- 1 file changed, 21 insertions(+), 14 deletions(-) diff --git a/sql/handler.cc b/sql/handler.cc index 948cb08b13f..853ab29d38a 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -429,14 +429,11 @@ int ha_initialize_handlerton(st_plugin_int *plugin) MYF(MY_WME | MY_ZEROFILL)); /* Historical Requirement */ plugin->data= hton; // shortcut for the future - if (plugin->plugin->init) + if (plugin->plugin->init && plugin->plugin->init(hton)) { - if (plugin->plugin->init(hton)) - { - sql_print_error("Plugin '%s' init function returned error.", - plugin->name.str); - goto err; - } + sql_print_error("Plugin '%s' init function returned error.", + plugin->name.str); + goto err; } /* @@ -463,17 +460,13 @@ int ha_initialize_handlerton(st_plugin_int *plugin) if (idx == (int) DB_TYPE_DEFAULT) { sql_print_warning("Too many storage engines!"); - DBUG_RETURN(1); + goto err_deinit; } if (hton->db_type != DB_TYPE_UNKNOWN) sql_print_warning("Storage engine '%s' has conflicting typecode. " "Assigning value %d.", plugin->plugin->name, idx); hton->db_type= (enum legacy_db_type) idx; } - installed_htons[hton->db_type]= hton; - tmp= hton->savepoint_offset; - hton->savepoint_offset= savepoint_alloc_size; - savepoint_alloc_size+= tmp; /* In case a plugin is uninstalled and re-installed later, it should @@ -494,11 +487,14 @@ int ha_initialize_handlerton(st_plugin_int *plugin) { sql_print_error("Too many plugins loaded. Limit is %lu. " "Failed on '%s'", (ulong) MAX_HA, plugin->name.str); - goto err; + goto err_deinit; } hton->slot= total_ha++; } - + installed_htons[hton->db_type]= hton; + tmp= hton->savepoint_offset; + hton->savepoint_offset= savepoint_alloc_size; + savepoint_alloc_size+= tmp; hton2plugin[hton->slot]=plugin; if (hton->prepare) total_ha_2pc++; @@ -530,7 +526,18 @@ int ha_initialize_handlerton(st_plugin_int *plugin) }; DBUG_RETURN(0); + +err_deinit: + /* + Let plugin do its inner deinitialization as plugin->init() + was successfully called before. + */ + if (plugin->plugin->deinit) + (void) plugin->plugin->deinit(NULL); + err: + my_free((uchar*) hton, MYF(0)); + plugin->data= NULL; DBUG_RETURN(1); } From 0669b79363b940c4673d972d1fa8142c2d3e0823 Mon Sep 17 00:00:00 2001 From: Georgi Kodinov Date: Tue, 10 Feb 2009 11:58:19 +0200 Subject: [PATCH 052/219] Bug #33813: Schema names are case-sensitive in DROP FUNCTION The parser was not using the correct fully-qualified-name production for DROP FUNCTION. Fixed by copying the production from DROP PROCEDURE. Tested in the windows specific suite to make sure it's tested on a case-insensitive file system. mysql-test/r/windows.result: Bug #33813: test case mysql-test/t/windows.test: Bug #33813: test case sql/sql_yacc.yy: Bug #33813: use the correct production for the name in DROP PROCEDURE --- mysql-test/r/windows.result | 18 ++++++++++++++++++ mysql-test/t/windows.test | 31 +++++++++++++++++++++++++++++++ sql/sql_yacc.yy | 33 +++------------------------------ 3 files changed, 52 insertions(+), 30 deletions(-) diff --git a/mysql-test/r/windows.result b/mysql-test/r/windows.result index 5a54db8bb84..43ba878b9a5 100644 --- a/mysql-test/r/windows.result +++ b/mysql-test/r/windows.result @@ -19,4 +19,22 @@ id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables 2 SUBQUERY NULL NULL NULL NULL NULL NULL NULL No tables used DROP TABLE t1; +CREATE DATABASE `TESTDB`; +USE `TESTDB`; +CREATE FUNCTION test_fn() RETURNS INTEGER +BEGIN +DECLARE rId bigint; +RETURN rId; +END +// +CREATE FUNCTION test_fn2() RETURNS INTEGER +BEGIN +DECLARE rId bigint; +RETURN rId; +END +// +DROP FUNCTION `TESTDB`.`test_fn`; +DROP FUNCTION `testdb`.`test_fn2`; +USE test; +DROP DATABASE `TESTDB`; End of 5.0 tests. diff --git a/mysql-test/t/windows.test b/mysql-test/t/windows.test index 6e6a7ec93a3..adaf8d3ea17 100755 --- a/mysql-test/t/windows.test +++ b/mysql-test/t/windows.test @@ -35,4 +35,35 @@ CREATE TABLE t1 (a int, b int); INSERT INTO t1 VALUES (1,1); EXPLAIN SELECT * FROM t1 WHERE b = (SELECT max(2)); DROP TABLE t1; +# +# Bug #33813: Schema names are case-sensitive in DROP FUNCTION +# + +CREATE DATABASE `TESTDB`; + +USE `TESTDB`; +DELIMITER //; + +CREATE FUNCTION test_fn() RETURNS INTEGER +BEGIN +DECLARE rId bigint; +RETURN rId; +END +// + +CREATE FUNCTION test_fn2() RETURNS INTEGER +BEGIN +DECLARE rId bigint; +RETURN rId; +END +// + +DELIMITER ;// + +DROP FUNCTION `TESTDB`.`test_fn`; +DROP FUNCTION `testdb`.`test_fn2`; + +USE test; +DROP DATABASE `TESTDB`; + --echo End of 5.0 tests. diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 0eefe782354..fbaf761cc33 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -7507,11 +7507,9 @@ drop: lex->drop_if_exists=$3; lex->name=$4.str; } - | DROP FUNCTION_SYM if_exists ident '.' ident + | DROP FUNCTION_SYM if_exists sp_name { - THD *thd= YYTHD; - LEX *lex= thd->lex; - sp_name *spname; + LEX *lex= Lex; if (lex->sphead) { my_error(ER_SP_NO_DROP_SP, MYF(0), "FUNCTION"); @@ -7519,32 +7517,7 @@ drop: } lex->sql_command = SQLCOM_DROP_FUNCTION; lex->drop_if_exists= $3; - spname= new sp_name($4, $6, true); - if (spname == NULL) - MYSQL_YYABORT; - spname->init_qname(thd); - lex->spname= spname; - } - | DROP FUNCTION_SYM if_exists ident - { - THD *thd= YYTHD; - LEX *lex= thd->lex; - LEX_STRING db= {0, 0}; - sp_name *spname; - if (lex->sphead) - { - my_error(ER_SP_NO_DROP_SP, MYF(0), "FUNCTION"); - MYSQL_YYABORT; - } - if (thd->db && lex->copy_db_to(&db.str, &db.length)) - MYSQL_YYABORT; - lex->sql_command = SQLCOM_DROP_FUNCTION; - lex->drop_if_exists= $3; - spname= new sp_name(db, $4, false); - if (spname == NULL) - MYSQL_YYABORT; - spname->init_qname(thd); - lex->spname= spname; + lex->spname= $4; } | DROP PROCEDURE if_exists sp_name { From 46f91045f8e87434f84b2b268f29f54adcb344eb Mon Sep 17 00:00:00 2001 From: Bjorn Munch Date: Tue, 10 Feb 2009 11:00:16 +0100 Subject: [PATCH 053/219] Bug #42590 MTR v1 crashes under Active State Perl Perl crashes when MTR 2 tries to start v1 Replaced require with system() --- mysql-test/mysql-test-run.pl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl index 511cd4d07ba..ba426446075 100755 --- a/mysql-test/mysql-test-run.pl +++ b/mysql-test/mysql-test-run.pl @@ -45,8 +45,8 @@ BEGIN { print "=======================================================\n"; print " WARNING: Using mysql-test-run.pl version 1! \n"; print "=======================================================\n"; - require "lib/v1/mysql-test-run.pl"; - exit(1); + # Should use exec() here on *nix but this appears not to work on Windows + exit(system($^X, "lib/v1/mysql-test-run.pl", @ARGV) >> 8); } elsif ( $version == 2 ) { From b7b6773f6967e3e8d0514cd09477d75d6485c85e Mon Sep 17 00:00:00 2001 From: Luis Soares Date: Tue, 10 Feb 2009 11:52:19 +0100 Subject: [PATCH 054/219] BUG#13684: SP: DROP PROCEDURE|FUNCTION IF EXISTS not binlogged if routine does not exist There is an inconsistency with DROP DATABASE IF EXISTS, DROP TABLE IF EXISTS and DROP VIEW IF EXISTS: those are binlogged even if the DB or TABLE does not exist, whereas DROP PROCEDURE IF EXISTS does not. It would be nice or at least consistent if DROP PROCEDURE/STATEMENT worked the same too. Fixed DROP PROCEDURE|FUNCTION IF EXISTS by adding a call to write_bin_log in mysql_execute_command. Checked also if all documented "DROP (...) IF EXISTS" get binlogged. Left out DROP SERVER IF EXISTS because it seems that it only gets binlogged when using row event (see BUG#25705). --- .../suite/rpl/r/rpl_drop_if_exists.result | 97 +++++++++++++++ mysql-test/suite/rpl/r/rpl_sp.result | 16 +++ .../suite/rpl/t/rpl_drop_if_exists.test | 114 ++++++++++++++++++ sql/sql_parse.cc | 1 + 4 files changed, 228 insertions(+) create mode 100644 mysql-test/suite/rpl/r/rpl_drop_if_exists.result create mode 100644 mysql-test/suite/rpl/t/rpl_drop_if_exists.test diff --git a/mysql-test/suite/rpl/r/rpl_drop_if_exists.result b/mysql-test/suite/rpl/r/rpl_drop_if_exists.result new file mode 100644 index 00000000000..bc02dd22561 --- /dev/null +++ b/mysql-test/suite/rpl/r/rpl_drop_if_exists.result @@ -0,0 +1,97 @@ +DROP PROCEDURE IF EXISTS db_bug_13684.p; +DROP FUNCTION IF EXISTS db_bug_13684.f; +DROP TRIGGER IF EXISTS db_bug_13684.tr; +DROP VIEW IF EXISTS db_bug_13684.v; +DROP EVENT IF EXISTS db_bug_13684.e; +DROP TABLE IF EXISTS db_bug_13684.t; +DROP DATABASE IF EXISTS db_bug_13684; +show binlog events from ; +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query # # use `test`; DROP PROCEDURE IF EXISTS db_bug_13684.p +master-bin.000001 # Query # # use `test`; DROP FUNCTION IF EXISTS db_bug_13684.f +master-bin.000001 # Query # # use `test`; DROP TRIGGER IF EXISTS db_bug_13684.tr +master-bin.000001 # Query # # use `test`; DROP VIEW IF EXISTS db_bug_13684.v +master-bin.000001 # Query # # use `test`; DROP EVENT IF EXISTS db_bug_13684.e +master-bin.000001 # Query # # use `test`; DROP TABLE IF EXISTS db_bug_13684.t +master-bin.000001 # Query # # DROP DATABASE IF EXISTS db_bug_13684 +CREATE DATABASE db_bug_13684; +CREATE TABLE db_bug_13684.t (a int); +CREATE EVENT db_bug_13684.e +ON SCHEDULE AT CURRENT_TIMESTAMP + INTERVAL 1 HOUR +DO +UPDATE db_bug_13684.t SET a = a + 1; +CREATE VIEW db_bug_13684.v +AS SELECT * FROM db_bug_13684.t; +CREATE TRIGGER db_bug_13684.tr BEFORE INSERT ON db_bug_13684.t +FOR EACH ROW BEGIN +END; +CREATE PROCEDURE db_bug_13684.p (OUT p1 INT) +BEGIN +END; +CREATE FUNCTION db_bug_13684.f (s CHAR(20)) +RETURNS CHAR(50) DETERMINISTIC +RETURN s; +show binlog events from ; +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query # # use `test`; DROP PROCEDURE IF EXISTS db_bug_13684.p +master-bin.000001 # Query # # use `test`; DROP FUNCTION IF EXISTS db_bug_13684.f +master-bin.000001 # Query # # use `test`; DROP TRIGGER IF EXISTS db_bug_13684.tr +master-bin.000001 # Query # # use `test`; DROP VIEW IF EXISTS db_bug_13684.v +master-bin.000001 # Query # # use `test`; DROP EVENT IF EXISTS db_bug_13684.e +master-bin.000001 # Query # # use `test`; DROP TABLE IF EXISTS db_bug_13684.t +master-bin.000001 # Query # # DROP DATABASE IF EXISTS db_bug_13684 +master-bin.000001 # Query # # CREATE DATABASE db_bug_13684 +master-bin.000001 # Query # # use `test`; CREATE TABLE db_bug_13684.t (a int) +master-bin.000001 # Query # # use `test`; CREATE EVENT db_bug_13684.e +ON SCHEDULE AT CURRENT_TIMESTAMP + INTERVAL 1 HOUR +DO +UPDATE db_bug_13684.t SET a = a + 1 +master-bin.000001 # Query # # use `test`; CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `db_bug_13684`.`v` AS SELECT * FROM db_bug_13684.t +master-bin.000001 # Query # # use `test`; CREATE DEFINER=`root`@`localhost` TRIGGER db_bug_13684.tr BEFORE INSERT ON db_bug_13684.t +FOR EACH ROW BEGIN +END +master-bin.000001 # Query # # use `test`; CREATE DEFINER=`root`@`localhost` PROCEDURE `db_bug_13684`.`p`(OUT p1 INT) +BEGIN +END +master-bin.000001 # Query # # use `test`; CREATE DEFINER=`root`@`localhost` FUNCTION `db_bug_13684`.`f`(s CHAR(20)) RETURNS char(50) CHARSET latin1 + DETERMINISTIC +RETURN s +DROP PROCEDURE IF EXISTS db_bug_13684.p; +DROP FUNCTION IF EXISTS db_bug_13684.f; +DROP TRIGGER IF EXISTS db_bug_13684.tr; +DROP VIEW IF EXISTS db_bug_13684.v; +DROP EVENT IF EXISTS db_bug_13684.e; +DROP TABLE IF EXISTS db_bug_13684.t; +DROP DATABASE IF EXISTS db_bug_13684; +show binlog events from ; +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query # # use `test`; DROP PROCEDURE IF EXISTS db_bug_13684.p +master-bin.000001 # Query # # use `test`; DROP FUNCTION IF EXISTS db_bug_13684.f +master-bin.000001 # Query # # use `test`; DROP TRIGGER IF EXISTS db_bug_13684.tr +master-bin.000001 # Query # # use `test`; DROP VIEW IF EXISTS db_bug_13684.v +master-bin.000001 # Query # # use `test`; DROP EVENT IF EXISTS db_bug_13684.e +master-bin.000001 # Query # # use `test`; DROP TABLE IF EXISTS db_bug_13684.t +master-bin.000001 # Query # # DROP DATABASE IF EXISTS db_bug_13684 +master-bin.000001 # Query # # CREATE DATABASE db_bug_13684 +master-bin.000001 # Query # # use `test`; CREATE TABLE db_bug_13684.t (a int) +master-bin.000001 # Query # # use `test`; CREATE EVENT db_bug_13684.e +ON SCHEDULE AT CURRENT_TIMESTAMP + INTERVAL 1 HOUR +DO +UPDATE db_bug_13684.t SET a = a + 1 +master-bin.000001 # Query # # use `test`; CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `db_bug_13684`.`v` AS SELECT * FROM db_bug_13684.t +master-bin.000001 # Query # # use `test`; CREATE DEFINER=`root`@`localhost` TRIGGER db_bug_13684.tr BEFORE INSERT ON db_bug_13684.t +FOR EACH ROW BEGIN +END +master-bin.000001 # Query # # use `test`; CREATE DEFINER=`root`@`localhost` PROCEDURE `db_bug_13684`.`p`(OUT p1 INT) +BEGIN +END +master-bin.000001 # Query # # use `test`; CREATE DEFINER=`root`@`localhost` FUNCTION `db_bug_13684`.`f`(s CHAR(20)) RETURNS char(50) CHARSET latin1 + DETERMINISTIC +RETURN s +master-bin.000001 # Query # # use `test`; DROP PROCEDURE IF EXISTS db_bug_13684.p +master-bin.000001 # Query # # use `test`; DROP FUNCTION IF EXISTS db_bug_13684.f +master-bin.000001 # Query # # use `test`; DROP TRIGGER IF EXISTS db_bug_13684.tr +master-bin.000001 # Query # # use `test`; DROP VIEW IF EXISTS db_bug_13684.v +master-bin.000001 # Query # # use `test`; DROP EVENT IF EXISTS db_bug_13684.e +master-bin.000001 # Query # # use `test`; DROP TABLE IF EXISTS db_bug_13684.t +master-bin.000001 # Query # # DROP DATABASE IF EXISTS db_bug_13684 diff --git a/mysql-test/suite/rpl/r/rpl_sp.result b/mysql-test/suite/rpl/r/rpl_sp.result index 4a8a4050c02..86d126f6176 100644 --- a/mysql-test/suite/rpl/r/rpl_sp.result +++ b/mysql-test/suite/rpl/r/rpl_sp.result @@ -511,6 +511,7 @@ master-bin.000001 # Query 1 # use `mysqltest1`; drop procedure foo master-bin.000001 # Query 1 # use `mysqltest1`; drop function fn1 master-bin.000001 # Query 1 # drop database mysqltest1 master-bin.000001 # Query 1 # drop user "zedjzlcsjhd"@127.0.0.1 +master-bin.000001 # Query 1 # use `test`; drop function if exists f1 master-bin.000001 # Query 1 # use `test`; CREATE DEFINER=`root`@`localhost` FUNCTION `f1`() RETURNS int(11) READS SQL DATA begin @@ -526,12 +527,15 @@ master-bin.000001 # Query 1 # use `test`; create table t1 (a int) master-bin.000001 # Query 1 # use `test`; insert into t1 (a) values (f1()) master-bin.000001 # Query 1 # use `test`; drop view v1 master-bin.000001 # Query 1 # use `test`; drop function f1 +master-bin.000001 # Query 1 # use `test`; DROP PROCEDURE IF EXISTS p1 master-bin.000001 # Query 1 # use `test`; DROP TABLE IF EXISTS t1 master-bin.000001 # Query 1 # use `test`; CREATE TABLE t1(col VARCHAR(10)) master-bin.000001 # Query 1 # use `test`; CREATE DEFINER=`root`@`localhost` PROCEDURE `p1`(arg VARCHAR(10)) INSERT INTO t1 VALUES(arg) master-bin.000001 # Query 1 # use `test`; INSERT INTO t1 VALUES( NAME_CONST('arg',_latin1'test' COLLATE 'latin1_swedish_ci')) master-bin.000001 # Query 1 # use `test`; DROP PROCEDURE p1 +master-bin.000001 # Query 1 # use `test`; DROP PROCEDURE IF EXISTS p1 +master-bin.000001 # Query 1 # use `test`; DROP FUNCTION IF EXISTS f1 master-bin.000001 # Query 1 # use `test`; CREATE DEFINER=`root`@`localhost` PROCEDURE `p1`() SET @a = 1 master-bin.000001 # Query 1 # use `test`; CREATE DEFINER=`root`@`localhost` FUNCTION `f1`() RETURNS int(11) @@ -842,6 +846,9 @@ drop user "zedjzlcsjhd"@127.0.0.1 /*!*/; use test/*!*/; SET TIMESTAMP=t/*!*/; +drop function if exists f1 +/*!*/; +SET TIMESTAMP=t/*!*/; CREATE DEFINER=`root`@`localhost` FUNCTION `f1`() RETURNS int(11) READS SQL DATA begin @@ -869,6 +876,9 @@ SET TIMESTAMP=t/*!*/; drop function f1 /*!*/; SET TIMESTAMP=t/*!*/; +DROP PROCEDURE IF EXISTS p1 +/*!*/; +SET TIMESTAMP=t/*!*/; DROP TABLE IF EXISTS t1 /*!*/; SET TIMESTAMP=t/*!*/; @@ -885,6 +895,12 @@ SET TIMESTAMP=t/*!*/; DROP PROCEDURE p1 /*!*/; SET TIMESTAMP=t/*!*/; +DROP PROCEDURE IF EXISTS p1 +/*!*/; +SET TIMESTAMP=t/*!*/; +DROP FUNCTION IF EXISTS f1 +/*!*/; +SET TIMESTAMP=t/*!*/; CREATE DEFINER=`root`@`localhost` PROCEDURE `p1`() SET @a = 1 /*!*/; diff --git a/mysql-test/suite/rpl/t/rpl_drop_if_exists.test b/mysql-test/suite/rpl/t/rpl_drop_if_exists.test new file mode 100644 index 00000000000..41abdc51fd1 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_drop_if_exists.test @@ -0,0 +1,114 @@ +# BUG#13684: +# SP: DROP PROCEDURE|FUNCTION IF EXISTS not binlogged if routine +# does not exist +# +# There is an inconsistency with DROP DATABASE IF EXISTS, DROP +# TABLE IF EXISTS and DROP VIEW IF EXISTS: those are binlogged even +# if the DB or TABLE does not exist, whereas DROP PROCEDURE IF +# EXISTS does not. It would be nice or at least consistent if DROP +# PROCEDURE/STATEMENT worked the same too. +# +# Description: +# DROP PROCEDURE|FUNCTION IF EXISTS does not get binlogged whereas DROP +# DATABASE|TABLE|TRIGGER|... IF EXISTS do. +# +# Fixed DROP PROCEDURE|FUNCTION IF EXISTS by adding a call to +# write_bin_log in mysql_execute_command. Checked also if all +# documented "DROP (...) IF EXISTS" get binlogged. Left out DROP +# SERVER IF EXISTS because it seems that it only gets binlogged when +# using row event (see BUG#25705). +# +# TODO: add DROP SERVER IF EXISTS to the test case when its +# binlogging procedure gets fixed (BUG#25705). Furthermore, when +# logging in RBR format the events that get logged are effectively in +# RBR format and not in STATEMENT format meaning that one must needs +# to be extra careful when writing a test for it, or change the CREATE +# SERVER logging to always log as STATEMENT. You can quickly check this +# by enabling the flag below $fixed_bug_25705=1 and watch the diff on +# the STDOUT. More detail may be found on the generated reject file. +# +# Test is implemented as follows: +# +# i) test each "drop if exists" (DDL), found in MySQL 5.1 manual, +# on inexistent objects (except for DROP SERVER); +# ii) show binlog events; +# iii) create an object for each drop if exists statement; +# iv) issue "drop if exists" in existent objects. +# v) show binlog events; +# +# References: +# http://dev.mysql.com/doc/refman/5.1/en/sql-syntax-data-definition.html +# +--source include/have_log_bin.inc + +disable_warnings; + +# test all "drop if exists" in manual with inexistent objects +DROP PROCEDURE IF EXISTS db_bug_13684.p; +DROP FUNCTION IF EXISTS db_bug_13684.f; +DROP TRIGGER IF EXISTS db_bug_13684.tr; +DROP VIEW IF EXISTS db_bug_13684.v; +DROP EVENT IF EXISTS db_bug_13684.e; +DROP TABLE IF EXISTS db_bug_13684.t; +DROP DATABASE IF EXISTS db_bug_13684; + +let $fixed_bug_25705 = 0; + +if($fixed_bug_25705) +{ + DROP SERVER IF EXISTS s_bug_13684; +} +--source include/show_binlog_events.inc + +# test drop with existing values + +# create +CREATE DATABASE db_bug_13684; + +CREATE TABLE db_bug_13684.t (a int); + +CREATE EVENT db_bug_13684.e + ON SCHEDULE AT CURRENT_TIMESTAMP + INTERVAL 1 HOUR + DO + UPDATE db_bug_13684.t SET a = a + 1; + +CREATE VIEW db_bug_13684.v + AS SELECT * FROM db_bug_13684.t; + +CREATE TRIGGER db_bug_13684.tr BEFORE INSERT ON db_bug_13684.t + FOR EACH ROW BEGIN + END; + +CREATE PROCEDURE db_bug_13684.p (OUT p1 INT) + BEGIN + END; + +CREATE FUNCTION db_bug_13684.f (s CHAR(20)) + RETURNS CHAR(50) DETERMINISTIC + RETURN s; + +if($fixed_bug_25705) +{ + CREATE SERVER s_bug_13684 + FOREIGN DATA WRAPPER mysql + OPTIONS (USER 'Remote', HOST '192.168.1.106', DATABASE 'test'); +} + +--source include/show_binlog_events.inc + +# drop existing +DROP PROCEDURE IF EXISTS db_bug_13684.p; +DROP FUNCTION IF EXISTS db_bug_13684.f; +DROP TRIGGER IF EXISTS db_bug_13684.tr; +DROP VIEW IF EXISTS db_bug_13684.v; +DROP EVENT IF EXISTS db_bug_13684.e; +DROP TABLE IF EXISTS db_bug_13684.t; +DROP DATABASE IF EXISTS db_bug_13684; +if($fixed_bug_25705) +{ + DROP SERVER IF EXISTS s_bug_13684; +} + +--source include/show_binlog_events.inc + +enable_warnings; diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 592dbe9f43b..7c5f469da41 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -4427,6 +4427,7 @@ create_sp_error: case SP_KEY_NOT_FOUND: if (lex->drop_if_exists) { + write_bin_log(thd, TRUE, thd->query, thd->query_length); push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE, ER_SP_DOES_NOT_EXIST, ER(ER_SP_DOES_NOT_EXIST), SP_COM_STRING(lex), lex->spname->m_name.str); From fd8bf58ca972ef3f521aec03c0bd09fa3ec78335 Mon Sep 17 00:00:00 2001 From: Alexey Kopytov Date: Tue, 10 Feb 2009 15:38:56 +0300 Subject: [PATCH 055/219] Fix for bug #41868: crash or memory overrun with concat + upper, date_format functions String::realloc() did not check whether the existing string data fits in the newly allocated buffer for cases when reallocating a String object with external buffer (i.e.alloced == FALSE). This could lead to memory overruns in some cases. client/sql_string.cc: Fixed String::realloc() to check whether the existing string data fits in the newly allocated buffer for cases when reallocating a String object with external buffer. mysql-test/r/func_str.result: Added a test case for bug #41868. mysql-test/t/func_str.test: Added a test case for bug #41868. sql/sql_class.cc: After each call to Item::send() in select_send::send_data() reset buffer to its original state to reduce unnecessary malloc() calls. See comments for bug #41868 for detailed analysis. sql/sql_string.cc: Fixed String::realloc() to check whether the existing string data fits in the newly allocated buffer for cases when reallocating a String object with external buffer. --- client/sql_string.cc | 15 ++++++--------- mysql-test/r/func_str.result | 6 ++++++ mysql-test/t/func_str.test | 9 +++++++++ sql/sql_class.cc | 5 +++++ sql/sql_string.cc | 15 ++++++--------- 5 files changed, 32 insertions(+), 18 deletions(-) diff --git a/client/sql_string.cc b/client/sql_string.cc index 9d887ff031c..fe1fd83a6f6 100644 --- a/client/sql_string.cc +++ b/client/sql_string.cc @@ -71,25 +71,22 @@ bool String::realloc(uint32 alloc_length) char *new_ptr; if (alloced) { - if ((new_ptr= (char*) my_realloc(Ptr,len,MYF(MY_WME)))) - { - Ptr=new_ptr; - Alloced_length=len; - } - else - return TRUE; // Signal error + if (!(new_ptr= (char*) my_realloc(Ptr,len,MYF(MY_WME)))) + return TRUE; // Signal error } else if ((new_ptr= (char*) my_malloc(len,MYF(MY_WME)))) { + if (str_length > len - 1) + str_length= 0; if (str_length) // Avoid bugs in memcpy on AIX memcpy(new_ptr,Ptr,str_length); new_ptr[str_length]=0; - Ptr=new_ptr; - Alloced_length=len; alloced=1; } else return TRUE; // Signal error + Ptr= new_ptr; + Alloced_length= len; } Ptr[alloc_length]=0; // This make other funcs shorter return FALSE; diff --git a/mysql-test/r/func_str.result b/mysql-test/r/func_str.result index c121c8937d7..d7fd8c5c887 100644 --- a/mysql-test/r/func_str.result +++ b/mysql-test/r/func_str.result @@ -2181,4 +2181,10 @@ def format(a, 2) 253 20 4 Y 0 2 8 format(a, 2) 1.33 drop table t1; +CREATE TABLE t1 (c DATE, aa VARCHAR(30)); +INSERT INTO t1 VALUES ('2008-12-31','aaaaaa'); +SELECT DATE_FORMAT(c, GET_FORMAT(DATE, 'eur')) h, CONCAT(UPPER(aa),', ', aa) i FROM t1; +h i +31.12.2008 AAAAAA, aaaaaa +DROP TABLE t1; End of 5.0 tests diff --git a/mysql-test/t/func_str.test b/mysql-test/t/func_str.test index 8298a50c277..389538c4cc0 100644 --- a/mysql-test/t/func_str.test +++ b/mysql-test/t/func_str.test @@ -1159,4 +1159,13 @@ select format(a, 2) from t1; --disable_metadata drop table t1; +# +# Bug #41868: crash or memory overrun with concat + upper, date_format functions +# + +CREATE TABLE t1 (c DATE, aa VARCHAR(30)); +INSERT INTO t1 VALUES ('2008-12-31','aaaaaa'); +SELECT DATE_FORMAT(c, GET_FORMAT(DATE, 'eur')) h, CONCAT(UPPER(aa),', ', aa) i FROM t1; +DROP TABLE t1; + --echo End of 5.0 tests diff --git a/sql/sql_class.cc b/sql/sql_class.cc index 91c0aa66761..9ff602bb62e 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -1047,6 +1047,11 @@ bool select_send::send_data(List &items) my_message(ER_OUT_OF_RESOURCES, ER(ER_OUT_OF_RESOURCES), MYF(0)); break; } + /* + Reset buffer to its original state, as it may have been altered in + Item::send(). + */ + buffer.set(buff, sizeof(buff), &my_charset_bin); } thd->sent_row_count++; if (!thd->vio_ok()) diff --git a/sql/sql_string.cc b/sql/sql_string.cc index 75e47dd0c8e..ed1dc9eac77 100644 --- a/sql/sql_string.cc +++ b/sql/sql_string.cc @@ -71,25 +71,22 @@ bool String::realloc(uint32 alloc_length) char *new_ptr; if (alloced) { - if ((new_ptr= (char*) my_realloc(Ptr,len,MYF(MY_WME)))) - { - Ptr=new_ptr; - Alloced_length=len; - } - else - return TRUE; // Signal error + if (!(new_ptr= (char*) my_realloc(Ptr,len,MYF(MY_WME)))) + return TRUE; // Signal error } else if ((new_ptr= (char*) my_malloc(len,MYF(MY_WME)))) { + if (str_length > len - 1) + str_length= 0; if (str_length) // Avoid bugs in memcpy on AIX memcpy(new_ptr,Ptr,str_length); new_ptr[str_length]=0; - Ptr=new_ptr; - Alloced_length=len; alloced=1; } else return TRUE; // Signal error + Ptr= new_ptr; + Alloced_length= len; } Ptr[alloc_length]=0; // This make other funcs shorter return FALSE; From fab053ccf84ccb537999615da8f962d03ef5da76 Mon Sep 17 00:00:00 2001 From: Georgi Kodinov Date: Tue, 10 Feb 2009 14:39:14 +0200 Subject: [PATCH 056/219] From jperkin : Merge libedit 2.11 and related files, based on NetBSD CVS as of 2009/02/06 20:09:00. --- client/mysql.cc | 4 +- cmd-line-utils/libedit/Makefile.am | 28 +- cmd-line-utils/libedit/README | 50 ++ cmd-line-utils/libedit/TEST/test.c | 269 ------ cmd-line-utils/libedit/chared.c | 45 +- cmd-line-utils/libedit/chared.h | 9 +- cmd-line-utils/libedit/common.c | 27 +- cmd-line-utils/libedit/compat.h | 43 - cmd-line-utils/libedit/compat_conf.h | 2 - cmd-line-utils/libedit/config.h | 14 - cmd-line-utils/libedit/editline.3 | 619 ------------- cmd-line-utils/libedit/editrc.5 | 491 ---------- cmd-line-utils/libedit/el.c | 204 +++-- cmd-line-utils/libedit/el.h | 6 +- cmd-line-utils/libedit/el_term.h | 28 +- cmd-line-utils/libedit/emacs.c | 15 +- cmd-line-utils/libedit/fgetln.h | 3 - cmd-line-utils/libedit/filecomplete.c | 558 ++++++++++++ .../libedit/{fgetln.c => filecomplete.h} | 72 +- cmd-line-utils/libedit/hist.c | 8 +- cmd-line-utils/libedit/histedit.h | 24 +- cmd-line-utils/libedit/history.c | 62 +- cmd-line-utils/libedit/key.c | 148 +-- cmd-line-utils/libedit/key.h | 6 +- cmd-line-utils/libedit/libedit_term.h | 124 --- cmd-line-utils/libedit/makelist.sh | 20 +- cmd-line-utils/libedit/map.c | 64 +- cmd-line-utils/libedit/np/fgetln.c | 50 +- cmd-line-utils/libedit/np/strlcat.c | 82 +- cmd-line-utils/libedit/np/strlcpy.c | 77 +- cmd-line-utils/libedit/np/unvis.c | 103 +-- cmd-line-utils/libedit/np/vis.c | 413 +++++---- cmd-line-utils/libedit/np/vis.h | 19 +- cmd-line-utils/libedit/parse.c | 12 +- cmd-line-utils/libedit/parse.h | 4 +- cmd-line-utils/libedit/prompt.c | 8 +- cmd-line-utils/libedit/read.c | 60 +- cmd-line-utils/libedit/read.h | 9 +- cmd-line-utils/libedit/readline.c | 843 +++++++----------- cmd-line-utils/libedit/readline/readline.h | 38 +- cmd-line-utils/libedit/refresh.c | 76 +- cmd-line-utils/libedit/search.c | 9 +- cmd-line-utils/libedit/sig.c | 20 +- cmd-line-utils/libedit/sig.h | 3 +- cmd-line-utils/libedit/strlcpy.c | 73 -- cmd-line-utils/libedit/strlcpy.h | 2 - cmd-line-utils/libedit/sys.h | 27 +- cmd-line-utils/libedit/term.c | 334 ++++--- cmd-line-utils/libedit/tokenizer.c | 8 +- cmd-line-utils/libedit/tokenizer.h | 54 -- cmd-line-utils/libedit/tty.c | 89 +- cmd-line-utils/libedit/tty.h | 6 +- cmd-line-utils/libedit/unvis.c | 311 ------- cmd-line-utils/libedit/vi.c | 39 +- cmd-line-utils/libedit/vis.c | 392 -------- cmd-line-utils/libedit/vis.h | 92 -- 56 files changed, 2273 insertions(+), 3923 deletions(-) create mode 100644 cmd-line-utils/libedit/README delete mode 100644 cmd-line-utils/libedit/TEST/test.c delete mode 100644 cmd-line-utils/libedit/compat.h delete mode 100644 cmd-line-utils/libedit/compat_conf.h delete mode 100644 cmd-line-utils/libedit/editline.3 delete mode 100644 cmd-line-utils/libedit/editrc.5 delete mode 100644 cmd-line-utils/libedit/fgetln.h create mode 100644 cmd-line-utils/libedit/filecomplete.c rename cmd-line-utils/libedit/{fgetln.c => filecomplete.h} (50%) delete mode 100644 cmd-line-utils/libedit/libedit_term.h delete mode 100644 cmd-line-utils/libedit/strlcpy.c delete mode 100644 cmd-line-utils/libedit/strlcpy.h delete mode 100644 cmd-line-utils/libedit/tokenizer.h delete mode 100644 cmd-line-utils/libedit/unvis.c delete mode 100644 cmd-line-utils/libedit/vis.c delete mode 100644 cmd-line-utils/libedit/vis.h diff --git a/client/mysql.cc b/client/mysql.cc index 20f87d5cdcd..88ddd40fa68 100644 --- a/client/mysql.cc +++ b/client/mysql.cc @@ -2247,8 +2247,10 @@ static char **new_mysql_completion (const char *text, int start, int end); if not. */ -#if defined(USE_NEW_READLINE_INTERFACE) || defined(USE_LIBEDIT_INTERFACE) +#if defined(USE_NEW_READLINE_INTERFACE) char *no_completion(const char*,int) +#elif defined(USE_LIBEDIT_INTERFACE) +int no_completion(const char*,int) #else char *no_completion() #endif diff --git a/cmd-line-utils/libedit/Makefile.am b/cmd-line-utils/libedit/Makefile.am index bb4b40180d1..5a01a746963 100644 --- a/cmd-line-utils/libedit/Makefile.am +++ b/cmd-line-utils/libedit/Makefile.am @@ -1,6 +1,4 @@ ## Process this file with automake to create Makefile.in -# Makefile for the GNU readline library. -# Copyright (C) 1994,1996,1997 Free Software Foundation, Inc. ASRC = $(srcdir)/vi.c $(srcdir)/emacs.c $(srcdir)/common.c AHDR = vi.h emacs.h common.h @@ -12,10 +10,9 @@ noinst_LIBRARIES = libedit.a libedit_a_SOURCES = chared.c el.c history.c map.c prompt.c readline.c \ search.c tokenizer.c vi.c common.c emacs.c \ hist.c key.c parse.c read.c refresh.c sig.c term.c \ - tty.c help.c fcns.c - -EXTRA_libedit_a_SOURCES = np/unvis.c np/strlcpy.c np/vis.c np/strlcat.c \ - np/fgetln.c + tty.c help.c fcns.c filecomplete.c \ + np/unvis.c np/strlcpy.c np/vis.c np/strlcat.c \ + np/fgetln.c libedit_a_LIBADD = @LIBEDIT_LOBJECTS@ libedit_a_DEPENDENCIES = @LIBEDIT_LOBJECTS@ @@ -23,22 +20,13 @@ libedit_a_DEPENDENCIES = @LIBEDIT_LOBJECTS@ pkginclude_HEADERS = readline/readline.h noinst_HEADERS = chared.h el.h el_term.h histedit.h key.h parse.h refresh.h sig.h \ - sys.h tokenizer.h config.h hist.h map.h prompt.h read.h \ - search.h tty.h libedit_term.h vis.h + sys.h config.h hist.h map.h prompt.h read.h \ + search.h tty.h filecomplete.h -EXTRA_DIST = makelist.sh np/unvis.c np/strlcpy.c np/vis.c np/vis.h np/strlcat.c np/fgetln.c +EXTRA_DIST = makelist.sh CLEANFILES = makelist common.h emacs.h vi.h fcns.h help.h fcns.c help.c -# Make sure to include stuff from this directory first, to get right "config.h" -# Automake puts into DEFAULT_INCLUDES this source and corresponding -# build directory together with ../../include to let all make files -# find the central "config.h". This variable is used before INCLUDES -# above. But in automake 1.10 the order of these are changed. Put the -# includes of this directory into DEFS to always be sure it is first -# before DEFAULT_INCLUDES on the compile line. -DEFS = -DUNDEF_THREADS_HACK -DHAVE_CONFIG_H -DNO_KILL_INTR -I. -I$(srcdir) - SUFFIXES = .sh .sh: @@ -101,6 +89,4 @@ term.o: vi.h emacs.h common.h help.h fcns.h tty.o: vi.h emacs.h common.h help.h fcns.h help.o: vi.h emacs.h common.h help.h fcns.h fcns.o: vi.h emacs.h common.h help.h fcns.h - -# Don't update the files from bitkeeper -%::SCCS/s.% +filecomplete.o: vi.h emacs.h common.h help.h fcns.h diff --git a/cmd-line-utils/libedit/README b/cmd-line-utils/libedit/README new file mode 100644 index 00000000000..0b698a6150d --- /dev/null +++ b/cmd-line-utils/libedit/README @@ -0,0 +1,50 @@ +An approximate method to merge from upstream is: + + # Fetch latest from upstream (we also include some compat stuff) + $ CVS_RSH=ssh; export CVS_RSH + $ CVSROOT="anoncvs@stripped:/cvsroot" + $ cvs co -d libedit -P src/lib/libedit + $ mkdir libedit/np + $ for f in src/common/lib/libc/string/strlcat.c \ + > src/common/lib/libc/string/strlcpy.c \ + > src/include/vis.h \ + > src/lib/libc/gen/unvis.c \ + > src/lib/libc/gen/vis.c \ + > src/tools/compat/fgetln.c + > do + > cvs co -P ${f} + > mv ${f} libedit/np + > done + $ rm -rf src + $ cd libedit + + # Remove files we don't need/use + $ rm -rf CVS TEST Makefile shlib_version *.[0-9] + $ (cd readline; rm -rf CVS Makefile) + + # Rename files to match our naming + $ mv makelist makelist.sh + $ mv term.h el_term.h + + # Remove NetBSD-specific bits + $ for file in $(find . -type f) + > do + > cp ${file} ${file}.orig + > sed -e 's/#include "term.h"/#include "el_term.h"/g' \ + > -e 's/sig_handler/el_sig_handler/g' \ + > -e 's/isprint/el_isprint/g' \ + > -e '/^__RCSID/d' \ + > ${file}.orig >${file} + > rm ${file}.orig + > done + +then merge remaining bits by hand. All MySQL-specific changes should be +marked with XXXMYSQL to make them easier to identify and merge. To generate +a 'clean' diff against upstream you can use the above commands but use + + cvs co -D "2009/02/06 20:09:00" [..] + +to fetch the baseline of most recent merge. + +Please feed any fixes to Jonathan Perkin who will endeavour +to merge them upstream and keep diffs minimal. diff --git a/cmd-line-utils/libedit/TEST/test.c b/cmd-line-utils/libedit/TEST/test.c deleted file mode 100644 index 605341eac62..00000000000 --- a/cmd-line-utils/libedit/TEST/test.c +++ /dev/null @@ -1,269 +0,0 @@ -/* $NetBSD: test.c,v 1.9 2000/09/04 23:36:41 lukem Exp $ */ - -/*- - * Copyright (c) 1992, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Christos Zoulas of Cornell University. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include -#include "compat.h" -#ifndef lint -__COPYRIGHT("@(#) Copyright (c) 1992, 1993\n\ - The Regents of the University of California. All rights reserved.\n"); -#endif /* not lint */ - -#if !defined(lint) && !defined(SCCSID) -#if 0 -static char sccsid[] = "@(#)test.c 8.1 (Berkeley) 6/4/93"; -#else -__RCSID("$NetBSD: test.c,v 1.9 2000/09/04 23:36:41 lukem Exp $"); -#endif -#endif /* not lint && not SCCSID */ - -/* - * test.c: A little test program - */ -#include "sys.h" -#include -#include -#include -#include -#include -#include -#include -#include - -#include "histedit.h" -#include "tokenizer.h" - -static int continuation = 0; -static EditLine *el = NULL; - -static u_char complete(EditLine *, int); - int main(int, char **); -static char *prompt(EditLine *); -static void sig(int); - -static char * -prompt(EditLine *el) -{ - static char a[] = "Edit$"; - static char b[] = "Edit>"; - - return (continuation ? b : a); -} - -static void -sig(int i) -{ - - (void) fprintf(stderr, "Got signal %d.\n", i); - el_reset(el); -} - -static unsigned char -complete(EditLine *el, int ch) -{ - DIR *dd = opendir("."); - struct dirent *dp; - const char* ptr; - const LineInfo *lf = el_line(el); - int len; - - /* - * Find the last word - */ - for (ptr = lf->cursor - 1; !isspace(*ptr) && ptr > lf->buffer; ptr--) - continue; - len = lf->cursor - ++ptr; - - for (dp = readdir(dd); dp != NULL; dp = readdir(dd)) { - if (len > strlen(dp->d_name)) - continue; - if (strncmp(dp->d_name, ptr, len) == 0) { - closedir(dd); - if (el_insertstr(el, &dp->d_name[len]) == -1) - return (CC_ERROR); - else - return (CC_REFRESH); - } - } - - closedir(dd); - return (CC_ERROR); -} - -int -main(int argc, char *argv[]) -{ - int num; - const char *buf; - Tokenizer *tok; - int lastevent = 0, ncontinuation; - History *hist; - HistEvent ev; - - (void) signal(SIGINT, sig); - (void) signal(SIGQUIT, sig); - (void) signal(SIGHUP, sig); - (void) signal(SIGTERM, sig); - - hist = history_init(); /* Init the builtin history */ - /* Remember 100 events */ - history(hist, &ev, H_SETSIZE, 100); - - tok = tok_init(NULL); /* Initialize the tokenizer */ - - /* Initialize editline */ - el = el_init(*argv, stdin, stdout, stderr); - - el_set(el, EL_EDITOR, "vi"); /* Default editor is vi */ - el_set(el, EL_SIGNAL, 1); /* Handle signals gracefully */ - el_set(el, EL_PROMPT, prompt); /* Set the prompt function */ - - /* Tell editline to use this history interface */ - el_set(el, EL_HIST, history, hist); - - /* Add a user-defined function */ - el_set(el, EL_ADDFN, "ed-complete", "Complete argument", complete); - - /* Bind tab to it */ - el_set(el, EL_BIND, "^I", "ed-complete", NULL); - - /* - * Bind j, k in vi command mode to previous and next line, instead - * of previous and next history. - */ - el_set(el, EL_BIND, "-a", "k", "ed-prev-line", NULL); - el_set(el, EL_BIND, "-a", "j", "ed-next-line", NULL); - - /* - * Source the user's defaults file. - */ - el_source(el, NULL); - - while ((buf = el_gets(el, &num)) != NULL && num != 0) { - int ac; - char **av; -#ifdef DEBUG - (void) fprintf(stderr, "got %d %s", num, buf); -#endif - if (!continuation && num == 1) - continue; - - if (tok_line(tok, buf, &ac, &av) > 0) - ncontinuation = 1; - -#if 0 - if (continuation) { - /* - * Append to the right event in case the user - * moved around in history. - */ - if (history(hist, &ev, H_SET, lastevent) == -1) - err(1, "%d: %s\n", lastevent, ev.str); - history(hist, &ev, H_ADD , buf); - } else { - history(hist, &ev, H_ENTER, buf); - lastevent = ev.num; - } -#else - /* Simpler */ - history(hist, &ev, continuation ? H_APPEND : H_ENTER, buf); -#endif - - continuation = ncontinuation; - ncontinuation = 0; - - if (strcmp(av[0], "history") == 0) { - int rv; - - switch (ac) { - case 1: - for (rv = history(hist, &ev, H_LAST); rv != -1; - rv = history(hist, &ev, H_PREV)) - (void) fprintf(stdout, "%4d %s", - ev.num, ev.str); - break; - - case 2: - if (strcmp(av[1], "clear") == 0) - history(hist, &ev, H_CLEAR); - else - goto badhist; - break; - - case 3: - if (strcmp(av[1], "load") == 0) - history(hist, &ev, H_LOAD, av[2]); - else if (strcmp(av[1], "save") == 0) - history(hist, &ev, H_SAVE, av[2]); - break; - - badhist: - default: - (void) fprintf(stderr, - "Bad history arguments\n"); - break; - } - } else if (el_parse(el, ac, av) == -1) { - switch (fork()) { - case 0: - execvp(av[0], av); - perror(av[0]); - _exit(1); - /*NOTREACHED*/ - break; - - case -1: - perror("fork"); - break; - - default: - if (wait(&num) == -1) - perror("wait"); - (void) fprintf(stderr, "Exit %x\n", num); - break; - } - } - - tok_reset(tok); - } - - el_end(el); - tok_end(tok); - history_end(hist); - - return (0); -} diff --git a/cmd-line-utils/libedit/chared.c b/cmd-line-utils/libedit/chared.c index 4cb6e00d26e..e4823db7147 100644 --- a/cmd-line-utils/libedit/chared.c +++ b/cmd-line-utils/libedit/chared.c @@ -1,4 +1,4 @@ -/* $NetBSD: chared.c,v 1.22 2004/08/13 12:10:38 mycroft Exp $ */ +/* $NetBSD: chared.c,v 1.26 2009/02/06 12:45:25 sketch Exp $ */ /*- * Copyright (c) 1992, 1993 @@ -32,7 +32,13 @@ * SUCH DAMAGE. */ -#include +#include "config.h" +#if !defined(lint) && !defined(SCCSID) +#if 0 +static char sccsid[] = "@(#)chared.c 8.1 (Berkeley) 6/4/93"; +#else +#endif +#endif /* not lint && not SCCSID */ /* * chared.c: Character editor utilities @@ -40,6 +46,8 @@ #include #include "el.h" +private void ch__clearmacro (EditLine *); + /* value to leave unused in line buffer */ #define EL_LEAVE 2 @@ -51,13 +59,13 @@ cv_undo(EditLine *el) { c_undo_t *vu = &el->el_chared.c_undo; c_redo_t *r = &el->el_chared.c_redo; - int size; + unsigned int size; /* Save entire line for undo */ size = el->el_line.lastchar - el->el_line.buffer; vu->len = size; vu->cursor = el->el_line.cursor - el->el_line.buffer; - memcpy(vu->buf, el->el_line.buffer, (size_t)size); + memcpy(vu->buf, el->el_line.buffer, size); /* save command info for redo */ r->count = el->el_state.doingarg ? el->el_state.argument : 0; @@ -439,6 +447,8 @@ cv__endword(char *p, char *high, int n, int (*wtest)(int)) protected int ch_init(EditLine *el) { + c_macro_t *ma = &el->el_chared.c_macro; + el->el_line.buffer = (char *) el_malloc(EL_BUFSIZ); if (el->el_line.buffer == NULL) return (-1); @@ -479,11 +489,10 @@ ch_init(EditLine *el) el->el_state.argument = 1; el->el_state.lastcmd = ED_UNASSIGNED; - el->el_chared.c_macro.level = -1; - el->el_chared.c_macro.offset = 0; - el->el_chared.c_macro.macro = (char **) el_malloc(EL_MAXMACRO * - sizeof(char *)); - if (el->el_chared.c_macro.macro == NULL) + ma->level = -1; + ma->offset = 0; + ma->macro = (char **) el_malloc(EL_MAXMACRO * sizeof(char *)); + if (ma->macro == NULL) return (-1); return (0); } @@ -492,7 +501,7 @@ ch_init(EditLine *el) * Reset the character editor */ protected void -ch_reset(EditLine *el) +ch_reset(EditLine *el, int mclear) { el->el_line.cursor = el->el_line.buffer; el->el_line.lastchar = el->el_line.buffer; @@ -513,9 +522,19 @@ ch_reset(EditLine *el) el->el_state.argument = 1; el->el_state.lastcmd = ED_UNASSIGNED; - el->el_chared.c_macro.level = -1; - el->el_history.eventno = 0; + + if (mclear) + ch__clearmacro(el); +} + +private void +ch__clearmacro(el) + EditLine *el; +{ + c_macro_t *ma = &el->el_chared.c_macro; + while (ma->level >= 0) + el_free((ptr_t)ma->macro[ma->level--]); } /* ch_enlargebufs(): @@ -623,9 +642,9 @@ ch_end(EditLine *el) el->el_chared.c_redo.cmd = ED_UNASSIGNED; el_free((ptr_t) el->el_chared.c_kill.buf); el->el_chared.c_kill.buf = NULL; + ch_reset(el, 1); el_free((ptr_t) el->el_chared.c_macro.macro); el->el_chared.c_macro.macro = NULL; - ch_reset(el); } diff --git a/cmd-line-utils/libedit/chared.h b/cmd-line-utils/libedit/chared.h index 2dd0a5795c7..fa8f5a58d83 100644 --- a/cmd-line-utils/libedit/chared.h +++ b/cmd-line-utils/libedit/chared.h @@ -1,4 +1,4 @@ -/* $NetBSD: chared.h,v 1.14 2004/08/13 12:10:39 mycroft Exp $ */ +/* $NetBSD: chared.h,v 1.17 2006/03/06 21:11:56 christos Exp $ */ /*- * Copyright (c) 1992, 1993 @@ -48,7 +48,7 @@ #define EL_MAXMACRO 10 /* - * This is a issue of basic "vi" look-and-feel. Defining VI_MOVE works + * This is an issue of basic "vi" look-and-feel. Defining VI_MOVE works * like real vi: i.e. the transition from command<->insert modes moves * the cursor. * @@ -116,11 +116,10 @@ typedef struct el_chared_t { } el_chared_t; -#define STReof "^D\b\b" #define STRQQ "\"\"" #define isglob(a) (strchr("*[]?", (a)) != NULL) -#define isword(a) (isprint(a)) +#define isword(a) (el_isprint(a)) #define NOP 0x00 #define DELETE 0x01 @@ -161,7 +160,7 @@ protected int c_gets(EditLine *, char *, const char *); protected int c_hpos(EditLine *); protected int ch_init(EditLine *); -protected void ch_reset(EditLine *); +protected void ch_reset(EditLine *, int); protected int ch_enlargebufs(EditLine *, size_t); protected void ch_end(EditLine *); diff --git a/cmd-line-utils/libedit/common.c b/cmd-line-utils/libedit/common.c index 81bf9bf29ff..d4d024eae10 100644 --- a/cmd-line-utils/libedit/common.c +++ b/cmd-line-utils/libedit/common.c @@ -1,4 +1,4 @@ -/* $NetBSD: common.c,v 1.16 2003/08/07 16:44:30 agc Exp $ */ +/* $NetBSD: common.c,v 1.21 2008/09/30 08:37:42 aymeric Exp $ */ /*- * Copyright (c) 1992, 1993 @@ -32,7 +32,13 @@ * SUCH DAMAGE. */ -#include +#include "config.h" +#if !defined(lint) && !defined(SCCSID) +#if 0 +static char sccsid[] = "@(#)common.c 8.1 (Berkeley) 6/4/93"; +#else +#endif +#endif /* not lint && not SCCSID */ /* * common.c: Common Editor functions @@ -130,7 +136,7 @@ ed_delete_prev_word(EditLine *el, int c __attribute__((__unused__))) */ protected el_action_t /*ARGSUSED*/ -ed_delete_next_char(EditLine *el, int c __attribute__((__unused__))) +ed_delete_next_char(EditLine *el, int c) { #ifdef notdef /* XXX */ #define EL el->el_line @@ -147,9 +153,8 @@ ed_delete_next_char(EditLine *el, int c __attribute__((__unused__))) #ifdef KSHVI return (CC_ERROR); #else - term_overwrite(el, STReof, 4); - /* then do a EOF */ - term__flush(); + /* then do an EOF */ + term_writechar(el, c); return (CC_EOF); #endif } else { @@ -207,13 +212,13 @@ ed_move_to_end(EditLine *el, int c __attribute__((__unused__))) el->el_line.cursor = el->el_line.lastchar; if (el->el_map.type == MAP_VI) { -#ifdef VI_MOVE - el->el_line.cursor--; -#endif if (el->el_chared.c_vcmd.action != NOP) { cv_delfini(el); return (CC_REFRESH); } +#ifdef VI_MOVE + el->el_line.cursor--; +#endif } return (CC_CURSOR); } @@ -609,7 +614,7 @@ protected el_action_t ed_start_over(EditLine *el, int c __attribute__((__unused__))) { - ch_reset(el); + ch_reset(el, 0); return (CC_REFRESH); } @@ -904,7 +909,7 @@ ed_command(EditLine *el, int c __attribute__((__unused__))) int tmplen; tmplen = c_gets(el, tmpbuf, "\n: "); - term__putc('\n'); + term__putc(el, '\n'); if (tmplen < 0 || (tmpbuf[tmplen] = 0, parse_line(el, tmpbuf)) == -1) term_beep(el); diff --git a/cmd-line-utils/libedit/compat.h b/cmd-line-utils/libedit/compat.h deleted file mode 100644 index 3693a2db809..00000000000 --- a/cmd-line-utils/libedit/compat.h +++ /dev/null @@ -1,43 +0,0 @@ -#ifndef __LIBEDIT_COMPATH_H -#define __LIBEDIT_COMPATH_H - -#define __RCSID(x) -#define __COPYRIGHT(x) - -#include "compat_conf.h" - -#ifndef HAVE_VIS_H -/* string visual representation - may want to reimplement */ -#define strvis(d,s,m) strcpy(d,s) -#define strunvis(d,s) strcpy(d,s) -#endif - -#ifndef HAVE_FGETLN -#include "fgetln.h" -#endif - -#ifndef HAVE_ISSETUGID -#define issetugid() (getuid()!=geteuid() || getegid()!=getgid()) -#endif - -#ifndef HAVE_STRLCPY -#include "strlcpy.h" -#endif - -#if HAVE_SYS_CDEFS_H -#include -#endif - -#ifndef __P -#ifdef __STDC__ -#define __P(x) x -#else -#define __P(x) () -#endif -#endif - -#if !defined(__attribute__) && (defined(__cplusplus) || !defined(__GNUC__) || __GNUC__ == 2 && __GNUC_MINOR__ < 8) -#define __attribute__(A) -#endif - -#endif diff --git a/cmd-line-utils/libedit/compat_conf.h b/cmd-line-utils/libedit/compat_conf.h deleted file mode 100644 index e2b9557f5b1..00000000000 --- a/cmd-line-utils/libedit/compat_conf.h +++ /dev/null @@ -1,2 +0,0 @@ - -#include "my_config.h" diff --git a/cmd-line-utils/libedit/config.h b/cmd-line-utils/libedit/config.h index 642123d1ddc..2c3989ee316 100644 --- a/cmd-line-utils/libedit/config.h +++ b/cmd-line-utils/libedit/config.h @@ -1,16 +1,2 @@ - #include "my_config.h" #include "sys.h" - -#if defined(LIBC_SCCS) && !defined(lint) -#define __RCSID(x) -#define __COPYRIGHT(x) -#endif -#define __RENAME(x) -#define _DIAGASSERT(x) - -#if !defined(__attribute__) && (defined(__cplusplus) || !defined(__GNUC__) || __GNUC__ == 2 && __GNUC_MINOR__ < 8) -#define __attribute__(A) -#endif - - diff --git a/cmd-line-utils/libedit/editline.3 b/cmd-line-utils/libedit/editline.3 deleted file mode 100644 index 1b812ebcc79..00000000000 --- a/cmd-line-utils/libedit/editline.3 +++ /dev/null @@ -1,619 +0,0 @@ -.\" $NetBSD: editline.3,v 1.21 2001/04/02 18:29:49 wiz Exp $ -.\" -.\" Copyright (c) 1997-1999 The NetBSD Foundation, Inc. -.\" All rights reserved. -.\" -.\" This file was contributed to The NetBSD Foundation by Luke Mewburn. -.\" -.\" Redistribution and use in source and binary forms, with or without -.\" modification, are permitted provided that the following conditions -.\" are met: -.\" 1. Redistributions of source code must retain the above copyright -.\" notice, this list of conditions and the following disclaimer. -.\" 2. Redistributions in binary form must reproduce the above copyright -.\" notice, this list of conditions and the following disclaimer in the -.\" documentation and/or other materials provided with the distribution. -.\" 3. All advertising materials mentioning features or use of this software -.\" must display the following acknowledgement: -.\" This product includes software developed by the NetBSD -.\" Foundation, Inc. and its contributors. -.\" 4. Neither the name of The NetBSD Foundation nor the names of its -.\" contributors may be used to endorse or promote products derived -.\" from this software without specific prior written permission. -.\" -.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS -.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED -.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS -.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -.\" POSSIBILITY OF SUCH DAMAGE. -.\" -.Dd November 12, 1999 -.Os -.Dt EDITLINE 3 -.Sh NAME -.Nm editline , -.Nm el_init , -.Nm el_end , -.Nm el_reset , -.Nm el_gets , -.Nm el_getc , -.Nm el_push , -.Nm el_parse , -.Nm el_set , -.Nm el_source , -.Nm el_resize , -.Nm el_line , -.Nm el_insertstr , -.Nm el_deletestr , -.Nm history_init , -.Nm history_end , -.Nm history -.Nd line editor and history functions -.Sh LIBRARY -.Lb libedit -.Sh SYNOPSIS -.Fd #include -.Ft EditLine * -.Fn el_init "const char *prog" "FILE *fin" "FILE *fout" "FILE *ferr" -.Ft void -.Fn el_end "EditLine *e" -.Ft void -.Fn el_reset "EditLine *e" -.Ft const char * -.Fn el_gets "EditLine *e" "int *count" -.Ft int -.Fn el_getc "EditLine *e" "char *ch" -.Ft void -.Fn el_push "EditLine *e" "const char *str" -.Ft int -.Fn el_parse "EditLine *e" "int argc" "char *argv[]" -.Ft int -.Fn el_set "EditLine *e" "int op" "..." -.Ft int -.Fn el_get "EditLine *e" "int op" "void *result" -.Ft int -.Fn el_source "EditLine *e" "const char *file" -.Ft void -.Fn el_resize "EditLine *e" -.Ft const LineInfo * -.Fn el_line "EditLine *e" -.Ft int -.Fn el_insertstr "EditLine *e" "const char *str" -.Ft void -.Fn el_deletestr "EditLine *e" "int count" -.Ft History * -.Fn history_init -.Ft void -.Fn history_end "History *h" -.Ft int -.Fn history "History *h" "HistEvent *ev" "int op" "..." -.Sh DESCRIPTION -The -.Nm -library provides generic line editing and history functions, -similar to those found in -.Xr sh 1 . -.Pp -These functions are available in the -.Nm libedit -library (which needs the -.Nm libtermcap -library). -Programs should be linked with -.Fl ledit ltermcap . -.Sh LINE EDITING FUNCTIONS -The line editing functions use a common data structure, -.Fa EditLine , -which is created by -.Fn el_init -and freed by -.Fn el_end . -.Pp -The following functions are available: -.Bl -tag -width 4n -.It Fn el_init -Initialise the line editor, and return a data structure -to be used by all other line editing functions. -.Fa prog -is the name of the invoking program, used when reading the -.Xr editrc 5 -file to determine which settings to use. -.Fa fin , -.Fa fout -and -.Fa ferr -are the input, output, and error streams (respectively) to use. -In this documentation, references to -.Dq the tty -are actually to this input/output stream combination. -.It Fn el_end -Clean up and finish with -.Fa e , -assumed to have been created with -.Fn el_init . -.It Fn el_reset -Reset the tty and the parser. -This should be called after an error which may have upset the tty's -state. -.It Fn el_gets -Read a line from the tty. -.Fa count -is modified to contain the number of characters read. -Returns the line read if successful, or -.Dv NULL -if no characters were read or if an error occurred. -.It Fn el_getc -Read a character from the tty. -.Fa ch -is modified to contain the character read. -Returns the number of characters read if successful, -1 otherwise. -.It Fn el_push -Pushes -.Fa str -back onto the input stream. -This is used by the macro expansion mechanism. -Refer to the description of -.Ic bind -.Fl s -in -.Xr editrc 5 -for more information. -.It Fn el_parse -Parses the -.Fa argv -array (which is -.Fa argc -elements in size) -to execute builtin -.Nm -commands. -If the command is prefixed with -.Dq prog: -then -.Fn el_parse -will only execute the command if -.Dq prog -matches the -.Fa prog -argument supplied to -.Fn el_init . -The return value is --1 if the command is unknown, -0 if there was no error or -.Dq prog -didn't match, or -1 if the command returned an error. -Refer to -.Xr editrc 5 -for more information. -.It Fn el_set -Set -.Nm -parameters. -.Fa op -determines which parameter to set, and each operation has its -own parameter list. -.Pp -The following values for -.Fa op -are supported, along with the required argument list: -.Bl -tag -width 4n -.It Dv EL_PROMPT , Fa "char *(*f)(EditLine *)" -Define prompt printing function as -.Fa f , -which is to return a string that contains the prompt. -.It Dv EL_RPROMPT , Fa "char *(*f)(EditLine *)" -Define right side prompt printing function as -.Fa f , -which is to return a string that contains the prompt. -.It Dv EL_TERMINAL , Fa "const char *type" -Define terminal type of the tty to be -.Fa type , -or to -.Ev TERM -if -.Fa type -is -.Dv NULL . -.It Dv EL_EDITOR , Fa "const char *mode" -Set editing mode to -.Fa mode , -which must be one of -.Dq emacs -or -.Dq vi . -.It Dv EL_SIGNAL , Fa "int flag" -If -.Fa flag -is non-zero, -.Nm -will install its own signal handler for the following signals when -reading command input: -.Dv SIGCONT , -.Dv SIGHUP , -.Dv SIGINT , -.Dv SIGQUIT , -.Dv SIGSTOP , -.Dv SIGTERM , -.Dv SIGTSTP , -and -.Dv SIGWINCH . -Otherwise, the current signal handlers will be used. -.It Dv EL_BIND , Xo -.Fa "const char *" , -.Fa "..." , -.Dv NULL -.Xc -Perform the -.Ic bind -builtin command. -Refer to -.Xr editrc 5 -for more information. -.It Dv EL_ECHOTC , Xo -.Fa "const char *" , -.Fa "..." , -.Dv NULL -.Xc -Perform the -.Ic echotc -builtin command. -Refer to -.Xr editrc 5 -for more information. -.It Dv EL_SETTC , Xo -.Fa "const char *" , -.Fa "..." , -.Dv NULL -.Xc -Perform the -.Ic settc -builtin command. -Refer to -.Xr editrc 5 -for more information. -.It Dv EL_SETTY , Xo -.Fa "const char *" , -.Fa "..." , -.Dv NULL -.Xc -Perform the -.Ic setty -builtin command. -Refer to -.Xr editrc 5 -for more information. -.It Dv EL_TELLTC , Xo -.Fa "const char *" , -.Fa "..." , -.Dv NULL -.Xc -Perform the -.Ic telltc -builtin command. -Refer to -.Xr editrc 5 -for more information. -.It Dv EL_ADDFN , Xo -.Fa "const char *name" , -.Fa "const char *help" , -.Fa "unsigned char (*func)(EditLine *e, int ch) -.Xc -Add a user defined function, -.Fn func , -referred to as -.Fa name -which is invoked when a key which is bound to -.Fa name -is entered. -.Fa help -is a description of -.Fa name . -At invocation time, -.Fa ch -is the key which caused the invocation. -The return value of -.Fn func -should be one of: -.Bl -tag -width "CC_REDISPLAY" -.It Dv CC_NORM -Add a normal character. -.It Dv CC_NEWLINE -End of line was entered. -.It Dv CC_EOF -EOF was entered. -.It Dv CC_ARGHACK -Expecting further command input as arguments, do nothing visually. -.It Dv CC_REFRESH -Refresh display. -.It Dv CC_REFRESH_BEEP -Refresh display, and beep. -.It Dv CC_CURSOR -Cursor moved, so update and perform -.Dv CC_REFRESH. -.It Dv CC_REDISPLAY -Redisplay entire input line. -This is useful if a key binding outputs extra information. -.It Dv CC_ERROR -An error occurred. -Beep, and flush tty. -.It Dv CC_FATAL -Fatal error, reset tty to known state. -.El -.It Dv EL_HIST , Xo -.Fa "History *(*func)(History *, int op, ...)" , -.Fa "const char *ptr" -.Xc -Defines which history function to use, which is usually -.Fn history . -.Fa ptr -should be the value returned by -.Fn history_init . -.It Dv EL_EDITMODE , Fa "int flag" -If -.Fa flag -is non-zero, -editing is enabled (the default). -Note that this is only an indication, and does not -affect the operation of -.Nm "" . -At this time, it is the caller's responsibility to -check this -(using -.Fn el_get ) -to determine if editing should be enabled or not. -.El -.It Fn el_get -Get -.Nm -parameters. -.Fa op -determines which parameter to retrieve into -.Fa result . -.Pp -The following values for -.Fa op -are supported, along with actual type of -.Fa result : -.Bl -tag -width 4n -.It Dv EL_PROMPT , Fa "char *(*f)(EditLine *)" -Return a pointer to the function that displays the prompt. -.It Dv EL_RPROMPT , Fa "char *(*f)(EditLine *)" -Return a pointer to the function that displays the rightside prompt. -.It Dv EL_EDITOR , Fa "const char *" -Return the name of the editor, which will be one of -.Dq emacs -or -.Dq vi . -.It Dv EL_SIGNAL , Fa "int *" -Return non-zero if -.Nm -has installed private signal handlers (see -.Fn el_get -above). -.It Dv EL_EDITMODE, Fa "int *" -Return non-zero if editing is enabled. -.El -.It Fn el_source -Initialise -.Nm -by reading the contents of -.Fa file . -.Fn el_parse -is called for each line in -.Fa file . -If -.Fa file -is -.Dv NULL , -try -.Pa $PWD/.editrc -then -.Pa $HOME/.editrc . -Refer to -.Xr editrc 5 -for details on the format of -.Fa file . -.It Fn el_resize -Must be called if the terminal size changes. -If -.Dv EL_SIGNAL -has been set with -.Fn el_set , -then this is done automatically. -Otherwise, it's the responsibility of the application to call -.Fn el_resize -on the appropriate occasions. -.It Fn el_line -Return the editing information for the current line in a -.Fa LineInfo -structure, which is defined as follows: -.Bd -literal -typedef struct lineinfo { - const char *buffer; /* address of buffer */ - const char *cursor; /* address of cursor */ - const char *lastchar; /* address of last character */ -} LineInfo; -.Ed -.It Fn el_insertstr -Insert -.Fa str -into the line at the cursor. -Returns -1 if -.Fa str -is empty or won't fit, and 0 otherwise. -.It Fn el_deletestr -Delete -.Fa num -characters before the cursor. -.El -.Sh HISTORY LIST FUNCTIONS -The history functions use a common data structure, -.Fa History , -which is created by -.Fn history_init -and freed by -.Fn history_end . -.Pp -The following functions are available: -.Bl -tag -width 4n -.It Fn history_init -Initialise the history list, and return a data structure -to be used by all other history list functions. -.It Fn history_end -Clean up and finish with -.Fa h , -assumed to have been created with -.Fn history_init . -.It Fn history -Perform operation -.Fa op -on the history list, with optional arguments as needed by the -operation. -.Fa ev -is changed accordingly to operation. -The following values for -.Fa op -are supported, along with the required argument list: -.Bl -tag -width 4n -.It Dv H_SETSIZE , Fa "int size" -Set size of history to -.Fa size -elements. -.It Dv H_GETSIZE -Get number of events currently in history. -.It Dv H_END -Cleans up and finishes with -.Fa h , -assumed to be created with -.Fn history_init . -.It Dv H_CLEAR -Clear the history. -.It Dv H_FUNC , Xo -.Fa "void *ptr" , -.Fa "history_gfun_t first" , -.Fa "history_gfun_t next" , -.Fa "history_gfun_t last" , -.Fa "history_gfun_t prev" , -.Fa "history_gfun_t curr" , -.Fa "history_sfun_t set" , -.Fa "history_vfun_t clear" , -.Fa "history_efun_t enter" , -.Fa "history_efun_t add" -.Xc -Define functions to perform various history operations. -.Fa ptr -is the argument given to a function when it's invoked. -.It Dv H_FIRST -Return the first element in the history. -.It Dv H_LAST -Return the last element in the history. -.It Dv H_PREV -Return the previous element in the history. -.It Dv H_NEXT -Return the next element in the history. -.It Dv H_CURR -Return the current element in the history. -.It Dv H_SET -Set the cursor to point to the requested element. -.It Dv H_ADD , Fa "const char *str" -Append -.Fa str -to the current element of the history, or create an element with -.It Dv H_APPEND , Fa "const char *str" -Append -.Fa str -to the last new element of the history. -.It Dv H_ENTER , Fa "const char *str" -Add -.Fa str -as a new element to the history, and, if necessary, -removing the oldest entry to keep the list to the created size. -.It Dv H_PREV_STR , Fa "const char *str" -Return the closest previous event that starts with -.Fa str . -.It Dv H_NEXT_STR , Fa "const char *str" -Return the closest next event that starts with -.Fa str . -.It Dv H_PREV_EVENT , Fa "int e" -Return the previous event numbered -.Fa e . -.It Dv H_NEXT_EVENT , Fa "int e" -Return the next event numbered -.Fa e . -.It Dv H_LOAD , Fa "const char *file" -Load the history list stored in -.Fa file . -.It Dv H_SAVE , Fa "const char *file" -Save the history list to -.Fa file . -.El -.Pp -.Fn history -returns 0 if the operation -.Fa op -succeeds. Otherwise, -1 is returned and -.Fa ev -is updated to contain more details about the error. -.El -.\"XXX.Sh EXAMPLES -.\"XXX: provide some examples -.Sh SEE ALSO -.Xr editrc 5 , -.Xr sh 1 , -.Xr signal 3 , -.Xr termcap 3 -.Sh HISTORY -The -.Nm -library first appeared in -.Bx 4.4 . -.Dv CC_REDISPLAY -appeared in -.Nx 1.3 . -.Dv CC_REFRESH_BEEP , -.Dv EL_EDITMODE -and the readline emulation appeared in -.Nx 1.4 . -.Dv EL_RPROMPT -appeared in -.Nx 1.5 . -.Sh AUTHORS -The -.Nm -library was written by Christos Zoulas. -Luke Mewburn wrote this manual and implemented -.Dv CC_REDISPLAY , -.Dv CC_REFRESH_BEEP , -.Dv EL_EDITMODE , -and -.Dv EL_RPROMPT . -Jaromir Dolecek implemented the readline emulation. -.Sh BUGS -The tokenization functions are not publically defined in -.Fd . -.Pp -At this time, it is the responsibility of the caller to -check the result of the -.Dv EL_EDITMODE -operation of -.Fn el_get -(after an -.Fn el_source -or -.Fn el_parse ) -to determine if -.Nm -should be used for further input. -I.e., -.Dv EL_EDITMODE -is purely an indication of the result of the most recent -.Xr editrc 5 -.Ic edit -command. diff --git a/cmd-line-utils/libedit/editrc.5 b/cmd-line-utils/libedit/editrc.5 deleted file mode 100644 index b1122618939..00000000000 --- a/cmd-line-utils/libedit/editrc.5 +++ /dev/null @@ -1,491 +0,0 @@ -.\" $NetBSD: editrc.5,v 1.11 2001/06/19 13:42:09 wiz Exp $ -.\" -.\" Copyright (c) 1997-2000 The NetBSD Foundation, Inc. -.\" All rights reserved. -.\" -.\" This file was contributed to The NetBSD Foundation by Luke Mewburn. -.\" -.\" Redistribution and use in source and binary forms, with or without -.\" modification, are permitted provided that the following conditions -.\" are met: -.\" 1. Redistributions of source code must retain the above copyright -.\" notice, this list of conditions and the following disclaimer. -.\" 2. Redistributions in binary form must reproduce the above copyright -.\" notice, this list of conditions and the following disclaimer in the -.\" documentation and/or other materials provided with the distribution. -.\" 3. All advertising materials mentioning features or use of this software -.\" must display the following acknowledgement: -.\" This product includes software developed by the NetBSD -.\" Foundation, Inc. and its contributors. -.\" 4. Neither the name of The NetBSD Foundation nor the names of its -.\" contributors may be used to endorse or promote products derived -.\" from this software without specific prior written permission. -.\" -.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS -.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED -.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS -.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -.\" POSSIBILITY OF SUCH DAMAGE. -.\" -.Dd November 8, 2000 -.Os -.Dt EDITRC 5 -.Sh NAME -.Nm editrc -.Nd configuration file for editline library -.Sh SYNOPSIS -.Nm -.Sh DESCRIPTION -The -.Nm -file defines various settings to be used by the -.Xr editline 3 -library. -.Pp -The format of each line is: -.Dl [prog:]command [arg [...]] -.Pp -.Ar command -is one of the -.Xr editline 3 -builtin commands. -Refer to -.Sx BUILTIN COMMANDS -for more information. -.Pp -.Ar prog -is the program name string that a program defines when it calls -.Xr el_init 3 -to setup -.Xr editline 3 , -which is usually -.Va argv[0] . -.Ar command -will be executed for any program which matches -.Ar prog . -.Pp -.Ar prog -may also be a -.Xr regex 3 -style -regular expression, in which case -.Ar command -will be executed for any program that matches the regular expression. -.Pp -If -.Ar prog -is absent, -.Ar command -is executed for all programs. -.Sh BUILTIN COMMANDS -The -.Nm editline -library has some builtin commands, which affect the way -that the line editing and history functions operate. -These are based on similar named builtins present in the -.Xr tcsh 1 -shell. -.Pp -The following builtin commands are available: -.Bl -tag -width 4n -.It Ic bind Xo -.Op Fl a -.Op Fl e -.Op Fl k -.Op Fl l -.Op Fl r -.Op Fl s -.Op Fl v -.Op Ar key Op Ar command -.Xc -Without options, list all bound keys, and the editor command to which -each is bound. -If -.Ar key -is supplied, show the bindings for -.Ar key . -If -.Ar key command -is supplied, bind -.Ar command -to -.Ar key . -Options include: -.Bl -tag -width 4n -.It Fl e -Bind all keys to the standard GNU Emacs-like bindings. -.It Fl v -Bind all keys to the standard -.Xr vi 1 -like -bindings. -.It Fl a -List or change key bindings in the -.Xr vi 1 -mode alternate (command mode) key map. -.It Fl k -.Ar key -is interpreted as a symbolic arrow key name, which may be one of -.Sq up , -.Sq down , -.Sq left -or -.Sq right . -.It Fl l -List all editor commands and a short description of each. -.It Fl r -Remove a key's binding. -.It Fl s -.Ar command -is taken as a literal string and treated as terminal input when -.Ar key -is typed. -Bound keys in -.Ar command -are themselves reinterpreted, and this continues for ten levels of -interpretation. -.El -.Pp -.Ar command -may be one of the commands documented in -.Sx "EDITOR COMMANDS" -below, or another key. -.Pp -.Ar key -and -.Ar command -can contain control characters of the form -.Sm off -.Sq No ^ Ar character -.Sm on -.Po -e.g. -.Sq ^A -.Pc , -and the following backslashed escape sequences: -.Pp -.Bl -tag -compact -offset indent -width 4n -.It Ic \ea -Bell -.It Ic \eb -Backspace -.It Ic \ee -Escape -.It Ic \ef -Formfeed -.It Ic \en -Newline -.It Ic \er -Carriage return -.It Ic \et -Horizontal tab -.It Ic \ev -Vertical tab -.Sm off -.It Sy \e Ar nnn -.Sm on -The ASCII character corresponding to the octal number -.Ar nnn . -.El -.Pp -.Sq \e -nullifies the special meaning of the following character, -if it has any, notably -.Sq \e -and -.Sq ^ . -.It Ic echotc Xo -.Op Fl sv -.Ar arg -.Ar ... -.Xc -Exercise terminal capabilities given in -.Ar arg Ar ... . -If -.Ar arg -is -.Sq baud , -.Sq cols , -.Sq lines , -.Sq rows , -.Sq meta or -.Sq tabs , -the value of that capability is printed, with -.Dq yes -or -.Dq no -indicating that the terminal does or does not have that capability. -.Pp -.Fl s -returns an emptry string for non-existent capabilities, rather than -causing an error. -.Fl v -causes messages to be verbose. -.It Ic edit Op Li on | Li off -Enable or disable the -.Nm editline -functionality in a program. -.It Ic history -List the history. -.It Ic telltc -List the values of all the terminal capabilities (see -.Xr termcap 5 ). -.It Ic settc Ar cap Ar val -Set the terminal capability -.Ar cap -to -.Ar val , -as defined in -.Xr termcap 5 . -No sanity checking is done. -.It Ic setty Xo -.Op Fl a -.Op Fl d -.Op Fl q -.Op Fl x -.Op Ar +mode -.Op Ar -mode -.Op Ar mode -.Xc -Control which tty modes that -.Nm -won't allow the user to change. -.Fl d , -.Fl q -or -.Fl x -tells -.Ic setty -to act on the -.Sq edit , -.Sq quote -or -.Sq execute -set of tty modes respectively; defaulting to -.Fl x . -.Pp -Without other arguments, -.Ic setty -lists the modes in the chosen set which are fixed on -.Po -.Sq +mode -.Pc -or off -.Po -.Sq -mode -.Pc . -.Fl a -lists all tty modes in the chosen set regardless of the setting. -With -.Ar +mode , -.Ar -mode -or -.Ar mode , -fixes -.Ar mode -on or off or removes control of -.Ar mode -in the chosen set. -.El -.Sh EDITOR COMMANDS -The following editor commands are available for use in key bindings: -.\" Section automatically generated with makelist -.Bl -tag -width 4n -.It Ic vi-paste-next -Vi paste previous deletion to the right of the cursor. -.It Ic vi-paste-prev -Vi paste previous deletion to the left of the cursor. -.It Ic vi-prev-space-word -Vi move to the previous space delimited word. -.It Ic vi-prev-word -Vi move to the previous word. -.It Ic vi-next-space-word -Vi move to the next space delimited word. -.It Ic vi-next-word -Vi move to the next word. -.It Ic vi-change-case -Vi change case of character under the cursor and advance one character. -.It Ic vi-change-meta -Vi change prefix command. -.It Ic vi-insert-at-bol -Vi enter insert mode at the beginning of line. -.It Ic vi-replace-char -Vi replace character under the cursor with the next character typed. -.It Ic vi-replace-mode -Vi enter replace mode. -.It Ic vi-substitute-char -Vi replace character under the cursor and enter insert mode. -.It Ic vi-substitute-line -Vi substitute entire line. -.It Ic vi-change-to-eol -Vi change to end of line. -.It Ic vi-insert -Vi enter insert mode. -.It Ic vi-add -Vi enter insert mode after the cursor. -.It Ic vi-add-at-eol -Vi enter insert mode at end of line. -.It Ic vi-delete-meta -Vi delete prefix command. -.It Ic vi-end-word -Vi move to the end of the current space delimited word. -.It Ic vi-to-end-word -Vi move to the end of the current word. -.It Ic vi-undo -Vi undo last change. -.It Ic vi-command-mode -Vi enter command mode (use alternative key bindings). -.It Ic vi-zero -Vi move to the beginning of line. -.It Ic vi-delete-prev-char -Vi move to previous character (backspace). -.It Ic vi-list-or-eof -Vi list choices for completion or indicate end of file if empty line. -.It Ic vi-kill-line-prev -Vi cut from beginning of line to cursor. -.It Ic vi-search-prev -Vi search history previous. -.It Ic vi-search-next -Vi search history next. -.It Ic vi-repeat-search-next -Vi repeat current search in the same search direction. -.It Ic vi-repeat-search-prev -Vi repeat current search in the opposite search direction. -.It Ic vi-next-char -Vi move to the character specified next. -.It Ic vi-prev-char -Vi move to the character specified previous. -.It Ic vi-to-next-char -Vi move up to the character specified next. -.It Ic vi-to-prev-char -Vi move up to the character specified previous. -.It Ic vi-repeat-next-char -Vi repeat current character search in the same search direction. -.It Ic vi-repeat-prev-char -Vi repeat current character search in the opposite search direction. -.It Ic em-delete-or-list -Delete character under cursor or list completions if at end of line. -.It Ic em-delete-next-word -Cut from cursor to end of current word. -.It Ic em-yank -Paste cut buffer at cursor position. -.It Ic em-kill-line -Cut the entire line and save in cut buffer. -.It Ic em-kill-region -Cut area between mark and cursor and save in cut buffer. -.It Ic em-copy-region -Copy area between mark and cursor to cut buffer. -.It Ic em-gosmacs-traspose -Exchange the two characters before the cursor. -.It Ic em-next-word -Move next to end of current word. -.It Ic em-upper-case -Uppercase the characters from cursor to end of current word. -.It Ic em-capitol-case -Capitalize the characters from cursor to end of current word. -.It Ic em-lower-case -Lowercase the characters from cursor to end of current word. -.It Ic em-set-mark -Set the mark at cursor. -.It Ic em-exchange-mark -Exchange the cursor and mark. -.It Ic em-universal-argument -Universal argument (argument times 4). -.It Ic em-meta-next -Add 8th bit to next character typed. -.It Ic em-toggle-overwrite -Switch from insert to overwrite mode or vice versa. -.It Ic em-copy-prev-word -Copy current word to cursor. -.It Ic em-inc-search-next -Emacs incremental next search. -.It Ic em-inc-search-prev -Emacs incremental reverse search. -.It Ic ed-end-of-file -Indicate end of file. -.It Ic ed-insert -Add character to the line. -.It Ic ed-delete-prev-word -Delete from beginning of current word to cursor. -.It Ic ed-delete-next-char -Delete character under cursor. -.It Ic ed-kill-line -Cut to the end of line. -.It Ic ed-move-to-end -Move cursor to the end of line. -.It Ic ed-move-to-beg -Move cursor to the beginning of line. -.It Ic ed-transpose-chars -Exchange the character to the left of the cursor with the one under it. -.It Ic ed-next-char -Move to the right one character. -.It Ic ed-prev-word -Move to the beginning of the current word. -.It Ic ed-prev-char -Move to the left one character. -.It Ic ed-quoted-insert -Add the next character typed verbatim. -.It Ic ed-digit -Adds to argument or enters a digit. -.It Ic ed-argument-digit -Digit that starts argument. -.It Ic ed-unassigned -Indicates unbound character. -.It Ic ed-tty-sigint -Tty interrupt character. -.It Ic ed-tty-dsusp -Tty delayed suspend character. -.It Ic ed-tty-flush-output -Tty flush output characters. -.It Ic ed-tty-sigquit -Tty quit character. -.It Ic ed-tty-sigtstp -Tty suspend character. -.It Ic ed-tty-stop-output -Tty disallow output characters. -.It Ic ed-tty-start-output -Tty allow output characters. -.It Ic ed-newline -Execute command. -.It Ic ed-delete-prev-char -Delete the character to the left of the cursor. -.It Ic ed-clear-screen -Clear screen leaving current line at the top. -.It Ic ed-redisplay -Redisplay everything. -.It Ic ed-start-over -Erase current line and start from scratch. -.It Ic ed-sequence-lead-in -First character in a bound sequence. -.It Ic ed-prev-history -Move to the previous history line. -.It Ic ed-next-history -Move to the next history line. -.It Ic ed-search-prev-history -Search previous in history for a line matching the current. -.It Ic ed-search-next-history -Search next in history for a line matching the current. -.It Ic ed-prev-line -Move up one line. -.It Ic ed-next-line -Move down one line. -.It Ic ed-command -Editline extended command. -.El -.\" End of section automatically generated with makelist -.Sh SEE ALSO -.Xr editline 3 , -.Xr regex 3 , -.Xr termcap 5 -.Sh AUTHORS -The -.Nm editline -library was written by Christos Zoulas, -and this manual was written by Luke Mewburn, -with some sections inspired by -.Xr tcsh 1 . diff --git a/cmd-line-utils/libedit/el.c b/cmd-line-utils/libedit/el.c index c32a01b2151..d99946eb68f 100644 --- a/cmd-line-utils/libedit/el.c +++ b/cmd-line-utils/libedit/el.c @@ -1,4 +1,4 @@ -/* $NetBSD: el.c,v 1.39 2004/07/08 00:51:36 christos Exp $ */ +/* $NetBSD: el.c,v 1.47 2009/01/18 12:17:24 lukem Exp $ */ /*- * Copyright (c) 1992, 1993 @@ -32,7 +32,13 @@ * SUCH DAMAGE. */ -#include +#include "config.h" +#if !defined(lint) && !defined(SCCSID) +#if 0 +static char sccsid[] = "@(#)el.c 8.2 (Berkeley) 1/3/94"; +#else +#endif +#endif /* not lint && not SCCSID */ /* * el.c: EditLine interface functions @@ -58,9 +64,12 @@ el_init(const char *prog, FILE *fin, FILE *fout, FILE *ferr) memset(el, 0, sizeof(EditLine)); - el->el_infd = fileno(fin); + el->el_infile = fin; el->el_outfile = fout; el->el_errfile = ferr; + + el->el_infd = fileno(fin); + if ((el->el_prog = el_strdup(prog)) == NULL) { el_free(el); return NULL; @@ -126,7 +135,7 @@ el_reset(EditLine *el) { tty_cookedmode(el); - ch_reset(el); /* XXX: Do we want that? */ + ch_reset(el, 0); /* XXX: Do we want that? */ } @@ -136,29 +145,29 @@ el_reset(EditLine *el) public int el_set(EditLine *el, int op, ...) { - va_list va; + va_list ap; int rv = 0; if (el == NULL) return (-1); - va_start(va, op); + va_start(ap, op); switch (op) { case EL_PROMPT: case EL_RPROMPT: - rv = prompt_set(el, va_arg(va, el_pfunc_t), op); + rv = prompt_set(el, va_arg(ap, el_pfunc_t), op); break; case EL_TERMINAL: - rv = term_set(el, va_arg(va, char *)); + rv = term_set(el, va_arg(ap, char *)); break; case EL_EDITOR: - rv = map_set_editor(el, va_arg(va, char *)); + rv = map_set_editor(el, va_arg(ap, char *)); break; case EL_SIGNAL: - if (va_arg(va, int)) + if (va_arg(ap, int)) el->el_flags |= HANDLE_SIGNALS; else el->el_flags &= ~HANDLE_SIGNALS; @@ -167,6 +176,7 @@ el_set(EditLine *el, int op, ...) case EL_BIND: case EL_TELLTC: case EL_SETTC: + case EL_GETTC: case EL_ECHOTC: case EL_SETTY: { @@ -174,7 +184,7 @@ el_set(EditLine *el, int op, ...) int i; for (i = 1; i < 20; i++) - if ((argv[i] = va_arg(va, char *)) == NULL) + if ((argv[i] = va_arg(ap, char *)) == NULL) break; switch (op) { @@ -213,9 +223,9 @@ el_set(EditLine *el, int op, ...) case EL_ADDFN: { - char *name = va_arg(va, char *); - char *help = va_arg(va, char *); - el_func_t func = va_arg(va, el_func_t); + char *name = va_arg(ap, char *); + char *help = va_arg(ap, char *); + el_func_t func = va_arg(ap, el_func_t); rv = map_addfunc(el, name, help, func); break; @@ -223,15 +233,15 @@ el_set(EditLine *el, int op, ...) case EL_HIST: { - hist_fun_t func = va_arg(va, hist_fun_t); - ptr_t ptr = va_arg(va, char *); + hist_fun_t func = va_arg(ap, hist_fun_t); + ptr_t ptr = va_arg(ap, char *); rv = hist_set(el, func, ptr); break; } case EL_EDITMODE: - if (va_arg(va, int)) + if (va_arg(ap, int)) el->el_flags &= ~EDIT_DISABLED; else el->el_flags |= EDIT_DISABLED; @@ -240,17 +250,17 @@ el_set(EditLine *el, int op, ...) case EL_GETCFN: { - el_rfunc_t rc = va_arg(va, el_rfunc_t); + el_rfunc_t rc = va_arg(ap, el_rfunc_t); rv = el_read_setfn(el, rc); break; } case EL_CLIENTDATA: - el->el_data = va_arg(va, void *); + el->el_data = va_arg(ap, void *); break; case EL_UNBUFFERED: - rv = va_arg(va, int); + rv = va_arg(ap, int); if (rv && !(el->el_flags & UNBUFFERED)) { el->el_flags |= UNBUFFERED; read_prepare(el); @@ -262,7 +272,7 @@ el_set(EditLine *el, int op, ...) break; case EL_PREP_TERM: - rv = va_arg(va, int); + rv = va_arg(ap, int); if (rv) (void) tty_rawmode(el); else @@ -270,12 +280,45 @@ el_set(EditLine *el, int op, ...) rv = 0; break; + case EL_SETFP: + { + FILE *fp; + int what; + + what = va_arg(ap, int); + fp = va_arg(ap, FILE *); + + rv = 0; + switch (what) { + case 0: + el->el_infile = fp; + el->el_infd = fileno(fp); + break; + case 1: + el->el_outfile = fp; + break; + case 2: + el->el_errfile = fp; + break; + default: + rv = -1; + break; + } + break; + } + + case EL_REFRESH: + re_clear_display(el); + re_refresh(el); + term__flush(el); + break; + default: rv = -1; break; } - va_end(va); + va_end(ap); return (rv); } @@ -284,90 +327,71 @@ el_set(EditLine *el, int op, ...) * retrieve the editline parameters */ public int -el_get(EditLine *el, int op, void *ret) +el_get(EditLine *el, int op, ...) { + va_list ap; int rv; - if (el == NULL || ret == NULL) - return (-1); + if (el == NULL) + return -1; + + va_start(ap, op); + switch (op) { case EL_PROMPT: case EL_RPROMPT: - rv = prompt_get(el, (void *) &ret, op); + rv = prompt_get(el, va_arg(ap, el_pfunc_t *), op); break; case EL_EDITOR: - rv = map_get_editor(el, (void *) &ret); + rv = map_get_editor(el, va_arg(ap, const char **)); break; case EL_SIGNAL: - *((int *) ret) = (el->el_flags & HANDLE_SIGNALS); + *va_arg(ap, int *) = (el->el_flags & HANDLE_SIGNALS); rv = 0; break; case EL_EDITMODE: - *((int *) ret) = (!(el->el_flags & EDIT_DISABLED)); + *va_arg(ap, int *) = !(el->el_flags & EDIT_DISABLED); rv = 0; break; case EL_TERMINAL: - term_get(el, (const char **)ret); + term_get(el, va_arg(ap, const char **)); rv = 0; break; -#if 0 /* XXX */ - case EL_BIND: - case EL_TELLTC: - case EL_SETTC: - case EL_ECHOTC: - case EL_SETTY: + case EL_GETTC: { - const char *argv[20]; + static char name[] = "gettc"; + char *argv[20]; int i; - for (i = 1; i < sizeof(argv) / sizeof(argv[0]); i++) - if ((argv[i] = va_arg(va, char *)) == NULL) + for (i = 1; i < (int)(sizeof(argv) / sizeof(argv[0])); i++) + if ((argv[i] = va_arg(ap, char *)) == NULL) break; switch (op) { - case EL_BIND: - argv[0] = "bind"; - rv = map_bind(el, i, argv); - break; - - case EL_TELLTC: - argv[0] = "telltc"; - rv = term_telltc(el, i, argv); - break; - - case EL_SETTC: - argv[0] = "settc"; - rv = term_settc(el, i, argv); - break; - - case EL_ECHOTC: - argv[0] = "echotc"; - rv = term_echotc(el, i, argv); - break; - - case EL_SETTY: - argv[0] = "setty"; - rv = tty_stty(el, i, argv); + case EL_GETTC: + argv[0] = name; + rv = term_gettc(el, i, argv); break; default: rv = -1; - EL_ABORT((el->errfile, "Bad op %d\n", op)); + EL_ABORT((el->el_errfile, "Bad op %d\n", op)); break; } break; } +#if 0 /* XXX */ case EL_ADDFN: { - char *name = va_arg(va, char *); - char *help = va_arg(va, char *); - el_func_t func = va_arg(va, el_func_t); + char *name = va_arg(ap, char *); + char *help = va_arg(ap, char *); + el_func_t func = va_arg(ap, el_func_t); rv = map_addfunc(el, name, help, func); break; @@ -375,31 +399,57 @@ el_get(EditLine *el, int op, void *ret) case EL_HIST: { - hist_fun_t func = va_arg(va, hist_fun_t); - ptr_t ptr = va_arg(va, char *); + hist_fun_t func = va_arg(ap, hist_fun_t); + ptr_t ptr = va_arg(ap, char *); rv = hist_set(el, func, ptr); } break; #endif /* XXX */ case EL_GETCFN: - *((el_rfunc_t *)ret) = el_read_getfn(el); + *va_arg(ap, el_rfunc_t *) = el_read_getfn(el); rv = 0; break; case EL_CLIENTDATA: - *((void **)ret) = el->el_data; + *va_arg(ap, void **) = el->el_data; rv = 0; break; case EL_UNBUFFERED: - *((int *) ret) = (!(el->el_flags & UNBUFFERED)); + *va_arg(ap, int *) = (!(el->el_flags & UNBUFFERED)); rv = 0; break; + case EL_GETFP: + { + int what; + FILE **fpp; + + what = va_arg(ap, int); + fpp = va_arg(ap, FILE **); + rv = 0; + switch (what) { + case 0: + *fpp = el->el_infile; + break; + case 1: + *fpp = el->el_outfile; + break; + case 2: + *fpp = el->el_errfile; + break; + default: + rv = -1; + break; + } + break; + } default: rv = -1; + break; } + va_end(ap); return (rv); } @@ -428,17 +478,17 @@ el_source(EditLine *el, const char *fname) fp = NULL; if (fname == NULL) { +#ifdef HAVE_ISSETUGID static const char elpath[] = "/.editrc"; +/* XXXMYSQL: Portability fix (for which platforms?) */ #ifdef MAXPATHLEN char path[MAXPATHLEN]; #else char path[4096]; #endif -#ifdef HAVE_ISSETUGID if (issetugid()) return (-1); -#endif if ((ptr = getenv("HOME")) == NULL) return (-1); if (strlcpy(path, ptr, sizeof(path)) >= sizeof(path)) @@ -446,6 +496,14 @@ el_source(EditLine *el, const char *fname) if (strlcat(path, elpath, sizeof(path)) >= sizeof(path)) return (-1); fname = path; +#else + /* + * If issetugid() is missing, always return an error, in order + * to keep from inadvertently opening up the user to a security + * hole. + */ + return (-1); +#endif } if (fp == NULL) fp = fopen(fname, "r"); diff --git a/cmd-line-utils/libedit/el.h b/cmd-line-utils/libedit/el.h index d9379d7c8aa..05d88ad88ba 100644 --- a/cmd-line-utils/libedit/el.h +++ b/cmd-line-utils/libedit/el.h @@ -1,4 +1,4 @@ -/* $NetBSD: el.h,v 1.16 2003/10/18 23:48:42 christos Exp $ */ +/* $NetBSD: el.h,v 1.17 2006/12/15 22:13:33 christos Exp $ */ /*- * Copyright (c) 1992, 1993 @@ -110,6 +110,7 @@ typedef struct el_state_t { struct editline { char *el_prog; /* the program name */ + FILE *el_infile; /* Stdio stuff */ FILE *el_outfile; /* Stdio stuff */ FILE *el_errfile; /* Stdio stuff */ int el_infd; /* Input file descriptor */ @@ -136,7 +137,8 @@ struct editline { protected int el_editmode(EditLine *, int, const char **); -#define el_isprint(x) ((unsigned char) (x) < 0x80 ? isprint(x) : 1) +/* XXXMYSQL: Bug#23097 mysql can't insert korean on mysql prompt. */ +#define el_isprint(x) ((unsigned char) (x) < 0x80 ? isprint(x) : 1) #ifdef DEBUG #define EL_ABORT(a) do { \ diff --git a/cmd-line-utils/libedit/el_term.h b/cmd-line-utils/libedit/el_term.h index 00ca48e38e2..0e7ddd555f4 100644 --- a/cmd-line-utils/libedit/el_term.h +++ b/cmd-line-utils/libedit/el_term.h @@ -1,4 +1,4 @@ -/* $NetBSD: term.h,v 1.15 2003/09/14 21:48:55 christos Exp $ */ +/* $NetBSD: term.h,v 1.19 2008/09/10 15:45:37 christos Exp $ */ /*- * Copyright (c) 1992, 1993 @@ -81,25 +81,6 @@ typedef struct { #define A_K_EN 5 #define A_K_NKEYS 6 -#ifdef _SUNOS -extern int tgetent(char *, const char *); -extern int tgetflag(char *); -extern int tgetnum(char *); -extern int tputs(const char *, int, int (*)(int)); -extern char* tgoto(const char*, int, int); -extern char* tgetstr(char*, char**); -#endif - - -#if !HAVE_DECL_TGOTO -/* - 'tgoto' is not declared in the system header files, this causes - problems on 64-bit systems. The function returns a 64 bit pointer - but caller see it as "int" and it's thus truncated to 32-bit -*/ -extern char* tgoto(const char*, int, int); -#endif - protected void term_move_to_line(EditLine *, int); protected void term_move_to_char(EditLine *, int); protected void term_clear_EOL(EditLine *, int); @@ -119,10 +100,12 @@ protected void term_end(EditLine *); protected void term_get(EditLine *, const char **); protected int term_set(EditLine *, const char *); protected int term_settc(EditLine *, int, const char **); +protected int term_gettc(EditLine *, int, char **); protected int term_telltc(EditLine *, int, const char **); protected int term_echotc(EditLine *, int, const char **); -protected int term__putc(int); -protected void term__flush(void); +protected void term_writec(EditLine *, int); +protected int term__putc(EditLine *, int); +protected void term__flush(EditLine *); /* * Easy access macros @@ -134,6 +117,7 @@ protected void term__flush(void); #define EL_CAN_CEOL (EL_FLAGS & TERM_CAN_CEOL) #define EL_CAN_TAB (EL_FLAGS & TERM_CAN_TAB) #define EL_CAN_ME (EL_FLAGS & TERM_CAN_ME) +#define EL_CAN_UP (EL_FLAGS & TERM_CAN_UP) #define EL_HAS_META (EL_FLAGS & TERM_HAS_META) #define EL_HAS_AUTO_MARGINS (EL_FLAGS & TERM_HAS_AUTO_MARGINS) #define EL_HAS_MAGIC_MARGINS (EL_FLAGS & TERM_HAS_MAGIC_MARGINS) diff --git a/cmd-line-utils/libedit/emacs.c b/cmd-line-utils/libedit/emacs.c index 79f2bf0c818..135bd75f566 100644 --- a/cmd-line-utils/libedit/emacs.c +++ b/cmd-line-utils/libedit/emacs.c @@ -1,4 +1,4 @@ -/* $NetBSD: emacs.c,v 1.19 2004/10/28 21:14:52 dsl Exp $ */ +/* $NetBSD: emacs.c,v 1.21 2006/03/06 21:11:56 christos Exp $ */ /*- * Copyright (c) 1992, 1993 @@ -32,7 +32,13 @@ * SUCH DAMAGE. */ -#include +#include "config.h" +#if !defined(lint) && !defined(SCCSID) +#if 0 +static char sccsid[] = "@(#)emacs.c 8.1 (Berkeley) 6/4/93"; +#else +#endif +#endif /* not lint && not SCCSID */ /* * emacs.c: Emacs functions @@ -45,15 +51,14 @@ */ protected el_action_t /*ARGSUSED*/ -em_delete_or_list(EditLine *el, int c __attribute__((__unused__))) +em_delete_or_list(EditLine *el, int c) { if (el->el_line.cursor == el->el_line.lastchar) { /* if I'm at the end */ if (el->el_line.cursor == el->el_line.buffer) { /* and the beginning */ - term_overwrite(el, STReof, 4); /* then do a EOF */ - term__flush(); + term_writec(el, c); /* then do an EOF */ return (CC_EOF); } else { /* diff --git a/cmd-line-utils/libedit/fgetln.h b/cmd-line-utils/libedit/fgetln.h deleted file mode 100644 index b2ddce01da9..00000000000 --- a/cmd-line-utils/libedit/fgetln.h +++ /dev/null @@ -1,3 +0,0 @@ -#include - -char *fgetln(FILE *stream, size_t *len); diff --git a/cmd-line-utils/libedit/filecomplete.c b/cmd-line-utils/libedit/filecomplete.c new file mode 100644 index 00000000000..4c63f57bc45 --- /dev/null +++ b/cmd-line-utils/libedit/filecomplete.c @@ -0,0 +1,558 @@ +/* $NetBSD: filecomplete.c,v 1.13 2009/01/26 17:32:41 apb Exp $ */ + +/*- + * Copyright (c) 1997 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Jaromir Dolecek. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* AIX requires this to be the first thing in the file. */ +#if defined (_AIX) && !defined (__GNUC__) + #pragma alloca +#endif + +#include "config.h" + +/* XXXMYSQL */ +#ifdef __GNUC__ +# undef alloca +# define alloca(n) __builtin_alloca (n) +#else +# ifdef HAVE_ALLOCA_H +# include +# else +# ifndef _AIX +extern char *alloca (); +# endif +# endif +#endif + +#if !defined(lint) && !defined(SCCSID) +#endif /* not lint && not SCCSID */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef HAVE_VIS_H +#include +#else +#include "np/vis.h" +#endif +#ifdef HAVE_ALLOCA_H +#include +#endif +#include "el.h" +#include "fcns.h" /* for EL_NUM_FCNS */ +#include "histedit.h" +#include "filecomplete.h" + +static char break_chars[] = { ' ', '\t', '\n', '"', '\\', '\'', '`', '@', '$', + '>', '<', '=', ';', '|', '&', '{', '(', '\0' }; + + +/********************************/ +/* completion functions */ + +/* + * does tilde expansion of strings of type ``~user/foo'' + * if ``user'' isn't valid user name or ``txt'' doesn't start + * w/ '~', returns pointer to strdup()ed copy of ``txt'' + * + * it's callers's responsibility to free() returned string + */ +char * +fn_tilde_expand(const char *txt) +{ + struct passwd pwres, *pass; + char *temp; + size_t len = 0; + char pwbuf[1024]; + + if (txt[0] != '~') + return (strdup(txt)); + + temp = strchr(txt + 1, '/'); + if (temp == NULL) { + temp = strdup(txt + 1); + if (temp == NULL) + return NULL; + } else { + len = temp - txt + 1; /* text until string after slash */ + temp = malloc(len); + if (temp == NULL) + return NULL; + (void)strncpy(temp, txt + 1, len - 2); + temp[len - 2] = '\0'; + } + /* XXXMYSQL: use non-_r functions for now */ + if (temp[0] == 0) { + pass = getpwuid(getuid()); + } else { + pass = getpwnam(temp); + } + free(temp); /* value no more needed */ + if (pass == NULL) + return (strdup(txt)); + + /* update pointer txt to point at string immedially following */ + /* first slash */ + txt += len; + + temp = malloc(strlen(pass->pw_dir) + 1 + strlen(txt) + 1); + if (temp == NULL) + return NULL; + (void)sprintf(temp, "%s/%s", pass->pw_dir, txt); + + return (temp); +} + + +/* + * return first found file name starting by the ``text'' or NULL if no + * such file can be found + * value of ``state'' is ignored + * + * it's caller's responsibility to free returned string + */ +char * +fn_filename_completion_function(const char *text, int state) +{ + static DIR *dir = NULL; + static char *filename = NULL, *dirname = NULL, *dirpath = NULL; + static size_t filename_len = 0; + struct dirent *entry; + char *temp; + size_t len; + + if (state == 0 || dir == NULL) { + temp = strrchr(text, '/'); + if (temp) { + char *nptr; + temp++; + nptr = realloc(filename, strlen(temp) + 1); + if (nptr == NULL) { + free(filename); + return NULL; + } + filename = nptr; + (void)strcpy(filename, temp); + len = temp - text; /* including last slash */ + nptr = realloc(dirname, len + 1); + if (nptr == NULL) { + free(filename); + return NULL; + } + dirname = nptr; + (void)strncpy(dirname, text, len); + dirname[len] = '\0'; + } else { + if (*text == 0) + filename = NULL; + else { + filename = strdup(text); + if (filename == NULL) + return NULL; + } + dirname = NULL; + } + + if (dir != NULL) { + (void)closedir(dir); + dir = NULL; + } + + /* support for ``~user'' syntax */ + free(dirpath); + + if (dirname == NULL && (dirname = strdup("./")) == NULL) + return NULL; + + if (*dirname == '~') + dirpath = fn_tilde_expand(dirname); + else + dirpath = strdup(dirname); + + if (dirpath == NULL) + return NULL; + + dir = opendir(dirpath); + if (!dir) + return (NULL); /* cannot open the directory */ + + /* will be used in cycle */ + filename_len = filename ? strlen(filename) : 0; + } + + /* find the match */ + while ((entry = readdir(dir)) != NULL) { + /* skip . and .. */ + if (entry->d_name[0] == '.' && (!entry->d_name[1] + || (entry->d_name[1] == '.' && !entry->d_name[2]))) + continue; + if (filename_len == 0) + break; + /* otherwise, get first entry where first */ + /* filename_len characters are equal */ + if (entry->d_name[0] == filename[0] +#if HAVE_STRUCT_DIRENT_D_NAMLEN + && entry->d_namlen >= filename_len +#else + && strlen(entry->d_name) >= filename_len +#endif + && strncmp(entry->d_name, filename, + filename_len) == 0) + break; + } + + if (entry) { /* match found */ + +#if HAVE_STRUCT_DIRENT_D_NAMLEN + len = entry->d_namlen; +#else + len = strlen(entry->d_name); +#endif + + temp = malloc(strlen(dirname) + len + 1); + if (temp == NULL) + return NULL; + (void)sprintf(temp, "%s%s", dirname, entry->d_name); + } else { + (void)closedir(dir); + dir = NULL; + temp = NULL; + } + + return (temp); +} + + +static const char * +append_char_function(const char *name) +{ + struct stat stbuf; + char *expname = *name == '~' ? fn_tilde_expand(name) : NULL; + const char *rs = " "; + + if (stat(expname ? expname : name, &stbuf) == -1) + goto out; + if (S_ISDIR(stbuf.st_mode)) + rs = "/"; +out: + if (expname) + free(expname); + return rs; +} +/* + * returns list of completions for text given + * non-static for readline. + */ +char ** completion_matches(const char *, char *(*)(const char *, int)); +char ** +completion_matches(const char *text, char *(*genfunc)(const char *, int)) +{ + char **match_list = NULL, *retstr, *prevstr; + size_t match_list_len, max_equal, which, i; + size_t matches; + + matches = 0; + match_list_len = 1; + while ((retstr = (*genfunc) (text, (int)matches)) != NULL) { + /* allow for list terminator here */ + if (matches + 3 >= match_list_len) { + char **nmatch_list; + while (matches + 3 >= match_list_len) + match_list_len <<= 1; + nmatch_list = realloc(match_list, + match_list_len * sizeof(char *)); + if (nmatch_list == NULL) { + free(match_list); + return NULL; + } + match_list = nmatch_list; + + } + match_list[++matches] = retstr; + } + + if (!match_list) + return NULL; /* nothing found */ + + /* find least denominator and insert it to match_list[0] */ + which = 2; + prevstr = match_list[1]; + max_equal = strlen(prevstr); + for (; which <= matches; which++) { + for (i = 0; i < max_equal && + prevstr[i] == match_list[which][i]; i++) + continue; + max_equal = i; + } + + retstr = malloc(max_equal + 1); + if (retstr == NULL) { + free(match_list); + return NULL; + } + (void)strncpy(retstr, match_list[1], max_equal); + retstr[max_equal] = '\0'; + match_list[0] = retstr; + + /* add NULL as last pointer to the array */ + match_list[matches + 1] = (char *) NULL; + + return (match_list); +} + +/* + * Sort function for qsort(). Just wrapper around strcasecmp(). + */ +static int +_fn_qsort_string_compare(const void *i1, const void *i2) +{ + const char *s1 = ((const char * const *)i1)[0]; + const char *s2 = ((const char * const *)i2)[0]; + + return strcasecmp(s1, s2); +} + +/* + * Display list of strings in columnar format on readline's output stream. + * 'matches' is list of strings, 'len' is number of strings in 'matches', + * 'max' is maximum length of string in 'matches'. + */ +void +fn_display_match_list (EditLine *el, char **matches, int len, int max) +{ + int i, idx, limit, count; + int screenwidth = el->el_term.t_size.h; + + /* + * Find out how many entries can be put on one line, count + * with two spaces between strings. + */ + limit = screenwidth / (max + 2); + if (limit == 0) + limit = 1; + + /* how many lines of output */ + count = len / limit; + if (count * limit < len) + count++; + + /* Sort the items if they are not already sorted. */ + qsort(&matches[1], (size_t)(len - 1), sizeof(char *), + _fn_qsort_string_compare); + + idx = 1; + for(; count > 0; count--) { + for(i = 0; i < limit && matches[idx]; i++, idx++) + (void)fprintf(el->el_outfile, "%-*s ", max, + matches[idx]); + (void)fprintf(el->el_outfile, "\n"); + } +} + +/* + * Complete the word at or before point, + * 'what_to_do' says what to do with the completion. + * \t means do standard completion. + * `?' means list the possible completions. + * `*' means insert all of the possible completions. + * `!' means to do standard completion, and list all possible completions if + * there is more than one. + * + * Note: '*' support is not implemented + * '!' could never be invoked + */ +int +fn_complete(EditLine *el, + char *(*complet_func)(const char *, int), + char **(*attempted_completion_function)(const char *, int, int), + const char *word_break, const char *special_prefixes, + const char *(*app_func)(const char *), int query_items, + int *completion_type, int *over, int *point, int *end) +{ + const LineInfo *li; + char *temp, **matches; + const char *ctemp; + size_t len; + int what_to_do = '\t'; + int retval = CC_NORM; + + if (el->el_state.lastcmd == el->el_state.thiscmd) + what_to_do = '?'; + + /* readline's rl_complete() has to be told what we did... */ + if (completion_type != NULL) + *completion_type = what_to_do; + + if (!complet_func) + complet_func = fn_filename_completion_function; + if (!app_func) + app_func = append_char_function; + + /* We now look backwards for the start of a filename/variable word */ + li = el_line(el); + ctemp = (const char *) li->cursor; + while (ctemp > li->buffer + && !strchr(word_break, ctemp[-1]) + && (!special_prefixes || !strchr(special_prefixes, ctemp[-1]) ) ) + ctemp--; + + len = li->cursor - ctemp; +#if defined(__SSP__) || defined(__SSP_ALL__) + temp = malloc(len + 1); +#else + temp = alloca(len + 1); +#endif + (void)strncpy(temp, ctemp, len); + temp[len] = '\0'; + + /* these can be used by function called in completion_matches() */ + /* or (*attempted_completion_function)() */ + if (point != 0) + *point = li->cursor - li->buffer; + if (end != NULL) + *end = li->lastchar - li->buffer; + + if (attempted_completion_function) { + int cur_off = li->cursor - li->buffer; + matches = (*attempted_completion_function) (temp, + (int)(cur_off - len), cur_off); + } else + matches = 0; + if (!attempted_completion_function || + (over != NULL && !*over && !matches)) + matches = completion_matches(temp, complet_func); + + if (over != NULL) + *over = 0; + + if (matches) { + int i; + int matches_num, maxlen, match_len, match_display=1; + + retval = CC_REFRESH; + /* + * Only replace the completed string with common part of + * possible matches if there is possible completion. + */ + if (matches[0][0] != '\0') { + el_deletestr(el, (int) len); + el_insertstr(el, matches[0]); + } + + if (what_to_do == '?') + goto display_matches; + + if (matches[2] == NULL && strcmp(matches[0], matches[1]) == 0) { + /* + * We found exact match. Add a space after + * it, unless we do filename completion and the + * object is a directory. + */ + el_insertstr(el, (*app_func)(matches[0])); + } else if (what_to_do == '!') { + display_matches: + /* + * More than one match and requested to list possible + * matches. + */ + + for(i=1, maxlen=0; matches[i]; i++) { + match_len = strlen(matches[i]); + if (match_len > maxlen) + maxlen = match_len; + } + matches_num = i - 1; + + /* newline to get on next line from command line */ + (void)fprintf(el->el_outfile, "\n"); + + /* + * If there are too many items, ask user for display + * confirmation. + */ + if (matches_num > query_items) { + (void)fprintf(el->el_outfile, + "Display all %d possibilities? (y or n) ", + matches_num); + (void)fflush(el->el_outfile); + if (getc(stdin) != 'y') + match_display = 0; + (void)fprintf(el->el_outfile, "\n"); + } + + if (match_display) + fn_display_match_list(el, matches, matches_num, + maxlen); + retval = CC_REDISPLAY; + } else if (matches[0][0]) { + /* + * There was some common match, but the name was + * not complete enough. Next tab will print possible + * completions. + */ + el_beep(el); + } else { + /* lcd is not a valid object - further specification */ + /* is needed */ + el_beep(el); + retval = CC_NORM; + } + + /* free elements of array and the array itself */ + for (i = 0; matches[i]; i++) + free(matches[i]); + free(matches); + matches = NULL; + } +#if defined(__SSP__) || defined(__SSP_ALL__) + free(temp); +#endif + return retval; +} + +/* + * el-compatible wrapper around rl_complete; needed for key binding + */ +/* ARGSUSED */ +unsigned char +_el_fn_complete(EditLine *el, int ch __attribute__((__unused__))) +{ + return (unsigned char)fn_complete(el, NULL, NULL, + break_chars, NULL, NULL, 100, + NULL, NULL, NULL, NULL); +} diff --git a/cmd-line-utils/libedit/fgetln.c b/cmd-line-utils/libedit/filecomplete.h similarity index 50% rename from cmd-line-utils/libedit/fgetln.c rename to cmd-line-utils/libedit/filecomplete.h index 5b95b2f6584..12e0c6f14b0 100644 --- a/cmd-line-utils/libedit/fgetln.c +++ b/cmd-line-utils/libedit/filecomplete.h @@ -1,11 +1,11 @@ -/* $NetBSD: fgetln.c,v 1.2 2003/12/10 01:30:27 lukem Exp $ */ +/* $NetBSD: filecomplete.h,v 1.6 2008/04/29 06:53:01 martin Exp $ */ /*- - * Copyright (c) 1998 The NetBSD Foundation, Inc. + * Copyright (c) 1997 The NetBSD Foundation, Inc. * All rights reserved. * * This code is derived from software contributed to The NetBSD Foundation - * by Christos Zoulas. + * by Jaromir Dolecek. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -15,13 +15,6 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the NetBSD - * Foundation, Inc. and its contributors. - * 4. Neither the name of The NetBSD Foundation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED @@ -35,54 +28,17 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ +#ifndef _FILECOMPLETE_H_ +#define _FILECOMPLETE_H_ -#include -#include -#include -#include -#include -#include +int fn_complete(EditLine *, + char *(*)(const char *, int), + char **(*)(const char *, int, int), + const char *, const char *, const char *(*)(const char *), int, + int *, int *, int *, int *); +void fn_display_match_list(EditLine *, char **, int, int); +char *fn_tilde_expand(const char *); +char *fn_filename_completion_function(const char *, int); -char * -fgetln(FILE *fp, size_t *len) -{ - static char *buf = NULL; - static size_t bufsiz = 0; - char *ptr; - - - if (buf == NULL) { - bufsiz = BUFSIZ; - if ((buf = malloc(bufsiz)) == NULL) - return NULL; - } - - if (fgets(buf, bufsiz, fp) == NULL) - return NULL; - *len = 0; - - while ((ptr = strchr(&buf[*len], '\n')) == NULL) { - size_t nbufsiz = bufsiz + BUFSIZ; - char *nbuf = realloc(buf, nbufsiz); - - if (nbuf == NULL) { - int oerrno = errno; - free(buf); - errno = oerrno; - buf = NULL; - return NULL; - } else - buf = nbuf; - - *len = bufsiz; - if (fgets(&buf[bufsiz], BUFSIZ, fp) == NULL) - return buf; - - bufsiz = nbufsiz; - } - - *len = (ptr - buf) + 1; - return buf; -} - +#endif diff --git a/cmd-line-utils/libedit/hist.c b/cmd-line-utils/libedit/hist.c index e8f5c0f39ba..c0b23ee6641 100644 --- a/cmd-line-utils/libedit/hist.c +++ b/cmd-line-utils/libedit/hist.c @@ -32,7 +32,13 @@ * SUCH DAMAGE. */ -#include +#include "config.h" +#if !defined(lint) && !defined(SCCSID) +#if 0 +static char sccsid[] = "@(#)hist.c 8.1 (Berkeley) 6/4/93"; +#else +#endif +#endif /* not lint && not SCCSID */ /* * hist.c: History access functions diff --git a/cmd-line-utils/libedit/histedit.h b/cmd-line-utils/libedit/histedit.h index c58eb62dcfa..37823141c06 100644 --- a/cmd-line-utils/libedit/histedit.h +++ b/cmd-line-utils/libedit/histedit.h @@ -1,4 +1,4 @@ -/* $NetBSD: histedit.h,v 1.25 2003/12/05 13:37:48 lukem Exp $ */ +/* $NetBSD: histedit.h,v 1.35 2009/02/05 19:15:44 christos Exp $ */ /*- * Copyright (c) 1992, 1993 @@ -41,11 +41,15 @@ #define _HISTEDIT_H_ #define LIBEDIT_MAJOR 2 -#define LIBEDIT_MINOR 9 +#define LIBEDIT_MINOR 11 #include #include +#ifdef __cplusplus +extern "C" { +#endif + /* * ==== Editing ==== */ @@ -88,7 +92,7 @@ void el_reset(EditLine *); */ const char *el_gets(EditLine *, int *); int el_getc(EditLine *, char *); -void el_push(EditLine *, char *); +void el_push(EditLine *, const char *); /* * Beep! @@ -105,7 +109,8 @@ int el_parse(EditLine *, int, const char **); * Low level editline access functions */ int el_set(EditLine *, int, ...); -int el_get(EditLine *, int, void *); +int el_get(EditLine *, int, ...); +unsigned char _el_fn_complete(EditLine *, int); /* * el_set/el_get parameters @@ -128,8 +133,12 @@ int el_get(EditLine *, int, void *); #define EL_CLIENTDATA 14 /* , void *); */ #define EL_UNBUFFERED 15 /* , int); */ #define EL_PREP_TERM 16 /* , int); */ +#define EL_GETTC 17 /* , const char *, ..., NULL); */ +#define EL_GETFP 18 /* , int, FILE **); */ +#define EL_SETFP 19 /* , int, FILE *); */ +#define EL_REFRESH 20 /* , void); */ -#define EL_BUILTIN_GETCFN (NULL) +#define EL_BUILTIN_GETCFN (NULL) /* * Source named file or $PWD/.editrc or $HOME/.editrc @@ -192,6 +201,7 @@ int history(History *, HistEvent *, int, ...); #define H_CLEAR 19 /* , void); */ #define H_SETUNIQUE 20 /* , int); */ #define H_GETUNIQUE 21 /* , void); */ +#define H_DEL 22 /* , int); */ /* @@ -211,4 +221,8 @@ int tok_line(Tokenizer *, const LineInfo *, int tok_str(Tokenizer *, const char *, int *, const char ***); +#ifdef __cplusplus +} +#endif + #endif /* _HISTEDIT_H_ */ diff --git a/cmd-line-utils/libedit/history.c b/cmd-line-utils/libedit/history.c index c0fa7cc717d..3080dd231f6 100644 --- a/cmd-line-utils/libedit/history.c +++ b/cmd-line-utils/libedit/history.c @@ -1,4 +1,4 @@ -/* $NetBSD: history.c,v 1.28 2004/11/27 18:31:45 christos Exp $ */ +/* $NetBSD: history.c,v 1.33 2009/02/06 14:40:32 sketch Exp $ */ /*- * Copyright (c) 1992, 1993 @@ -32,7 +32,13 @@ * SUCH DAMAGE. */ -#include +#include "config.h" +#if !defined(lint) && !defined(SCCSID) +#if 0 +static char sccsid[] = "@(#)history.c 8.1 (Berkeley) 6/4/93"; +#else +#endif +#endif /* not lint && not SCCSID */ /* * hist.c: History access functions @@ -40,7 +46,11 @@ #include #include #include +#ifdef HAVE_VIS_H #include +#else +#include "np/vis.h" +#endif #include static const char hist_cookie[] = "_HiStOrY_V2_\n"; @@ -61,6 +71,7 @@ struct history { history_gfun_t h_prev; /* Get the previous element */ history_gfun_t h_curr; /* Get the current element */ history_sfun_t h_set; /* Set the current element */ + history_sfun_t h_del; /* Set the given element */ history_vfun_t h_clear; /* Clear the history list */ history_efun_t h_enter; /* Add an element */ history_efun_t h_add; /* Append to an element */ @@ -75,6 +86,7 @@ struct history { #define HCLEAR(h, ev) (*(h)->h_clear)((h)->h_ref, ev) #define HENTER(h, ev, str) (*(h)->h_enter)((h)->h_ref, ev, str) #define HADD(h, ev, str) (*(h)->h_add)((h)->h_ref, ev, str) +#define HDEL(h, ev, n) (*(h)->h_del)((h)->h_ref, ev, n) #define h_strdup(a) strdup(a) #define h_malloc(a) malloc(a) @@ -122,16 +134,18 @@ typedef struct history_t { #define H_UNIQUE 1 /* Store only unique elements */ } history_t; -private int history_def_first(ptr_t, HistEvent *); -private int history_def_last(ptr_t, HistEvent *); private int history_def_next(ptr_t, HistEvent *); +private int history_def_first(ptr_t, HistEvent *); private int history_def_prev(ptr_t, HistEvent *); +private int history_def_last(ptr_t, HistEvent *); private int history_def_curr(ptr_t, HistEvent *); -private int history_def_set(ptr_t, HistEvent *, const int n); +private int history_def_set(ptr_t, HistEvent *, const int); +private void history_def_clear(ptr_t, HistEvent *); private int history_def_enter(ptr_t, HistEvent *, const char *); private int history_def_add(ptr_t, HistEvent *, const char *); +private int history_def_del(ptr_t, HistEvent *, const int); + private int history_def_init(ptr_t *, HistEvent *, int); -private void history_def_clear(ptr_t, HistEvent *); private int history_def_insert(history_t *, HistEvent *, const char *); private void history_def_delete(history_t *, HistEvent *, hentry_t *); @@ -353,6 +367,24 @@ history_def_add(ptr_t p, HistEvent *ev, const char *str) } +/* history_def_del(): + * Delete element hp of the h list + */ +/* ARGSUSED */ +private int +history_def_del(ptr_t p, HistEvent *ev __attribute__((__unused__)), + const int num) +{ + history_t *h = (history_t *) p; + if (history_def_set(h, ev, num) != 0) + return (-1); + ev->str = strdup(h->cursor->ev.str); + ev->num = h->cursor->ev.num; + history_def_delete(h, ev, h->cursor); + return (0); +} + + /* history_def_delete(): * Delete element hp of the h list */ @@ -364,6 +396,8 @@ history_def_delete(history_t *h, HistEventPrivate *evp = (void *)&hp->ev; if (hp == &h->list) abort(); + if (h->cursor == hp) + h->cursor = hp->prev; hp->prev->next = hp->next; hp->next->prev = hp->prev; h_free((ptr_t) evp->str); @@ -497,6 +531,7 @@ history_init(void) h->h_clear = history_def_clear; h->h_enter = history_def_enter; h->h_add = history_def_add; + h->h_del = history_def_del; return (h); } @@ -512,6 +547,8 @@ history_end(History *h) if (h->h_next == history_def_next) history_def_clear(h->h_ref, &ev); + h_free(h->h_ref); + h_free(h); } @@ -597,7 +634,7 @@ history_set_fun(History *h, History *nh) if (nh->h_first == NULL || nh->h_next == NULL || nh->h_last == NULL || nh->h_prev == NULL || nh->h_curr == NULL || nh->h_set == NULL || nh->h_enter == NULL || nh->h_add == NULL || nh->h_clear == NULL || - nh->h_ref == NULL) { + nh->h_del == NULL || nh->h_ref == NULL) { if (h->h_next != history_def_next) { history_def_init(&h->h_ref, &ev, 0); h->h_first = history_def_first; @@ -609,6 +646,7 @@ history_set_fun(History *h, History *nh) h->h_clear = history_def_clear; h->h_enter = history_def_enter; h->h_add = history_def_add; + h->h_del = history_def_del; } return (-1); } @@ -625,6 +663,7 @@ history_set_fun(History *h, History *nh) h->h_clear = nh->h_clear; h->h_enter = nh->h_enter; h->h_add = nh->h_add; + h->h_del = nh->h_del; return (0); } @@ -676,8 +715,8 @@ history_load(History *h, const char *fname) (void) strunvis(ptr, line); line[sz] = c; if (HENTER(h, &ev, ptr) == -1) { - i = -1; - goto oomem; + i = -1; + goto oomem; } } oomem: @@ -841,6 +880,10 @@ history(History *h, HistEvent *ev, int fun, ...) retval = HADD(h, ev, str); break; + case H_DEL: + retval = HDEL(h, ev, va_arg(va, const int)); + break; + case H_ENTER: str = va_arg(va, const char *); if ((retval = HENTER(h, ev, str)) != -1) @@ -925,6 +968,7 @@ history(History *h, HistEvent *ev, int fun, ...) hf.h_clear = va_arg(va, history_vfun_t); hf.h_enter = va_arg(va, history_efun_t); hf.h_add = va_arg(va, history_efun_t); + hf.h_del = va_arg(va, history_sfun_t); if ((retval = history_set_fun(h, &hf)) == -1) he_seterrev(ev, _HE_PARAM_MISSING); diff --git a/cmd-line-utils/libedit/key.c b/cmd-line-utils/libedit/key.c index 35fcf0651b2..cda02816861 100644 --- a/cmd-line-utils/libedit/key.c +++ b/cmd-line-utils/libedit/key.c @@ -1,4 +1,4 @@ -/* $NetBSD: key.c,v 1.15 2003/10/18 23:48:42 christos Exp $ */ +/* $NetBSD: key.c,v 1.19 2006/03/23 20:22:51 christos Exp $ */ /*- * Copyright (c) 1992, 1993 @@ -32,14 +32,20 @@ * SUCH DAMAGE. */ -#include +#include "config.h" +#if !defined(lint) && !defined(SCCSID) +#if 0 +static char sccsid[] = "@(#)key.c 8.1 (Berkeley) 6/4/93"; +#else +#endif +#endif /* not lint && not SCCSID */ /* * key.c: This module contains the procedures for maintaining * the extended-key map. * * An extended-key (key) is a sequence of keystrokes introduced - * with an sequence introducer and consisting of an arbitrary + * with a sequence introducer and consisting of an arbitrary * number of characters. This module maintains a map (the el->el_key.map) * to convert these extended-key sequences into input strs * (XK_STR), editor functions (XK_CMD), or unix commands (XK_EXE). @@ -78,12 +84,12 @@ private int node_trav(EditLine *, key_node_t *, char *, private int node__try(EditLine *, key_node_t *, const char *, key_value_t *, int); private key_node_t *node__get(int); +private void node__free(key_node_t *); private void node__put(EditLine *, key_node_t *); private int node__delete(EditLine *, key_node_t **, const char *); private int node_lookup(EditLine *, const char *, key_node_t *, int); private int node_enum(EditLine *, key_node_t *, int); -private int key__decode_char(char *, int, int); #define KEY_BUFSIZ EL_BUFSIZ @@ -103,7 +109,6 @@ key_init(EditLine *el) return (0); } - /* key_end(): * Free the key maps */ @@ -113,8 +118,7 @@ key_end(EditLine *el) el_free((ptr_t) el->el_key.buf); el->el_key.buf = NULL; - /* XXX: provide a function to clear the keys */ - el->el_key.map = NULL; + node__free(el->el_key.map); } @@ -443,7 +447,7 @@ node__put(EditLine *el, key_node_t *ptr) /* node__get(): - * Returns pointer to an key_node_t for ch. + * Returns pointer to a key_node_t for ch. */ private key_node_t * node__get(int ch) @@ -461,7 +465,15 @@ node__get(int ch) return (ptr); } - +private void +node__free(key_node_t *k) +{ + if (k == NULL) + return; + node__free(k->sibling); + node__free(k->next); + el_free((ptr_t) k); +} /* node_lookup(): * look for the str starting at node ptr. @@ -483,7 +495,7 @@ node_lookup(EditLine *el, const char *str, key_node_t *ptr, int cnt) /* If match put this char into el->el_key.buf. Recurse */ if (ptr->ch == *str) { /* match found */ - ncnt = key__decode_char(el->el_key.buf, cnt, + ncnt = key__decode_char(el->el_key.buf, KEY_BUFSIZ, cnt, (unsigned char) ptr->ch); if (ptr->next != NULL) /* not yet at leaf */ @@ -537,7 +549,8 @@ node_enum(EditLine *el, key_node_t *ptr, int cnt) return (-1); } /* put this char at end of str */ - ncnt = key__decode_char(el->el_key.buf, cnt, (unsigned char) ptr->ch); + ncnt = key__decode_char(el->el_key.buf, KEY_BUFSIZ, cnt, + (unsigned char)ptr->ch); if (ptr->next == NULL) { /* print this key and function */ el->el_key.buf[ncnt + 1] = '"'; @@ -568,9 +581,10 @@ key_kprint(EditLine *el, const char *key, key_value_t *val, int ntype) switch (ntype) { case XK_STR: case XK_EXE: - (void) fprintf(el->el_outfile, fmt, key, - key__decode_str(val->str, unparsbuf, - ntype == XK_STR ? "\"\"" : "[]")); + (void) key__decode_str(val->str, unparsbuf, + sizeof(unparsbuf), + ntype == XK_STR ? "\"\"" : "[]"); + (void) fprintf(el->el_outfile, fmt, key, unparsbuf); break; case XK_CMD: for (fp = el->el_map.help; fp->name; fp++) @@ -595,83 +609,97 @@ key_kprint(EditLine *el, const char *key, key_value_t *val, int ntype) } +#define ADDC(c) \ + if (b < eb) \ + *b++ = c; \ + else \ + b++ /* key__decode_char(): * Put a printable form of char in buf. */ -private int -key__decode_char(char *buf, int cnt, int ch) +protected int +key__decode_char(char *buf, int cnt, int off, int ch) { + char *sb = buf + off; + char *eb = buf + cnt; + char *b = sb; if (ch == 0) { - buf[cnt++] = '^'; - buf[cnt] = '@'; - return (cnt); + ADDC('^'); + ADDC('@'); + return b - sb; } if (iscntrl(ch)) { - buf[cnt++] = '^'; + ADDC('^'); if (ch == '\177') - buf[cnt] = '?'; + ADDC('?'); else - buf[cnt] = ch | 0100; + ADDC(ch | 0100); } else if (ch == '^') { - buf[cnt++] = '\\'; - buf[cnt] = '^'; + ADDC('\\'); + ADDC('^'); } else if (ch == '\\') { - buf[cnt++] = '\\'; - buf[cnt] = '\\'; + ADDC('\\'); + ADDC('\\'); } else if (ch == ' ' || (el_isprint(ch) && !isspace(ch))) { - buf[cnt] = ch; + ADDC(ch); } else { - buf[cnt++] = '\\'; - buf[cnt++] = (((unsigned int) ch >> 6) & 7) + '0'; - buf[cnt++] = (((unsigned int) ch >> 3) & 7) + '0'; - buf[cnt] = (ch & 7) + '0'; + ADDC('\\'); + ADDC((((unsigned int) ch >> 6) & 7) + '0'); + ADDC((((unsigned int) ch >> 3) & 7) + '0'); + ADDC((ch & 7) + '0'); } - return (cnt); + return b - sb; } /* key__decode_str(): * Make a printable version of the ey */ -protected char * -key__decode_str(const char *str, char *buf, const char *sep) +protected int +key__decode_str(const char *str, char *buf, int len, const char *sep) { - char *b; + char *b = buf, *eb = b + len; const char *p; b = buf; - if (sep[0] != '\0') - *b++ = sep[0]; - if (*str == 0) { - *b++ = '^'; - *b++ = '@'; - if (sep[0] != '\0' && sep[1] != '\0') - *b++ = sep[1]; - *b++ = 0; - return (buf); + if (sep[0] != '\0') { + ADDC(sep[0]); + } + if (*str == '\0') { + ADDC('^'); + ADDC('@'); + if (sep[0] != '\0' && sep[1] != '\0') { + ADDC(sep[1]); + } + goto done; } for (p = str; *p != 0; p++) { if (iscntrl((unsigned char) *p)) { - *b++ = '^'; - if (*p == '\177') - *b++ = '?'; - else - *b++ = *p | 0100; + ADDC('^'); + if (*p == '\177') { + ADDC('?'); + } else { + ADDC(*p | 0100); + } } else if (*p == '^' || *p == '\\') { - *b++ = '\\'; - *b++ = *p; + ADDC('\\'); + ADDC(*p); } else if (*p == ' ' || (el_isprint((unsigned char) *p) && !isspace((unsigned char) *p))) { - *b++ = *p; + ADDC(*p); } else { - *b++ = '\\'; - *b++ = (((unsigned int) *p >> 6) & 7) + '0'; - *b++ = (((unsigned int) *p >> 3) & 7) + '0'; - *b++ = (*p & 7) + '0'; + ADDC('\\'); + ADDC((((unsigned int) *p >> 6) & 7) + '0'); + ADDC((((unsigned int) *p >> 3) & 7) + '0'); + ADDC((*p & 7) + '0'); } } - if (sep[0] != '\0' && sep[1] != '\0') - *b++ = sep[1]; - *b++ = 0; - return (buf); /* should check for overflow */ + if (sep[0] != '\0' && sep[1] != '\0') { + ADDC(sep[1]); + } +done: + ADDC('\0'); + if (b - buf >= len) + buf[len - 1] = '\0'; + return b - buf; } diff --git a/cmd-line-utils/libedit/key.h b/cmd-line-utils/libedit/key.h index 39a075c504e..9c6844e6d99 100644 --- a/cmd-line-utils/libedit/key.h +++ b/cmd-line-utils/libedit/key.h @@ -1,4 +1,4 @@ -/* $NetBSD: key.h,v 1.8 2003/08/07 16:44:32 agc Exp $ */ +/* $NetBSD: key.h,v 1.10 2006/03/23 20:22:51 christos Exp $ */ /*- * Copyright (c) 1992, 1993 @@ -74,6 +74,8 @@ protected int key_delete(EditLine *, const char *); protected void key_print(EditLine *, const char *); protected void key_kprint(EditLine *, const char *, key_value_t *, int); -protected char *key__decode_str(const char *, char *, const char *); +protected int key__decode_str(const char *, char *, int, + const char *); +protected int key__decode_char(char *, int, int, int); #endif /* _h_el_key */ diff --git a/cmd-line-utils/libedit/libedit_term.h b/cmd-line-utils/libedit/libedit_term.h deleted file mode 100644 index 9f03c549515..00000000000 --- a/cmd-line-utils/libedit/libedit_term.h +++ /dev/null @@ -1,124 +0,0 @@ -/* $NetBSD: term.h,v 1.12 2001/01/04 15:56:32 christos Exp $ */ - -/*- - * Copyright (c) 1992, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Christos Zoulas of Cornell University. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)term.h 8.1 (Berkeley) 6/4/93 - */ - -/* - * el.term.h: Termcap header - */ -#ifndef _h_el_term -#define _h_el_term - -#include "histedit.h" - -typedef struct { /* Symbolic function key bindings */ - const char *name; /* name of the key */ - int key; /* Index in termcap table */ - key_value_t fun; /* Function bound to it */ - int type; /* Type of function */ -} fkey_t; - -typedef struct { - coord_t t_size; /* # lines and cols */ - int t_flags; -#define TERM_CAN_INSERT 0x001 /* Has insert cap */ -#define TERM_CAN_DELETE 0x002 /* Has delete cap */ -#define TERM_CAN_CEOL 0x004 /* Has CEOL cap */ -#define TERM_CAN_TAB 0x008 /* Can use tabs */ -#define TERM_CAN_ME 0x010 /* Can turn all attrs. */ -#define TERM_CAN_UP 0x020 /* Can move up */ -#define TERM_HAS_META 0x040 /* Has a meta key */ -#define TERM_HAS_AUTO_MARGINS 0x080 /* Has auto margins */ -#define TERM_HAS_MAGIC_MARGINS 0x100 /* Has magic margins */ - char *t_buf; /* Termcap buffer */ - int t_loc; /* location used */ - char **t_str; /* termcap strings */ - int *t_val; /* termcap values */ - char *t_cap; /* Termcap buffer */ - fkey_t *t_fkey; /* Array of keys */ -} el_term_t; - -/* - * fKey indexes - */ -#define A_K_DN 0 -#define A_K_UP 1 -#define A_K_LT 2 -#define A_K_RT 3 -#define A_K_HO 4 -#define A_K_EN 5 -#define A_K_NKEYS 6 - -protected void term_move_to_line(EditLine *, int); -protected void term_move_to_char(EditLine *, int); -protected void term_clear_EOL(EditLine *, int); -protected void term_overwrite(EditLine *, const char *, int); -protected void term_insertwrite(EditLine *, char *, int); -protected void term_deletechars(EditLine *, int); -protected void term_clear_screen(EditLine *); -protected void term_beep(EditLine *); -protected int term_change_size(EditLine *, int, int); -protected int term_get_size(EditLine *, int *, int *); -protected int term_init(EditLine *); -protected void term_bind_arrow(EditLine *); -protected void term_print_arrow(EditLine *, const char *); -protected int term_clear_arrow(EditLine *, const char *); -protected int term_set_arrow(EditLine *, const char *, key_value_t *, int); -protected void term_end(EditLine *); -protected int term_set(EditLine *, const char *); -protected int term_settc(EditLine *, int, const char **); -protected int term_telltc(EditLine *, int, const char **); -protected int term_echotc(EditLine *, int, const char **); -protected int term__putc(int); -protected void term__flush(void); - -/* - * Easy access macros - */ -#define EL_FLAGS (el)->el_term.t_flags - -#define EL_CAN_INSERT (EL_FLAGS & TERM_CAN_INSERT) -#define EL_CAN_DELETE (EL_FLAGS & TERM_CAN_DELETE) -#define EL_CAN_CEOL (EL_FLAGS & TERM_CAN_CEOL) -#define EL_CAN_TAB (EL_FLAGS & TERM_CAN_TAB) -#define EL_CAN_ME (EL_FLAGS & TERM_CAN_ME) -#define EL_HAS_META (EL_FLAGS & TERM_HAS_META) -#define EL_HAS_AUTO_MARGINS (EL_FLAGS & TERM_HAS_AUTO_MARGINS) -#define EL_HAS_MAGIC_MARGINS (EL_FLAGS & TERM_HAS_MAGIC_MARGINS) - -#endif /* _h_el_term */ diff --git a/cmd-line-utils/libedit/makelist.sh b/cmd-line-utils/libedit/makelist.sh index f15b3d1eb9f..fdd3f934e15 100644 --- a/cmd-line-utils/libedit/makelist.sh +++ b/cmd-line-utils/libedit/makelist.sh @@ -1,5 +1,5 @@ #!/bin/sh - -# $NetBSD: makelist,v 1.8 2003/03/10 21:21:10 christos Exp $ +# $NetBSD: makelist,v 1.11 2005/10/22 16:45:03 christos Exp $ # # Copyright (c) 1992, 1993 # The Regents of the University of California. All rights reserved. @@ -15,11 +15,7 @@ # 2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. -# 3. All advertising materials mentioning features or use of this software -# must display the following acknowledgement: -# This product includes software developed by the University of -# California, Berkeley and its contributors. -# 4. Neither the name of the University nor the names of its contributors +# 3. Neither the name of the University nor the names of its contributors # may be used to endorse or promote products derived from this software # without specific prior written permission. # @@ -68,6 +64,7 @@ case $FLAG in /\(\):/ { pr = substr($2, 1, 2); if (pr == "vi" || pr == "em" || pr == "ed") { + # XXXMYSQL: support CRLF name = substr($2, 1, index($2,"(") - 1); # # XXX: need a space between name and prototype so that -fc and -fh @@ -87,7 +84,7 @@ case $FLAG in cat $FILES | $AWK ' BEGIN { printf("/* Automatically generated file, do not edit */\n"); - printf("#include \"config.h\"\n#include \"el.h\"\n"); + printf("#include \"sys.h\"\n#include \"el.h\"\n"); printf("private const struct el_bindings_t el_func_help[] = {\n"); low = "abcdefghijklmnopqrstuvwxyz_"; high = "ABCDEFGHIJKLMNOPQRSTUVWXYZ_"; @@ -97,6 +94,7 @@ case $FLAG in /\(\):/ { pr = substr($2, 1, 2); if (pr == "vi" || pr == "em" || pr == "ed") { + # XXXMYSQL: support CRLF name = substr($2, 1, index($2,"(") - 1); uname = ""; fname = ""; @@ -117,13 +115,13 @@ case $FLAG in printf(" \""); for (i = 2; i < NF; i++) printf("%s ", $i); - sub("\r", "", $i); + # XXXMYSQL: support CRLF + sub("\r", "", $i); printf("%s\" },\n", $i); ok = 0; } } END { - printf(" { NULL, 0, NULL }\n"); printf("};\n"); printf("\nprotected const el_bindings_t* help__get()"); printf("{ return el_func_help; }\n"); @@ -144,6 +142,7 @@ case $FLAG in # generate fcns.h from various .h files # +# XXXMYSQL: use portable tr syntax -fh) cat $FILES | $AWK '/el_action_t/ { print $3 }' | \ sort | tr abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ | $AWK ' @@ -170,7 +169,7 @@ case $FLAG in cat $FILES | $AWK '/el_action_t/ { print $3 }' | sort | $AWK ' BEGIN { printf("/* Automatically generated file, do not edit */\n"); - printf("#include \"config.h\"\n#include \"el.h\"\n"); + printf("#include \"sys.h\"\n#include \"el.h\"\n"); printf("private const el_func_t el_func[] = {"); maxlen = 80; needn = 1; @@ -220,6 +219,7 @@ case $FLAG in /\(\):/ { pr = substr($2, 1, 2); if (pr == "vi" || pr == "em" || pr == "ed") { + # XXXMYSQL: support CRLF name = substr($2, 1, index($2, "(") - 1); fname = ""; for (i = 1; i <= length(name); i++) { diff --git a/cmd-line-utils/libedit/map.c b/cmd-line-utils/libedit/map.c index 6be9279b5e5..693b56c82ba 100644 --- a/cmd-line-utils/libedit/map.c +++ b/cmd-line-utils/libedit/map.c @@ -1,4 +1,4 @@ -/* $NetBSD: map.c,v 1.20 2004/08/13 12:10:39 mycroft Exp $ */ +/* $NetBSD: map.c,v 1.24 2006/04/09 01:36:51 christos Exp $ */ /*- * Copyright (c) 1992, 1993 @@ -32,7 +32,13 @@ * SUCH DAMAGE. */ -#include +#include "config.h" +#if !defined(lint) && !defined(SCCSID) +#if 0 +static char sccsid[] = "@(#)map.c 8.1 (Berkeley) 6/4/93"; +#else +#endif +#endif /* not lint && not SCCSID */ /* * map.c: Editor function definitions @@ -1118,11 +1124,12 @@ private void map_print_key(EditLine *el, el_action_t *map, const char *in) { char outbuf[EL_BUFSIZ]; - el_bindings_t *bp; + el_bindings_t *bp, *ep; if (in[0] == '\0' || in[1] == '\0') { - (void) key__decode_str(in, outbuf, ""); - for (bp = el->el_map.help; bp->name != NULL; bp++) + (void) key__decode_str(in, outbuf, sizeof(outbuf), ""); + ep = &el->el_map.help[el->el_map.nfunc]; + for (bp = el->el_map.help; bp < ep; bp++) if (bp->func == map[(unsigned char) *in]) { (void) fprintf(el->el_outfile, "%s\t->\t%s\n", outbuf, bp->name); @@ -1139,7 +1146,7 @@ map_print_key(EditLine *el, el_action_t *map, const char *in) private void map_print_some_keys(EditLine *el, el_action_t *map, int first, int last) { - el_bindings_t *bp; + el_bindings_t *bp, *ep; char firstbuf[2], lastbuf[2]; char unparsbuf[EL_BUFSIZ], extrabuf[EL_BUFSIZ]; @@ -1148,39 +1155,47 @@ map_print_some_keys(EditLine *el, el_action_t *map, int first, int last) lastbuf[0] = last; lastbuf[1] = 0; if (map[first] == ED_UNASSIGNED) { - if (first == last) + if (first == last) { + (void) key__decode_str(firstbuf, unparsbuf, + sizeof(unparsbuf), STRQQ); (void) fprintf(el->el_outfile, - "%-15s-> is undefined\n", - key__decode_str(firstbuf, unparsbuf, STRQQ)); + "%-15s-> is undefined\n", unparsbuf); + } return; } - for (bp = el->el_map.help; bp->name != NULL; bp++) { + ep = &el->el_map.help[el->el_map.nfunc]; + for (bp = el->el_map.help; bp < ep; bp++) { if (bp->func == map[first]) { if (first == last) { + (void) key__decode_str(firstbuf, unparsbuf, + sizeof(unparsbuf), STRQQ); (void) fprintf(el->el_outfile, "%-15s-> %s\n", - key__decode_str(firstbuf, unparsbuf, STRQQ), - bp->name); + unparsbuf, bp->name); } else { + (void) key__decode_str(firstbuf, unparsbuf, + sizeof(unparsbuf), STRQQ); + (void) key__decode_str(lastbuf, extrabuf, + sizeof(extrabuf), STRQQ); (void) fprintf(el->el_outfile, "%-4s to %-7s-> %s\n", - key__decode_str(firstbuf, unparsbuf, STRQQ), - key__decode_str(lastbuf, extrabuf, STRQQ), - bp->name); + unparsbuf, extrabuf, bp->name); } return; } } #ifdef MAP_DEBUG if (map == el->el_map.key) { + (void) key__decode_str(firstbuf, unparsbuf, + sizeof(unparsbuf), STRQQ); (void) fprintf(el->el_outfile, - "BUG!!! %s isn't bound to anything.\n", - key__decode_str(firstbuf, unparsbuf, STRQQ)); + "BUG!!! %s isn't bound to anything.\n", unparsbuf); (void) fprintf(el->el_outfile, "el->el_map.key[%d] == %d\n", first, el->el_map.key[first]); } else { + (void) key__decode_str(firstbuf, unparsbuf, + sizeof(unparsbuf), STRQQ); (void) fprintf(el->el_outfile, - "BUG!!! %s isn't bound to anything.\n", - key__decode_str(firstbuf, unparsbuf, STRQQ)); + "BUG!!! %s isn't bound to anything.\n", unparsbuf); (void) fprintf(el->el_outfile, "el->el_map.alt[%d] == %d\n", first, el->el_map.alt[first]); } @@ -1237,7 +1252,7 @@ map_bind(EditLine *el, int argc, const char **argv) char outbuf[EL_BUFSIZ]; const char *in = NULL; char *out = NULL; - el_bindings_t *bp; + el_bindings_t *bp, *ep; int cmd; int key; @@ -1279,8 +1294,8 @@ map_bind(EditLine *el, int argc, const char **argv) return (0); case 'l': - for (bp = el->el_map.help; bp->name != NULL; - bp++) + ep = &el->el_map.help[el->el_map.nfunc]; + for (bp = el->el_map.help; bp < ep; bp++) (void) fprintf(el->el_outfile, "%s\n\t%s\n", bp->name, bp->description); @@ -1367,7 +1382,7 @@ map_bind(EditLine *el, int argc, const char **argv) break; default: - EL_ABORT((el->el_errfile, "Bad XK_ type\n", ntype)); + EL_ABORT((el->el_errfile, "Bad XK_ type %d\n", ntype)); break; } return (0); @@ -1381,7 +1396,7 @@ protected int map_addfunc(EditLine *el, const char *name, const char *help, el_func_t func) { void *p; - int nf = el->el_map.nfunc + 2; + int nf = el->el_map.nfunc + 1; if (name == NULL || help == NULL || func == NULL) return (-1); @@ -1400,7 +1415,6 @@ map_addfunc(EditLine *el, const char *name, const char *help, el_func_t func) el->el_map.help[nf].name = name; el->el_map.help[nf].func = nf; el->el_map.help[nf].description = help; - el->el_map.help[++nf].name = NULL; el->el_map.nfunc++; return (0); diff --git a/cmd-line-utils/libedit/np/fgetln.c b/cmd-line-utils/libedit/np/fgetln.c index 93da9914dc8..898abc758dc 100644 --- a/cmd-line-utils/libedit/np/fgetln.c +++ b/cmd-line-utils/libedit/np/fgetln.c @@ -1,4 +1,4 @@ -/* $NetBSD: fgetln.c,v 1.1.1.1 1999/04/12 07:43:21 crooksa Exp $ */ +/* $NetBSD: fgetln.c,v 1.9 2008/04/29 06:53:03 martin Exp $ */ /*- * Copyright (c) 1998 The NetBSD Foundation, Inc. @@ -15,13 +15,6 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the NetBSD - * Foundation, Inc. and its contributors. - * 4. Neither the name of The NetBSD Foundation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED @@ -36,17 +29,24 @@ * POSSIBILITY OF SUCH DAMAGE. */ +#ifdef HAVE_NBTOOL_CONFIG_H +#include "nbtool_config.h" +#else #include "config.h" -#include +#endif + +#if !HAVE_FGETLN #include +#ifndef HAVE_NBTOOL_CONFIG_H +/* These headers are required, but included from nbtool_config.h */ +#include #include #include #include +#endif char * -fgetln(fp, len) - FILE *fp; - size_t *len; +fgetln(FILE *fp, size_t *len) { static char *buf = NULL; static size_t bufsiz = 0; @@ -61,8 +61,8 @@ fgetln(fp, len) if (fgets(buf, bufsiz, fp) == NULL) return NULL; - *len = 0; + *len = 0; while ((ptr = strchr(&buf[*len], '\n')) == NULL) { size_t nbufsiz = bufsiz + BUFSIZ; char *nbuf = realloc(buf, nbufsiz); @@ -76,13 +76,33 @@ fgetln(fp, len) } else buf = nbuf; - *len = bufsiz; - if (fgets(&buf[bufsiz], BUFSIZ, fp) == NULL) + if (fgets(&buf[bufsiz], BUFSIZ, fp) == NULL) { + buf[bufsiz] = '\0'; + *len = strlen(buf); return buf; + } + *len = bufsiz; bufsiz = nbufsiz; } *len = (ptr - buf) + 1; return buf; } + +#endif + +#ifdef TEST +int +main(int argc, char *argv[]) +{ + char *p; + size_t len; + + while ((p = fgetln(stdin, &len)) != NULL) { + (void)printf("%zu %s", len, p); + free(p); + } + return 0; +} +#endif diff --git a/cmd-line-utils/libedit/np/strlcat.c b/cmd-line-utils/libedit/np/strlcat.c index 6c9f1e92d79..4e2897d8f35 100644 --- a/cmd-line-utils/libedit/np/strlcat.c +++ b/cmd-line-utils/libedit/np/strlcat.c @@ -1,59 +1,68 @@ +/* $NetBSD: strlcat.c,v 1.3 2007/06/04 18:19:27 christos Exp $ */ +/* $OpenBSD: strlcat.c,v 1.10 2003/04/12 21:56:39 millert Exp $ */ + /* * Copyright (c) 1998 Todd C. Miller - * All rights reserved. * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL - * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; - * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * THE SOFTWARE IS PROVIDED "AS IS" AND TODD C. MILLER DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL TODD C. MILLER BE LIABLE + * FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#if !defined(_KERNEL) && !defined(_STANDALONE) +#if HAVE_NBTOOL_CONFIG_H +#include "nbtool_config.h" +#else #include "config.h" -#if defined(LIBC_SCCS) && !defined(lint) -static char *rcsid = "$OpenBSD: strlcat.c,v 1.2 1999/06/17 16:28:58 millert Exp $"; -#endif /* LIBC_SCCS and not lint */ -#ifndef lint -static const char rcsid[] = - "$FreeBSD: src/lib/libc/string/strlcat.c,v 1.2.4.2 2001/07/09 23:30:06 obrien Exp $"; #endif +#if defined(LIBC_SCCS) && !defined(lint) +#endif /* LIBC_SCCS and not lint */ + +#ifdef _LIBC +#include "namespace.h" +#endif #include +#include #include +#ifdef _LIBC +# ifdef __weak_alias +__weak_alias(strlcat, _strlcat) +# endif +#endif + +#else +#include +#endif /* !_KERNEL && !_STANDALONE */ + +#if !HAVE_STRLCAT /* * Appends src to string dst of size siz (unlike strncat, siz is the * full size of dst, not space left). At most siz-1 characters * will be copied. Always NUL terminates (unless siz <= strlen(dst)). - * Returns strlen(initial dst) + strlen(src); if retval >= siz, - * truncation occurred. + * Returns strlen(src) + MIN(siz, strlen(initial dst)). + * If retval >= siz, truncation occurred. */ -size_t strlcat(dst, src, siz) - char *dst; - const char *src; - size_t siz; +size_t +strlcat(char *dst, const char *src, size_t siz) { - register char *d = dst; - register const char *s = src; - register size_t n = siz; + char *d = dst; + const char *s = src; + size_t n = siz; size_t dlen; + _DIAGASSERT(dst != NULL); + _DIAGASSERT(src != NULL); + /* Find the end of dst and adjust bytes left but don't go past end */ while (n-- != 0 && *d != '\0') d++; @@ -73,3 +82,4 @@ size_t strlcat(dst, src, siz) return(dlen + (s - src)); /* count does not include NUL */ } +#endif diff --git a/cmd-line-utils/libedit/np/strlcpy.c b/cmd-line-utils/libedit/np/strlcpy.c index 1f154bcf2ea..092a9757c0f 100644 --- a/cmd-line-utils/libedit/np/strlcpy.c +++ b/cmd-line-utils/libedit/np/strlcpy.c @@ -1,59 +1,63 @@ -/* $OpenBSD: strlcpy.c,v 1.4 1999/05/01 18:56:41 millert Exp $ */ +/* $NetBSD: strlcpy.c,v 1.3 2007/06/04 18:19:27 christos Exp $ */ +/* $OpenBSD: strlcpy.c,v 1.7 2003/04/12 21:56:39 millert Exp $ */ /* * Copyright (c) 1998 Todd C. Miller - * All rights reserved. * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL - * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; - * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * THE SOFTWARE IS PROVIDED "AS IS" AND TODD C. MILLER DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL TODD C. MILLER BE LIABLE + * FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#if !defined(_KERNEL) && !defined(_STANDALONE) +#if HAVE_NBTOOL_CONFIG_H +#include "nbtool_config.h" +#else #include "config.h" +#endif #if defined(LIBC_SCCS) && !defined(lint) -#if 0 -static char *rcsid = "$OpenBSD: strlcpy.c,v 1.4 1999/05/01 18:56:41 millert Exp $"; -#endif #endif /* LIBC_SCCS and not lint */ -#ifndef lint -static const char rcsid[] = - "$FreeBSD: src/lib/libc/string/strlcpy.c,v 1.2.4.1 2001/07/09 23:30:06 obrien Exp $"; -#endif +#ifdef _LIBC +#include "namespace.h" +#endif #include +#include #include +#ifdef _LIBC +# ifdef __weak_alias +__weak_alias(strlcpy, _strlcpy) +# endif +#endif +#else +#include +#endif /* !_KERNEL && !_STANDALONE */ + + +#if !HAVE_STRLCPY /* * Copy src to string dst of size siz. At most siz-1 characters * will be copied. Always NUL terminates (unless siz == 0). * Returns strlen(src); if retval >= siz, truncation occurred. */ -size_t strlcpy(dst, src, siz) - char *dst; - const char *src; - size_t siz; +size_t +strlcpy(char *dst, const char *src, size_t siz) { - register char *d = dst; - register const char *s = src; - register size_t n = siz; + char *d = dst; + const char *s = src; + size_t n = siz; + + _DIAGASSERT(dst != NULL); + _DIAGASSERT(src != NULL); /* Copy as many bytes as will fit */ if (n != 0 && --n != 0) { @@ -73,3 +77,4 @@ size_t strlcpy(dst, src, siz) return(s - src - 1); /* count does not include NUL */ } +#endif diff --git a/cmd-line-utils/libedit/np/unvis.c b/cmd-line-utils/libedit/np/unvis.c index 895ff2059ac..3c37c231ceb 100644 --- a/cmd-line-utils/libedit/np/unvis.c +++ b/cmd-line-utils/libedit/np/unvis.c @@ -1,4 +1,4 @@ -/* $NetBSD: unvis.c,v 1.22 2002/03/23 17:38:27 christos Exp $ */ +/* $NetBSD: unvis.c,v 1.28 2005/09/13 01:44:09 christos Exp $ */ /*- * Copyright (c) 1989, 1993 @@ -12,11 +12,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * @@ -34,34 +30,30 @@ */ #include "config.h" + #if defined(LIBC_SCCS) && !defined(lint) #if 0 static char sccsid[] = "@(#)unvis.c 8.1 (Berkeley) 6/4/93"; #else -__RCSID("$NetBSD: unvis.c,v 1.22 2002/03/23 17:38:27 christos Exp $"); #endif #endif /* LIBC_SCCS and not lint */ -#define __LIBC12_SOURCE__ - #include #include #include #include +#ifdef HAVE_VIS_H +#include +#else #include "np/vis.h" +#endif #ifdef __weak_alias __weak_alias(strunvis,_strunvis) -__weak_alias(unvis,_unvis) #endif -#ifdef __warn_references -__warn_references(unvis, - "warning: reference to compatibility unvis(); include for correct reference") -#endif - -#if !HAVE_VIS_H +#if !HAVE_VIS /* * decode driven by state machine */ @@ -72,30 +64,22 @@ __warn_references(unvis, #define S_CTRL 4 /* control char started (^) */ #define S_OCTAL2 5 /* octal digit 2 */ #define S_OCTAL3 6 /* octal digit 3 */ -#define S_HEX1 7 /* hex digit */ -#define S_HEX2 8 /* hex digit 2 */ +#define S_HEX1 7 /* hex digit */ +#define S_HEX2 8 /* hex digit 2 */ #define isoctal(c) (((u_char)(c)) >= '0' && ((u_char)(c)) <= '7') #define xtod(c) (isdigit(c) ? (c - '0') : ((tolower(c) - 'a') + 10)) +/* + * unvis - decode characters previously encoded by vis + */ int unvis(cp, c, astate, flag) char *cp; int c; int *astate, flag; { - return __unvis13(cp, (int)c, astate, flag); -} - -/* - * unvis - decode characters previously encoded by vis - */ -int -__unvis13(cp, c, astate, flag) - char *cp; - int c; - int *astate, flag; -{ + unsigned char uc = (unsigned char)c; _DIAGASSERT(cp != NULL); _DIAGASSERT(astate != NULL); @@ -105,7 +89,7 @@ __unvis13(cp, c, astate, flag) || *astate == S_HEX2) { *astate = S_GROUND; return (UNVIS_VALID); - } + } return (*astate == S_GROUND ? UNVIS_NOCHAR : UNVIS_SYNBAD); } @@ -116,7 +100,7 @@ __unvis13(cp, c, astate, flag) if (c == '\\') { *astate = S_START; return (0); - } + } if ((flag & VIS_HTTPSTYLE) && c == '%') { *astate = S_HEX1; return (0); @@ -193,7 +177,7 @@ __unvis13(cp, c, astate, flag) } *astate = S_GROUND; return (UNVIS_SYNBAD); - + case S_META: if (c == '-') *astate = S_META1; @@ -204,12 +188,12 @@ __unvis13(cp, c, astate, flag) return (UNVIS_SYNBAD); } return (0); - + case S_META1: *astate = S_GROUND; *cp |= c; return (UNVIS_VALID); - + case S_CTRL: if (c == '?') *cp |= 0177; @@ -219,23 +203,23 @@ __unvis13(cp, c, astate, flag) return (UNVIS_VALID); case S_OCTAL2: /* second possible octal digit */ - if (isoctal(c)) { - /* - * yes - and maybe a third + if (isoctal(uc)) { + /* + * yes - and maybe a third */ *cp = (*cp << 3) + (c - '0'); - *astate = S_OCTAL3; + *astate = S_OCTAL3; return (0); - } - /* - * no - done with current sequence, push back passed char + } + /* + * no - done with current sequence, push back passed char */ *astate = S_GROUND; return (UNVIS_VALIDPUSH); case S_OCTAL3: /* third possible octal digit */ *astate = S_GROUND; - if (isoctal(c)) { + if (isoctal(uc)) { *cp = (*cp << 3) + (c - '0'); return (UNVIS_VALID); } @@ -243,27 +227,30 @@ __unvis13(cp, c, astate, flag) * we were done, push back passed char */ return (UNVIS_VALIDPUSH); + case S_HEX1: - if (isxdigit(c)) { - *cp = xtod(c); + if (isxdigit(uc)) { + *cp = xtod(uc); *astate = S_HEX2; return (0); } - /* - * no - done with current sequence, push back passed char + /* + * no - done with current sequence, push back passed char */ *astate = S_GROUND; return (UNVIS_VALIDPUSH); + case S_HEX2: - *astate = S_GROUND; - if (isxdigit(c)) { - *cp = xtod(c) | (*cp << 4); + *astate = S_GROUND; + if (isxdigit(uc)) { + *cp = xtod(uc) | (*cp << 4); return (UNVIS_VALID); } - return (UNVIS_VALIDPUSH); - default: - /* - * decoder in unknown state - (probably uninitialized) + return (UNVIS_VALIDPUSH); + + default: + /* + * decoder in unknown state - (probably uninitialized) */ *astate = S_GROUND; return (UNVIS_SYNBAD); @@ -271,7 +258,7 @@ __unvis13(cp, c, astate, flag) } /* - * strunvis - decode src into dst + * strunvis - decode src into dst * * Number of chars decoded into dst is returned, -1 on error. * Dst is null terminated. @@ -291,8 +278,8 @@ strunvisx(dst, src, flag) _DIAGASSERT(dst != NULL); while ((c = *src++) != '\0') { - again: - switch (__unvis13(dst, c, &state, flag)) { + again: + switch (unvis(dst, c, &state, flag)) { case UNVIS_VALID: dst++; break; @@ -306,7 +293,7 @@ strunvisx(dst, src, flag) return (-1); } } - if (__unvis13(dst, c, &state, UNVIS_END) == UNVIS_VALID) + if (unvis(dst, c, &state, UNVIS_END) == UNVIS_VALID) dst++; *dst = '\0'; return (dst - start); diff --git a/cmd-line-utils/libedit/np/vis.c b/cmd-line-utils/libedit/np/vis.c index e8f5c195f10..2a746274681 100644 --- a/cmd-line-utils/libedit/np/vis.c +++ b/cmd-line-utils/libedit/np/vis.c @@ -1,7 +1,6 @@ -/* $NetBSD: vis.c,v 1.22 2002/03/23 17:38:27 christos Exp $ */ +/* $NetBSD: vis.c,v 1.38 2008/09/04 09:41:44 lukem Exp $ */ /*- - * Copyright (c) 1999 The NetBSD Foundation, Inc. * Copyright (c) 1989, 1993 * The Regents of the University of California. All rights reserved. * @@ -13,11 +12,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * @@ -34,21 +29,47 @@ * SUCH DAMAGE. */ +/*- + * Copyright (c) 1999, 2005 The NetBSD Foundation, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + #include "config.h" #if defined(LIBC_SCCS) && !defined(lint) -__RCSID("$NetBSD: vis.c,v 1.22 2002/03/23 17:38:27 christos Exp $"); #endif /* LIBC_SCCS and not lint */ #include + #include -#ifdef HAVE_ALLOCA_H -#include +#ifdef HAVE_VIS_H +#include +#else +#include "np/vis.h" #endif #include -#include "np/vis.h" - #ifdef __weak_alias __weak_alias(strsvis,_strsvis) __weak_alias(strsvisx,_strsvisx) @@ -58,63 +79,61 @@ __weak_alias(svis,_svis) __weak_alias(vis,_vis) #endif -#if !HAVE_VIS_H +#if !HAVE_VIS || !HAVE_SVIS #include #include #include #include -#include -#undef BELL -#if defined(__STDC__) -#define BELL '\a' -#else -#define BELL '\007' -#endif -#define isoctal(c) (((unsigned char)(c)) >= '0' && ((unsigned char)(c)) <= '7') +static char *do_svis(char *, int, int, int, const char *); + +#undef BELL +#define BELL '\a' + +#define isoctal(c) (((u_char)(c)) >= '0' && ((u_char)(c)) <= '7') #define iswhite(c) (c == ' ' || c == '\t' || c == '\n') #define issafe(c) (c == '\b' || c == BELL || c == '\r') #define xtoa(c) "0123456789abcdef"[c] -#define MAXEXTRAS 5 +#define MAXEXTRAS 5 +#define MAKEEXTRALIST(flag, extra, orig_str) \ +do { \ + const char *orig = orig_str; \ + const char *o = orig; \ + char *e; \ + while (*o++) \ + continue; \ + extra = malloc((size_t)((o - orig) + MAXEXTRAS)); \ + if (!extra) break; \ + for (o = orig, e = extra; (*e++ = *o++) != '\0';) \ + continue; \ + e--; \ + if (flag & VIS_SP) *e++ = ' '; \ + if (flag & VIS_TAB) *e++ = '\t'; \ + if (flag & VIS_NL) *e++ = '\n'; \ + if ((flag & VIS_NOSLASH) == 0) *e++ = '\\'; \ + *e = '\0'; \ +} while (/*CONSTCOND*/0) -char *MAKEEXTRALIST(unsigned int flag, const char *orig) -{ - const char *o = orig; - char *e, *extra; - while (*o++) - continue; - extra = (char*) malloc((size_t)((o - orig) + MAXEXTRAS)); - assert(extra); - for (o = orig, e = extra; (*e++ = *o++) != '\0';) - continue; - e--; - if (flag & VIS_SP) *e++ = ' '; - if (flag & VIS_TAB) *e++ = '\t'; - if (flag & VIS_NL) *e++ = '\n'; - if ((flag & VIS_NOSLASH) == 0) *e++ = '\\'; - *e = '\0'; - return extra; +/* + * This is do_hvis, for HTTP style (RFC 1808) + */ +static char * +do_hvis(char *dst, int c, int flag, int nextc, const char *extra) +{ + if (!isascii(c) || !isalnum(c) || strchr("$-_.+!*'(),", c) != NULL) { + *dst++ = '%'; + *dst++ = xtoa(((unsigned int)c >> 4) & 0xf); + *dst++ = xtoa((unsigned int)c & 0xf); + } else { + dst = do_svis(dst, c, flag, nextc, extra); + } + return dst; } - /* - * This is HVIS, the macro of vis used to HTTP style (RFC 1808) - */ -#define HVIS(dst, c, flag, nextc, extra) \ -do \ - if (!isascii(c) || !isalnum(c) || strchr("$-_.+!*'(),", c) != NULL) { \ - *dst++ = '%'; \ - *dst++ = xtoa(((unsigned int)c >> 4) & 0xf); \ - *dst++ = xtoa((unsigned int)c & 0xf); \ - } else { \ - SVIS(dst, c, flag, nextc, extra); \ - } \ -while (/*CONSTCOND*/0) - -/* - * This is SVIS, the central macro of vis. + * This is do_vis, the central code of vis. * dst: Pointer to the destination buffer * c: Character to encode * flag: Flag word @@ -122,95 +141,103 @@ while (/*CONSTCOND*/0) * extra: Pointer to the list of extra characters to be * backslash-protected. */ -#define SVIS(dst, c, flag, nextc, extra) \ -do { \ - int isextra, isc; \ - isextra = strchr(extra, c) != NULL; \ - if (!isextra && isascii(c) && (isgraph(c) || iswhite(c) || \ - ((flag & VIS_SAFE) && issafe(c)))) { \ - *dst++ = c; \ - break; \ - } \ - isc = 0; \ - if (flag & VIS_CSTYLE) { \ - switch (c) { \ - case '\n': \ - isc = 1; *dst++ = '\\'; *dst++ = 'n'; \ - break; \ - case '\r': \ - isc = 1; *dst++ = '\\'; *dst++ = 'r'; \ - break; \ - case '\b': \ - isc = 1; *dst++ = '\\'; *dst++ = 'b'; \ - break; \ - case BELL: \ - isc = 1; *dst++ = '\\'; *dst++ = 'a'; \ - break; \ - case '\v': \ - isc = 1; *dst++ = '\\'; *dst++ = 'v'; \ - break; \ - case '\t': \ - isc = 1; *dst++ = '\\'; *dst++ = 't'; \ - break; \ - case '\f': \ - isc = 1; *dst++ = '\\'; *dst++ = 'f'; \ - break; \ - case ' ': \ - isc = 1; *dst++ = '\\'; *dst++ = 's'; \ - break; \ - case '\0': \ - isc = 1; *dst++ = '\\'; *dst++ = '0'; \ - if (isoctal(nextc)) { \ - *dst++ = '0'; \ - *dst++ = '0'; \ - } \ - } \ - } \ - if (isc) break; \ - if (isextra || ((c & 0177) == ' ') || (flag & VIS_OCTAL)) { \ - *dst++ = '\\'; \ - *dst++ = (unsigned char)(((unsigned int)(unsigned char)c >> 6) & 03) + '0'; \ - *dst++ = (unsigned char)(((unsigned int)(unsigned char)c >> 3) & 07) + '0'; \ - *dst++ = (c & 07) + '0'; \ - } else { \ - if ((flag & VIS_NOSLASH) == 0) *dst++ = '\\'; \ - if (c & 0200) { \ - c &= 0177; *dst++ = 'M'; \ - } \ - if (iscntrl(c)) { \ - *dst++ = '^'; \ - if (c == 0177) \ - *dst++ = '?'; \ - else \ - *dst++ = c + '@'; \ - } else { \ - *dst++ = '-'; *dst++ = c; \ - } \ - } \ -} while (/*CONSTCOND*/0) +static char * +do_svis(char *dst, int c, int flag, int nextc, const char *extra) +{ + int isextra; + isextra = strchr(extra, c) != NULL; + if (!isextra && isascii(c) && (isgraph(c) || iswhite(c) || + ((flag & VIS_SAFE) && issafe(c)))) { + *dst++ = c; + return dst; + } + if (flag & VIS_CSTYLE) { + switch (c) { + case '\n': + *dst++ = '\\'; *dst++ = 'n'; + return dst; + case '\r': + *dst++ = '\\'; *dst++ = 'r'; + return dst; + case '\b': + *dst++ = '\\'; *dst++ = 'b'; + return dst; + case BELL: + *dst++ = '\\'; *dst++ = 'a'; + return dst; + case '\v': + *dst++ = '\\'; *dst++ = 'v'; + return dst; + case '\t': + *dst++ = '\\'; *dst++ = 't'; + return dst; + case '\f': + *dst++ = '\\'; *dst++ = 'f'; + return dst; + case ' ': + *dst++ = '\\'; *dst++ = 's'; + return dst; + case '\0': + *dst++ = '\\'; *dst++ = '0'; + if (isoctal(nextc)) { + *dst++ = '0'; + *dst++ = '0'; + } + return dst; + default: + if (isgraph(c)) { + *dst++ = '\\'; *dst++ = c; + return dst; + } + } + } + if (isextra || ((c & 0177) == ' ') || (flag & VIS_OCTAL)) { + *dst++ = '\\'; + *dst++ = (u_char)(((u_int32_t)(u_char)c >> 6) & 03) + '0'; + *dst++ = (u_char)(((u_int32_t)(u_char)c >> 3) & 07) + '0'; + *dst++ = (c & 07) + '0'; + } else { + if ((flag & VIS_NOSLASH) == 0) *dst++ = '\\'; + if (c & 0200) { + c &= 0177; *dst++ = 'M'; + } + if (iscntrl(c)) { + *dst++ = '^'; + if (c == 0177) + *dst++ = '?'; + else + *dst++ = c + '@'; + } else { + *dst++ = '-'; *dst++ = c; + } + } + return dst; +} /* * svis - visually encode characters, also encoding the characters - * pointed to by `extra' + * pointed to by `extra' */ char * -svis(dst, c, flag, nextc, extra) - char *dst; - int c, flag, nextc; - const char *extra; +svis(char *dst, int c, int flag, int nextc, const char *extra) { - char *nextra, *to_be_freed; + char *nextra = NULL; + _DIAGASSERT(dst != NULL); _DIAGASSERT(extra != NULL); - nextra= to_be_freed= MAKEEXTRALIST(flag, extra); + MAKEEXTRALIST(flag, nextra, extra); + if (!nextra) { + *dst = '\0'; /* can't create nextra, return "" */ + return dst; + } if (flag & VIS_HTTPSTYLE) - HVIS(dst, c, flag, nextc, nextra); + dst = do_hvis(dst, c, flag, nextc, nextra); else - SVIS(dst, c, flag, nextc, nextra); + dst = do_svis(dst, c, flag, nextc, nextra); + free(nextra); *dst = '\0'; - free(to_be_freed); - return(dst); + return dst; } @@ -221,140 +248,146 @@ svis(dst, c, flag, nextc, extra) * be encoded, too. These functions are useful e. g. to * encode strings in such a way so that they are not interpreted * by a shell. - * + * * Dst must be 4 times the size of src to account for possible * expansion. The length of dst, not including the trailing NULL, - * is returned. + * is returned. * * Strsvisx encodes exactly len bytes from src into dst. * This is useful for encoding a block of data. */ int -strsvis(dst, src, flag, extra) - char *dst; - const char *src; - int flag; - const char *extra; +strsvis(char *dst, const char *csrc, int flag, const char *extra) { - char c; + int c; char *start; - char *nextra, *to_be_freed; + char *nextra = NULL; + const unsigned char *src = (const unsigned char *)csrc; _DIAGASSERT(dst != NULL); _DIAGASSERT(src != NULL); _DIAGASSERT(extra != NULL); - nextra= to_be_freed= MAKEEXTRALIST(flag, extra); + MAKEEXTRALIST(flag, nextra, extra); + if (!nextra) { + *dst = '\0'; /* can't create nextra, return "" */ + return 0; + } if (flag & VIS_HTTPSTYLE) { for (start = dst; (c = *src++) != '\0'; /* empty */) - HVIS(dst, c, flag, *src, nextra); + dst = do_hvis(dst, c, flag, *src, nextra); } else { for (start = dst; (c = *src++) != '\0'; /* empty */) - SVIS(dst, c, flag, *src, nextra); + dst = do_svis(dst, c, flag, *src, nextra); } + free(nextra); *dst = '\0'; - free(to_be_freed); return (dst - start); } int -strsvisx(dst, src, len, flag, extra) - char *dst; - const char *src; - size_t len; - int flag; - const char *extra; +strsvisx(char *dst, const char *csrc, size_t len, int flag, const char *extra) { - char c; + unsigned char c; char *start; - char *nextra, *to_be_freed; + char *nextra = NULL; + const unsigned char *src = (const unsigned char *)csrc; _DIAGASSERT(dst != NULL); _DIAGASSERT(src != NULL); _DIAGASSERT(extra != NULL); - nextra= to_be_freed= MAKEEXTRALIST(flag, extra); + MAKEEXTRALIST(flag, nextra, extra); + if (! nextra) { + *dst = '\0'; /* can't create nextra, return "" */ + return 0; + } if (flag & VIS_HTTPSTYLE) { for (start = dst; len > 0; len--) { c = *src++; - HVIS(dst, c, flag, len ? *src : '\0', nextra); + dst = do_hvis(dst, c, flag, + len > 1 ? *src : '\0', nextra); } } else { for (start = dst; len > 0; len--) { c = *src++; - SVIS(dst, c, flag, len ? *src : '\0', nextra); + dst = do_svis(dst, c, flag, + len > 1 ? *src : '\0', nextra); } } + free(nextra); *dst = '\0'; - free(to_be_freed); return (dst - start); } +#endif - +#if !HAVE_VIS /* * vis - visually encode characters */ char * -vis(dst, c, flag, nextc) - char *dst; - int c, flag, nextc; - +vis(char *dst, int c, int flag, int nextc) { - char *extra, *to_be_freed; + char *extra = NULL; + unsigned char uc = (unsigned char)c; _DIAGASSERT(dst != NULL); - extra= to_be_freed= MAKEEXTRALIST(flag, ""); - + MAKEEXTRALIST(flag, extra, ""); + if (! extra) { + *dst = '\0'; /* can't create extra, return "" */ + return dst; + } if (flag & VIS_HTTPSTYLE) - HVIS(dst, c, flag, nextc, extra); + dst = do_hvis(dst, uc, flag, nextc, extra); else - SVIS(dst, c, flag, nextc, extra); + dst = do_svis(dst, uc, flag, nextc, extra); + free(extra); *dst = '\0'; - free(to_be_freed); - return (dst); + return dst; } /* * strvis, strvisx - visually encode characters from src into dst - * + * * Dst must be 4 times the size of src to account for possible * expansion. The length of dst, not including the trailing NULL, - * is returned. + * is returned. * * Strvisx encodes exactly len bytes from src into dst. * This is useful for encoding a block of data. */ int -strvis(dst, src, flag) - char *dst; - const char *src; - int flag; +strvis(char *dst, const char *src, int flag) { - char *extra; - int tmp; + char *extra = NULL; + int rv; - extra= MAKEEXTRALIST(flag, ""); - tmp= strsvis(dst, src, flag, extra); + MAKEEXTRALIST(flag, extra, ""); + if (!extra) { + *dst = '\0'; /* can't create extra, return "" */ + return 0; + } + rv = strsvis(dst, src, flag, extra); free(extra); - return tmp; + return rv; } int -strvisx(dst, src, len, flag) - char *dst; - const char *src; - size_t len; - int flag; +strvisx(char *dst, const char *src, size_t len, int flag) { - char *extra; - int tmp; + char *extra = NULL; + int rv; - extra= MAKEEXTRALIST(flag, ""); - tmp= strsvisx(dst, src, len, flag, extra); + MAKEEXTRALIST(flag, extra, ""); + if (!extra) { + *dst = '\0'; /* can't create extra, return "" */ + return 0; + } + rv = strsvisx(dst, src, len, flag, extra); free(extra); - return tmp; + return rv; } #endif diff --git a/cmd-line-utils/libedit/np/vis.h b/cmd-line-utils/libedit/np/vis.h index 1a49c9e3ed2..11f5b740e2d 100644 --- a/cmd-line-utils/libedit/np/vis.h +++ b/cmd-line-utils/libedit/np/vis.h @@ -1,4 +1,4 @@ -/* $NetBSD: vis.h,v 1.12 2002/03/23 17:39:05 christos Exp $ */ +/* $NetBSD: vis.h,v 1.16 2005/09/13 01:44:32 christos Exp $ */ /*- * Copyright (c) 1990, 1993 @@ -12,11 +12,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * @@ -38,9 +34,7 @@ #ifndef _VIS_H_ #define _VIS_H_ -#ifdef HAVE_SYS_CDEFS_H -#include -#endif +#include /* * to select alternate encoding format @@ -78,6 +72,7 @@ */ #define UNVIS_END 1 /* no more characters */ +__BEGIN_DECLS char *vis(char *, int, int, int); char *svis(char *, int, int, int, const char *); int strvis(char *, const char *, int); @@ -86,11 +81,7 @@ int strvisx(char *, const char *, size_t, int); int strsvisx(char *, const char *, size_t, int, const char *); int strunvis(char *, const char *); int strunvisx(char *, const char *, int); -#ifdef __LIBC12_SOURCE__ int unvis(char *, int, int *, int); -int __unvis13(char *, int, int *, int); -#else -int unvis(char *, int, int *, int) __RENAME(__unvis13); -#endif +__END_DECLS #endif /* !_VIS_H_ */ diff --git a/cmd-line-utils/libedit/parse.c b/cmd-line-utils/libedit/parse.c index 993cf5b752d..5bdefb5a0e4 100644 --- a/cmd-line-utils/libedit/parse.c +++ b/cmd-line-utils/libedit/parse.c @@ -1,4 +1,4 @@ -/* $NetBSD: parse.c,v 1.20 2003/12/05 13:37:48 lukem Exp $ */ +/* $NetBSD: parse.c,v 1.22 2005/05/29 04:58:15 lukem Exp $ */ /*- * Copyright (c) 1992, 1993 @@ -32,7 +32,13 @@ * SUCH DAMAGE. */ -#include +#include "config.h" +#if !defined(lint) && !defined(SCCSID) +#if 0 +static char sccsid[] = "@(#)parse.c 8.1 (Berkeley) 6/4/93"; +#else +#endif +#endif /* not lint && not SCCSID */ /* * parse.c: parse an editline extended command @@ -129,7 +135,7 @@ el_parse(EditLine *el, int argc, const char *argv[]) * the appropriate character or -1 if the escape is not valid */ protected int -parse__escape(const char **const ptr) +parse__escape(const char **ptr) { const char *p; int c; diff --git a/cmd-line-utils/libedit/parse.h b/cmd-line-utils/libedit/parse.h index 4b796666b8e..58dced1aeaa 100644 --- a/cmd-line-utils/libedit/parse.h +++ b/cmd-line-utils/libedit/parse.h @@ -1,4 +1,4 @@ -/* $NetBSD: parse.h,v 1.5 2003/08/07 16:44:32 agc Exp $ */ +/* $NetBSD: parse.h,v 1.6 2005/05/29 04:58:15 lukem Exp $ */ /*- * Copyright (c) 1992, 1993 @@ -41,7 +41,7 @@ #define _h_el_parse protected int parse_line(EditLine *, const char *); -protected int parse__escape(const char ** const); +protected int parse__escape(const char **); protected char *parse__string(char *, const char *); protected int parse_cmd(EditLine *, const char *); diff --git a/cmd-line-utils/libedit/prompt.c b/cmd-line-utils/libedit/prompt.c index 455dd60331b..982943afd30 100644 --- a/cmd-line-utils/libedit/prompt.c +++ b/cmd-line-utils/libedit/prompt.c @@ -32,7 +32,13 @@ * SUCH DAMAGE. */ -#include +#include "config.h" +#if !defined(lint) && !defined(SCCSID) +#if 0 +static char sccsid[] = "@(#)prompt.c 8.1 (Berkeley) 6/4/93"; +#else +#endif +#endif /* not lint && not SCCSID */ /* * prompt.c: Prompt printing functions diff --git a/cmd-line-utils/libedit/read.c b/cmd-line-utils/libedit/read.c index 51848c2038e..ac768142e79 100644 --- a/cmd-line-utils/libedit/read.c +++ b/cmd-line-utils/libedit/read.c @@ -1,4 +1,4 @@ -/* $NetBSD: read.c,v 1.35 2005/03/09 23:55:02 christos Exp $ */ +/* $NetBSD: read.c,v 1.43 2009/02/05 19:15:44 christos Exp $ */ /*- * Copyright (c) 1992, 1993 @@ -32,7 +32,13 @@ * SUCH DAMAGE. */ -#include +#include "config.h" +#if !defined(lint) && !defined(SCCSID) +#if 0 +static char sccsid[] = "@(#)read.c 8.1 (Berkeley) 6/4/93"; +#else +#endif +#endif /* not lint && not SCCSID */ /* * read.c: Clean this junk up! This is horrible code. @@ -50,6 +56,7 @@ private int read__fixio(int, int); private int read_preread(EditLine *); private int read_char(EditLine *, char *); private int read_getcmd(EditLine *, el_action_t *, char *); +private void read_pop(c_macro_t *); /* read_init(): * Initialize the read stuff @@ -205,7 +212,7 @@ read_preread(EditLine *el) * Push a macro */ public void -el_push(EditLine *el, char *str) +el_push(EditLine *el, const char *str) { c_macro_t *ma = &el->el_chared.c_macro; @@ -216,7 +223,7 @@ el_push(EditLine *el, char *str) ma->level--; } term_beep(el); - term__flush(); + term__flush(el); } @@ -294,6 +301,19 @@ read_char(EditLine *el, char *cp) return (num_read); } +/* read_pop(): + * Pop a macro from the stack + */ +private void +read_pop(c_macro_t *ma) +{ + int i; + + el_free(ma->macro[0]); + for (i = ma->level--; i > 0; i--) + ma->macro[i - 1] = ma->macro[i]; + ma->offset = 0; +} /* el_getc(): * Read a character @@ -304,26 +324,28 @@ el_getc(EditLine *el, char *cp) int num_read; c_macro_t *ma = &el->el_chared.c_macro; - term__flush(); + term__flush(el); for (;;) { if (ma->level < 0) { if (!read_preread(el)) break; } + if (ma->level < 0) break; - if (ma->macro[ma->level][ma->offset] == '\0') { - el_free(ma->macro[ma->level--]); - ma->offset = 0; + if (ma->macro[0][ma->offset] == '\0') { + read_pop(ma); continue; } - *cp = ma->macro[ma->level][ma->offset++] & 0377; - if (ma->macro[ma->level][ma->offset] == '\0') { + + *cp = ma->macro[0][ma->offset++] & 0377; + + if (ma->macro[0][ma->offset] == '\0') { /* Needed for QuoteMode On */ - el_free(ma->macro[ma->level--]); - ma->offset = 0; + read_pop(ma); } + return (1); } @@ -357,11 +379,11 @@ read_prepare(EditLine *el) we have the wrong size. */ el_resize(el); re_clear_display(el); /* reset the display stuff */ - ch_reset(el); + ch_reset(el, 0); re_refresh(el); /* print the prompt */ if (el->el_flags & UNBUFFERED) - term__flush(); + term__flush(el); } protected void @@ -438,7 +460,7 @@ el_gets(EditLine *el, int *nread) else cp = el->el_line.lastchar; - term__flush(); + term__flush(el); while ((*el->el_read.read_char)(el, cp) == 1) { /* make sure there is space next character */ @@ -478,7 +500,7 @@ el_gets(EditLine *el, int *nread) #endif /* DEBUG_READ */ break; } - if ((unsigned int)cmdnum >= el->el_map.nfunc) { /* BUG CHECK command */ + if ((unsigned int)cmdnum >= (unsigned int)el->el_map.nfunc) { /* BUG CHECK command */ #ifdef DEBUG_EDIT (void) fprintf(el->el_errfile, "ERROR: illegal command from key 0%o\r\n", ch); @@ -570,7 +592,7 @@ el_gets(EditLine *el, int *nread) #endif /* DEBUG_READ */ /* put (real) cursor in a known place */ re_clear_display(el); /* reset the display stuff */ - ch_reset(el); /* reset the input pointers */ + ch_reset(el, 1); /* reset the input pointers */ re_refresh(el); /* print the prompt again */ break; @@ -581,7 +603,7 @@ el_gets(EditLine *el, int *nread) "*** editor ERROR ***\r\n\n"); #endif /* DEBUG_READ */ term_beep(el); - term__flush(); + term__flush(el); break; } el->el_state.argument = 1; @@ -591,7 +613,7 @@ el_gets(EditLine *el, int *nread) break; } - term__flush(); /* flush any buffered output */ + term__flush(el); /* flush any buffered output */ /* make sure the tty is set up correctly */ if ((el->el_flags & UNBUFFERED) == 0) { read_finish(el); diff --git a/cmd-line-utils/libedit/read.h b/cmd-line-utils/libedit/read.h index 1982f47253b..bd8d4c1f5bb 100644 --- a/cmd-line-utils/libedit/read.h +++ b/cmd-line-utils/libedit/read.h @@ -1,4 +1,4 @@ -/* $NetBSD: read.h,v 1.4 2004/02/27 14:52:18 christos Exp $ */ +/* $NetBSD: read.h,v 1.6 2008/04/29 06:53:01 martin Exp $ */ /*- * Copyright (c) 2001 The NetBSD Foundation, Inc. @@ -15,13 +15,6 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the NetBSD - * Foundation, Inc. and its contributors. - * 4. Neither the name of The NetBSD Foundation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED diff --git a/cmd-line-utils/libedit/readline.c b/cmd-line-utils/libedit/readline.c index 004fcf7d183..ca8796fbd37 100644 --- a/cmd-line-utils/libedit/readline.c +++ b/cmd-line-utils/libedit/readline.c @@ -1,4 +1,4 @@ -/* $NetBSD: readline.c,v 1.49 2005/03/10 19:34:46 christos Exp $ */ +/* $NetBSD: readline.c,v 1.78 2009/02/05 19:15:26 christos Exp $ */ /*- * Copyright (c) 1997 The NetBSD Foundation, Inc. @@ -15,13 +15,6 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the NetBSD - * Foundation, Inc. and its contributors. - * 4. Neither the name of The NetBSD Foundation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED @@ -36,25 +29,9 @@ * POSSIBILITY OF SUCH DAMAGE. */ -/* AIX requires this to be the first thing in the file. */ -#if defined (_AIX) && !defined (__GNUC__) - #pragma alloca -#endif - -#include - -#ifdef __GNUC__ -# undef alloca -# define alloca(n) __builtin_alloca (n) -#else -# ifdef HAVE_ALLOCA_H -# include -# else -# ifndef _AIX -extern char *alloca (); -# endif -# endif -#endif +#include "config.h" +#if !defined(lint) && !defined(SCCSID) +#endif /* not lint && not SCCSID */ #include #include @@ -68,12 +45,23 @@ extern char *alloca (); #include #include #include +#include +#ifdef HAVE_VIS_H #include - -#include "readline/readline.h" +#else +#include "np/vis.h" +#endif +#ifdef HAVE_ALLOCA_H +#include +#endif #include "el.h" #include "fcns.h" /* for EL_NUM_FCNS */ #include "histedit.h" +#include "readline/readline.h" +#include "filecomplete.h" + +void rl_prep_terminal(int); +void rl_deprep_terminal(void); /* for rl_complete() */ #define TAB '\r' @@ -94,9 +82,12 @@ FILE *rl_outstream = NULL; int rl_point = 0; int rl_end = 0; char *rl_line_buffer = NULL; -VFunction *rl_linefunc = NULL; +VCPFunction *rl_linefunc = NULL; int rl_done = 0; VFunction *rl_event_hook = NULL; +KEYMAP_ENTRY_ARRAY emacs_standard_keymap, + emacs_meta_keymap, + emacs_ctlx_keymap; int history_base = 1; /* probably never subject to change */ int history_length = 0; @@ -112,21 +103,23 @@ int rl_attempted_completion_over = 0; char *rl_basic_word_break_characters = break_chars; char *rl_completer_word_break_characters = NULL; char *rl_completer_quote_characters = NULL; -CPFunction *rl_completion_entry_function = NULL; +Function *rl_completion_entry_function = NULL; CPPFunction *rl_attempted_completion_function = NULL; Function *rl_pre_input_hook = NULL; Function *rl_startup1_hook = NULL; -Function *rl_getc_function = NULL; +int (*rl_getc_function)(FILE *) = NULL; char *rl_terminal_name = NULL; int rl_already_prompted = 0; int rl_filename_completion_desired = 0; int rl_ignore_completion_duplicates = 0; int rl_catch_signals = 1; +int readline_echoing_p = 1; +int _rl_print_completions_horizontally = 0; VFunction *rl_redisplay_function = NULL; Function *rl_startup_hook = NULL; VFunction *rl_completion_display_matches_hook = NULL; -VFunction *rl_prep_term_function = NULL; -VFunction *rl_deprep_term_function = NULL; +VFunction *rl_prep_term_function = (VFunction *)rl_prep_terminal; +VFunction *rl_deprep_term_function = (VFunction *)rl_deprep_terminal; /* * The current prompt string. @@ -150,7 +143,7 @@ int rl_completion_query_items = 100; * in the parsed text when it is passed to the completion function. * Shell uses this to help determine what kind of completing to do. */ -char *rl_special_prefixes = (char *)NULL; +char *rl_special_prefixes = NULL; /* * This is the character appended to the completed words if at the end of @@ -160,25 +153,21 @@ int rl_completion_append_character = ' '; /* stuff below is used internally by libedit for readline emulation */ -/* if not zero, non-unique completions always show list of possible matches */ -static int _rl_complete_show_all = 0; - static History *h = NULL; static EditLine *e = NULL; static Function *map[256]; -static int el_rl_complete_cmdnum = 0; +static jmp_buf topbuf; /* internal functions */ static unsigned char _el_rl_complete(EditLine *, int); static unsigned char _el_rl_tstp(EditLine *, int); static char *_get_prompt(EditLine *); +static int _getc_function(EditLine *, char *); static HIST_ENTRY *_move_history(int); static int _history_expand_command(const char *, size_t, size_t, char **); static char *_rl_compat_sub(const char *, const char *, const char *, int); -static int _rl_complete_internal(int); -static int _rl_qsort_string_compare(const void *, const void *); static int _rl_event_read_char(EditLine *, char *); static void _rl_update_pos(void); @@ -205,16 +194,49 @@ _move_history(int op) return (HIST_ENTRY *) NULL; rl_he.line = ev.str; - rl_he.data = (histdata_t) &(ev.num); + rl_he.data = NULL; return (&rl_he); } +/* + * read one key from user defined input function + */ +static int +/*ARGSUSED*/ +_getc_function(EditLine *el, char *c) +{ + int i; + + i = (*rl_getc_function)(NULL); + if (i == -1) + return 0; + *c = i; + return 1; +} + + /* * READLINE compatibility stuff */ +/* + * Set the prompt + */ +int +rl_set_prompt(const char *prompt) +{ + if (!prompt) + prompt = ""; + if (rl_prompt != NULL && strcmp(rl_prompt, prompt) == 0) + return 0; + if (rl_prompt) + free(rl_prompt); + rl_prompt = strdup(prompt); + return rl_prompt == NULL ? -1 : 0; +} + /* * initialize rl compat stuff */ @@ -223,7 +245,6 @@ rl_initialize(void) { HistEvent ev; const LineInfo *li; - int i; int editmode = 1; struct termios t; @@ -257,9 +278,12 @@ rl_initialize(void) max_input_history = INT_MAX; el_set(e, EL_HIST, history, h); + /* setup getc function if valid */ + if (rl_getc_function) + el_set(e, EL_GETCFN, _getc_function); + /* for proper prompt printing in readline() */ - rl_prompt = strdup(""); - if (rl_prompt == NULL) { + if (rl_set_prompt("") == -1) { history_end(h); el_end(e); return -1; @@ -291,17 +315,6 @@ rl_initialize(void) "ReadLine compatible suspend function", _el_rl_tstp); el_set(e, EL_BIND, "^Z", "rl_tstp", NULL); - - /* - * Find out where the rl_complete function was added; this is - * used later to detect that lastcmd was also rl_complete. - */ - for(i=EL_NUM_FCNS; i < e->el_map.nfunc; i++) { - if (e->el_map.func[i] == _el_rl_complete) { - el_rl_complete_cmdnum = i; - break; - } - } /* read settings from configuration file */ el_source(e, NULL); @@ -327,9 +340,10 @@ rl_initialize(void) * trailing newline (if there is any) */ char * -readline(const char *prompt) +readline(const char *p) { HistEvent ev; + const char * volatile prompt = p; int count; const char *ret; char *buf; @@ -340,15 +354,11 @@ readline(const char *prompt) rl_done = 0; + (void)setjmp(topbuf); + /* update prompt accordingly to what has been passed */ - if (!prompt) - prompt = ""; - if (strcmp(rl_prompt, prompt) != 0) { - free(rl_prompt); - rl_prompt = strdup(prompt); - if (rl_prompt == NULL) - return NULL; - } + if (rl_set_prompt(prompt) == -1) + return NULL; if (rl_pre_input_hook) (*rl_pre_input_hook)(NULL, 0); @@ -446,7 +456,7 @@ _rl_compat_sub(const char *str, const char *what, const char *with, } else *r++ = *s++; } - *r = 0; + *r = '\0'; return(result); } @@ -467,7 +477,7 @@ get_history_event(const char *cmd, int *cindex, int qchar) return(NULL); /* find out which event to take */ - if (cmd[idx] == history_expansion_char || cmd[idx] == 0) { + if (cmd[idx] == history_expansion_char || cmd[idx] == '\0') { if (history(h, &ev, H_FIRST) != 0) return(NULL); *cindex = cmd[idx]? (idx + 1):idx; @@ -689,7 +699,7 @@ _history_expand_command(const char *command, size_t offs, size_t cmdlen, if (aptr) free(aptr); - if (*cmd == 0 || (cmd - (command + offs) >= cmdlen)) { + if (*cmd == '\0' || ((size_t)(cmd - (command + offs)) >= cmdlen)) { *result = tmp; return(1); } @@ -699,7 +709,7 @@ _history_expand_command(const char *command, size_t offs, size_t cmdlen, continue; else if (*cmd == 'h') { /* remove trailing path */ if ((aptr = strrchr(tmp, '/')) != NULL) - *aptr = 0; + *aptr = '\0'; } else if (*cmd == 't') { /* remove leading path */ if ((aptr = strrchr(tmp, '/')) != NULL) { aptr = strdup(aptr + 1); @@ -708,7 +718,7 @@ _history_expand_command(const char *command, size_t offs, size_t cmdlen, } } else if (*cmd == 'r') { /* remove trailing suffix */ if ((aptr = strrchr(tmp, '.')) != NULL) - *aptr = 0; + *aptr = '\0'; } else if (*cmd == 'e') { /* remove all but suffix */ if ((aptr = strrchr(tmp, '.')) != NULL) { aptr = strdup(aptr); @@ -732,6 +742,7 @@ _history_expand_command(const char *command, size_t offs, size_t cmdlen, what = realloc(from, size); if (what == NULL) { free(from); + free(tmp); return 0; } len = 0; @@ -744,6 +755,7 @@ _history_expand_command(const char *command, size_t offs, size_t cmdlen, (size <<= 1)); if (nwhat == NULL) { free(what); + free(tmp); return 0; } what = nwhat; @@ -756,10 +768,13 @@ _history_expand_command(const char *command, size_t offs, size_t cmdlen, free(what); if (search) { from = strdup(search); - if (from == NULL) + if (from == NULL) { + free(tmp); return 0; + } } else { from = NULL; + free(tmp); return (-1); } } @@ -771,6 +786,7 @@ _history_expand_command(const char *command, size_t offs, size_t cmdlen, with = realloc(to, size); if (with == NULL) { free(to); + free(tmp); return -1; } len = 0; @@ -782,6 +798,7 @@ _history_expand_command(const char *command, size_t offs, size_t cmdlen, nwith = realloc(with, size); if (nwith == NULL) { free(with); + free(tmp); return -1; } with = nwith; @@ -850,12 +867,14 @@ history_expand(char *str, char **output) return 0; } -#define ADD_STRING(what, len) \ +#define ADD_STRING(what, len, fr) \ { \ if (idx + len + 1 > size) { \ char *nresult = realloc(result, (size += len + 1));\ if (nresult == NULL) { \ free(*output); \ + if (/*CONSTCOND*/fr) \ + free(tmp); \ return 0; \ } \ result = nresult; \ @@ -867,6 +886,7 @@ history_expand(char *str, char **output) result = NULL; size = idx = 0; + tmp = NULL; for (i = 0; str[i];) { int qchar, loop_again; size_t len, start, j; @@ -904,13 +924,11 @@ loop: goto loop; } len = i - start; - tmp = &str[start]; - ADD_STRING(tmp, len); + ADD_STRING(&str[start], len, 0); if (str[i] == '\0' || str[i] != history_expansion_char) { len = j - i; - tmp = &str[i]; - ADD_STRING(tmp, len); + ADD_STRING(&str[i], len, 0); if (start == 0) ret = 0; else @@ -920,8 +938,11 @@ loop: ret = _history_expand_command (str, i, (j - i), &tmp); if (ret > 0 && tmp) { len = strlen(tmp); - ADD_STRING(tmp, len); + ADD_STRING(tmp, len, 1); + } + if (tmp) { free(tmp); + tmp = NULL; } i = j; } @@ -973,23 +994,23 @@ history_arg_extract(int start, int end, const char *str) if (start < 0) start = end; - if (start < 0 || end < 0 || start > max || end > max || start > end) + if (start < 0 || end < 0 || (size_t)start > max || (size_t)end > max || start > end) return(NULL); - for (i = start, len = 0; i <= end; i++) + for (i = start, len = 0; i <= (size_t)end; i++) len += strlen(arr[i]) + 1; len++; result = malloc(len); if (result == NULL) return NULL; - for (i = start, len = 0; i <= end; i++) { + for (i = start, len = 0; i <= (size_t)end; i++) { (void)strcpy(result + len, arr[i]); len += strlen(arr[i]); - if (i < end) + if (i < (size_t)end) result[len++] = ' '; } - result[len] = 0; + result[len] = '\0'; for (i = 0; arr[i]; i++) free(arr[i]); @@ -1152,7 +1173,7 @@ history_get(int num) return (NULL); /* error */ /* look backwards for event matching specified offset */ - if (history(h, &ev, H_NEXT_EVENT, num)) + if (history(h, &ev, H_NEXT_EVENT, num + 1)) return (NULL); she.line = ev.str; @@ -1184,6 +1205,31 @@ add_history(const char *line) } +/* + * remove the specified entry from the history list and return it. + */ +HIST_ENTRY * +remove_history(int num) +{ + HIST_ENTRY *she; + HistEvent ev; + + if (h == NULL || e == NULL) + rl_initialize(); + + if (history(h, &ev, H_DEL, num) != 0) + return NULL; + + if ((she = malloc(sizeof(*she))) == NULL) + return NULL; + + she->line = ev.str; + she->data = NULL; + + return she; +} + + /* * clear the history list - delete all entries */ @@ -1377,172 +1423,18 @@ history_search_pos(const char *str, /********************************/ /* completion functions */ -/* - * does tilde expansion of strings of type ``~user/foo'' - * if ``user'' isn't valid user name or ``txt'' doesn't start - * w/ '~', returns pointer to strdup()ed copy of ``txt'' - * - * it's callers's responsibility to free() returned string - */ char * -tilde_expand(char *txt) +tilde_expand(char *name) { - struct passwd *pass; - char *temp; - size_t len = 0; - - if (txt[0] != '~') - return (strdup(txt)); - - temp = strchr(txt + 1, '/'); - if (temp == NULL) { - temp = strdup(txt + 1); - if (temp == NULL) - return NULL; - } else { - len = temp - txt + 1; /* text until string after slash */ - temp = malloc(len); - if (temp == NULL) - return NULL; - (void)strncpy(temp, txt + 1, len - 2); - temp[len - 2] = '\0'; - } - pass = getpwnam(temp); - free(temp); /* value no more needed */ - if (pass == NULL) - return (strdup(txt)); - - /* update pointer txt to point at string immedially following */ - /* first slash */ - txt += len; - - temp = malloc(strlen(pass->pw_dir) + 1 + strlen(txt) + 1); - if (temp == NULL) - return NULL; - (void)sprintf(temp, "%s/%s", pass->pw_dir, txt); - - return (temp); + return fn_tilde_expand(name); } - -/* - * return first found file name starting by the ``text'' or NULL if no - * such file can be found - * value of ``state'' is ignored - * - * it's caller's responsibility to free returned string - */ char * -filename_completion_function(const char *text, int state) +filename_completion_function(const char *name, int state) { - static DIR *dir = NULL; - static char *filename = NULL, *dirname = NULL; - static size_t filename_len = 0; - struct dirent *entry; - char *temp; - size_t len; - - if (state == 0 || dir == NULL) { - temp = strrchr(text, '/'); - if (temp) { - char *nptr; - temp++; - nptr = realloc(filename, strlen(temp) + 1); - if (nptr == NULL) { - free(filename); - return NULL; - } - filename = nptr; - (void)strcpy(filename, temp); - len = temp - text; /* including last slash */ - nptr = realloc(dirname, len + 1); - if (nptr == NULL) { - free(filename); - return NULL; - } - dirname = nptr; - (void)strncpy(dirname, text, len); - dirname[len] = '\0'; - } else { - if (*text == 0) - filename = NULL; - else { - filename = strdup(text); - if (filename == NULL) - return NULL; - } - dirname = NULL; - } - - /* support for ``~user'' syntax */ - if (dirname && *dirname == '~') { - char *nptr; - temp = tilde_expand(dirname); - if (temp == NULL) - return NULL; - nptr = realloc(dirname, strlen(temp) + 1); - if (nptr == NULL) { - free(dirname); - return NULL; - } - dirname = nptr; - (void)strcpy(dirname, temp); /* safe */ - free(temp); /* no longer needed */ - } - /* will be used in cycle */ - filename_len = filename ? strlen(filename) : 0; - - if (dir != NULL) { - (void)closedir(dir); - dir = NULL; - } - dir = opendir(dirname ? dirname : "."); - if (!dir) - return (NULL); /* cannot open the directory */ - } - /* find the match */ - while ((entry = readdir(dir)) != NULL) { - /* skip . and .. */ - if (entry->d_name[0] == '.' && (!entry->d_name[1] - || (entry->d_name[1] == '.' && !entry->d_name[2]))) - continue; - if (filename_len == 0) - break; - /* otherwise, get first entry where first */ - /* filename_len characters are equal */ - if (entry->d_name[0] == filename[0] - /* Some dirents have d_namlen, but it is not portable. */ - && strlen(entry->d_name) >= filename_len - && strncmp(entry->d_name, filename, - filename_len) == 0) - break; - } - - if (entry) { /* match found */ - - struct stat stbuf; - /* Some dirents have d_namlen, but it is not portable. */ - len = strlen(entry->d_name) + - ((dirname) ? strlen(dirname) : 0) + 1 + 1; - temp = malloc(len); - if (temp == NULL) - return NULL; - (void)sprintf(temp, "%s%s", - dirname ? dirname : "", entry->d_name); /* safe */ - - /* test, if it's directory */ - if (stat(temp, &stbuf) == 0 && S_ISDIR(stbuf.st_mode)) - strcat(temp, "/"); /* safe */ - } else { - (void)closedir(dir); - dir = NULL; - temp = NULL; - } - - return (temp); + return fn_filename_completion_function(name, state); } - /* * a completion generator for usernames; returns _first_ username * which starts with supplied text @@ -1564,6 +1456,7 @@ username_completion_function(const char *text, int state) if (state == 0) setpwent(); + /* XXXMYSQL: just use non-_r functions for now */ while ((pwd = getpwent()) && text[0] == pwd->pw_name[0] && strcmp(text, pwd->pw_name) == 0); @@ -1575,16 +1468,6 @@ username_completion_function(const char *text, int state) } -/* - * el-compatible wrapper around rl_complete; needed for key binding - */ -/* ARGSUSED */ -static unsigned char -_el_rl_complete(EditLine *el __attribute__((__unused__)), int ch) -{ - return (unsigned char) rl_complete(0, ch); -} - /* * el-compatible wrapper to send TSTP on ^Z */ @@ -1596,273 +1479,36 @@ _el_rl_tstp(EditLine *el __attribute__((__unused__)), int ch __attribute__((__un return CC_NORM; } -/* - * returns list of completions for text given - */ -char ** -completion_matches(const char *text, CPFunction *genfunc) -{ - char **match_list = NULL, *retstr, *prevstr; - size_t match_list_len, max_equal, which, i; - size_t matches; - - if (h == NULL || e == NULL) - rl_initialize(); - - matches = 0; - match_list_len = 1; - while ((retstr = (*genfunc) (text, (int)matches)) != NULL) { - /* allow for list terminator here */ - if (matches + 3 >= match_list_len) { - char **nmatch_list; - while (matches + 3 >= match_list_len) - match_list_len <<= 1; - nmatch_list = realloc(match_list, - match_list_len * sizeof(char *)); - if (nmatch_list == NULL) { - free(match_list); - return NULL; - } - match_list = nmatch_list; - - } - match_list[++matches] = retstr; - } - - if (!match_list) - return NULL; /* nothing found */ - - /* find least denominator and insert it to match_list[0] */ - which = 2; - prevstr = match_list[1]; - max_equal = strlen(prevstr); - for (; which <= matches; which++) { - for (i = 0; i < max_equal && - prevstr[i] == match_list[which][i]; i++) - continue; - max_equal = i; - } - - retstr = malloc(max_equal + 1); - if (retstr == NULL) { - free(match_list); - return NULL; - } - (void)strncpy(retstr, match_list[1], max_equal); - retstr[max_equal] = '\0'; - match_list[0] = retstr; - - /* add NULL as last pointer to the array */ - match_list[matches + 1] = (char *) NULL; - - return (match_list); -} - -/* - * Sort function for qsort(). Just wrapper around strcasecmp(). - */ -static int -_rl_qsort_string_compare(i1, i2) - const void *i1, *i2; -{ - const char *s1 = ((const char * const *)i1)[0]; - const char *s2 = ((const char * const *)i2)[0]; - - return strcasecmp(s1, s2); -} - /* * Display list of strings in columnar format on readline's output stream. * 'matches' is list of strings, 'len' is number of strings in 'matches', * 'max' is maximum length of string in 'matches'. */ void -rl_display_match_list (matches, len, max) - char **matches; - int len, max; +rl_display_match_list(char **matches, int len, int max) { - int i, idx, limit, count; - int screenwidth = e->el_term.t_size.h; - /* - * Find out how many entries can be put on one line, count - * with two spaces between strings. - */ - limit = screenwidth / (max + 2); - if (limit == 0) - limit = 1; - - /* how many lines of output */ - count = len / limit; - if (count * limit < len) - count++; - - /* Sort the items if they are not already sorted. */ - qsort(&matches[1], (size_t)(len - 1), sizeof(char *), - _rl_qsort_string_compare); - - idx = 1; - for(; count > 0; count--) { - for(i = 0; i < limit && matches[idx]; i++, idx++) - (void)fprintf(e->el_outfile, "%-*s ", max, - matches[idx]); - (void)fprintf(e->el_outfile, "\n"); - } + fn_display_match_list(e, matches, len, max); } -/* - * Complete the word at or before point, called by rl_complete() - * 'what_to_do' says what to do with the completion. - * `?' means list the possible completions. - * TAB means do standard completion. - * `*' means insert all of the possible completions. - * `!' means to do standard completion, and list all possible completions if - * there is more than one. - * - * Note: '*' support is not implemented - */ -static int -_rl_complete_internal(int what_to_do) +static const char * +/*ARGSUSED*/ +_rl_completion_append_character_function(const char *dummy + __attribute__((__unused__))) { - CPFunction *complet_func; - const LineInfo *li; - char *temp, **matches; - const char *ctemp; - size_t len; - - rl_completion_type = what_to_do; - - if (h == NULL || e == NULL) - rl_initialize(); - - complet_func = rl_completion_entry_function; - if (!complet_func) - complet_func = filename_completion_function; - - /* We now look backwards for the start of a filename/variable word */ - li = el_line(e); - ctemp = (const char *) li->cursor; - while (ctemp > li->buffer - && !strchr(rl_basic_word_break_characters, ctemp[-1]) - && (!rl_special_prefixes - || !strchr(rl_special_prefixes, ctemp[-1]) ) ) - ctemp--; - - len = li->cursor - ctemp; - temp = alloca(len + 1); - (void)strncpy(temp, ctemp, len); - temp[len] = '\0'; - - /* these can be used by function called in completion_matches() */ - /* or (*rl_attempted_completion_function)() */ - _rl_update_pos(); - - if (rl_attempted_completion_function) { - int end = li->cursor - li->buffer; - matches = (*rl_attempted_completion_function) (temp, (int) - (end - len), end); - } else - matches = 0; - if (!rl_attempted_completion_function || !matches) - matches = completion_matches(temp, complet_func); - - if (matches) { - int i, retval = CC_REFRESH; - int matches_num, maxlen, match_len, match_display=1; - - /* - * Only replace the completed string with common part of - * possible matches if there is possible completion. - */ - if (matches[0][0] != '\0') { - el_deletestr(e, (int) len); - el_insertstr(e, matches[0]); - } - - if (what_to_do == '?') - goto display_matches; - - if (matches[2] == NULL && strcmp(matches[0], matches[1]) == 0) { - /* - * We found exact match. Add a space after - * it, unless we do filename completion and the - * object is a directory. - */ - size_t alen = strlen(matches[0]); - if ((complet_func != filename_completion_function - || (alen > 0 && (matches[0])[alen - 1] != '/')) - && rl_completion_append_character) { - char buf[2]; - buf[0] = rl_completion_append_character; - buf[1] = '\0'; - el_insertstr(e, buf); - } - } else if (what_to_do == '!') { - display_matches: - /* - * More than one match and requested to list possible - * matches. - */ - - for(i=1, maxlen=0; matches[i]; i++) { - match_len = strlen(matches[i]); - if (match_len > maxlen) - maxlen = match_len; - } - matches_num = i - 1; - - /* newline to get on next line from command line */ - (void)fprintf(e->el_outfile, "\n"); - - /* - * If there are too many items, ask user for display - * confirmation. - */ - if (matches_num > rl_completion_query_items) { - (void)fprintf(e->el_outfile, - "Display all %d possibilities? (y or n) ", - matches_num); - (void)fflush(e->el_outfile); - if (getc(stdin) != 'y') - match_display = 0; - (void)fprintf(e->el_outfile, "\n"); - } - - if (match_display) - rl_display_match_list(matches, matches_num, - maxlen); - retval = CC_REDISPLAY; - } else if (matches[0][0]) { - /* - * There was some common match, but the name was - * not complete enough. Next tab will print possible - * completions. - */ - el_beep(e); - } else { - /* lcd is not a valid object - further specification */ - /* is needed */ - el_beep(e); - retval = CC_NORM; - } - - /* free elements of array and the array itself */ - for (i = 0; matches[i]; i++) - free(matches[i]); - free(matches), matches = NULL; - - return (retval); - } - return (CC_NORM); + static char buf[2]; + buf[0] = rl_completion_append_character; + buf[1] = '\0'; + return buf; } /* * complete word at current point */ +/* ARGSUSED */ int -/*ARGSUSED*/ -rl_complete(int ignore, int invoking_key) +rl_complete(int ignore __attribute__((__unused__)), int invoking_key) { if (h == NULL || e == NULL) rl_initialize(); @@ -1873,15 +1519,26 @@ rl_complete(int ignore, int invoking_key) arr[1] = '\0'; el_insertstr(e, arr); return (CC_REFRESH); - } else if (e->el_state.lastcmd == el_rl_complete_cmdnum) - return _rl_complete_internal('?'); - else if (_rl_complete_show_all) - return _rl_complete_internal('!'); - else - return _rl_complete_internal(TAB); + } + + /* Just look at how many global variables modify this operation! */ + return fn_complete(e, + (CPFunction *)rl_completion_entry_function, + rl_attempted_completion_function, + rl_basic_word_break_characters, rl_special_prefixes, + _rl_completion_append_character_function, rl_completion_query_items, + &rl_completion_type, &rl_attempted_completion_over, + &rl_point, &rl_end); } +/* ARGSUSED */ +static unsigned char +_el_rl_complete(EditLine *el __attribute__((__unused__)), int ch) +{ + return (unsigned char)rl_complete(0, ch); +} + /* * misc other functions */ @@ -1989,7 +1646,7 @@ int rl_add_defun(const char *name, Function *fun, int c) { char dest[8]; - if (c >= sizeof(map) / sizeof(map[0]) || c < 0) + if ((size_t)c >= sizeof(map) / sizeof(map[0]) || c < 0) return -1; map[(unsigned char)c] = fun; el_set(e, EL_ADDFN, name, name, rl_bind_wrapper); @@ -2007,11 +1664,7 @@ rl_callback_read_char() if (buf == NULL || count-- <= 0) return; -#ifdef CTRL2 /* _AIX */ - if (count == 0 && buf[0] == CTRL2('d')) -#else - if (count == 0 && buf[0] == CTRL('d')) -#endif + if (count == 0 && buf[0] == e->el_tty.t_c[TS_IO][C_EOF]) done = 1; if (buf[count] == '\n' || buf[count] == '\r') done = 2; @@ -2029,14 +1682,12 @@ rl_callback_read_char() } void -rl_callback_handler_install (const char *prompt, VFunction *linefunc) +rl_callback_handler_install(const char *prompt, VCPFunction *linefunc) { if (e == NULL) { rl_initialize(); } - if (rl_prompt) - free(rl_prompt); - rl_prompt = prompt ? strdup(strchr(prompt, *prompt)) : NULL; + (void)rl_set_prompt(prompt); rl_linefunc = linefunc; el_set(e, EL_UNBUFFERED, 1); } @@ -2045,17 +1696,14 @@ void rl_callback_handler_remove(void) { el_set(e, EL_UNBUFFERED, 0); + rl_linefunc = NULL; } void rl_redisplay(void) { char a[2]; -#ifdef CTRL2 /* _AIX */ - a[0] = CTRL2('r'); -#else - a[0] = CTRL('r'); -#endif + a[0] = e->el_tty.t_c[TS_IO][C_REPRINT]; a[1] = '\0'; el_push(e, a); } @@ -2079,7 +1727,7 @@ rl_prep_terminal(int meta_flag) } void -rl_deprep_terminal() +rl_deprep_terminal(void) { el_set(e, EL_PREP_TERM, 0); } @@ -2104,6 +1752,16 @@ rl_parse_and_bind(const char *line) return (argc ? 1 : 0); } +int +rl_variable_bind(const char *var, const char *value) +{ + /* + * The proper return value is undocument, but this is what the + * readline source seems to do. + */ + return ((el_set(e, EL_BIND, "", var, value) == -1) ? 1 : 0); +} + void rl_stuff_char(int c) { @@ -2119,7 +1777,7 @@ _rl_event_read_char(EditLine *el, char *cp) { int n, num_read = 0; - *cp = 0; + *cp = '\0'; while (rl_event_hook) { (*rl_event_hook)(); @@ -2164,3 +1822,142 @@ _rl_update_pos(void) rl_point = li->cursor - li->buffer; rl_end = li->lastchar - li->buffer; } + +void +rl_get_screen_size(int *rows, int *cols) +{ + if (rows) + el_get(e, EL_GETTC, "li", rows); + if (cols) + el_get(e, EL_GETTC, "co", cols); +} + +void +rl_set_screen_size(int rows, int cols) +{ + char buf[64]; + (void)snprintf(buf, sizeof(buf), "%d", rows); + el_set(e, EL_SETTC, "li", buf); + (void)snprintf(buf, sizeof(buf), "%d", cols); + el_set(e, EL_SETTC, "co", buf); +} + +char ** +rl_completion_matches(const char *str, rl_compentry_func_t *fun) +{ + size_t len, max, i, j, min; + char **list, *match, *a, *b; + + len = 1; + max = 10; + if ((list = malloc(max * sizeof(*list))) == NULL) + return NULL; + + while ((match = (*fun)(str, (int)(len - 1))) != NULL) { + if (len == max) { + char **nl; + max += 10; + if ((nl = realloc(list, max * sizeof(*nl))) == NULL) + goto out; + list = nl; + } + list[len++] = match; + } + if (len == 1) + goto out; + list[len] = NULL; + if (len == 2) { + if ((list[0] = strdup(list[1])) == NULL) + goto out; + return list; + } + qsort(&list[1], len - 1, sizeof(*list), + (int (*)(const void *, const void *)) strcmp); + min = SIZE_T_MAX; + for (i = 1, a = list[i]; i < len - 1; i++, a = b) { + b = list[i + 1]; + for (j = 0; a[j] && a[j] == b[j]; j++) + continue; + if (min > j) + min = j; + } + if (min == 0 && *str) { + if ((list[0] = strdup(str)) == NULL) + goto out; + } else { + if ((list[0] = malloc(min + 1)) == NULL) + goto out; + (void)memcpy(list[0], list[1], min); + list[0][min] = '\0'; + } + return list; + +out: + free(list); + return NULL; +} + +char * +rl_filename_completion_function (const char *text, int state) +{ + return fn_filename_completion_function(text, state); +} + +void +rl_forced_update_display(void) +{ + el_set(e, EL_REFRESH); +} + +int +_rl_abort_internal(void) +{ + el_beep(e); + longjmp(topbuf, 1); + /*NOTREACHED*/ +} + +int +_rl_qsort_string_compare(char **s1, char **s2) +{ + return strcoll(*s1, *s2); +} + +int +/*ARGSUSED*/ +rl_kill_text(int from, int to) +{ + return 0; +} + +Keymap +rl_make_bare_keymap(void) +{ + return NULL; +} + +Keymap +rl_get_keymap(void) +{ + return NULL; +} + +void +/*ARGSUSED*/ +rl_set_keymap(Keymap k) +{ +} + +int +/*ARGSUSED*/ +rl_generic_bind(int type, const char * keyseq, const char * data, Keymap k) +{ + return 0; +} + +int +/*ARGSUSED*/ +rl_bind_key_in_map(int key, Function *fun, Keymap k) +{ + return 0; +} diff --git a/cmd-line-utils/libedit/readline/readline.h b/cmd-line-utils/libedit/readline/readline.h index 6b1fa186512..c4806734bc5 100644 --- a/cmd-line-utils/libedit/readline/readline.h +++ b/cmd-line-utils/libedit/readline/readline.h @@ -1,4 +1,4 @@ -/* $NetBSD: readline.h,v 1.12 2004/09/08 18:15:37 christos Exp $ */ +/* $NetBSD: readline.h,v 1.24 2009/02/05 19:15:26 christos Exp $ */ /*- * Copyright (c) 1997 The NetBSD Foundation, Inc. @@ -15,13 +15,6 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the NetBSD - * Foundation, Inc. and its contributors. - * 4. Neither the name of The NetBSD Foundation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED @@ -45,14 +38,14 @@ /* typedefs */ typedef int Function(const char *, int); typedef void VFunction(void); +typedef void VCPFunction(char *); typedef char *CPFunction(const char *, int); typedef char **CPPFunction(const char *, int, int); - -typedef void *histdata_t; +typedef char *rl_compentry_func_t(const char *, int); typedef struct _hist_entry { const char *line; - histdata_t *data; + const char *data; } HIST_ENTRY; typedef struct _keymap_entry { @@ -73,7 +66,7 @@ typedef KEYMAP_ENTRY *Keymap; #ifndef CTRL #include -#if defined(__GLIBC__) || defined(__MWERKS__) +#if !defined(__sun__) && !defined(__hpux__) #include #endif #ifndef CTRL @@ -102,8 +95,9 @@ extern int max_input_history; extern char *rl_basic_word_break_characters; extern char *rl_completer_word_break_characters; extern char *rl_completer_quote_characters; -extern CPFunction *rl_completion_entry_function; +extern Function *rl_completion_entry_function; extern CPPFunction *rl_attempted_completion_function; +extern int rl_attempted_completion_over; extern int rl_completion_type; extern int rl_completion_query_items; extern char *rl_special_prefixes; @@ -122,11 +116,13 @@ extern KEYMAP_ENTRY_ARRAY emacs_standard_keymap, emacs_ctlx_keymap; extern int rl_filename_completion_desired; extern int rl_ignore_completion_duplicates; -extern Function *rl_getc_function; +extern int (*rl_getc_function)(FILE *); extern VFunction *rl_redisplay_function; extern VFunction *rl_completion_display_matches_hook; extern VFunction *rl_prep_term_function; extern VFunction *rl_deprep_term_function; +extern int readline_echoing_p; +extern int _rl_print_completions_horizontally; /* supported functions */ char *readline(const char *); @@ -141,6 +137,7 @@ int history_is_stifled(void); int where_history(void); HIST_ENTRY *current_history(void); HIST_ENTRY *history_get(int); +HIST_ENTRY *remove_history(int); int history_total_bytes(void); int history_set_pos(int); HIST_ENTRY *previous_history(void); @@ -168,7 +165,7 @@ void rl_reset_terminal(const char *); int rl_bind_key(int, int (*)(int, int)); int rl_newline(int, int); void rl_callback_read_char(void); -void rl_callback_handler_install(const char *, VFunction *); +void rl_callback_handler_install(const char *, VCPFunction *); void rl_callback_handler_remove(void); void rl_redisplay(void); int rl_get_previous_history(int, int); @@ -176,13 +173,24 @@ void rl_prep_terminal(int); void rl_deprep_terminal(void); int rl_read_init_file(const char *); int rl_parse_and_bind(const char *); +int rl_variable_bind(const char *, const char *); void rl_stuff_char(int); int rl_add_defun(const char *, Function *, int); +void rl_get_screen_size(int *, int *); +void rl_set_screen_size(int, int); +char *rl_filename_completion_function (const char *, int); +int _rl_abort_internal(void); +int _rl_qsort_string_compare(char **, char **); +char **rl_completion_matches(const char *, rl_compentry_func_t *); +void rl_forced_update_display(void); +int rl_set_prompt(const char *); /* * The following are not implemented */ +int rl_kill_text(int, int); Keymap rl_get_keymap(void); +void rl_set_keymap(Keymap); Keymap rl_make_bare_keymap(void); int rl_generic_bind(int, const char *, const char *, Keymap); int rl_bind_key_in_map(int, Function *, Keymap); diff --git a/cmd-line-utils/libedit/refresh.c b/cmd-line-utils/libedit/refresh.c index 46aca15ef08..5edd1fe78fc 100644 --- a/cmd-line-utils/libedit/refresh.c +++ b/cmd-line-utils/libedit/refresh.c @@ -1,4 +1,4 @@ -/* $NetBSD: refresh.c,v 1.26 2003/08/07 16:44:33 agc Exp $ */ +/* $NetBSD: refresh.c,v 1.28 2008/09/10 15:45:37 christos Exp $ */ /*- * Copyright (c) 1992, 1993 @@ -32,7 +32,13 @@ * SUCH DAMAGE. */ -#include +#include "config.h" +#if !defined(lint) && !defined(SCCSID) +#if 0 +static char sccsid[] = "@(#)refresh.c 8.1 (Berkeley) 6/4/93"; +#else +#endif +#endif /* not lint && not SCCSID */ /* * refresh.c: Lower level screen refreshing functions @@ -49,6 +55,7 @@ private void re_update_line(EditLine *, char *, char *, int); private void re_insert (EditLine *, char *, int, int, char *, int); private void re_delete(EditLine *, char *, int, int, int); private void re_fastputc(EditLine *, int); +private void re_clear_eol(EditLine *, int, int, int); private void re__strncopy(char *, char *, size_t); private void re__copy_and_pad(char *, const char *, size_t); @@ -315,9 +322,9 @@ re_goto_bottom(EditLine *el) { term_move_to_line(el, el->el_refresh.r_oldcv); - term__putc('\n'); + term__putc(el, '\n'); re_clear_display(el); - term__flush(); + term__flush(el); } @@ -340,7 +347,7 @@ re_insert(EditLine *el __attribute__((__unused__)), ELRE_DEBUG(1, (__F, "re_insert() starting: %d at %d max %d, d == \"%s\"\n", num, dat, dlen, d)); - ELRE_DEBUG(1, (__F, "s == \"%s\"n", s)); + ELRE_DEBUG(1, (__F, "s == \"%s\"\n", s)); /* open up the space for num chars */ if (num > 0) { @@ -353,7 +360,7 @@ re_insert(EditLine *el __attribute__((__unused__)), ELRE_DEBUG(1, (__F, "re_insert() after insert: %d at %d max %d, d == \"%s\"\n", num, dat, dlen, d)); - ELRE_DEBUG(1, (__F, "s == \"%s\"n", s)); + ELRE_DEBUG(1, (__F, "s == \"%s\"\n", s)); /* copy the characters */ for (a = d + dat; (a < d + dlen) && (num > 0); num--) @@ -362,7 +369,7 @@ re_insert(EditLine *el __attribute__((__unused__)), ELRE_DEBUG(1, (__F, "re_insert() after copy: %d at %d max %d, %s == \"%s\"\n", num, dat, dlen, d, s)); - ELRE_DEBUG(1, (__F, "s == \"%s\"n", s)); + ELRE_DEBUG(1, (__F, "s == \"%s\"\n", s)); } @@ -411,6 +418,32 @@ re__strncopy(char *a, char *b, size_t n) *a++ = *b++; } +/* re_clear_eol(): + * Find the number of characters we need to clear till the end of line + * in order to make sure that we have cleared the previous contents of + * the line. fx and sx is the number of characters inserted or deleted + * int the first or second diff, diff is the difference between the + * number of characters between the new and old line. + */ +private void +re_clear_eol(EditLine *el, int fx, int sx, int diff) +{ + + ELRE_DEBUG(1, (__F, "re_clear_eol sx %d, fx %d, diff %d\n", + sx, fx, diff)); + + if (fx < 0) + fx = -fx; + if (sx < 0) + sx = -sx; + if (fx > diff) + diff = fx; + if (sx > diff) + diff = sx; + + ELRE_DEBUG(1, (__F, "re_clear_eol %d\n", diff)); + term_clear_EOL(el, diff); +} /***************************************************************** re_update_line() is based on finding the middle difference of each line @@ -626,7 +659,7 @@ re_update_line(EditLine *el, char *old, char *new, int i) fx = (nsb - nfd) - (osb - ofd); sx = (nls - nse) - (ols - ose); - ELRE_DEBUG(1, (__F, "\n")); + ELRE_DEBUG(1, (__F, "fx %d, sx %d\n", fx, sx)); ELRE_DEBUG(1, (__F, "ofd %d, osb %d, ose %d, ols %d, oe %d\n", ofd - old, osb - old, ose - old, ols - old, oe - old)); ELRE_DEBUG(1, (__F, "nfd %d, nsb %d, nse %d, nls %d, ne %d\n", @@ -775,9 +808,7 @@ re_update_line(EditLine *el, char *old, char *new, int i) * write (nsb-nfd) chars of new starting at nfd */ term_overwrite(el, nfd, (nsb - nfd)); - ELRE_DEBUG(1, (__F, - "cleareol %d\n", (oe - old) - (ne - new))); - term_clear_EOL(el, (oe - old) - (ne - new)); + re_clear_eol(el, fx, sx, (oe - old) - (ne - new)); /* * Done */ @@ -818,10 +849,7 @@ re_update_line(EditLine *el, char *old, char *new, int i) ELRE_DEBUG(1, (__F, "but with nothing left to save\r\n")); term_overwrite(el, nse, (nls - nse)); - ELRE_DEBUG(1, (__F, - "cleareol %d\n", (oe - old) - (ne - new))); - if ((oe - old) - (ne - new) != 0) - term_clear_EOL(el, (oe - old) - (ne - new)); + re_clear_eol(el, fx, sx, (oe - old) - (ne - new)); } } /* @@ -982,7 +1010,7 @@ re_refresh_cursor(EditLine *el) /* now go there */ term_move_to_line(el, v); term_move_to_char(el, h); - term__flush(); + term__flush(el); } @@ -993,7 +1021,7 @@ private void re_fastputc(EditLine *el, int c) { - term__putc(c); + term__putc(el, c); el->el_display[el->el_cursor.v][el->el_cursor.h++] = c; if (el->el_cursor.h >= el->el_term.t_size.h) { /* if we must overflow */ @@ -1020,12 +1048,12 @@ re_fastputc(EditLine *el, int c) } if (EL_HAS_AUTO_MARGINS) { if (EL_HAS_MAGIC_MARGINS) { - term__putc(' '); - term__putc('\b'); + term__putc(el, ' '); + term__putc(el, '\b'); } } else { - term__putc('\r'); - term__putc('\n'); + term__putc(el, '\r'); + term__putc(el, '\n'); } } } @@ -1065,7 +1093,7 @@ re_fastaddc(EditLine *el) re_fastputc(el, (int)(((((unsigned int)c) >> 3) & 7) + '0')); re_fastputc(el, (c & 7) + '0'); } - term__flush(); + term__flush(el); } @@ -1104,7 +1132,7 @@ re_clear_lines(EditLine *el) } else { term_move_to_line(el, el->el_refresh.r_oldcv); /* go to last line */ - term__putc('\r'); /* go to BOL */ - term__putc('\n'); /* go to new line */ + term__putc(el, '\r'); /* go to BOL */ + term__putc(el, '\n'); /* go to new line */ } } diff --git a/cmd-line-utils/libedit/search.c b/cmd-line-utils/libedit/search.c index 850c5f27140..df50c7e7370 100644 --- a/cmd-line-utils/libedit/search.c +++ b/cmd-line-utils/libedit/search.c @@ -32,12 +32,17 @@ * SUCH DAMAGE. */ -#include +#include "config.h" +#if !defined(lint) && !defined(SCCSID) +#if 0 +static char sccsid[] = "@(#)search.c 8.1 (Berkeley) 6/4/93"; +#else +#endif +#endif /* not lint && not SCCSID */ /* * search.c: History and character search functions */ -#include #include #if defined(REGEX) #include diff --git a/cmd-line-utils/libedit/sig.c b/cmd-line-utils/libedit/sig.c index 8e70933d606..5307ee6ec60 100644 --- a/cmd-line-utils/libedit/sig.c +++ b/cmd-line-utils/libedit/sig.c @@ -1,4 +1,4 @@ -/* $NetBSD: sig.c,v 1.11 2003/08/07 16:44:33 agc Exp $ */ +/* $NetBSD: sig.c,v 1.12 2008/09/10 15:45:37 christos Exp $ */ /*- * Copyright (c) 1992, 1993 @@ -32,7 +32,13 @@ * SUCH DAMAGE. */ -#include +#include "config.h" +#if !defined(lint) && !defined(SCCSID) +#if 0 +static char sccsid[] = "@(#)sig.c 8.1 (Berkeley) 6/4/93"; +#else +#endif +#endif /* not lint && not SCCSID */ /* * sig.c: Signal handling stuff. @@ -51,15 +57,15 @@ private const int sighdl[] = { - 1 }; -private void sig_handler(int); +private void el_sig_handler(int); -/* sig_handler(): +/* el_sig_handler(): * This is the handler called for all signals * XXX: we cannot pass any data so we just store the old editline * state in a private variable */ private void -sig_handler(int signo) +el_sig_handler(int signo) { int i; sigset_t nset, oset; @@ -73,7 +79,7 @@ sig_handler(int signo) tty_rawmode(sel); if (ed_redisplay(sel, 0) == CC_REFRESH) re_refresh(sel); - term__flush(); + term__flush(sel); break; case SIGWINCH: @@ -154,7 +160,7 @@ sig_set(EditLine *el) for (i = 0; sighdl[i] != -1; i++) { el_signalhandler_t s; /* This could happen if we get interrupted */ - if ((s = signal(sighdl[i], sig_handler)) != sig_handler) + if ((s = signal(sighdl[i], el_sig_handler)) != el_sig_handler) el->el_signal[i] = s; } sel = el; diff --git a/cmd-line-utils/libedit/sig.h b/cmd-line-utils/libedit/sig.h index 0bf1fc37e39..2bd3c516d46 100644 --- a/cmd-line-utils/libedit/sig.h +++ b/cmd-line-utils/libedit/sig.h @@ -1,4 +1,4 @@ -/* $NetBSD: sig.h,v 1.5 2003/08/07 16:44:33 agc Exp $ */ +/* $NetBSD: sig.h,v 1.6 2008/07/12 15:27:14 christos Exp $ */ /*- * Copyright (c) 1992, 1993 @@ -51,7 +51,6 @@ #define ALLSIGS \ _DO(SIGINT) \ _DO(SIGTSTP) \ - _DO(SIGSTOP) \ _DO(SIGQUIT) \ _DO(SIGHUP) \ _DO(SIGTERM) \ diff --git a/cmd-line-utils/libedit/strlcpy.c b/cmd-line-utils/libedit/strlcpy.c deleted file mode 100644 index e38d6cf1c4b..00000000000 --- a/cmd-line-utils/libedit/strlcpy.c +++ /dev/null @@ -1,73 +0,0 @@ -/* $NetBSD: strlcpy.c,v 1.14 2003/10/27 00:12:42 lukem Exp $ */ -/* $OpenBSD: strlcpy.c,v 1.7 2003/04/12 21:56:39 millert Exp $ */ - -/* - * Copyright (c) 1998 Todd C. Miller - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND TODD C. MILLER DISCLAIMS ALL - * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL TODD C. MILLER BE LIABLE - * FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION - * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN - * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include - -#include -#include -#include - -#ifdef _LIBC -# ifdef __weak_alias -__weak_alias(strlcpy, _strlcpy) -# endif -#endif - -#if !HAVE_STRLCPY -/* - * Copy src to string dst of size siz. At most siz-1 characters - * will be copied. Always NUL terminates (unless siz == 0). - * Returns strlen(src); if retval >= siz, truncation occurred. - */ -size_t -#ifdef _LIBC -_strlcpy(dst, src, siz) -#else -strlcpy(dst, src, siz) -#endif - char *dst; - const char *src; - size_t siz; -{ - char *d = dst; - const char *s = src; - size_t n = siz; - - _DIAGASSERT(dst != NULL); - _DIAGASSERT(src != NULL); - - /* Copy as many bytes as will fit */ - if (n != 0 && --n != 0) { - do { - if ((*d++ = *s++) == 0) - break; - } while (--n != 0); - } - - /* Not enough room in dst, add NUL and traverse rest of src */ - if (n == 0) { - if (siz != 0) - *d = '\0'; /* NUL-terminate dst */ - while (*s++) - ; - } - - return(s - src - 1); /* count does not include NUL */ -} -#endif diff --git a/cmd-line-utils/libedit/strlcpy.h b/cmd-line-utils/libedit/strlcpy.h deleted file mode 100644 index e4d3a7ffa3f..00000000000 --- a/cmd-line-utils/libedit/strlcpy.h +++ /dev/null @@ -1,2 +0,0 @@ -size_t strlcpy(char *dst, const char *src, size_t size); -size_t strlcat(char *dst, const char *src, size_t size); diff --git a/cmd-line-utils/libedit/sys.h b/cmd-line-utils/libedit/sys.h index c8a29dbfb05..a0369affbb0 100644 --- a/cmd-line-utils/libedit/sys.h +++ b/cmd-line-utils/libedit/sys.h @@ -48,14 +48,14 @@ # define __attribute__(A) #endif -#ifndef __P -# define __P(x) x -#endif - #ifndef _DIAGASSERT # define _DIAGASSERT(x) #endif +#ifndef SIZE_T_MAX +# define SIZE_T_MAX UINT_MAX +#endif + #ifndef __BEGIN_DECLS # ifdef __cplusplus # define __BEGIN_DECLS extern "C" { @@ -113,6 +113,25 @@ char *fgetln(FILE *fp, size_t *len); #define REGEX /* Use POSIX.2 regular expression functions */ #undef REGEXP /* Use UNIX V8 regular expression functions */ +#ifdef __SunOS +extern int tgetent(char *, const char *); +extern int tgetflag(char *); +extern int tgetnum(char *); +extern int tputs(const char *, int, int (*)(int)); +extern char* tgoto(const char*, int, int); +extern char* tgetstr(char*, char**); +#endif + +/* XXXMYSQL: Bug#10218 Command line recall rolls into segfault */ +#if !HAVE_DECL_TGOTO +/* + 'tgoto' is not declared in the system header files, this causes + problems on 64-bit systems. The function returns a 64 bit pointer + but caller see it as "int" and it's thus truncated to 32-bit +*/ +extern char* tgoto(const char*, int, int); +#endif + #ifdef notdef # undef REGEX # undef REGEXP diff --git a/cmd-line-utils/libedit/term.c b/cmd-line-utils/libedit/term.c index b516d6753c3..7a9d0250114 100644 --- a/cmd-line-utils/libedit/term.c +++ b/cmd-line-utils/libedit/term.c @@ -1,4 +1,4 @@ -/* $NetBSD: term.c,v 1.40 2004/05/22 23:21:28 christos Exp $ */ +/* $NetBSD: term.c,v 1.48 2009/02/06 20:08:13 sketch Exp $ */ /*- * Copyright (c) 1992, 1993 @@ -32,7 +32,13 @@ * SUCH DAMAGE. */ -#include +#include "config.h" +#if !defined(lint) && !defined(SCCSID) +#if 0 +static char sccsid[] = "@(#)term.c 8.2 (Berkeley) 4/30/95"; +#else +#endif +#endif /* not lint && not SCCSID */ /* * term.c: Editor/termcap-curses interface @@ -44,21 +50,26 @@ #include #include #include - +#ifdef HAVE_TERMCAP_H +#include +#endif #ifdef HAVE_CURSES_H -# include -#elif HAVE_NCURSES_H -# include +#include +#endif +#ifdef HAVE_NCURSES_H +#include #endif - /* Solaris's term.h does horrid things. */ -#if (defined(HAVE_TERM_H) && !defined(_SUNOS)) -# include +#if (defined(HAVE_TERM_H) && !defined(__SunOS)) +#include #endif - #include #include +#ifdef _REENTRANT +#include +#endif + #include "el.h" /* @@ -263,9 +274,13 @@ private int term_alloc_display(EditLine *); private void term_alloc(EditLine *, const struct termcapstr *, const char *); private void term_init_arrow(EditLine *); private void term_reset_arrow(EditLine *); +private int term_putc(int); +private void term_tputs(EditLine *, const char *, int); - -private FILE *term_outfile = NULL; /* XXX: How do we fix that? */ +#ifdef _REENTRANT +private pthread_mutex_t term_mutex = PTHREAD_MUTEX_INITIALIZER; +#endif +private FILE *term_outfile = NULL; /* term_setflags(): @@ -313,7 +328,6 @@ term_setflags(EditLine *el) #endif /* DEBUG_SCREEN */ } - /* term_init(): * Initialize the terminal stuff */ @@ -339,7 +353,6 @@ term_init(EditLine *el) if (el->el_term.t_val == NULL) return (-1); (void) memset(el->el_term.t_val, 0, T_val * sizeof(int)); - term_outfile = el->el_outfile; (void) term_set(el, NULL); term_init_arrow(el); return (0); @@ -390,7 +403,8 @@ term_alloc(EditLine *el, const struct termcapstr *t, const char *cap) * New string is shorter; no need to allocate space */ if (clen <= tlen) { - (void) strcpy(*str, cap); /* XXX strcpy is safe */ + if (*str) + (void) strcpy(*str, cap); /* XXX strcpy is safe */ return; } /* @@ -464,8 +478,12 @@ term_alloc_display(EditLine *el) return (-1); for (i = 0; i < c->v; i++) { b[i] = (char *) el_malloc((size_t) (sizeof(char) * (c->h + 1))); - if (b[i] == NULL) + if (b[i] == NULL) { + while (--i >= 0) + el_free((ptr_t) b[i]); + el_free((ptr_t) b); return (-1); + } } b[c->v] = NULL; el->el_display = b; @@ -475,8 +493,12 @@ term_alloc_display(EditLine *el) return (-1); for (i = 0; i < c->v; i++) { b[i] = (char *) el_malloc((size_t) (sizeof(char) * (c->h + 1))); - if (b[i] == NULL) + if (b[i] == NULL) { + while (--i >= 0) + el_free((ptr_t) b[i]); + el_free((ptr_t) b); return (-1); + } } b[c->v] = NULL; el->el_vdisplay = b; @@ -542,12 +564,12 @@ term_move_to_line(EditLine *el, int where) del--; } else { if ((del > 1) && GoodStr(T_DO)) { - (void) tputs(tgoto(Str(T_DO), del, del), - del, term__putc); + term_tputs(el, tgoto(Str(T_DO), del, + del), del); del = 0; } else { for (; del > 0; del--) - term__putc('\n'); + term__putc(el, '\n'); /* because the \n will become \r\n */ el->el_cursor.h = 0; } @@ -555,12 +577,11 @@ term_move_to_line(EditLine *el, int where) } } else { /* del < 0 */ if (GoodStr(T_UP) && (-del > 1 || !GoodStr(T_up))) - (void) tputs(tgoto(Str(T_UP), -del, -del), -del, - term__putc); + term_tputs(el, tgoto(Str(T_UP), -del, -del), -del); else { if (GoodStr(T_up)) for (; del < 0; del++) - (void) tputs(Str(T_up), 1, term__putc); + term_tputs(el, Str(T_up), 1); } } el->el_cursor.v = where;/* now where is here */ @@ -587,7 +608,7 @@ mc_again: return; } if (!where) { /* if where is first column */ - term__putc('\r'); /* do a CR */ + term__putc(el, '\r'); /* do a CR */ el->el_cursor.h = 0; return; } @@ -595,12 +616,11 @@ mc_again: if ((del < -4 || del > 4) && GoodStr(T_ch)) /* go there directly */ - (void) tputs(tgoto(Str(T_ch), where, where), where, term__putc); + term_tputs(el, tgoto(Str(T_ch), where, where), where); else { if (del > 0) { /* moving forward */ if ((del > 4) && GoodStr(T_RI)) - (void) tputs(tgoto(Str(T_RI), del, del), - del, term__putc); + term_tputs(el, tgoto(Str(T_RI), del, del), del); else { /* if I can do tabs, use them */ if (EL_CAN_TAB) { @@ -611,7 +631,7 @@ mc_again: (el->el_cursor.h & 0370); i < (where & 0370); i += 8) - term__putc('\t'); + term__putc(el, '\t'); /* then tab over */ el->el_cursor.h = where & 0370; } @@ -631,8 +651,8 @@ mc_again: } } else { /* del < 0 := moving backward */ if ((-del > 4) && GoodStr(T_LE)) - (void) tputs(tgoto(Str(T_LE), -del, -del), - -del, term__putc); + term_tputs(el, tgoto(Str(T_LE), -del, -del), + -del); else { /* can't go directly there */ /* * if the "cost" is greater than the "cost" @@ -643,12 +663,12 @@ mc_again: (((unsigned int) where >> 3) + (where & 07))) : (-del > where)) { - term__putc('\r'); /* do a CR */ + term__putc(el, '\r'); /* do a CR */ el->el_cursor.h = 0; goto mc_again; /* and try again */ } for (i = 0; i < -del; i++) - term__putc('\b'); + term__putc(el, '\b'); } } } @@ -673,7 +693,7 @@ term_overwrite(EditLine *el, const char *cp, int n) return; } do { - term__putc(*cp++); + term__putc(el, *cp++); el->el_cursor.h++; } while (--n); @@ -689,7 +709,7 @@ term_overwrite(EditLine *el, const char *cp, int n) != '\0') term_overwrite(el, &c, 1); else - term__putc(' '); + term__putc(el, ' '); el->el_cursor.h = 1; } } else /* no wrap, but cursor stays on screen */ @@ -723,19 +743,18 @@ term_deletechars(EditLine *el, int num) if (GoodStr(T_DC)) /* if I have multiple delete */ if ((num > 1) || !GoodStr(T_dc)) { /* if dc would be more * expen. */ - (void) tputs(tgoto(Str(T_DC), num, num), - num, term__putc); + term_tputs(el, tgoto(Str(T_DC), num, num), num); return; } if (GoodStr(T_dm)) /* if I have delete mode */ - (void) tputs(Str(T_dm), 1, term__putc); + term_tputs(el, Str(T_dm), 1); if (GoodStr(T_dc)) /* else do one at a time */ while (num--) - (void) tputs(Str(T_dc), 1, term__putc); + term_tputs(el, Str(T_dc), 1); if (GoodStr(T_ed)) /* if I have delete mode */ - (void) tputs(Str(T_ed), 1, term__putc); + term_tputs(el, Str(T_ed), 1); } @@ -764,37 +783,35 @@ term_insertwrite(EditLine *el, char *cp, int num) if (GoodStr(T_IC)) /* if I have multiple insert */ if ((num > 1) || !GoodStr(T_ic)) { /* if ic would be more expensive */ - (void) tputs(tgoto(Str(T_IC), num, num), - num, term__putc); + term_tputs(el, tgoto(Str(T_IC), num, num), num); term_overwrite(el, cp, num); /* this updates el_cursor.h */ return; } if (GoodStr(T_im) && GoodStr(T_ei)) { /* if I have insert mode */ - (void) tputs(Str(T_im), 1, term__putc); + term_tputs(el, Str(T_im), 1); el->el_cursor.h += num; do - term__putc(*cp++); + term__putc(el, *cp++); while (--num); if (GoodStr(T_ip)) /* have to make num chars insert */ - (void) tputs(Str(T_ip), 1, term__putc); + term_tputs(el, Str(T_ip), 1); - (void) tputs(Str(T_ei), 1, term__putc); + term_tputs(el, Str(T_ei), 1); return; } do { if (GoodStr(T_ic)) /* have to make num chars insert */ - (void) tputs(Str(T_ic), 1, term__putc); - /* insert a char */ + term_tputs(el, Str(T_ic), 1); - term__putc(*cp++); + term__putc(el, *cp++); el->el_cursor.h++; if (GoodStr(T_ip)) /* have to make num chars insert */ - (void) tputs(Str(T_ip), 1, term__putc); + term_tputs(el, Str(T_ip), 1); /* pad the inserted char */ } while (--num); @@ -810,10 +827,10 @@ term_clear_EOL(EditLine *el, int num) int i; if (EL_CAN_CEOL && GoodStr(T_ce)) - (void) tputs(Str(T_ce), 1, term__putc); + term_tputs(el, Str(T_ce), 1); else { for (i = 0; i < num; i++) - term__putc(' '); + term__putc(el, ' '); el->el_cursor.h += num; /* have written num spaces */ } } @@ -828,14 +845,14 @@ term_clear_screen(EditLine *el) if (GoodStr(T_cl)) /* send the clear screen code */ - (void) tputs(Str(T_cl), Val(T_li), term__putc); + term_tputs(el, Str(T_cl), Val(T_li)); else if (GoodStr(T_ho) && GoodStr(T_cd)) { - (void) tputs(Str(T_ho), Val(T_li), term__putc); /* home */ + term_tputs(el, Str(T_ho), Val(T_li)); /* home */ /* clear to bottom of screen */ - (void) tputs(Str(T_cd), Val(T_li), term__putc); + term_tputs(el, Str(T_cd), Val(T_li)); } else { - term__putc('\r'); - term__putc('\n'); + term__putc(el, '\r'); + term__putc(el, '\n'); } } @@ -848,9 +865,9 @@ term_beep(EditLine *el) { if (GoodStr(T_bl)) /* what termcap says we should use */ - (void) tputs(Str(T_bl), 1, term__putc); + term_tputs(el, Str(T_bl), 1); else - term__putc('\007'); /* an ASCII bell; ^G */ + term__putc(el, '\007'); /* an ASCII bell; ^G */ } @@ -862,9 +879,9 @@ protected void term_clear_to_bottom(EditLine *el) { if (GoodStr(T_cd)) - (void) tputs(Str(T_cd), Val(T_li), term__putc); + term_tputs(el, Str(T_cd), Val(T_li)); else if (GoodStr(T_ce)) - (void) tputs(Str(T_ce), Val(T_li), term__putc); + term_tputs(el, Str(T_ce), Val(T_li)); } #endif @@ -936,7 +953,7 @@ term_set(EditLine *el, const char *term) Val(T_co) = tgetnum("co"); Val(T_li) = tgetnum("li"); for (t = tstr; t->name != NULL; t++) { - /* XXX: some systems tgetstr needs non const */ + /* XXX: some systems' tgetstr needs non const */ term_alloc(el, t, tgetstr(strchr(t->name, *t->name), &area)); } @@ -1220,26 +1237,62 @@ term_bind_arrow(EditLine *el) } } +/* term_putc(): + * Add a character + */ +private int +term_putc(int c) +{ + + if (term_outfile == NULL) + return -1; + return fputc(c, term_outfile); +} + +private void +term_tputs(EditLine *el, const char *cap, int affcnt) +{ +#ifdef _REENTRANT + pthread_mutex_lock(&term_mutex); +#endif + term_outfile = el->el_outfile; + (void)tputs(cap, affcnt, term_putc); +#ifdef _REENTRANT + pthread_mutex_unlock(&term_mutex); +#endif +} /* term__putc(): * Add a character */ protected int -term__putc(int c) +term__putc(EditLine *el, int c) { - return (fputc(c, term_outfile)); + return fputc(c, el->el_outfile); } - /* term__flush(): * Flush output */ protected void -term__flush(void) +term__flush(EditLine *el) { - (void) fflush(term_outfile); + (void) fflush(el->el_outfile); +} + +/* term_writec(): + * Write the given character out, in a human readable form + */ +protected void +term_writec(EditLine *el, int c) +{ + char buf[8]; + int cnt = key__decode_char(buf, sizeof(buf), 0, c); + buf[cnt] = '\0'; + term_overwrite(el, buf, cnt); + term__flush(el); } @@ -1269,11 +1322,17 @@ term_telltc(EditLine *el, int argc __attribute__((__unused__)), (void) fprintf(el->el_outfile, "\tIt %s magic margins\n", EL_HAS_MAGIC_MARGINS ? "has" : "does not have"); - for (t = tstr, ts = el->el_term.t_str; t->name != NULL; t++, ts++) + for (t = tstr, ts = el->el_term.t_str; t->name != NULL; t++, ts++) { + const char *ub; + if (*ts && **ts) { + (void) key__decode_str(*ts, upbuf, sizeof(upbuf), ""); + ub = upbuf; + } else { + ub = "(empty)"; + } (void) fprintf(el->el_outfile, "\t%25s (%s) == %s\n", - t->long_name, - t->name, *ts && **ts ? - key__decode_str(*ts, upbuf, "") : "(empty)"); + t->long_name, t->name, ub); + } (void) fputc('\n', el->el_outfile); return (0); } @@ -1292,7 +1351,7 @@ term_settc(EditLine *el, int argc __attribute__((__unused__)), const char *what, *how; if (argv == NULL || argv[1] == NULL || argv[2] == NULL) - return (-1); + return -1; what = argv[1]; how = argv[2]; @@ -1307,7 +1366,7 @@ term_settc(EditLine *el, int argc __attribute__((__unused__)), if (ts->name != NULL) { term_alloc(el, ts, how); term_setflags(el); - return (0); + return 0; } /* * Do the numeric ones second @@ -1316,46 +1375,100 @@ term_settc(EditLine *el, int argc __attribute__((__unused__)), if (strcmp(tv->name, what) == 0) break; - if (tv->name != NULL) { - if (tv == &tval[T_pt] || tv == &tval[T_km] || - tv == &tval[T_am] || tv == &tval[T_xn]) { - if (strcmp(how, "yes") == 0) - el->el_term.t_val[tv - tval] = 1; - else if (strcmp(how, "no") == 0) - el->el_term.t_val[tv - tval] = 0; - else { - (void) fprintf(el->el_errfile, - "settc: Bad value `%s'.\n", how); - return (-1); - } - term_setflags(el); - if (term_change_size(el, Val(T_li), Val(T_co)) == -1) - return (-1); - return (0); - } else { - long i; - char *ep; + if (tv->name != NULL) + return -1; - i = strtol(how, &ep, 10); - if (*ep != '\0') { - (void) fprintf(el->el_errfile, - "settc: Bad value `%s'.\n", how); - return (-1); - } - el->el_term.t_val[tv - tval] = (int) i; - el->el_term.t_size.v = Val(T_co); - el->el_term.t_size.h = Val(T_li); - if (tv == &tval[T_co] || tv == &tval[T_li]) - if (term_change_size(el, Val(T_li), Val(T_co)) - == -1) - return (-1); - return (0); + if (tv == &tval[T_pt] || tv == &tval[T_km] || + tv == &tval[T_am] || tv == &tval[T_xn]) { + if (strcmp(how, "yes") == 0) + el->el_term.t_val[tv - tval] = 1; + else if (strcmp(how, "no") == 0) + el->el_term.t_val[tv - tval] = 0; + else { + (void) fprintf(el->el_errfile, + "%s: Bad value `%s'.\n", argv[0], how); + return -1; } + term_setflags(el); + if (term_change_size(el, Val(T_li), Val(T_co)) == -1) + return -1; + return 0; + } else { + long i; + char *ep; + + i = strtol(how, &ep, 10); + if (*ep != '\0') { + (void) fprintf(el->el_errfile, + "%s: Bad value `%s'.\n", argv[0], how); + return -1; + } + el->el_term.t_val[tv - tval] = (int) i; + el->el_term.t_size.v = Val(T_co); + el->el_term.t_size.h = Val(T_li); + if (tv == &tval[T_co] || tv == &tval[T_li]) + if (term_change_size(el, Val(T_li), Val(T_co)) + == -1) + return -1; + return 0; } - return (-1); } +/* term_gettc(): + * Get the current terminal characteristics + */ +protected int +/*ARGSUSED*/ +term_gettc(EditLine *el, int argc __attribute__((__unused__)), char **argv) +{ + const struct termcapstr *ts; + const struct termcapval *tv; + char *what; + void *how; + + if (argv == NULL || argv[1] == NULL || argv[2] == NULL) + return (-1); + + what = argv[1]; + how = argv[2]; + + /* + * Do the strings first + */ + for (ts = tstr; ts->name != NULL; ts++) + if (strcmp(ts->name, what) == 0) + break; + + if (ts->name != NULL) { + *(char **)how = el->el_term.t_str[ts - tstr]; + return 0; + } + /* + * Do the numeric ones second + */ + for (tv = tval; tv->name != NULL; tv++) + if (strcmp(tv->name, what) == 0) + break; + + if (tv->name == NULL) + return -1; + + if (tv == &tval[T_pt] || tv == &tval[T_km] || + tv == &tval[T_am] || tv == &tval[T_xn]) { + static char yes[] = "yes"; + static char no[] = "no"; + if (el->el_term.t_val[tv - tval]) + *(char **)how = yes; + else + *(char **)how = no; + return 0; + } else { + *(int *)how = el->el_term.t_val[tv - tval]; + return 0; + } +} + /* term_echotc(): * Print the termcap string out with variable substitution */ @@ -1441,7 +1554,7 @@ term_echotc(EditLine *el, int argc __attribute__((__unused__)), break; } if (t->name == NULL) { - /* XXX: some systems tgetstr needs non const */ + /* XXX: some systems' tgetstr needs non const */ scap = tgetstr(strchr(*argv, **argv), &area); } if (!scap || scap[0] == '\0') { @@ -1494,7 +1607,7 @@ term_echotc(EditLine *el, int argc __attribute__((__unused__)), *argv); return (-1); } - (void) tputs(scap, 1, term__putc); + term_tputs(el, scap, 1); break; case 1: argv++; @@ -1522,7 +1635,7 @@ term_echotc(EditLine *el, int argc __attribute__((__unused__)), *argv); return (-1); } - (void) tputs(tgoto(scap, arg_cols, arg_rows), 1, term__putc); + term_tputs(el, tgoto(scap, arg_cols, arg_rows), 1); break; default: /* This is wrong, but I will ignore it... */ @@ -1578,8 +1691,7 @@ term_echotc(EditLine *el, int argc __attribute__((__unused__)), *argv); return (-1); } - (void) tputs(tgoto(scap, arg_cols, arg_rows), arg_rows, - term__putc); + term_tputs(el, tgoto(scap, arg_cols, arg_rows), arg_rows); break; } return (0); diff --git a/cmd-line-utils/libedit/tokenizer.c b/cmd-line-utils/libedit/tokenizer.c index 561b41740f8..5161cdd0a22 100644 --- a/cmd-line-utils/libedit/tokenizer.c +++ b/cmd-line-utils/libedit/tokenizer.c @@ -32,7 +32,13 @@ * SUCH DAMAGE. */ -#include +#include "config.h" +#if !defined(lint) && !defined(SCCSID) +#if 0 +static char sccsid[] = "@(#)tokenizer.c 8.1 (Berkeley) 6/4/93"; +#else +#endif +#endif /* not lint && not SCCSID */ /* * tokenize.c: Bourne shell like tokenizer diff --git a/cmd-line-utils/libedit/tokenizer.h b/cmd-line-utils/libedit/tokenizer.h deleted file mode 100644 index 7cc7a3346e4..00000000000 --- a/cmd-line-utils/libedit/tokenizer.h +++ /dev/null @@ -1,54 +0,0 @@ -/* $NetBSD: tokenizer.h,v 1.5 2002/03/18 16:01:00 christos Exp $ */ - -/*- - * Copyright (c) 1992, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Christos Zoulas of Cornell University. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)tokenizer.h 8.1 (Berkeley) 6/4/93 - */ - -/* - * tokenizer.h: Header file for tokenizer routines - */ -#ifndef _h_tokenizer -#define _h_tokenizer - -typedef struct tokenizer Tokenizer; - -Tokenizer *tok_init(const char *); -void tok_reset(Tokenizer *); -void tok_end(Tokenizer *); -int tok_line(Tokenizer *, const char *, int *, const char ***); - -#endif /* _h_tokenizer */ diff --git a/cmd-line-utils/libedit/tty.c b/cmd-line-utils/libedit/tty.c index 6f73fb4f9e7..3706905fc79 100644 --- a/cmd-line-utils/libedit/tty.c +++ b/cmd-line-utils/libedit/tty.c @@ -1,4 +1,4 @@ -/* $NetBSD: tty.c,v 1.21 2004/08/13 12:10:39 mycroft Exp $ */ +/* $NetBSD: tty.c,v 1.28 2009/02/06 19:53:23 sketch Exp $ */ /*- * Copyright (c) 1992, 1993 @@ -32,18 +32,25 @@ * SUCH DAMAGE. */ -#include +#include "config.h" +#if !defined(lint) && !defined(SCCSID) +#if 0 +static char sccsid[] = "@(#)tty.c 8.1 (Berkeley) 6/4/93"; +#else +#endif +#endif /* not lint && not SCCSID */ /* * tty.c: tty interface stuff */ #include +#include #include "tty.h" #include "el.h" typedef struct ttymodes_t { const char *m_name; - u_int m_value; + unsigned int m_value; int m_type; } ttymodes_t; @@ -438,13 +445,12 @@ private const ttymodes_t ttymodes[] = { -#define tty_getty(el, td) tcgetattr((el)->el_infd, (td)) -#define tty_setty(el, td) tcsetattr((el)->el_infd, TCSADRAIN, (td)) - #define tty__gettabs(td) ((((td)->c_oflag & TAB3) == TAB3) ? 0 : 1) #define tty__geteightbit(td) (((td)->c_cflag & CSIZE) == CS8) #define tty__cooked_mode(td) ((td)->c_lflag & ICANON) +private int tty_getty(EditLine *, struct termios *); +private int tty_setty(EditLine *, int, const struct termios *); private int tty__getcharindex(int); private void tty__getchar(struct termios *, unsigned char *); private void tty__setchar(struct termios *, unsigned char *); @@ -453,6 +459,29 @@ private int tty_setup(EditLine *); #define t_qu t_ts +/* tty_getty(): + * Wrapper for tcgetattr to handle EINTR + */ +private int +tty_getty(EditLine *el, struct termios *t) +{ + int rv; + while ((rv = tcgetattr(el->el_infd, t)) == -1 && errno == EINTR) + continue; + return rv; +} + +/* tty_setty(): + * Wrapper for tcsetattr to handle EINTR + */ +private int +tty_setty(EditLine *el, int action, const struct termios *t) +{ + int rv; + while ((rv = tcsetattr(el->el_infd, action, t)) == -1 && errno == EINTR) + continue; + return rv; +} /* tty_setup(): * Get the tty parameters and initialize the editing state @@ -514,7 +543,7 @@ tty_setup(EditLine *el) el->el_tty.t_c[TS_IO][rst]; } tty__setchar(&el->el_tty.t_ex, el->el_tty.t_c[EX_IO]); - if (tty_setty(el, &el->el_tty.t_ex) == -1) { + if (tty_setty(el, TCSADRAIN, &el->el_tty.t_ex) == -1) { #ifdef DEBUG_TTY (void) fprintf(el->el_errfile, "tty_setup: tty_setty: %s\n", @@ -522,8 +551,11 @@ tty_setup(EditLine *el) #endif /* DEBUG_TTY */ return (-1); } - } else + } +#ifdef notdef + else tty__setchar(&el->el_tty.t_ex, el->el_tty.t_c[EX_IO]); +#endif el->el_tty.t_ed.c_iflag &= ~el->el_tty.t_t[ED_IO][MD_INP].t_clrmask; el->el_tty.t_ed.c_iflag |= el->el_tty.t_t[ED_IO][MD_INP].t_setmask; @@ -1040,7 +1072,7 @@ tty_rawmode(EditLine *el) } } } - if (tty_setty(el, &el->el_tty.t_ed) == -1) { + if (tty_setty(el, TCSADRAIN, &el->el_tty.t_ed) == -1) { #ifdef DEBUG_TTY (void) fprintf(el->el_errfile, "tty_rawmode: tty_setty: %s\n", strerror(errno)); @@ -1065,7 +1097,7 @@ tty_cookedmode(EditLine *el) if (el->el_flags & EDIT_DISABLED) return (0); - if (tty_setty(el, &el->el_tty.t_ex) == -1) { + if (tty_setty(el, TCSADRAIN, &el->el_tty.t_ex) == -1) { #ifdef DEBUG_TTY (void) fprintf(el->el_errfile, "tty_cookedmode: tty_setty: %s\n", @@ -1101,7 +1133,7 @@ tty_quotemode(EditLine *el) el->el_tty.t_qu.c_lflag &= ~el->el_tty.t_t[QU_IO][MD_LIN].t_clrmask; el->el_tty.t_qu.c_lflag |= el->el_tty.t_t[QU_IO][MD_LIN].t_setmask; - if (tty_setty(el, &el->el_tty.t_qu) == -1) { + if (tty_setty(el, TCSADRAIN, &el->el_tty.t_qu) == -1) { #ifdef DEBUG_TTY (void) fprintf(el->el_errfile, "QuoteModeOn: tty_setty: %s\n", strerror(errno)); @@ -1122,7 +1154,7 @@ tty_noquotemode(EditLine *el) if (el->el_tty.t_mode != QU_IO) return (0); - if (tty_setty(el, &el->el_tty.t_ed) == -1) { + if (tty_setty(el, TCSADRAIN, &el->el_tty.t_ed) == -1) { #ifdef DEBUG_TTY (void) fprintf(el->el_errfile, "QuoteModeOff: tty_setty: %s\n", strerror(errno)); @@ -1193,10 +1225,14 @@ tty_stty(EditLine *el, int argc __attribute__((__unused__)), const char **argv) st = len = strlen(el->el_tty.t_t[z][m->m_type].t_name); } - x = (el->el_tty.t_t[z][i].t_setmask & m->m_value) - ? '+' : '\0'; - x = (el->el_tty.t_t[z][i].t_clrmask & m->m_value) - ? '-' : x; + if (i != -1) { + x = (el->el_tty.t_t[z][i].t_setmask & m->m_value) + ? '+' : '\0'; + x = (el->el_tty.t_t[z][i].t_clrmask & m->m_value) + ? '-' : x; + } else { + x = '\0'; + } if (x != '\0' || aflag) { @@ -1221,7 +1257,7 @@ tty_stty(EditLine *el, int argc __attribute__((__unused__)), const char **argv) return (0); } while (argv && (s = *argv++)) { - char *p; + const char *p; switch (*s) { case '+': case '-': @@ -1232,10 +1268,10 @@ tty_stty(EditLine *el, int argc __attribute__((__unused__)), const char **argv) break; } d = s; - if ((p = strchr(s, '=')) != NULL) - *p++ = '\0'; + p = strchr(s, '='); for (m = ttymodes; m->m_name; m++) - if (strcmp(m->m_name, d) == 0 && + if ((p ? strncmp(m->m_name, d, (size_t)(p - d)) : + strcmp(m->m_name, d)) == 0 && (p == NULL || m->m_type == MD_CHAR)) break; @@ -1246,7 +1282,7 @@ tty_stty(EditLine *el, int argc __attribute__((__unused__)), const char **argv) } if (p) { int c = ffs((int)m->m_value); - int v = *p ? parse__escape((const char **const) &p) : + int v = *++p ? parse__escape((const char **) &p) : el->el_tty.t_vdisable; assert(c-- != 0); c = tty__getcharindex(c); @@ -1269,6 +1305,17 @@ tty_stty(EditLine *el, int argc __attribute__((__unused__)), const char **argv) break; } } + + if (el->el_tty.t_mode == z) { + if (tty_setty(el, TCSADRAIN, tios) == -1) { +#ifdef DEBUG_TTY + (void) fprintf(el->el_errfile, + "tty_stty: tty_setty: %s\n", strerror(errno)); +#endif /* DEBUG_TTY */ + return (-1); + } + } + return (0); } diff --git a/cmd-line-utils/libedit/tty.h b/cmd-line-utils/libedit/tty.h index cc7c4ad8c66..10e9b98c953 100644 --- a/cmd-line-utils/libedit/tty.h +++ b/cmd-line-utils/libedit/tty.h @@ -1,4 +1,4 @@ -/* $NetBSD: tty.h,v 1.10 2003/08/07 16:44:34 agc Exp $ */ +/* $NetBSD: tty.h,v 1.11 2005/06/01 11:37:52 lukem Exp $ */ /*- * Copyright (c) 1992, 1993 @@ -450,8 +450,8 @@ typedef struct { const char *t_name; - u_int t_setmask; - u_int t_clrmask; + unsigned int t_setmask; + unsigned int t_clrmask; } ttyperm_t[NN_IO][MD_NN]; typedef unsigned char ttychar_t[NN_IO][C_NCC]; diff --git a/cmd-line-utils/libedit/unvis.c b/cmd-line-utils/libedit/unvis.c deleted file mode 100644 index ffa8ac4251c..00000000000 --- a/cmd-line-utils/libedit/unvis.c +++ /dev/null @@ -1,311 +0,0 @@ -/* $NetBSD: unvis.c,v 1.24 2003/08/07 16:42:59 agc Exp $ */ - -/*- - * Copyright (c) 1989, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include - -#define __LIBC12_SOURCE__ - -#include - -#include -#include -#include -#include - -#ifdef __weak_alias -__weak_alias(strunvis,_strunvis) -__weak_alias(unvis,_unvis) -#endif - -#ifdef __warn_references -__warn_references(unvis, - "warning: reference to compatibility unvis(); include for correct reference") -#endif - -#if !HAVE_VIS -/* - * decode driven by state machine - */ -#define S_GROUND 0 /* haven't seen escape char */ -#define S_START 1 /* start decoding special sequence */ -#define S_META 2 /* metachar started (M) */ -#define S_META1 3 /* metachar more, regular char (-) */ -#define S_CTRL 4 /* control char started (^) */ -#define S_OCTAL2 5 /* octal digit 2 */ -#define S_OCTAL3 6 /* octal digit 3 */ -#define S_HEX1 7 /* hex digit */ -#define S_HEX2 8 /* hex digit 2 */ - -#define isoctal(c) (((u_char)(c)) >= '0' && ((u_char)(c)) <= '7') -#define xtod(c) (isdigit(c) ? (c - '0') : ((tolower(c) - 'a') + 10)) - -int -unvis(cp, c, astate, flag) - char *cp; - int c; - int *astate, flag; -{ - return __unvis13(cp, (int)c, astate, flag); -} - -/* - * unvis - decode characters previously encoded by vis - */ -int -__unvis13(cp, c, astate, flag) - char *cp; - int c; - int *astate, flag; -{ - - _DIAGASSERT(cp != NULL); - _DIAGASSERT(astate != NULL); - - if (flag & UNVIS_END) { - if (*astate == S_OCTAL2 || *astate == S_OCTAL3 - || *astate == S_HEX2) { - *astate = S_GROUND; - return (UNVIS_VALID); - } - return (*astate == S_GROUND ? UNVIS_NOCHAR : UNVIS_SYNBAD); - } - - switch (*astate) { - - case S_GROUND: - *cp = 0; - if (c == '\\') { - *astate = S_START; - return (0); - } - if ((flag & VIS_HTTPSTYLE) && c == '%') { - *astate = S_HEX1; - return (0); - } - *cp = c; - return (UNVIS_VALID); - - case S_START: - switch(c) { - case '\\': - *cp = c; - *astate = S_GROUND; - return (UNVIS_VALID); - case '0': case '1': case '2': case '3': - case '4': case '5': case '6': case '7': - *cp = (c - '0'); - *astate = S_OCTAL2; - return (0); - case 'M': - *cp = (char)0200; - *astate = S_META; - return (0); - case '^': - *astate = S_CTRL; - return (0); - case 'n': - *cp = '\n'; - *astate = S_GROUND; - return (UNVIS_VALID); - case 'r': - *cp = '\r'; - *astate = S_GROUND; - return (UNVIS_VALID); - case 'b': - *cp = '\b'; - *astate = S_GROUND; - return (UNVIS_VALID); - case 'a': - *cp = '\007'; - *astate = S_GROUND; - return (UNVIS_VALID); - case 'v': - *cp = '\v'; - *astate = S_GROUND; - return (UNVIS_VALID); - case 't': - *cp = '\t'; - *astate = S_GROUND; - return (UNVIS_VALID); - case 'f': - *cp = '\f'; - *astate = S_GROUND; - return (UNVIS_VALID); - case 's': - *cp = ' '; - *astate = S_GROUND; - return (UNVIS_VALID); - case 'E': - *cp = '\033'; - *astate = S_GROUND; - return (UNVIS_VALID); - case '\n': - /* - * hidden newline - */ - *astate = S_GROUND; - return (UNVIS_NOCHAR); - case '$': - /* - * hidden marker - */ - *astate = S_GROUND; - return (UNVIS_NOCHAR); - } - *astate = S_GROUND; - return (UNVIS_SYNBAD); - - case S_META: - if (c == '-') - *astate = S_META1; - else if (c == '^') - *astate = S_CTRL; - else { - *astate = S_GROUND; - return (UNVIS_SYNBAD); - } - return (0); - - case S_META1: - *astate = S_GROUND; - *cp |= c; - return (UNVIS_VALID); - - case S_CTRL: - if (c == '?') - *cp |= 0177; - else - *cp |= c & 037; - *astate = S_GROUND; - return (UNVIS_VALID); - - case S_OCTAL2: /* second possible octal digit */ - if (isoctal(c)) { - /* - * yes - and maybe a third - */ - *cp = (*cp << 3) + (c - '0'); - *astate = S_OCTAL3; - return (0); - } - /* - * no - done with current sequence, push back passed char - */ - *astate = S_GROUND; - return (UNVIS_VALIDPUSH); - - case S_OCTAL3: /* third possible octal digit */ - *astate = S_GROUND; - if (isoctal(c)) { - *cp = (*cp << 3) + (c - '0'); - return (UNVIS_VALID); - } - /* - * we were done, push back passed char - */ - return (UNVIS_VALIDPUSH); - case S_HEX1: - if (isxdigit(c)) { - *cp = xtod(c); - *astate = S_HEX2; - return (0); - } - /* - * no - done with current sequence, push back passed char - */ - *astate = S_GROUND; - return (UNVIS_VALIDPUSH); - case S_HEX2: - *astate = S_GROUND; - if (isxdigit(c)) { - *cp = xtod(c) | (*cp << 4); - return (UNVIS_VALID); - } - return (UNVIS_VALIDPUSH); - default: - /* - * decoder in unknown state - (probably uninitialized) - */ - *astate = S_GROUND; - return (UNVIS_SYNBAD); - } -} - -/* - * strunvis - decode src into dst - * - * Number of chars decoded into dst is returned, -1 on error. - * Dst is null terminated. - */ - -int -strunvisx(dst, src, flag) - char *dst; - const char *src; - int flag; -{ - char c; - char *start = dst; - int state = 0; - - _DIAGASSERT(src != NULL); - _DIAGASSERT(dst != NULL); - - while ((c = *src++) != '\0') { - again: - switch (__unvis13(dst, c, &state, flag)) { - case UNVIS_VALID: - dst++; - break; - case UNVIS_VALIDPUSH: - dst++; - goto again; - case 0: - case UNVIS_NOCHAR: - break; - default: - return (-1); - } - } - if (__unvis13(dst, c, &state, UNVIS_END) == UNVIS_VALID) - dst++; - *dst = '\0'; - return (dst - start); -} - -int -strunvis(dst, src) - char *dst; - const char *src; -{ - return strunvisx(dst, src, 0); -} -#endif diff --git a/cmd-line-utils/libedit/vi.c b/cmd-line-utils/libedit/vi.c index b977ce716c6..602383f3231 100644 --- a/cmd-line-utils/libedit/vi.c +++ b/cmd-line-utils/libedit/vi.c @@ -1,4 +1,4 @@ -/* $NetBSD: vi.c,v 1.20 2004/08/13 12:10:39 mycroft Exp $ */ +/* $NetBSD: vi.c,v 1.28 2009/02/06 13:14:37 sketch Exp $ */ /*- * Copyright (c) 1992, 1993 @@ -32,11 +32,17 @@ * SUCH DAMAGE. */ -#include +#include "config.h" #include #include #include +#if !defined(lint) && !defined(SCCSID) +#if 0 +static char sccsid[] = "@(#)vi.c 8.1 (Berkeley) 6/4/93"; +#else +#endif +#endif /* not lint && not SCCSID */ /* * vi.c: Vi mode commands. @@ -64,8 +70,10 @@ cv_action(EditLine *el, int c) el->el_line.lastchar - el->el_line.buffer); el->el_chared.c_vcmd.action = NOP; el->el_chared.c_vcmd.pos = 0; - el->el_line.lastchar = el->el_line.buffer; - el->el_line.cursor = el->el_line.buffer; + if (!(c & YANK)) { + el->el_line.lastchar = el->el_line.buffer; + el->el_line.cursor = el->el_line.buffer; + } if (c & INSERT) el->el_map.current = el->el_map.key; @@ -82,7 +90,6 @@ cv_action(EditLine *el, int c) private el_action_t cv_paste(EditLine *el, int c) { - char *ptr; c_kill_t *k = &el->el_chared.c_kill; int len = k->last - k->buf; @@ -96,12 +103,12 @@ cv_paste(EditLine *el, int c) if (!c && el->el_line.cursor < el->el_line.lastchar) el->el_line.cursor++; - ptr = el->el_line.cursor; c_insert(el, len); if (el->el_line.cursor + len > el->el_line.lastchar) return (CC_ERROR); - (void) memcpy(ptr, k->buf, len +0u); + (void) memcpy(el->el_line.cursor, k->buf, len +0u); + return (CC_REFRESH); } @@ -592,13 +599,12 @@ vi_delete_prev_char(EditLine *el, int c __attribute__((__unused__))) */ protected el_action_t /*ARGSUSED*/ -vi_list_or_eof(EditLine *el, int c __attribute__((__unused__))) +vi_list_or_eof(EditLine *el, int c) { if (el->el_line.cursor == el->el_line.lastchar) { if (el->el_line.cursor == el->el_line.buffer) { - term_overwrite(el, STReof, 4); /* then do a EOF */ - term__flush(); + term_writec(el, c); /* then do a EOF */ return (CC_EOF); } else { /* @@ -888,7 +894,7 @@ vi_yank(EditLine *el, int c) /* vi_comment_out(): * Vi comment out current command - * [c] + * [#] */ protected el_action_t /*ARGSUSED*/ @@ -905,18 +911,19 @@ vi_comment_out(EditLine *el, int c) /* vi_alias(): * Vi include shell alias * [@] - * NB: posix impiles that we should enter insert mode, however + * NB: posix implies that we should enter insert mode, however * this is against historical precedent... */ +#ifdef __weak_reference +extern char *get_alias_text(const char *) __weak_reference(get_alias_text); +#endif protected el_action_t /*ARGSUSED*/ vi_alias(EditLine *el, int c) { -#ifdef __weak_extern +#ifdef __weak_reference char alias_name[3]; char *alias_text; - extern char *get_alias_text(const char *); - __weak_extern(get_alias_text); if (get_alias_text == 0) { return CC_ERROR; @@ -1014,7 +1021,7 @@ vi_histedit(EditLine *el, int c) return CC_ERROR; case 0: close(fd); - execlp("vi", "vi", tempfile, (char *) NULL); + execlp("vi", "vi", tempfile, (char *)NULL); exit(0); /*NOTREACHED*/ default: diff --git a/cmd-line-utils/libedit/vis.c b/cmd-line-utils/libedit/vis.c deleted file mode 100644 index 127d28733a8..00000000000 --- a/cmd-line-utils/libedit/vis.c +++ /dev/null @@ -1,392 +0,0 @@ -/* $NetBSD: vis.c,v 1.27 2004/02/26 23:01:15 enami Exp $ */ - -/*- - * Copyright (c) 1989, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -/*- - * Copyright (c) 1999 The NetBSD Foundation, Inc. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -/* AIX requires this to be the first thing in the file. */ -#if defined (_AIX) && !defined (__GNUC__) - #pragma alloca -#endif - -#include - -#ifdef __GNUC__ -# undef alloca -# define alloca(n) __builtin_alloca (n) -#else -# ifdef HAVE_ALLOCA_H -# include -# else -# ifndef _AIX -extern char *alloca (); -# endif -# endif -#endif - -#include - -#include -#include -#include - -#ifdef __weak_alias -__weak_alias(strsvis,_strsvis) -__weak_alias(strsvisx,_strsvisx) -__weak_alias(strvis,_strvis) -__weak_alias(strvisx,_strvisx) -__weak_alias(svis,_svis) -__weak_alias(vis,_vis) -#endif - -#if !HAVE_VIS || !HAVE_SVIS -#include -#include -#include -#include - -#undef BELL -#define BELL '\a' - -#define isoctal(c) (((u_char)(c)) >= '0' && ((u_char)(c)) <= '7') -#define iswhite(c) (c == ' ' || c == '\t' || c == '\n') -#define issafe(c) (c == '\b' || c == BELL || c == '\r') -#define xtoa(c) "0123456789abcdef"[c] - -#define MAXEXTRAS 5 - - -#define MAKEEXTRALIST(flag, extra, orig) \ -do { \ - const char *o = orig; \ - char *e; \ - while (*o++) \ - continue; \ - extra = alloca((size_t)((o - orig) + MAXEXTRAS)); \ - for (o = orig, e = extra; (*e++ = *o++) != '\0';) \ - continue; \ - e--; \ - if (flag & VIS_SP) *e++ = ' '; \ - if (flag & VIS_TAB) *e++ = '\t'; \ - if (flag & VIS_NL) *e++ = '\n'; \ - if ((flag & VIS_NOSLASH) == 0) *e++ = '\\'; \ - *e = '\0'; \ -} while (/*CONSTCOND*/0) - - -/* - * This is HVIS, the macro of vis used to HTTP style (RFC 1808) - */ -#define HVIS(dst, c, flag, nextc, extra) \ -do \ - if (!isascii(c) || !isalnum(c) || strchr("$-_.+!*'(),", c) != NULL) { \ - *dst++ = '%'; \ - *dst++ = xtoa(((unsigned int)c >> 4) & 0xf); \ - *dst++ = xtoa((unsigned int)c & 0xf); \ - } else { \ - SVIS(dst, c, flag, nextc, extra); \ - } \ -while (/*CONSTCOND*/0) - -/* - * This is SVIS, the central macro of vis. - * dst: Pointer to the destination buffer - * c: Character to encode - * flag: Flag word - * nextc: The character following 'c' - * extra: Pointer to the list of extra characters to be - * backslash-protected. - */ -#define SVIS(dst, c, flag, nextc, extra) \ -do { \ - int isextra; \ - isextra = strchr(extra, c) != NULL; \ - if (!isextra && isascii(c) && (isgraph(c) || iswhite(c) || \ - ((flag & VIS_SAFE) && issafe(c)))) { \ - *dst++ = c; \ - break; \ - } \ - if (flag & VIS_CSTYLE) { \ - switch (c) { \ - case '\n': \ - *dst++ = '\\'; *dst++ = 'n'; \ - continue; \ - case '\r': \ - *dst++ = '\\'; *dst++ = 'r'; \ - continue; \ - case '\b': \ - *dst++ = '\\'; *dst++ = 'b'; \ - continue; \ - case BELL: \ - *dst++ = '\\'; *dst++ = 'a'; \ - continue; \ - case '\v': \ - *dst++ = '\\'; *dst++ = 'v'; \ - continue; \ - case '\t': \ - *dst++ = '\\'; *dst++ = 't'; \ - continue; \ - case '\f': \ - *dst++ = '\\'; *dst++ = 'f'; \ - continue; \ - case ' ': \ - *dst++ = '\\'; *dst++ = 's'; \ - continue; \ - case '\0': \ - *dst++ = '\\'; *dst++ = '0'; \ - if (isoctal(nextc)) { \ - *dst++ = '0'; \ - *dst++ = '0'; \ - } \ - continue; \ - default: \ - if (isgraph(c)) { \ - *dst++ = '\\'; *dst++ = c; \ - continue; \ - } \ - } \ - } \ - if (isextra || ((c & 0177) == ' ') || (flag & VIS_OCTAL)) { \ - *dst++ = '\\'; \ - *dst++ = (u_char)(((u_int32_t)(u_char)c >> 6) & 03) + '0'; \ - *dst++ = (u_char)(((u_int32_t)(u_char)c >> 3) & 07) + '0'; \ - *dst++ = (c & 07) + '0'; \ - } else { \ - if ((flag & VIS_NOSLASH) == 0) *dst++ = '\\'; \ - if (c & 0200) { \ - c &= 0177; *dst++ = 'M'; \ - } \ - if (iscntrl(c)) { \ - *dst++ = '^'; \ - if (c == 0177) \ - *dst++ = '?'; \ - else \ - *dst++ = c + '@'; \ - } else { \ - *dst++ = '-'; *dst++ = c; \ - } \ - } \ -} while (/*CONSTCOND*/0) - - -/* - * svis - visually encode characters, also encoding the characters - * pointed to by `extra' - */ -char * -svis(dst, c, flag, nextc, extra) - char *dst; - int c, flag, nextc; - const char *extra; -{ - char *nextra; - _DIAGASSERT(dst != NULL); - _DIAGASSERT(extra != NULL); - MAKEEXTRALIST(flag, nextra, extra); - if (flag & VIS_HTTPSTYLE) - HVIS(dst, c, flag, nextc, nextra); - else - SVIS(dst, c, flag, nextc, nextra); - *dst = '\0'; - return(dst); -} - - -/* - * strsvis, strsvisx - visually encode characters from src into dst - * - * Extra is a pointer to a \0-terminated list of characters to - * be encoded, too. These functions are useful e. g. to - * encode strings in such a way so that they are not interpreted - * by a shell. - * - * Dst must be 4 times the size of src to account for possible - * expansion. The length of dst, not including the trailing NULL, - * is returned. - * - * Strsvisx encodes exactly len bytes from src into dst. - * This is useful for encoding a block of data. - */ -int -strsvis(dst, csrc, flag, extra) - char *dst; - const char *csrc; - int flag; - const char *extra; -{ - int c; - char *start; - char *nextra; - const unsigned char *src = (const unsigned char *)csrc; - - _DIAGASSERT(dst != NULL); - _DIAGASSERT(src != NULL); - _DIAGASSERT(extra != NULL); - MAKEEXTRALIST(flag, nextra, extra); - if (flag & VIS_HTTPSTYLE) { - for (start = dst; (c = *src++) != '\0'; /* empty */) - HVIS(dst, c, flag, *src, nextra); - } else { - for (start = dst; (c = *src++) != '\0'; /* empty */) - SVIS(dst, c, flag, *src, nextra); - } - *dst = '\0'; - return (dst - start); -} - - -int -strsvisx(dst, csrc, len, flag, extra) - char *dst; - const char *csrc; - size_t len; - int flag; - const char *extra; -{ - int c; - char *start; - char *nextra; - const unsigned char *src = (const unsigned char *)csrc; - - _DIAGASSERT(dst != NULL); - _DIAGASSERT(src != NULL); - _DIAGASSERT(extra != NULL); - MAKEEXTRALIST(flag, nextra, extra); - - if (flag & VIS_HTTPSTYLE) { - for (start = dst; len > 0; len--) { - c = *src++; - HVIS(dst, c, flag, len ? *src : '\0', nextra); - } - } else { - for (start = dst; len > 0; len--) { - c = *src++; - SVIS(dst, c, flag, len ? *src : '\0', nextra); - } - } - *dst = '\0'; - return (dst - start); -} -#endif - -#if !HAVE_VIS -/* - * vis - visually encode characters - */ -char * -vis(dst, c, flag, nextc) - char *dst; - int c, flag, nextc; - -{ - char *extra; - - _DIAGASSERT(dst != NULL); - - MAKEEXTRALIST(flag, extra, ""); - if (flag & VIS_HTTPSTYLE) - HVIS(dst, c, flag, nextc, extra); - else - SVIS(dst, c, flag, nextc, extra); - *dst = '\0'; - return (dst); -} - - -/* - * strvis, strvisx - visually encode characters from src into dst - * - * Dst must be 4 times the size of src to account for possible - * expansion. The length of dst, not including the trailing NULL, - * is returned. - * - * Strvisx encodes exactly len bytes from src into dst. - * This is useful for encoding a block of data. - */ -int -strvis(dst, src, flag) - char *dst; - const char *src; - int flag; -{ - char *extra; - - MAKEEXTRALIST(flag, extra, ""); - return (strsvis(dst, src, flag, extra)); -} - - -int -strvisx(dst, src, len, flag) - char *dst; - const char *src; - size_t len; - int flag; -{ - char *extra; - - MAKEEXTRALIST(flag, extra, ""); - return (strsvisx(dst, src, len, flag, extra)); -} -#endif diff --git a/cmd-line-utils/libedit/vis.h b/cmd-line-utils/libedit/vis.h deleted file mode 100644 index 44f6fc7d785..00000000000 --- a/cmd-line-utils/libedit/vis.h +++ /dev/null @@ -1,92 +0,0 @@ -/* $NetBSD: vis.h,v 1.15 2005/02/03 04:39:32 perry Exp $ */ - -/*- - * Copyright (c) 1990, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)vis.h 8.1 (Berkeley) 6/2/93 - */ - -#ifndef _VIS_H_ -#define _VIS_H_ - -#include - -/* - * to select alternate encoding format - */ -#define VIS_OCTAL 0x01 /* use octal \ddd format */ -#define VIS_CSTYLE 0x02 /* use \[nrft0..] where appropiate */ - -/* - * to alter set of characters encoded (default is to encode all - * non-graphic except space, tab, and newline). - */ -#define VIS_SP 0x04 /* also encode space */ -#define VIS_TAB 0x08 /* also encode tab */ -#define VIS_NL 0x10 /* also encode newline */ -#define VIS_WHITE (VIS_SP | VIS_TAB | VIS_NL) -#define VIS_SAFE 0x20 /* only encode "unsafe" characters */ - -/* - * other - */ -#define VIS_NOSLASH 0x40 /* inhibit printing '\' */ -#define VIS_HTTPSTYLE 0x80 /* http-style escape % HEX HEX */ - -/* - * unvis return codes - */ -#define UNVIS_VALID 1 /* character valid */ -#define UNVIS_VALIDPUSH 2 /* character valid, push back passed char */ -#define UNVIS_NOCHAR 3 /* valid sequence, no character produced */ -#define UNVIS_SYNBAD -1 /* unrecognized escape sequence */ -#define UNVIS_ERROR -2 /* decoder in unknown state (unrecoverable) */ - -/* - * unvis flags - */ -#define UNVIS_END 1 /* no more characters */ - -__BEGIN_DECLS -char *vis(char *, int, int, int); -char *svis(char *, int, int, int, const char *); -int strvis(char *, const char *, int); -int strsvis(char *, const char *, int, const char *); -int strvisx(char *, const char *, size_t, int); -int strsvisx(char *, const char *, size_t, int, const char *); -int strunvis(char *, const char *); -int strunvisx(char *, const char *, int); -#ifdef __LIBC12_SOURCE__ -int unvis(char *, int, int *, int); -int __unvis13(char *, int, int *, int); -#else -int unvis(char *, int, int *, int); -#endif -__END_DECLS - -#endif /* !_VIS_H_ */ From d880862549f2a10710f4f002a7850e72188559fd Mon Sep 17 00:00:00 2001 From: Chad MILLER Date: Tue, 10 Feb 2009 09:41:55 -0500 Subject: [PATCH 057/219] Bug#30261: "mysqld --help" no longer possible for root The check for root-ness would signal an error. Errors would make the server exit before usage (help) information was printed. Now, test for whether we want help regardless of whether we're going to exit with an error. If plugins are not initialized by the time we print usage information, inform the user that some parameters are missing. --- sql/mysqld.cc | 31 ++++++++++++++++++++++--------- 1 file changed, 22 insertions(+), 9 deletions(-) diff --git a/sql/mysqld.cc b/sql/mysqld.cc index e6980318a66..862f9effc68 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -682,6 +682,8 @@ bool mysqld_embedded=0; bool mysqld_embedded=1; #endif +static my_bool plugins_are_initialized= FALSE; + #ifndef DBUG_OFF static const char* default_dbug_option; #endif @@ -1176,10 +1178,10 @@ extern "C" void unireg_abort(int exit_code) { DBUG_ENTER("unireg_abort"); + if (opt_help) + usage(); if (exit_code) sql_print_error("Aborting\n"); - else if (opt_help) - usage(); clean_up(!opt_help && (exit_code || !opt_bootstrap)); /* purecov: inspected */ DBUG_PRINT("quit",("done with cleanup in unireg_abort")); wait_for_signal_thread_to_end(); @@ -3841,12 +3843,15 @@ server."); if (ha_init_errors()) DBUG_RETURN(1); - if (plugin_init(&defaults_argc, defaults_argv, - (opt_noacl ? PLUGIN_INIT_SKIP_PLUGIN_TABLE : 0) | - (opt_help ? PLUGIN_INIT_SKIP_INITIALIZATION : 0))) - { - sql_print_error("Failed to initialize plugins."); - unireg_abort(1); + { + if (plugin_init(&defaults_argc, defaults_argv, + (opt_noacl ? PLUGIN_INIT_SKIP_PLUGIN_TABLE : 0) | + (opt_help ? PLUGIN_INIT_SKIP_INITIALIZATION : 0))) + { + sql_print_error("Failed to initialize plugins."); + unireg_abort(1); + } + plugins_are_initialized= TRUE; /* Don't separate from init function */ } if (opt_help) @@ -7378,7 +7383,8 @@ static void usage(void) default_collation_name= (char*) default_charset_info->name; print_version(); puts("\ -Copyright (C) 2000 MySQL AB, by Monty and others\n\ +Copyright (C) 2000-2008 MySQL AB, by Monty and others\n\ +Copyright (C) 2008 Sun Microsystems, Inc.\n\ This software comes with ABSOLUTELY NO WARRANTY. This is free software,\n\ and you are welcome to modify and redistribute it under the GPL license\n\n\ Starts the MySQL database server\n"); @@ -7408,6 +7414,13 @@ Starts the MySQL database server\n"); /* Print out all the options including plugin supplied options */ my_print_help_inc_plugins(my_long_options, sizeof(my_long_options)/sizeof(my_option)); + if (! plugins_are_initialized) + { + puts("\n\ +Plugins have parameters that are not reflected in this list\n\ +because execution stopped before plugins were initialized."); + } + puts("\n\ To see what values a running MySQL server is using, type\n\ 'mysqladmin variables' instead of 'mysqld --verbose --help'."); From 9b612d2c905ab681fd8659f821caf679d692173a Mon Sep 17 00:00:00 2001 From: Mats Kindahl Date: Tue, 10 Feb 2009 15:44:58 +0100 Subject: [PATCH 058/219] BUG#36763: TRUNCATE TABLE fails to replicate when stmt-based binlogging is not supported. Post-merge fixes. Changes to some result sets. mysql-test/r/commit_1innodb.result: TRUNCATE TABLE does not cause the binary log to do commits any more. mysql-test/suite/binlog/r/binlog_row_mix_innodb_myisam.result: TRUNCATE TABLE is not transactional, hence does not have BEGIN/COMMIT around itself. mysql-test/suite/binlog/r/binlog_stm_mix_innodb_myisam.result: TRUNCATE TABLE is not transactional, hence does not have BEGIN/COMMIT around itself. mysql-test/suite/rpl/r/rpl_innodb_mixed_dml.result: TRUNCATE TABLE is not transactional, hence does not have BEGIN/COMMIT around itself. mysql-test/suite/rpl/r/rpl_truncate_2myisam.result: STOP SLAVE was replaced with include file. mysql-test/suite/rpl/r/rpl_truncate_3innodb.result: STOP SLAVE was replaced with include file. --- mysql-test/r/commit_1innodb.result | 8 ++++---- .../suite/binlog/r/binlog_row_mix_innodb_myisam.result | 4 ---- .../suite/binlog/r/binlog_stm_mix_innodb_myisam.result | 4 ---- mysql-test/suite/rpl/r/rpl_innodb_mixed_dml.result | 2 -- mysql-test/suite/rpl/r/rpl_truncate_2myisam.result | 8 ++++---- mysql-test/suite/rpl/r/rpl_truncate_3innodb.result | 8 ++++---- 6 files changed, 12 insertions(+), 22 deletions(-) diff --git a/mysql-test/r/commit_1innodb.result b/mysql-test/r/commit_1innodb.result index a31a881051f..de80dba47c1 100644 --- a/mysql-test/r/commit_1innodb.result +++ b/mysql-test/r/commit_1innodb.result @@ -687,8 +687,8 @@ SUCCESS truncate table t2; call p_verify_status_increment(4, 0, 4, 0); -SUCCESS - +ERROR +Expected commit increment: 4 actual: 2 commit; # There is nothing left to commit call p_verify_status_increment(0, 0, 0, 0); @@ -854,8 +854,8 @@ SUCCESS truncate table t3; call p_verify_status_increment(4, 4, 4, 4); -SUCCESS - +ERROR +Expected commit increment: 4 actual: 2 create view v1 as select * from t2; call p_verify_status_increment(1, 0, 1, 0); SUCCESS diff --git a/mysql-test/suite/binlog/r/binlog_row_mix_innodb_myisam.result b/mysql-test/suite/binlog/r/binlog_row_mix_innodb_myisam.result index 0606c223126..4f3bc57e576 100644 --- a/mysql-test/suite/binlog/r/binlog_row_mix_innodb_myisam.result +++ b/mysql-test/suite/binlog/r/binlog_row_mix_innodb_myisam.result @@ -379,9 +379,7 @@ master-bin.000001 # Query # # use `test`; BEGIN master-bin.000001 # Table_map # # table_id: # (test.t1) master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F master-bin.000001 # Query # # use `test`; COMMIT -master-bin.000001 # Query # # use `test`; BEGIN master-bin.000001 # Query # # use `test`; TRUNCATE table t2 -master-bin.000001 # Xid # # COMMIT /* XID */ master-bin.000001 # Query # # use `test`; BEGIN master-bin.000001 # Table_map # # table_id: # (test.t1) master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F @@ -401,9 +399,7 @@ master-bin.000001 # Query # # use `test`; BEGIN master-bin.000001 # Table_map # # table_id: # (test.t1) master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F master-bin.000001 # Query # # use `test`; ROLLBACK -master-bin.000001 # Query # # use `test`; BEGIN master-bin.000001 # Query # # use `test`; TRUNCATE table t2 -master-bin.000001 # Query # # use `test`; COMMIT master-bin.000001 # Query # # use `test`; BEGIN master-bin.000001 # Table_map # # table_id: # (test.t1) master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F diff --git a/mysql-test/suite/binlog/r/binlog_stm_mix_innodb_myisam.result b/mysql-test/suite/binlog/r/binlog_stm_mix_innodb_myisam.result index 6d943ed9da1..38488c9331d 100644 --- a/mysql-test/suite/binlog/r/binlog_stm_mix_innodb_myisam.result +++ b/mysql-test/suite/binlog/r/binlog_stm_mix_innodb_myisam.result @@ -346,9 +346,7 @@ master-bin.000001 # Query # # use `test`; INSERT INTO t1 values (3,3) master-bin.000001 # Query # # use `test`; DROP TABLE IF EXISTS t2 master-bin.000001 # Query # # use `test`; CREATE TABLE t2 (a int, b int, primary key (a)) engine=innodb master-bin.000001 # Query # # use `test`; INSERT INTO t1 VALUES (4,4) -master-bin.000001 # Query # # use `test`; BEGIN master-bin.000001 # Query # # use `test`; TRUNCATE table t2 -master-bin.000001 # Xid # # COMMIT /* XID */ master-bin.000001 # Query # # use `test`; INSERT INTO t1 VALUES (5,5) master-bin.000001 # Query # # use `test`; DROP TABLE t2 master-bin.000001 # Query # # use `test`; INSERT INTO t1 values (6,6) @@ -356,9 +354,7 @@ master-bin.000001 # Query # # use `test`; CREATE TEMPORARY TABLE t2 (a int, b in master-bin.000001 # Query # # use `test`; INSERT INTO t1 values (7,7) master-bin.000001 # Query # # use `test`; INSERT INTO t1 values (8,8) master-bin.000001 # Query # # use `test`; INSERT INTO t1 values (9,9) -master-bin.000001 # Query # # use `test`; BEGIN master-bin.000001 # Query # # use `test`; TRUNCATE table t2 -master-bin.000001 # Query # # use `test`; COMMIT master-bin.000001 # Query # # use `test`; INSERT INTO t1 values (10,10) master-bin.000001 # Query # # use `test`; BEGIN master-bin.000001 # Query # # use `test`; INSERT INTO t2 values (100,100) diff --git a/mysql-test/suite/rpl/r/rpl_innodb_mixed_dml.result b/mysql-test/suite/rpl/r/rpl_innodb_mixed_dml.result index 8602718ba46..1e795a85ce1 100644 --- a/mysql-test/suite/rpl/r/rpl_innodb_mixed_dml.result +++ b/mysql-test/suite/rpl/r/rpl_innodb_mixed_dml.result @@ -963,9 +963,7 @@ master-bin.000001 # Xid 1 # # master-bin.000001 # Query 1 # use `test_rpl`; BEGIN master-bin.000001 # Query 1 # use `test_rpl`; INSERT INTO t1 VALUES(1, 't1, text 1') master-bin.000001 # Xid 1 # # -master-bin.000001 # Query 1 # use `test_rpl`; BEGIN master-bin.000001 # Query 1 # use `test_rpl`; TRUNCATE t1 -master-bin.000001 # Xid 1 # # master-bin.000001 # Query 1 # use `test_rpl`; BEGIN master-bin.000001 # Query 1 # use `test_rpl`; DELETE FROM t1 master-bin.000001 # Xid 1 # # diff --git a/mysql-test/suite/rpl/r/rpl_truncate_2myisam.result b/mysql-test/suite/rpl/r/rpl_truncate_2myisam.result index 21904fdac51..38fb9e27764 100644 --- a/mysql-test/suite/rpl/r/rpl_truncate_2myisam.result +++ b/mysql-test/suite/rpl/r/rpl_truncate_2myisam.result @@ -5,10 +5,10 @@ reset slave; drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; start slave; **** Resetting master and slave **** -STOP SLAVE; +include/stop_slave.inc RESET SLAVE; RESET MASTER; -START SLAVE; +include/start_slave.inc **** On Master **** CREATE TABLE t1 (a INT, b LONG) ENGINE=MyISAM; INSERT INTO t1 VALUES (1,1), (2,2); @@ -25,10 +25,10 @@ TRUNCATE TABLE t1; Comparing tables master:test.t2 and slave:test.t2 DROP TABLE t1,t2; **** Resetting master and slave **** -STOP SLAVE; +include/stop_slave.inc RESET SLAVE; RESET MASTER; -START SLAVE; +include/start_slave.inc **** On Master **** CREATE TABLE t1 (a INT, b LONG) ENGINE=MyISAM; INSERT INTO t1 VALUES (1,1), (2,2); diff --git a/mysql-test/suite/rpl/r/rpl_truncate_3innodb.result b/mysql-test/suite/rpl/r/rpl_truncate_3innodb.result index 665d0b153e0..b5e5936834d 100644 --- a/mysql-test/suite/rpl/r/rpl_truncate_3innodb.result +++ b/mysql-test/suite/rpl/r/rpl_truncate_3innodb.result @@ -5,10 +5,10 @@ reset slave; drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; start slave; **** Resetting master and slave **** -STOP SLAVE; +include/stop_slave.inc RESET SLAVE; RESET MASTER; -START SLAVE; +include/start_slave.inc **** On Master **** CREATE TABLE t1 (a INT, b LONG) ENGINE=InnoDB; INSERT INTO t1 VALUES (1,1), (2,2); @@ -25,10 +25,10 @@ TRUNCATE TABLE t1; Comparing tables master:test.t2 and slave:test.t2 DROP TABLE t1,t2; **** Resetting master and slave **** -STOP SLAVE; +include/stop_slave.inc RESET SLAVE; RESET MASTER; -START SLAVE; +include/start_slave.inc **** On Master **** CREATE TABLE t1 (a INT, b LONG) ENGINE=InnoDB; INSERT INTO t1 VALUES (1,1), (2,2); From 4568152518d075ec543bcc55b77241e4a5bf7c17 Mon Sep 17 00:00:00 2001 From: Georgi Kodinov Date: Tue, 10 Feb 2009 20:19:03 +0200 Subject: [PATCH 059/219] fixed a libedit compilation problem --- cmd-line-utils/libedit/Makefile.am | 2 +- cmd-line-utils/libedit/term.c | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/cmd-line-utils/libedit/Makefile.am b/cmd-line-utils/libedit/Makefile.am index 5a01a746963..ddafa4aab44 100644 --- a/cmd-line-utils/libedit/Makefile.am +++ b/cmd-line-utils/libedit/Makefile.am @@ -21,7 +21,7 @@ pkginclude_HEADERS = readline/readline.h noinst_HEADERS = chared.h el.h el_term.h histedit.h key.h parse.h refresh.h sig.h \ sys.h config.h hist.h map.h prompt.h read.h \ - search.h tty.h filecomplete.h + search.h tty.h filecomplete.h np/vis.h EXTRA_DIST = makelist.sh diff --git a/cmd-line-utils/libedit/term.c b/cmd-line-utils/libedit/term.c index 7a9d0250114..488c760da14 100644 --- a/cmd-line-utils/libedit/term.c +++ b/cmd-line-utils/libedit/term.c @@ -50,9 +50,11 @@ static char sccsid[] = "@(#)term.c 8.2 (Berkeley) 4/30/95"; #include #include #include +#if 0 /* TODO: do we need this */ #ifdef HAVE_TERMCAP_H #include #endif +#endif #ifdef HAVE_CURSES_H #include #endif From 93ef74bfd1a25f240ab41c48ab89eff338ca4e27 Mon Sep 17 00:00:00 2001 From: Mats Kindahl Date: Tue, 10 Feb 2009 22:26:37 +0100 Subject: [PATCH 060/219] Bug #36763 TRUNCATE TABLE fails to replicate when stmt-based binlogging is not supported. Correcting some tests that was failing in pushbuild as well as fixing result file for some tests that are not executed in the default MTR run. mysql-test/suite/binlog/t/binlog_truncate_innodb.test: Need to reset master to avoid the check to be for the wrong binlog file. mysql-test/suite/binlog/t/binlog_truncate_myisam.test: Need to reset master to avoid the check to be for the wrong binlog file. --- mysql-test/r/mysqlbinlog_row_trans.result | 34 +------------------ .../binlog/r/binlog_truncate_myisam.result | 1 + .../binlog/t/binlog_truncate_innodb.test | 7 ++++ .../binlog/t/binlog_truncate_myisam.test | 7 ++++ 4 files changed, 16 insertions(+), 33 deletions(-) diff --git a/mysql-test/r/mysqlbinlog_row_trans.result b/mysql-test/r/mysqlbinlog_row_trans.result index 9c3348a9e76..d0180e4a7a3 100644 --- a/mysql-test/r/mysqlbinlog_row_trans.result +++ b/mysql-test/r/mysqlbinlog_row_trans.result @@ -215,7 +215,7 @@ COMMIT/*!*/; # at # #010909 4:46:40 server id 1 end_log_pos # Query thread_id=# exec_time=# error_code=0 SET TIMESTAMP=1000000000/*!*/; -BEGIN +TRUNCATE TABLE t1 /*!*/; # at # #010909 4:46:40 server id 1 end_log_pos # Query thread_id=# exec_time=# error_code=0 @@ -223,22 +223,6 @@ SET TIMESTAMP=1000000000/*!*/; TRUNCATE TABLE t1 /*!*/; # at # -#010909 4:46:40 server id 1 end_log_pos # Xid = # -COMMIT/*!*/; -# at # -#010909 4:46:40 server id 1 end_log_pos # Query thread_id=# exec_time=# error_code=0 -SET TIMESTAMP=1000000000/*!*/; -BEGIN -/*!*/; -# at # -#010909 4:46:40 server id 1 end_log_pos # Query thread_id=# exec_time=# error_code=0 -SET TIMESTAMP=1000000000/*!*/; -TRUNCATE TABLE t1 -/*!*/; -# at # -#010909 4:46:40 server id 1 end_log_pos # Xid = # -COMMIT/*!*/; -# at # #010909 4:46:40 server id 1 end_log_pos # Query thread_id=# exec_time=# error_code=0 SET TIMESTAMP=1000000000/*!*/; BEGIN @@ -347,17 +331,9 @@ COMMIT/*!*/; # at # #010909 4:46:40 server id 1 end_log_pos # Query thread_id=# exec_time=# error_code=0 SET TIMESTAMP=1000000000/*!*/; -BEGIN -/*!*/; -# at # -#010909 4:46:40 server id 1 end_log_pos # Query thread_id=# exec_time=# error_code=0 -SET TIMESTAMP=1000000000/*!*/; TRUNCATE TABLE t1 /*!*/; # at # -#010909 4:46:40 server id 1 end_log_pos # Xid = # -COMMIT/*!*/; -# at # #010909 4:46:40 server id 1 end_log_pos # Query thread_id=# exec_time=# error_code=0 SET TIMESTAMP=1000000000/*!*/; TRUNCATE TABLE t2 @@ -473,17 +449,9 @@ ROLLBACK # at # #010909 4:46:40 server id 1 end_log_pos # Query thread_id=# exec_time=# error_code=0 SET TIMESTAMP=1000000000/*!*/; -BEGIN -/*!*/; -# at # -#010909 4:46:40 server id 1 end_log_pos # Query thread_id=# exec_time=# error_code=0 -SET TIMESTAMP=1000000000/*!*/; TRUNCATE TABLE t1 /*!*/; # at # -#010909 4:46:40 server id 1 end_log_pos # Xid = # -COMMIT/*!*/; -# at # #010909 4:46:40 server id 1 end_log_pos # Query thread_id=# exec_time=# error_code=0 SET TIMESTAMP=1000000000/*!*/; TRUNCATE TABLE t2 diff --git a/mysql-test/suite/binlog/r/binlog_truncate_myisam.result b/mysql-test/suite/binlog/r/binlog_truncate_myisam.result index 544882c2c9b..9f01c015178 100644 --- a/mysql-test/suite/binlog/r/binlog_truncate_myisam.result +++ b/mysql-test/suite/binlog/r/binlog_truncate_myisam.result @@ -1,3 +1,4 @@ +RESET MASTER; CREATE TABLE t1 (a INT) ENGINE=MyISAM; CREATE TABLE t2 (a INT) ENGINE=MyISAM; INSERT INTO t2 VALUES (1),(2),(3); diff --git a/mysql-test/suite/binlog/t/binlog_truncate_innodb.test b/mysql-test/suite/binlog/t/binlog_truncate_innodb.test index 9695710377e..be0918a43f0 100644 --- a/mysql-test/suite/binlog/t/binlog_truncate_innodb.test +++ b/mysql-test/suite/binlog/t/binlog_truncate_innodb.test @@ -1,6 +1,13 @@ source include/have_log_bin.inc; source include/have_innodb.inc; +# It is necessary to reset the master since otherwise the binlog test +# might show the wrong binary log. The default for SHOW BINLOG EVENTS +# is to show the first binary log, not the current one (which is +# actually a better idea). + +RESET MASTER; + let $engine = InnoDB; source extra/binlog_tests/binlog_truncate.test; diff --git a/mysql-test/suite/binlog/t/binlog_truncate_myisam.test b/mysql-test/suite/binlog/t/binlog_truncate_myisam.test index 994647ab78a..e0e4673e876 100644 --- a/mysql-test/suite/binlog/t/binlog_truncate_myisam.test +++ b/mysql-test/suite/binlog/t/binlog_truncate_myisam.test @@ -1,4 +1,11 @@ source include/have_log_bin.inc; +# It is necessary to reset the master since otherwise the binlog test +# might show the wrong binary log. The default for SHOW BINLOG EVENTS +# is to show the first binary log, not the current one (which is +# actually a better idea). + +RESET MASTER; + let $engine = MyISAM; source extra/binlog_tests/binlog_truncate.test; From 48d4d34689c3fb8b0ba25f775b34ca5472568a33 Mon Sep 17 00:00:00 2001 From: Horst Hunger Date: Wed, 11 Feb 2009 10:27:52 +0100 Subject: [PATCH 061/219] Reviewed fix for bug#40882: Replaced "sleep 1" by wait_condition, added save/restore start values and closed open sessions. When trying to use "wait_for_query_to_succeed" a type has been fixed, also in "rename.test": Added session count and check and replaced error numbers. --- ...ceed.inc => wait_for_query_to_succeed.inc} | 4 +- mysql-test/r/read_only.result | 36 +++++++++- mysql-test/t/read_only.test | 69 +++++++++++++++---- mysql-test/t/rename.test | 22 +++--- 4 files changed, 105 insertions(+), 26 deletions(-) rename mysql-test/include/{wait_for_query_to_suceed.inc => wait_for_query_to_succeed.inc} (69%) diff --git a/mysql-test/include/wait_for_query_to_suceed.inc b/mysql-test/include/wait_for_query_to_succeed.inc similarity index 69% rename from mysql-test/include/wait_for_query_to_suceed.inc rename to mysql-test/include/wait_for_query_to_succeed.inc index 6ac1144620e..12ba5c4d9b8 100644 --- a/mysql-test/include/wait_for_query_to_suceed.inc +++ b/mysql-test/include/wait_for_query_to_succeed.inc @@ -1,5 +1,5 @@ # -# Run a query over and over until it suceeds ot timeout occurs +# Run a query over and over until it succeeds ot timeout occurs # @@ -17,7 +17,7 @@ while ($mysql_errno) if (!$counter) { - die("Waited too long for query to suceed"); + --die "Waited too long for query to succeed"; } } enable_abort_on_error; diff --git a/mysql-test/r/read_only.result b/mysql-test/r/read_only.result index cf81566f4e5..558e0356c5a 100644 --- a/mysql-test/r/read_only.result +++ b/mysql-test/r/read_only.result @@ -1,12 +1,18 @@ +set @start_read_only= @@global.read_only; DROP TABLE IF EXISTS t1,t2,t3; grant CREATE, SELECT, DROP on *.* to test@localhost; +connect (con1,localhost,test,,test); +connection default; set global read_only=0; +connection con1; create table t1 (a int); insert into t1 values(1); create table t2 select * from t1; +connection default; set global read_only=1; create table t3 (a int); drop table t3; +connection con1; select @@global.read_only; @@global.read_only 1 @@ -39,13 +45,18 @@ delete t1 from t1,t3 where t1.a=t3.a; drop table t1; insert into t1 values(1); ERROR HY000: The MySQL server is running with the --read-only option so it cannot execute this statement +connection default; set global read_only=0; lock table t1 write; +connection con1; lock table t2 write; +connection default; set global read_only=1; ERROR HY000: Can't execute the given command because you have active locked tables or an active transaction unlock tables ; +send set global read_only=1; set global read_only=1; +connection con1; select @@global.read_only; @@global.read_only 0 @@ -53,13 +64,20 @@ unlock tables ; select @@global.read_only; @@global.read_only 1 +connection default; +reap; +connection default; set global read_only=0; lock table t1 read; +connection con1; lock table t2 read; +connection default; set global read_only=1; ERROR HY000: Can't execute the given command because you have active locked tables or an active transaction unlock tables ; +send set global read_only=1; set global read_only=1; +connection con1; select @@global.read_only; @@global.read_only 0 @@ -67,24 +85,35 @@ unlock tables ; select @@global.read_only; @@global.read_only 1 +connection default; +reap; +connection default; set global read_only=0; BEGIN; +connection con1; BEGIN; +connection default; set global read_only=1; ERROR HY000: Can't execute the given command because you have active locked tables or an active transaction ROLLBACK; set global read_only=1; +connection con1; select @@global.read_only; @@global.read_only 1 ROLLBACK; +connection default; set global read_only=0; flush tables with read lock; set global read_only=1; unlock tables; +connect (root2,localhost,root,,test); +connection default; set global read_only=0; flush tables with read lock; +connection root2; set global read_only=1; +connection default; select @@global.read_only; @@global.read_only 1 @@ -94,6 +123,7 @@ ERROR 42S02: Unknown table 'ttt' drop temporary table if exists ttt; Warnings: Note 1051 Unknown table 'ttt' +connection default; set global read_only=0; drop table t1,t2; drop user test@localhost; @@ -112,16 +142,20 @@ grant all on mysqltest_db2.* to `mysqltest_u1`@`%`; create database mysqltest_db1; grant all on mysqltest_db1.* to `mysqltest_u1`@`%`; flush privileges; +connect (con_bug27440,127.0.0.1,mysqltest_u1,,test,MASTER_MYPORT,); +connection con_bug27440; create database mysqltest_db2; ERROR HY000: The MySQL server is running with the --read-only option so it cannot execute this statement show databases like '%mysqltest_db2%'; Database (%mysqltest_db2%) drop database mysqltest_db1; ERROR HY000: The MySQL server is running with the --read-only option so it cannot execute this statement +disconnect con_bug27440; +connection default; delete from mysql.user where User like 'mysqltest_%'; delete from mysql.db where User like 'mysqltest_%'; delete from mysql.tables_priv where User like 'mysqltest_%'; delete from mysql.columns_priv where User like 'mysqltest_%'; flush privileges; drop database mysqltest_db1; -set global read_only=0; +set global read_only= @start_read_only; diff --git a/mysql-test/t/read_only.test b/mysql-test/t/read_only.test index fd41a3225a6..5a498404b03 100644 --- a/mysql-test/t/read_only.test +++ b/mysql-test/t/read_only.test @@ -2,7 +2,10 @@ # check that it blocks updates unless they are only on temporary tables. # should work with embedded server after mysqltest is fixed --- source include/not_embedded.inc +--source include/not_embedded.inc +--source include/count_sessions.inc + +set @start_read_only= @@global.read_only; --disable_warnings DROP TABLE IF EXISTS t1,t2,t3; @@ -13,12 +16,15 @@ DROP TABLE IF EXISTS t1,t2,t3; grant CREATE, SELECT, DROP on *.* to test@localhost; +--echo connect (con1,localhost,test,,test); connect (con1,localhost,test,,test); +--echo connection default; connection default; set global read_only=0; +--echo connection con1; connection con1; create table t1 (a int); @@ -27,6 +33,7 @@ insert into t1 values(1); create table t2 select * from t1; +--echo connection default; connection default; set global read_only=1; @@ -36,28 +43,29 @@ set global read_only=1; create table t3 (a int); drop table t3; +--echo connection con1; connection con1; select @@global.read_only; ---error 1290 +--error ER_OPTION_PREVENTS_STATEMENT create table t3 (a int); ---error 1290 +--error ER_OPTION_PREVENTS_STATEMENT insert into t1 values(1); # if a statement, after parse stage, looks like it will update a # non-temp table, it will be rejected, even if at execution it would # have turned out that 0 rows would be updated ---error 1290 +--error ER_OPTION_PREVENTS_STATEMENT update t1 set a=1 where 1=0; # multi-update is special (see sql_parse.cc) so we test it ---error 1290 +--error ER_OPTION_PREVENTS_STATEMENT update t1,t2 set t1.a=t2.a+1 where t1.a=t2.a; # check multi-delete to be sure ---error 1290 +--error ER_OPTION_PREVENTS_STATEMENT delete t1,t2 from t1,t2 where t1.a=t2.a; # With temp tables updates should be accepted: @@ -71,7 +79,7 @@ insert into t3 values(1); insert into t4 select * from t3; # a non-temp table updated: ---error 1290 +--error ER_OPTION_PREVENTS_STATEMENT update t1,t3 set t1.a=t3.a+1 where t1.a=t3.a; # no non-temp table updated (just swapped): @@ -79,7 +87,7 @@ update t1,t3 set t3.a=t1.a+1 where t1.a=t3.a; update t4,t3 set t4.a=t3.a+1 where t4.a=t3.a; ---error 1290 +--error ER_OPTION_PREVENTS_STATEMENT delete t1 from t1,t3 where t1.a=t3.a; delete t3 from t1,t3 where t1.a=t3.a; @@ -98,7 +106,7 @@ delete t1 from t1,t3 where t1.a=t3.a; drop table t1; ---error 1290 +--error ER_OPTION_PREVENTS_STATEMENT insert into t1 values(1); # @@ -109,77 +117,96 @@ insert into t1 values(1); # - is an error in the same connection # - is ok in a different connection +--echo connection default; connection default; set global read_only=0; lock table t1 write; +--echo connection con1; connection con1; lock table t2 write; +--echo connection default; connection default; --error ER_LOCK_OR_ACTIVE_TRANSACTION set global read_only=1; unlock tables ; # The following call blocks until con1 releases the write lock. # Blocking is expected. +--echo send set global read_only=1; send set global read_only=1; +--echo connection con1; connection con1; ---sleep 1 select @@global.read_only; unlock tables ; ---sleep 1 +let $wait_condition= SELECT @@global.read_only= 1; +--source include/wait_condition.inc select @@global.read_only; +--echo connection default; connection default; +--echo reap; reap; # LOCK TABLE ... READ / READ_ONLY # - is an error in the same connection # - is ok in a different connection +--echo connection default; connection default; set global read_only=0; lock table t1 read; +--echo connection con1; connection con1; lock table t2 read; +--echo connection default; connection default; --error ER_LOCK_OR_ACTIVE_TRANSACTION set global read_only=1; unlock tables ; # The following call blocks until con1 releases the read lock. # Blocking is a limitation, and could be improved. +--echo send set global read_only=1; send set global read_only=1; +--echo connection con1; connection con1; ---sleep 1 select @@global.read_only; unlock tables ; ---sleep 1 +let $wait_condition= SELECT @@global.read_only= 1; +--source include/wait_condition.inc select @@global.read_only; +--echo connection default; connection default; +--echo reap; reap; # pending transaction / READ_ONLY # - is an error in the same connection # - is ok in a different connection +--echo connection default; connection default; set global read_only=0; BEGIN; +--echo connection con1; connection con1; BEGIN; +--echo connection default; connection default; --error ER_LOCK_OR_ACTIVE_TRANSACTION set global read_only=1; ROLLBACK; + set global read_only=1; +--echo connection con1; connection con1; select @@global.read_only; ROLLBACK; @@ -188,21 +215,26 @@ ROLLBACK; # - in the same SUPER connection # - in another SUPER connection +--echo connection default; connection default; set global read_only=0; flush tables with read lock; set global read_only=1; unlock tables; +--echo connect (root2,localhost,root,,test); connect (root2,localhost,root,,test); +--echo connection default; connection default; set global read_only=0; flush tables with read lock; +--echo connection root2; connection root2; set global read_only=1; +--echo connection default; connection default; select @@global.read_only; unlock tables; @@ -221,6 +253,7 @@ drop temporary table if exists ttt; # # Cleanup # +--echo connection default; connection default; set global read_only=0; drop table t1,t2; @@ -244,14 +277,18 @@ grant all on mysqltest_db2.* to `mysqltest_u1`@`%`; create database mysqltest_db1; grant all on mysqltest_db1.* to `mysqltest_u1`@`%`; flush privileges; +--echo connect (con_bug27440,127.0.0.1,mysqltest_u1,,test,MASTER_MYPORT,); connect (con_bug27440,127.0.0.1,mysqltest_u1,,test,$MASTER_MYPORT,); +--echo connection con_bug27440; connection con_bug27440; --error ER_OPTION_PREVENTS_STATEMENT create database mysqltest_db2; show databases like '%mysqltest_db2%'; --error ER_OPTION_PREVENTS_STATEMENT drop database mysqltest_db1; +--echo disconnect con_bug27440; disconnect con_bug27440; +--echo connection default; connection default; delete from mysql.user where User like 'mysqltest_%'; delete from mysql.db where User like 'mysqltest_%'; @@ -259,4 +296,8 @@ delete from mysql.tables_priv where User like 'mysqltest_%'; delete from mysql.columns_priv where User like 'mysqltest_%'; flush privileges; drop database mysqltest_db1; -set global read_only=0; +set global read_only= @start_read_only; +disconnect con1; +disconnect root2; +--source include/wait_until_count_sessions.inc + diff --git a/mysql-test/t/rename.test b/mysql-test/t/rename.test index fce37d8466d..5aa1a51a90f 100644 --- a/mysql-test/t/rename.test +++ b/mysql-test/t/rename.test @@ -2,6 +2,8 @@ # Test of rename table # +--source include/count_sessions.inc + --disable_warnings drop table if exists t0,t1,t2,t3,t4; # Clear up from other tests (to ensure that SHOW TABLES below is right) @@ -19,16 +21,16 @@ rename table t3 to t4, t2 to t3, t1 to t2, t4 to t1; select * from t1; # The following should give errors ---error 1050,1050 +--error ER_TABLE_EXISTS_ERROR,ER_TABLE_EXISTS_ERROR rename table t1 to t2; ---error 1050,1050 +--error ER_TABLE_EXISTS_ERROR,ER_TABLE_EXISTS_ERROR rename table t1 to t1; ---error 1050,1050 +--error ER_TABLE_EXISTS_ERROR,ER_TABLE_EXISTS_ERROR rename table t3 to t4, t2 to t3, t1 to t2, t4 to t2; show tables like "t_"; ---error 1050,1050 +--error ER_TABLE_EXISTS_ERROR,ER_TABLE_EXISTS_ERROR rename table t3 to t1, t2 to t3, t1 to t2, t4 to t1; ---error 1017,1017 +--error ER_FILE_NOT_FOUND,ER_FILE_NOT_FOUND rename table t3 to t4, t5 to t3, t1 to t2, t4 to t1; select * from t1; @@ -63,7 +65,7 @@ connection con2; # Wait for the the tables to be renamed # i.e the query below succeds let $query= select * from t2, t4; -source include/wait_for_query_to_suceed.inc; +source include/wait_for_query_to_succeed.inc; show tables; @@ -83,13 +85,15 @@ connection default; create table t1(f1 int); create view v1 as select * from t1; alter table v1 rename to v2; ---error 1146 +--error ER_NO_SUCH_TABLE alter table v1 rename to v2; rename table v2 to v1; ---error 1050 +--error ER_TABLE_EXISTS_ERROR rename table v2 to v1; drop view v1; drop table t1; - --echo End of 5.0 tests + +--source include/wait_until_count_sessions.inc + From a328926b1cf92f60e07cc92d7d9b83ec19369638 Mon Sep 17 00:00:00 2001 From: Georgi Kodinov Date: Wed, 11 Feb 2009 12:04:40 +0200 Subject: [PATCH 062/219] changed the tree id pending a merge of 5.0-bugteam -> 5.0-main --- .bzr-mysql/default.conf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.bzr-mysql/default.conf b/.bzr-mysql/default.conf index 557df1b1ffe..f79c1cd6319 100644 --- a/.bzr-mysql/default.conf +++ b/.bzr-mysql/default.conf @@ -1,4 +1,4 @@ [MYSQL] post_commit_to = "commits@lists.mysql.com" post_push_to = "commits@lists.mysql.com" -tree_name = "mysql-5.0-bugteam" +tree_name = "mysql-5.0" From 6bd93f670271eaf2bd79bd7fa538e9baaa7dcb0f Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 11 Feb 2009 14:58:50 +0100 Subject: [PATCH 063/219] Raise version number after cloning 5.1.32 --- configure.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.in b/configure.in index b5beb7a24f5..bdeb0f24c40 100644 --- a/configure.in +++ b/configure.in @@ -10,7 +10,7 @@ AC_CANONICAL_SYSTEM # # When changing major version number please also check switch statement # in mysqlbinlog::check_master_version(). -AM_INIT_AUTOMAKE(mysql, 5.1.32) +AM_INIT_AUTOMAKE(mysql, 5.1.33) AM_CONFIG_HEADER([include/config.h:config.h.in]) PROTOCOL_VERSION=10 From 8db289c4d56940489e801b06a631e04fdcb1fbc4 Mon Sep 17 00:00:00 2001 From: Luis Soares Date: Wed, 11 Feb 2009 18:46:43 +0100 Subject: [PATCH 064/219] BUG#13684: post push fix for test case. The test case relies on binlog entries for assertion. The problem is that the binlog does not get cleaned in pushbuild between tests, resulting in extra entries in the result file, causing the test to fail. This fix adds a reset master at the beginning of the test, so that we get a clean binlog file. --- mysql-test/suite/rpl/r/rpl_drop_if_exists.result | 1 + mysql-test/suite/rpl/t/rpl_drop_if_exists.test | 1 + 2 files changed, 2 insertions(+) diff --git a/mysql-test/suite/rpl/r/rpl_drop_if_exists.result b/mysql-test/suite/rpl/r/rpl_drop_if_exists.result index bc02dd22561..59a2470cfdb 100644 --- a/mysql-test/suite/rpl/r/rpl_drop_if_exists.result +++ b/mysql-test/suite/rpl/r/rpl_drop_if_exists.result @@ -1,3 +1,4 @@ +RESET MASTER; DROP PROCEDURE IF EXISTS db_bug_13684.p; DROP FUNCTION IF EXISTS db_bug_13684.f; DROP TRIGGER IF EXISTS db_bug_13684.tr; diff --git a/mysql-test/suite/rpl/t/rpl_drop_if_exists.test b/mysql-test/suite/rpl/t/rpl_drop_if_exists.test index 41abdc51fd1..6b2b37ae791 100644 --- a/mysql-test/suite/rpl/t/rpl_drop_if_exists.test +++ b/mysql-test/suite/rpl/t/rpl_drop_if_exists.test @@ -40,6 +40,7 @@ # http://dev.mysql.com/doc/refman/5.1/en/sql-syntax-data-definition.html # --source include/have_log_bin.inc +RESET MASTER; disable_warnings; From ece8757cec010bc30fda2eafdf2df019e22d1abd Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 11 Feb 2009 21:33:46 +0100 Subject: [PATCH 065/219] Changed to use the correct "__sun" and "__hpux" predefined preprocessor symbols in libedit --- cmd-line-utils/libedit/readline/readline.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd-line-utils/libedit/readline/readline.h b/cmd-line-utils/libedit/readline/readline.h index c4806734bc5..18456fcfbcf 100644 --- a/cmd-line-utils/libedit/readline/readline.h +++ b/cmd-line-utils/libedit/readline/readline.h @@ -66,7 +66,7 @@ typedef KEYMAP_ENTRY *Keymap; #ifndef CTRL #include -#if !defined(__sun__) && !defined(__hpux__) +#if !defined(__sun) && !defined(__hpux) #include #endif #ifndef CTRL From 69d59240acb30f5fd8dc9e93d09057ca0fb31f23 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 12 Feb 2009 03:31:31 +0100 Subject: [PATCH 066/219] Exclude libedit inclusion of on AIX as well --- cmd-line-utils/libedit/readline/readline.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd-line-utils/libedit/readline/readline.h b/cmd-line-utils/libedit/readline/readline.h index 18456fcfbcf..c77b080c439 100644 --- a/cmd-line-utils/libedit/readline/readline.h +++ b/cmd-line-utils/libedit/readline/readline.h @@ -66,7 +66,7 @@ typedef KEYMAP_ENTRY *Keymap; #ifndef CTRL #include -#if !defined(__sun) && !defined(__hpux) +#if !defined(__sun) && !defined(__hpux) && !defined(_AIX) #include #endif #ifndef CTRL From 5803e106282eddbfed171f5d76f5357418d32af7 Mon Sep 17 00:00:00 2001 From: Sergey Vojtovich Date: Thu, 12 Feb 2009 13:49:44 +0400 Subject: [PATCH 067/219] BUG#36737 - having + full text operator crashes mysql MATCH() function accepts column list as an argument. It was possible to override this requirement with aliased non-column select expression. Which results in server crash. With this fix aliased non-column select expressions are not accepted by MATCH() function, returning an error. mysql-test/r/fulltext.result: A test case for BUG#36737. mysql-test/t/fulltext.test: A test case for BUG#36737. sql/item_func.cc: Only accept fields as arguments to MATCH(). --- mysql-test/r/fulltext.result | 4 ++++ mysql-test/t/fulltext.test | 8 ++++++++ sql/item_func.cc | 5 ++++- 3 files changed, 16 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/fulltext.result b/mysql-test/r/fulltext.result index 6821691c9d0..6ea17644f9d 100644 --- a/mysql-test/r/fulltext.result +++ b/mysql-test/r/fulltext.result @@ -506,3 +506,7 @@ SELECT MATCH(a) AGAINST('aaa1* aaa14 aaa15 aaa16' IN BOOLEAN MODE) FROM t1; MATCH(a) AGAINST('aaa1* aaa14 aaa15 aaa16' IN BOOLEAN MODE) 2 DROP TABLE t1; +CREATE TABLE t1(a TEXT); +SELECT GROUP_CONCAT(a) AS st FROM t1 HAVING MATCH(st) AGAINST('test' IN BOOLEAN MODE); +ERROR HY000: Incorrect arguments to AGAINST +DROP TABLE t1; diff --git a/mysql-test/t/fulltext.test b/mysql-test/t/fulltext.test index 77d84c730d9..76661ba4e63 100644 --- a/mysql-test/t/fulltext.test +++ b/mysql-test/t/fulltext.test @@ -432,3 +432,11 @@ INSERT INTO t1 VALUES('aaa15'); SELECT MATCH(a) AGAINST('aaa1* aaa14 aaa16' IN BOOLEAN MODE) FROM t1; SELECT MATCH(a) AGAINST('aaa1* aaa14 aaa15 aaa16' IN BOOLEAN MODE) FROM t1; DROP TABLE t1; + +# +# BUG#36737 - having + full text operator crashes mysql +# +CREATE TABLE t1(a TEXT); +--error ER_WRONG_ARGUMENTS +SELECT GROUP_CONCAT(a) AS st FROM t1 HAVING MATCH(st) AGAINST('test' IN BOOLEAN MODE); +DROP TABLE t1; diff --git a/sql/item_func.cc b/sql/item_func.cc index 913b32ccb88..55324923fe2 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -4961,7 +4961,10 @@ bool Item_func_match::fix_fields(THD *thd, Item **ref) if (item->type() == Item::REF_ITEM) args[i]= item= *((Item_ref *)item)->ref; if (item->type() != Item::FIELD_ITEM) - key=NO_SUCH_KEY; + { + my_error(ER_WRONG_ARGUMENTS, MYF(0), "AGAINST"); + return TRUE; + } } /* Check that all columns come from the same table. From e80537b7912b4790817e3afb6fc3f84f3a82d224 Mon Sep 17 00:00:00 2001 From: V Narayanan Date: Thu, 12 Feb 2009 16:42:07 +0530 Subject: [PATCH 068/219] Bug#40675 MySQL 5.1 crash with index merge algorithm and Merge tables A Query in the MyISAM merge table was crashing if the index merge algorithm was being used Index Merge optimization requires the reading of multiple indexes at the same time. Reading multiple indexes at once with current SE API means that we need to have handler instance for each to-be-read index. This is done by creating clones of the handlers instances. The clone internally does a open of the handler. The open for a MERGE engine is handled in the following phases 1) open parent table 2) generate list of underlying table 3) attach underlying tables But the current implementation does only the first phase (i.e.) open parent table. The current patch fixes this at the MERGE engine level, by handling the clone operation within the MERGE engine rather than in the storage engine API. It opens and attaches the MyISAM tables on the MyISAM storage engine interface directly within the MERGE engine. The new MyISAM table instances, as well as the MERGE clone itself, are not visible in the table cache. This is not a problem because all locking is handled by the original MERGE table from which this is cloned of. mysql-test/r/merge.result: updated the result file to reflect the new tests added to test the fix mysql-test/t/merge.test: Added new tests to verify that the index merge algorithm does not crash in the merge engine. storage/myisammrg/ha_myisammrg.cc: Implement the clone method, that handles 1) Cloning the handler 2) Opening underlying MYISAM child tables 3) Copies the state of the original handler and the children into the cloned instances 4) Sets the appropriate flags storage/myisammrg/ha_myisammrg.h: Added a flag that is set to indicate that the current instance is cloned. Also added the prototype or the clone method. storage/myisammrg/myrg_open.c: Since we do now again use myrg_open() in the server removed the comments marking this as deadcode. --- mysql-test/r/merge.result | 45 +++++++++++++++++- mysql-test/t/merge.test | 52 +++++++++++++++++++- storage/myisammrg/ha_myisammrg.cc | 79 +++++++++++++++++++++++++++++-- storage/myisammrg/ha_myisammrg.h | 2 + storage/myisammrg/myrg_open.c | 2 - 5 files changed, 171 insertions(+), 9 deletions(-) diff --git a/mysql-test/r/merge.result b/mysql-test/r/merge.result index 9ab982a6688..ba2eae9408b 100644 --- a/mysql-test/r/merge.result +++ b/mysql-test/r/merge.result @@ -2025,7 +2025,6 @@ TABLE_SCHEMA = 'test' and TABLE_NAME='tm1'; TABLE_CATALOG TABLE_SCHEMA TABLE_NAME TABLE_TYPE ENGINE VERSION ROW_FORMAT TABLE_ROWS AVG_ROW_LENGTH DATA_LENGTH MAX_DATA_LENGTH INDEX_LENGTH DATA_FREE AUTO_INCREMENT CREATE_TIME UPDATE_TIME CHECK_TIME TABLE_COLLATION CHECKSUM CREATE_OPTIONS TABLE_COMMENT NULL test tm1 BASE TABLE NULL NULL NULL # # # # # # # # # # NULL # # Unable to open underlying table which is differently defined or of non-MyISAM ty DROP TABLE tm1; -End of 5.1 tests CREATE TABLE t1(C1 INT, C2 INT, KEY C1(C1), KEY C2(C2)) ENGINE=MYISAM; CREATE TABLE t2(C1 INT, C2 INT, KEY C1(C1), KEY C2(C2)) ENGINE=MYISAM; CREATE TABLE t3(C1 INT, C2 INT, KEY C1(C1), KEY C2(C2)) ENGINE=MYISAM; @@ -2041,4 +2040,48 @@ EXPLAIN SELECT COUNT(*) FROM t4; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Select tables optimized away DROP TABLE t1, t2, t3, t4; +# +# Bug #40675 MySQL 5.1 crash with index merge algorithm and Merge tables +# +# create MYISAM table t1 and insert values into it +CREATE TABLE t1(a INT); +INSERT INTO t1 VALUES(1); +# create MYISAM table t2 and insert values into it +CREATE TABLE t2(a INT, b INT, dummy CHAR(16) DEFAULT '', KEY(a), KEY(b)); +INSERT INTO t2(a,b) VALUES +(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0), +(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0), +(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0), +(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0), +(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0), +(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0), +(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0), +(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0), +(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0), +(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0), +(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0), +(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0), +(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0), +(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0), +(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0), +(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0), +(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0), +(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0), +(1,2); +# Create the merge table t3 +CREATE TABLE t3(a INT, b INT, dummy CHAR(16) DEFAULT '', KEY(a), KEY(b)) +ENGINE=MERGE UNION=(t2) INSERT_METHOD=FIRST; +# Lock tables t1 and t3 for write +LOCK TABLES t1 WRITE, t3 WRITE; +# Insert values into the merge table t3 +INSERT INTO t3(a,b) VALUES(1,2); +# select from the join of t2 and t3 (The merge table) +SELECT t3.a FROM t1,t3 WHERE t3.b=2 AND t3.a=1; +a +1 +1 +# Unlock the tables +UNLOCK TABLES; +# drop the created tables +DROP TABLE t1, t2, t3; End of 5.1 tests diff --git a/mysql-test/t/merge.test b/mysql-test/t/merge.test index 118f8771f91..bb87c295ac6 100644 --- a/mysql-test/t/merge.test +++ b/mysql-test/t/merge.test @@ -1418,8 +1418,6 @@ TABLE_SCHEMA = 'test' and TABLE_NAME='tm1'; DROP TABLE tm1; ---echo End of 5.1 tests - # # Bug#36006 - Optimizer does table scan for select count(*) # @@ -1435,4 +1433,54 @@ EXPLAIN SELECT COUNT(*) FROM t1; EXPLAIN SELECT COUNT(*) FROM t4; DROP TABLE t1, t2, t3, t4; +--echo # +--echo # Bug #40675 MySQL 5.1 crash with index merge algorithm and Merge tables +--echo # + +--echo # create MYISAM table t1 and insert values into it +CREATE TABLE t1(a INT); +INSERT INTO t1 VALUES(1); + +--echo # create MYISAM table t2 and insert values into it +CREATE TABLE t2(a INT, b INT, dummy CHAR(16) DEFAULT '', KEY(a), KEY(b)); +INSERT INTO t2(a,b) VALUES +(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0), +(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0), +(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0), +(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0), +(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0), +(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0), +(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0), +(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0), +(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0), +(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0), +(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0), +(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0), +(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0), +(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0), +(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0), +(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0), +(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0), +(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0), +(1,2); + +--echo # Create the merge table t3 +CREATE TABLE t3(a INT, b INT, dummy CHAR(16) DEFAULT '', KEY(a), KEY(b)) +ENGINE=MERGE UNION=(t2) INSERT_METHOD=FIRST; + +--echo # Lock tables t1 and t3 for write +LOCK TABLES t1 WRITE, t3 WRITE; + +--echo # Insert values into the merge table t3 +INSERT INTO t3(a,b) VALUES(1,2); + +--echo # select from the join of t2 and t3 (The merge table) +SELECT t3.a FROM t1,t3 WHERE t3.b=2 AND t3.a=1; + +--echo # Unlock the tables +UNLOCK TABLES; + +--echo # drop the created tables +DROP TABLE t1, t2, t3; + --echo End of 5.1 tests diff --git a/storage/myisammrg/ha_myisammrg.cc b/storage/myisammrg/ha_myisammrg.cc index 956f0e421cc..d674f6bc150 100644 --- a/storage/myisammrg/ha_myisammrg.cc +++ b/storage/myisammrg/ha_myisammrg.cc @@ -116,7 +116,7 @@ static handler *myisammrg_create_handler(handlerton *hton, */ ha_myisammrg::ha_myisammrg(handlerton *hton, TABLE_SHARE *table_arg) - :handler(hton, table_arg), file(0) + :handler(hton, table_arg), file(0), is_cloned(0) {} @@ -413,7 +413,28 @@ int ha_myisammrg::open(const char *name, int mode __attribute__((unused)), /* retrieve children table list. */ my_errno= 0; - if (!(file= myrg_parent_open(name, myisammrg_parent_open_callback, this))) + if (is_cloned) + { + /* + Open and attaches the MyISAM tables,that are under the MERGE table + parent, on the MyISAM storage engine interface directly within the + MERGE engine. The new MyISAM table instances, as well as the MERGE + clone itself, are not visible in the table cache. This is not a + problem because all locking is handled by the original MERGE table + from which this is cloned of. + */ + if (!(file= myrg_open(table->s->normalized_path.str, table->db_stat, + HA_OPEN_IGNORE_IF_LOCKED))) + { + DBUG_PRINT("error", ("my_errno %d", my_errno)); + DBUG_RETURN(my_errno ? my_errno : -1); + } + + file->children_attached= TRUE; + + info(HA_STATUS_NO_LOCK | HA_STATUS_VARIABLE | HA_STATUS_CONST); + } + else if (!(file= myrg_parent_open(name, myisammrg_parent_open_callback, this))) { DBUG_PRINT("error", ("my_errno %d", my_errno)); DBUG_RETURN(my_errno ? my_errno : -1); @@ -422,6 +443,55 @@ int ha_myisammrg::open(const char *name, int mode __attribute__((unused)), DBUG_RETURN(0); } +/** + Returns a cloned instance of the current handler. + + @return A cloned handler instance. + */ +handler *ha_myisammrg::clone(MEM_ROOT *mem_root) +{ + MYRG_TABLE *u_table,*newu_table; + ha_myisammrg *new_handler= + (ha_myisammrg*) get_new_handler(table->s, mem_root, table->s->db_type()); + if (!new_handler) + return NULL; + + /* Inform ha_myisammrg::open() that it is a cloned handler */ + new_handler->is_cloned= TRUE; + /* + Allocate handler->ref here because otherwise ha_open will allocate it + on this->table->mem_root and we will not be able to reclaim that memory + when the clone handler object is destroyed. + */ + if (!(new_handler->ref= (uchar*) alloc_root(mem_root, ALIGN_SIZE(ref_length)*2))) + { + delete new_handler; + return NULL; + } + + if (new_handler->ha_open(table, table->s->normalized_path.str, table->db_stat, + HA_OPEN_IGNORE_IF_LOCKED)) + { + delete new_handler; + return NULL; + } + + /* + Iterate through the original child tables and + copy the state into the cloned child tables. + We need to do this because all the child tables + can be involved in delete. + */ + newu_table= new_handler->file->open_tables; + for (u_table= file->open_tables; u_table < file->end_table; u_table++) + { + newu_table->table->state= u_table->table->state; + newu_table++; + } + + return new_handler; + } + /** @brief Attach children to a MERGE table. @@ -613,9 +683,10 @@ int ha_myisammrg::close(void) DBUG_ENTER("ha_myisammrg::close"); /* Children must not be attached here. Unless the MERGE table has no - children. In this case children_attached is always true. + children or the handler instance has been cloned. In these cases + children_attached is always true. */ - DBUG_ASSERT(!this->file->children_attached || !this->file->tables); + DBUG_ASSERT(!this->file->children_attached || !this->file->tables || this->is_cloned); rc= myrg_close(file); file= 0; DBUG_RETURN(rc); diff --git a/storage/myisammrg/ha_myisammrg.h b/storage/myisammrg/ha_myisammrg.h index 4e7ddebb836..21d41c9d75a 100644 --- a/storage/myisammrg/ha_myisammrg.h +++ b/storage/myisammrg/ha_myisammrg.h @@ -25,6 +25,7 @@ class ha_myisammrg: public handler { MYRG_INFO *file; + my_bool is_cloned; /* This instance has been cloned */ public: TABLE_LIST *next_child_attach; /* next child to attach */ @@ -60,6 +61,7 @@ class ha_myisammrg: public handler int open(const char *name, int mode, uint test_if_locked); int attach_children(void); int detach_children(void); + virtual handler *clone(MEM_ROOT *mem_root); int close(void); int write_row(uchar * buf); int update_row(const uchar * old_data, uchar * new_data); diff --git a/storage/myisammrg/myrg_open.c b/storage/myisammrg/myrg_open.c index 64b4be2b7ca..fc7f22dc4b2 100644 --- a/storage/myisammrg/myrg_open.c +++ b/storage/myisammrg/myrg_open.c @@ -33,7 +33,6 @@ myrg_attach_children(). Please duplicate changes in these functions or make common sub-functions. */ -/* purecov: begin deadcode */ /* not used in MySQL server */ MYRG_INFO *myrg_open(const char *name, int mode, int handle_locking) { @@ -198,7 +197,6 @@ err: my_errno=save_errno; DBUG_RETURN (NULL); } -/* purecov: end */ /** From 1c5fa3b6a90ab659f42e05f16f3e65b72c661700 Mon Sep 17 00:00:00 2001 From: Georgi Kodinov Date: Thu, 12 Feb 2009 16:36:43 +0200 Subject: [PATCH 069/219] Bug #33813: Schema names are case-sensitive in DROP FUNCTION Additional fix: 1. Revert the unification of DROP FUNCTION and DROP PROCEDURE, because DROP FUNCTION can be used to drop UDFs (that have a non-qualified name and don't require database name to be present and valid). 2. Fixed the case sensitivity problem by adding a call to check_db_name() (similar to the sp_name production). --- sql/sql_yacc.yy | 38 +++++++++++++++++++++++++++++++++++--- 1 file changed, 35 insertions(+), 3 deletions(-) diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index fbaf761cc33..51fb5dbdfe4 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -7507,9 +7507,16 @@ drop: lex->drop_if_exists=$3; lex->name=$4.str; } - | DROP FUNCTION_SYM if_exists sp_name + | DROP FUNCTION_SYM if_exists ident '.' ident { - LEX *lex= Lex; + THD *thd= YYTHD; + LEX *lex= thd->lex; + sp_name *spname; + if ($4.str && check_db_name($4.str)) + { + my_error(ER_WRONG_DB_NAME, MYF(0), $4.str); + MYSQL_YYABORT; + } if (lex->sphead) { my_error(ER_SP_NO_DROP_SP, MYF(0), "FUNCTION"); @@ -7517,7 +7524,32 @@ drop: } lex->sql_command = SQLCOM_DROP_FUNCTION; lex->drop_if_exists= $3; - lex->spname= $4; + spname= new sp_name($4, $6, true); + if (spname == NULL) + MYSQL_YYABORT; + spname->init_qname(thd); + lex->spname= spname; + } + | DROP FUNCTION_SYM if_exists ident + { + THD *thd= YYTHD; + LEX *lex= thd->lex; + LEX_STRING db= {0, 0}; + sp_name *spname; + if (lex->sphead) + { + my_error(ER_SP_NO_DROP_SP, MYF(0), "FUNCTION"); + MYSQL_YYABORT; + } + if (thd->db && lex->copy_db_to(&db.str, &db.length)) + MYSQL_YYABORT; + lex->sql_command = SQLCOM_DROP_FUNCTION; + lex->drop_if_exists= $3; + spname= new sp_name(db, $4, false); + if (spname == NULL) + MYSQL_YYABORT; + spname->init_qname(thd); + lex->spname= spname; } | DROP PROCEDURE if_exists sp_name { From d52312295ba325ee54c070a8ea85ba124f6337cd Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 12 Feb 2009 16:01:38 +0100 Subject: [PATCH 070/219] More portability fixes. --- cmd-line-utils/libedit/makelist.sh | 4 ++-- cmd-line-utils/libedit/readline.c | 5 +---- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/cmd-line-utils/libedit/makelist.sh b/cmd-line-utils/libedit/makelist.sh index fdd3f934e15..5d25b4776c9 100644 --- a/cmd-line-utils/libedit/makelist.sh +++ b/cmd-line-utils/libedit/makelist.sh @@ -84,7 +84,7 @@ case $FLAG in cat $FILES | $AWK ' BEGIN { printf("/* Automatically generated file, do not edit */\n"); - printf("#include \"sys.h\"\n#include \"el.h\"\n"); + printf("#include \"config.h\"\n#include \"el.h\"\n"); printf("private const struct el_bindings_t el_func_help[] = {\n"); low = "abcdefghijklmnopqrstuvwxyz_"; high = "ABCDEFGHIJKLMNOPQRSTUVWXYZ_"; @@ -169,7 +169,7 @@ case $FLAG in cat $FILES | $AWK '/el_action_t/ { print $3 }' | sort | $AWK ' BEGIN { printf("/* Automatically generated file, do not edit */\n"); - printf("#include \"sys.h\"\n#include \"el.h\"\n"); + printf("#include \"config.h\"\n#include \"el.h\"\n"); printf("private const el_func_t el_func[] = {"); maxlen = 80; needn = 1; diff --git a/cmd-line-utils/libedit/readline.c b/cmd-line-utils/libedit/readline.c index ca8796fbd37..1f1b18c97d8 100644 --- a/cmd-line-utils/libedit/readline.c +++ b/cmd-line-utils/libedit/readline.c @@ -51,13 +51,10 @@ #else #include "np/vis.h" #endif -#ifdef HAVE_ALLOCA_H -#include -#endif +#include "readline/readline.h" #include "el.h" #include "fcns.h" /* for EL_NUM_FCNS */ #include "histedit.h" -#include "readline/readline.h" #include "filecomplete.h" void rl_prep_terminal(int); From 34d066a21c543dfe640c10ffca8aa85ba9101061 Mon Sep 17 00:00:00 2001 From: Vladislav Vaintroub Date: Thu, 12 Feb 2009 17:13:56 +0100 Subject: [PATCH 071/219] Bug#42788 lib\My\CoreDump.pm needs to be ported for Windows. - output callstacks from crash using cdb debugger which is part of "Debugging Tools for Windows". Output other interesting information - function parameters, possibly source code fragment and other goodies of "!analyze" cdb extension. --- mysql-test/lib/My/CoreDump.pm | 127 ++++++++++++++++++++++++++++++++++ 1 file changed, 127 insertions(+) diff --git a/mysql-test/lib/My/CoreDump.pm b/mysql-test/lib/My/CoreDump.pm index 599f9ccbfca..f3e9f521384 100644 --- a/mysql-test/lib/My/CoreDump.pm +++ b/mysql-test/lib/My/CoreDump.pm @@ -104,9 +104,136 @@ EOF } +# Check that Debugging tools for Windows are installed +sub cdb_check { + `cdb -? 2>&1`; + if ($? >> 8) + { + print "Cannot find cdb. Please Install Debugging tools for Windows\n"; + print "from http://www.microsoft.com/whdc/devtools/debugging/"; + if($ENV{'ProgramW6432'}) + { + print "install64bit.mspx (native x64 version)\n"; + } + else + { + print "installx86.mspx\n"; + } + } +} + + +sub _cdb { + my ($core_name)= @_; + print "\nTrying 'cdb' to get a backtrace\n"; + return unless -f $core_name; + + # Try to set environment for debugging tools for Windows + if ($ENV{'PATH'} !~ /Debugging Tools/) + { + if ($ENV{'ProgramW6432'}) + { + # On x64 computer + $ENV{'PATH'}.= ";".$ENV{'ProgramW6432'}."\\Debugging Tools For Windows (x64)"; + } + else + { + # On x86 computer. Newest versions of Debugging tools are installed in the + # directory with (x86) suffix, older versions did not have this suffix. + $ENV{'PATH'}.= ";".$ENV{'ProgramFiles'}."\\Debugging Tools For Windows (x86)"; + $ENV{'PATH'}.= ";".$ENV{'ProgramFiles'}."\\Debugging Tools For Windows"; + } + } + + + # Read module list, find out the name of executable and + # build symbol path (required by cdb if executable was built on + # different machine) + my $tmp_name= $core_name.".cdb_lmv"; + `cdb -z $core_name -c \"lmv;q\" > $tmp_name 2>&1`; + if ($? >> 8) + { + unlink($tmp_name); + # check if cdb is installed and complain if not + cdb_check(); + return; + } + + open(temp,"< $tmp_name"); + my %dirhash=(); + while() + { + if($_ =~ /Image path\: (.*)/) + { + if (rindex($1,'\\') != -1) + { + my $dir= substr($1, 0, rindex($1,'\\')); + $dirhash{$dir}++; + } + } + } + close(temp); + unlink($tmp_name); + + my $image_path= join(";", (keys %dirhash),"."); + + # For better callstacks, setup _NT_SYMBOL_PATH to include + # OS symbols. Note : Dowloading symbols for the first time + # can take some minutes + if (!$ENV{'_NT_SYMBOL_PATH'}) + { + my $windir= $ENV{'windir'}; + my $symbol_cache= substr($windir ,0, index($windir,'\\'))."\\cdb_symbols"; + + print "OS debug symbols will be downloaded and stored in $symbol_cache.\n"; + print "You can control the location of symbol cache with _NT_SYMBOL_PATH\n"; + print "environment variable. Please refer to Microsoft KB article\n"; + print "http://support.microsoft.com/kb/311503 for details about _NT_SYMBOL_PATH\n"; + print "-------------------------------------------------------------------------\n"; + + $ENV{'_NT_SYMBOL_PATH'}.= + "srv*".$symbol_cache."*http://msdl.microsoft.com/download/symbols"; + } + + my $symbol_path= $image_path.";".$ENV{'_NT_SYMBOL_PATH'}; + + + # Run cdb. Use "analyze" extension to print crashing thread stacktrace + # and "uniqstack" to print other threads + + my $cdb_cmd = "!sym prompts off; !analyze -v; .ecxr; !for_each_frame dv /t;!uniqstack -p;q"; + my $cdb_output= + `cdb -z $core_name -i "$image_path" -y "$symbol_path" -t 0 -lines -c "$cdb_cmd" 2>&1`; + return if $? >> 8; + return unless $cdb_output; + + # Remove comments (lines starting with *), stack pointer and frame + # pointer adresses and offsets to function to make output better readable + $cdb_output=~ s/^\*.*\n//gm; + $cdb_output=~ s/^([\:0-9a-fA-F\`]+ )+//gm; + $cdb_output=~ s/^ChildEBP RetAddr//gm; + $cdb_output=~ s/^Child\-SP RetAddr Call Site//gm; + $cdb_output=~ s/\+0x([0-9a-fA-F]+)//gm; + + print < Date: Thu, 12 Feb 2009 17:36:58 +0100 Subject: [PATCH 072/219] Bug#42797 mtr.pl - temporary directory are deleted when child exit's - Since we are only using the auto cleanup in one place of mtr.pl today, disable the autocleanup and write our own END handler that clean up the tmpdir only when the process that created it exits. --- mysql-test/mysql-test-run.pl | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl index ba426446075..f8f9b89d141 100755 --- a/mysql-test/mysql-test-run.pl +++ b/mysql-test/mysql-test-run.pl @@ -107,6 +107,17 @@ our $default_vardir; our $opt_vardir; # Path to use for var/ dir my $path_vardir_trace; # unix formatted opt_vardir for trace files my $opt_tmpdir; # Path to use for tmp/ dir +my $opt_tmpdir_pid; + +END { + if (defined $opt_tmpdir_pid and + $opt_tmpdir_pid == $$){ + # Remove the tempdir this process has created + mtr_verbose("Removing tmpdir '$opt_tmpdir"); + rmtree($opt_tmpdir); + } +} + my $path_config_file; # The generated config file, var/my.cnf # Visual Studio produces executables in different sub-directories based on the @@ -1066,8 +1077,11 @@ sub command_line_setup { " creating a shorter one..."); # Create temporary directory in standard location for temporary files - $opt_tmpdir= tempdir( TMPDIR => 1, CLEANUP => 1 ); + $opt_tmpdir= tempdir( TMPDIR => 1, CLEANUP => 0 ); mtr_report(" - using tmpdir: '$opt_tmpdir'\n"); + + # Remember pid that created dir so it's removed by correct process + $opt_tmpdir_pid= $$; } } $opt_tmpdir =~ s,/+$,,; # Remove ending slash if any From 8865766a4e048e740a62e6b471104403e5803bbb Mon Sep 17 00:00:00 2001 From: Davi Arnaut Date: Thu, 12 Feb 2009 20:32:37 -0200 Subject: [PATCH 073/219] Backport from 6.0 fix for Bug#38249 2722 Konstantin Osipov 2008-10-03 Fix Bug#38249 innodb_log_arch_dir still in support files Remove a non-supported variable from cnf file templates. --- support-files/my-huge.cnf.sh | 1 - support-files/my-large.cnf.sh | 1 - support-files/my-medium.cnf.sh | 1 - support-files/my-small.cnf.sh | 1 - 4 files changed, 4 deletions(-) diff --git a/support-files/my-huge.cnf.sh b/support-files/my-huge.cnf.sh index 5be8f5e67a0..8763dc61bb4 100644 --- a/support-files/my-huge.cnf.sh +++ b/support-files/my-huge.cnf.sh @@ -124,7 +124,6 @@ server-id = 1 #innodb_data_home_dir = @localstatedir@/ #innodb_data_file_path = ibdata1:2000M;ibdata2:10M:autoextend #innodb_log_group_home_dir = @localstatedir@/ -#innodb_log_arch_dir = @localstatedir@/ # You can set .._buffer_pool_size up to 50 - 80 % # of RAM but beware of setting memory usage too high #innodb_buffer_pool_size = 384M diff --git a/support-files/my-large.cnf.sh b/support-files/my-large.cnf.sh index 0d5719e4438..2a010acdfd8 100644 --- a/support-files/my-large.cnf.sh +++ b/support-files/my-large.cnf.sh @@ -124,7 +124,6 @@ server-id = 1 #innodb_data_home_dir = @localstatedir@/ #innodb_data_file_path = ibdata1:10M:autoextend #innodb_log_group_home_dir = @localstatedir@/ -#innodb_log_arch_dir = @localstatedir@/ # You can set .._buffer_pool_size up to 50 - 80 % # of RAM but beware of setting memory usage too high #innodb_buffer_pool_size = 256M diff --git a/support-files/my-medium.cnf.sh b/support-files/my-medium.cnf.sh index 211b8ed5e8e..9dc2a299332 100644 --- a/support-files/my-medium.cnf.sh +++ b/support-files/my-medium.cnf.sh @@ -122,7 +122,6 @@ server-id = 1 #innodb_data_home_dir = @localstatedir@/ #innodb_data_file_path = ibdata1:10M:autoextend #innodb_log_group_home_dir = @localstatedir@/ -#innodb_log_arch_dir = @localstatedir@/ # You can set .._buffer_pool_size up to 50 - 80 % # of RAM but beware of setting memory usage too high #innodb_buffer_pool_size = 16M diff --git a/support-files/my-small.cnf.sh b/support-files/my-small.cnf.sh index 7bf8f323d57..c7a995ba95a 100644 --- a/support-files/my-small.cnf.sh +++ b/support-files/my-small.cnf.sh @@ -55,7 +55,6 @@ server-id = 1 #innodb_data_home_dir = @localstatedir@/ #innodb_data_file_path = ibdata1:10M:autoextend #innodb_log_group_home_dir = @localstatedir@/ -#innodb_log_arch_dir = @localstatedir@/ # You can set .._buffer_pool_size up to 50 - 80 % # of RAM but beware of setting memory usage too high #innodb_buffer_pool_size = 16M From 12f09e5ac0ae3a9edb50f04b89dd251bf7871fc5 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 13 Feb 2009 10:38:53 +0100 Subject: [PATCH 074/219] Work around for bug in some versions of the File::Temp Perl module --- mysql-test/mysql-test-run.pl | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl index ba426446075..89eed6a1736 100755 --- a/mysql-test/mysql-test-run.pl +++ b/mysql-test/mysql-test-run.pl @@ -107,6 +107,17 @@ our $default_vardir; our $opt_vardir; # Path to use for var/ dir my $path_vardir_trace; # unix formatted opt_vardir for trace files my $opt_tmpdir; # Path to use for tmp/ dir +my $opt_tmpdir_pid; + +END { + if ( defined $opt_tmpdir_pid and $opt_tmpdir_pid == $$ ) + { + # Remove the tempdir this process has created + mtr_verbose("Removing tmpdir '$opt_tmpdir"); + rmtree($opt_tmpdir); + } +} + my $path_config_file; # The generated config file, var/my.cnf # Visual Studio produces executables in different sub-directories based on the @@ -1066,8 +1077,11 @@ sub command_line_setup { " creating a shorter one..."); # Create temporary directory in standard location for temporary files - $opt_tmpdir= tempdir( TMPDIR => 1, CLEANUP => 1 ); + $opt_tmpdir= tempdir( TMPDIR => 1, CLEANUP => 0 ); mtr_report(" - using tmpdir: '$opt_tmpdir'\n"); + + # Remember pid that created dir so it's removed by correct process + $opt_tmpdir_pid= $$; } } $opt_tmpdir =~ s,/+$,,; # Remove ending slash if any From 018624301cb85418a09b63cff131eae2a695e1a1 Mon Sep 17 00:00:00 2001 From: MySQL Build Team Date: Fri, 13 Feb 2009 10:42:27 +0100 Subject: [PATCH 075/219] Added to source package the file "mysql-test/suite/bugs/combinations" and the directory "mysql-test/suite/jp/include" --- mysql-test/Makefile.am | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mysql-test/Makefile.am b/mysql-test/Makefile.am index dc9fbbd9aa5..60679e5b06d 100644 --- a/mysql-test/Makefile.am +++ b/mysql-test/Makefile.am @@ -81,7 +81,7 @@ TEST_DIRS = t r include std_data std_data/parts \ std_data/funcs_1 \ extra/binlog_tests/ extra/rpl_tests \ suite/binlog suite/binlog/t suite/binlog/r suite/binlog/std_data \ - suite/bugs/data suite/bugs/t suite/bugs/r \ + suite/bugs suite/bugs/data suite/bugs/t suite/bugs/r \ suite/federated \ suite/funcs_1 suite/funcs_1/bitdata \ suite/funcs_1/include suite/funcs_1/lib suite/funcs_1/r \ @@ -90,7 +90,7 @@ TEST_DIRS = t r include std_data std_data/parts \ suite/funcs_2 suite/funcs_2/charset suite/funcs_2/data \ suite/funcs_2/include suite/funcs_2/lib suite/funcs_2/r \ suite/funcs_2/t \ - suite/jp suite/jp/t suite/jp/r suite/jp/std_data \ + suite/jp suite/jp/t suite/jp/r suite/jp/std_data suite/jp/include \ suite/manual/t suite/manual/r \ suite/ndb_team suite/ndb_team/t suite/ndb_team/r \ suite/rpl suite/rpl/data suite/rpl/include suite/rpl/r \ From 39bf7340886aaa7c804c34fb5ee780a39cc08f69 Mon Sep 17 00:00:00 2001 From: Anurag Shekhar Date: Fri, 13 Feb 2009 17:11:54 +0530 Subject: [PATCH 076/219] Bug#40321 ha_myisam::info could update rec_per_key incorrectly MyISAM did copy of key statistics incorrectly, which may cause server crash or incorrect cardinality values. This may happen only on platforms where size of long differs from size of pointer. To determine number of bytes to be copied from array of ulong, MyISAM mistakenly used sizoef(pointer) instead of sizeof(ulong). --- storage/myisam/ha_myisam.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/storage/myisam/ha_myisam.cc b/storage/myisam/ha_myisam.cc index 4073044bf63..eb31c0b84cf 100644 --- a/storage/myisam/ha_myisam.cc +++ b/storage/myisam/ha_myisam.cc @@ -1753,7 +1753,7 @@ int ha_myisam::info(uint flag) if (share->key_parts) memcpy((char*) table->key_info[0].rec_per_key, (char*) misam_info.rec_per_key, - sizeof(table->key_info[0].rec_per_key)*share->key_parts); + sizeof(table->key_info[0].rec_per_key[0])*share->key_parts); if (share->tmp_table == NO_TMP_TABLE) pthread_mutex_unlock(&share->mutex); From e258efd4926dbcf677637f97365437cb58d5bfd2 Mon Sep 17 00:00:00 2001 From: Staale Smedseng Date: Fri, 13 Feb 2009 13:35:38 +0100 Subject: [PATCH 077/219] A fix for Bug#41528 --- sql-bench/test-create.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql-bench/test-create.sh b/sql-bench/test-create.sh index bc2f17c1f0a..63672519e61 100644 --- a/sql-bench/test-create.sh +++ b/sql-bench/test-create.sh @@ -247,7 +247,7 @@ for ($i=2 ; $i <= $keys ; $i++) $loop_time=new Benchmark; for ($i=1 ; $i <= $opt_loop_count ; $i++) { - do_many($dbh,$server->create("bench_$i", \@fields, \@index)); + do_many($dbh,$server->create("bench_$i", \@fields, \@keys)); $dbh->do("drop table bench_$i" . $server->{'drop_attr'}) or die $DBI::errstr; } From bdbe393db1b55cbde9aa4ca66cc551b57dad7f1f Mon Sep 17 00:00:00 2001 From: Rafal Somla Date: Fri, 13 Feb 2009 16:27:33 +0100 Subject: [PATCH 078/219] Modifications to MTR and mysqltest to improve feedback from the latter when testcase checks are made. MTR spawns mysqltest to run check-testcase test before and after each testcase it runs. It can also run check-warnings using mysqltest. Since it happened on PB that these checks hanged, this patch provides additional feedback to help investigating such failures: - mysqltest is modified to give feedback about main steps in execution of a testcase if run in verbose mode (including connection to the server), - MTR is modified to run mysqltest in verbose mode when doing check-testcase or check-warnings. The diagnostic output from mysqltest is preserved so that it is saved upon test failure. client/mysqltest.cc: Add verbose messages informing about main steps in execution of a testcase. mysql-test/mysql-test-run.pl: - When doing check-testcase or check-warnings run mysqltest in verbose mode. - Do not delete the mysqltest's error log if errors are detected during these --- client/mysqltest.cc | 14 ++++++++++++++ mysql-test/mysql-test-run.pl | 15 +++++---------- 2 files changed, 19 insertions(+), 10 deletions(-) diff --git a/client/mysqltest.cc b/client/mysqltest.cc index 89b9c78a049..e9e462b8d3f 100644 --- a/client/mysqltest.cc +++ b/client/mysqltest.cc @@ -4647,6 +4647,10 @@ void safe_connect(MYSQL* mysql, const char *name, const char *host, int failed_attempts= 0; DBUG_ENTER("safe_connect"); + + verbose_msg("Connecting to server %s:%d (socket %s) as '%s'" + ", connection '%s', attempt %d ...", + host, port, sock, user, name, failed_attempts); while(!mysql_real_connect(mysql, host,user, pass, db, port, sock, CLIENT_MULTI_STATEMENTS | CLIENT_REMEMBER_OPTIONS)) { @@ -4678,6 +4682,7 @@ void safe_connect(MYSQL* mysql, const char *name, const char *host, } failed_attempts++; } + verbose_msg("... Connected."); DBUG_VOID_RETURN; } @@ -7511,8 +7516,12 @@ int main(int argc, char **argv) parse_args(argc, argv); log_file.open(opt_logdir, result_file_name, ".log"); + verbose_msg("Logging to '%s'.", log_file.file_name()); if (opt_mark_progress) + { progress_file.open(opt_logdir, result_file_name, ".progress"); + verbose_msg("Tracing progress in '%s'.", progress_file.file_name()); + } var_set_int("$PS_PROTOCOL", ps_protocol); var_set_int("$SP_PROTOCOL", sp_protocol); @@ -7521,6 +7530,8 @@ int main(int argc, char **argv) DBUG_PRINT("info",("result_file: '%s'", result_file_name ? result_file_name : "")); + verbose_msg("Results saved in '%s'.", + result_file_name ? result_file_name : ""); if (mysql_server_init(embedded_server_arg_count, embedded_server_args, (char**) embedded_server_groups)) @@ -7591,6 +7602,7 @@ int main(int argc, char **argv) open_file(opt_include); } + verbose_msg("Start processing test commands from '%s' ...", cur_file->file_name); while (!read_command(&command) && !abort_flag) { int current_line_inc = 1, processed = 0; @@ -7908,6 +7920,7 @@ int main(int argc, char **argv) log_file.close(); start_lineno= 0; + verbose_msg("... Done processing test commands."); if (parsing_disabled) die("Test ended with parsing disabled"); @@ -7958,6 +7971,7 @@ int main(int argc, char **argv) if (!command_executed && result_file_name) die("No queries executed but result file found!"); + verbose_msg("Test has succeeded!"); timer_output(); /* Yes, if we got this far the test has suceeded! Sakila smiles */ cleanup_and_exit(0); diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl index f8f9b89d141..50617428d0f 100755 --- a/mysql-test/mysql-test-run.pl +++ b/mysql-test/mysql-test-run.pl @@ -2874,9 +2874,6 @@ test case was executed:\n"; $result= 2; } - # Remove the .err file the check generated - unlink($err_file); - # Remove the .result file the check generated unlink("$base_file.result"); @@ -3494,6 +3491,7 @@ sub start_check_warnings ($$) { mtr_add_arg($args, "--skip-safemalloc"); mtr_add_arg($args, "--test-file=%s", "include/check-warnings.test"); + mtr_add_arg($args, "--verbose"); if ( $opt_embedded_server ) { @@ -3583,10 +3581,9 @@ sub check_warnings ($) { if ( $res == 62 ) { # Test case was ok and called "skip" - ; + # Remove the .err file the check generated + unlink($err_file); } - # Remove the .err file the check generated - unlink($err_file); if ( keys(%started) == 0){ # All checks completed @@ -3608,8 +3605,6 @@ sub check_warnings ($) { $result= 2; } - # Remove the .err file the check generated - unlink($err_file); } elsif ( $proc eq $timeout_proc ) { $tinfo->{comment}.= "Timeout $timeout_proc for ". @@ -4493,6 +4488,7 @@ sub start_check_testcase ($$$) { mtr_add_arg($args, "--result-file=%s", "$opt_vardir/tmp/$name.result"); mtr_add_arg($args, "--test-file=%s", "include/check-testcase.test"); + mtr_add_arg($args, "--verbose"); if ( $mode eq "before" ) { @@ -4662,8 +4658,7 @@ sub start_mysqltest ($) { elsif ( $opt_client_debugger ) { debugger_arguments(\$args, \$exe, "client"); - } - + } my $proc= My::SafeProcess->new ( From 694323952aafe3030cf2d9bdc5cae77c3d817fbc Mon Sep 17 00:00:00 2001 From: "Tatiana A. Nurnberg" Date: Fri, 13 Feb 2009 19:07:03 +0100 Subject: [PATCH 079/219] Bug#42146 - DATETIME fractional seconds parse error Bug#38435 - LONG Microseconds cause MySQL to fail a CAST to DATETIME or DATE Parsing of optional microsecond part in datetime did not fail gracefully when field width was larger than the allowed six places. Now handles up to the correct six places, and disregards any extra digits without messing up what we've already got. mysql-test/r/type_datetime.result: show graceful handling of overly long microsecond parts (correct truncation). mysql-test/t/type_datetime.test: show graceful handling of overly long microsecond parts (correct truncation). sql-common/my_time.c: Special case for time-parsing: for microsecond part, leading zeroes are actually meaningful! Also, don't break the entire date on more than the allowed six digits in microsecond part, just truncate the extra digits. --- mysql-test/r/type_datetime.result | 19 +++++++++++++++++++ mysql-test/t/type_datetime.test | 19 +++++++++++++++++++ sql-common/my_time.c | 13 ++++++++++++- 3 files changed, 50 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/type_datetime.result b/mysql-test/r/type_datetime.result index 6a692ed58e4..b6281443751 100644 --- a/mysql-test/r/type_datetime.result +++ b/mysql-test/r/type_datetime.result @@ -619,3 +619,22 @@ ERROR 42000: Invalid default value for 'da' create table t1 (t time default '916:00:00 a'); ERROR 42000: Invalid default value for 't' set @@sql_mode= @org_mode; +SELECT CAST(CAST('2006-08-10 10:11:12.0123450' AS DATETIME) AS DECIMAL(30,7)); +CAST(CAST('2006-08-10 10:11:12.0123450' AS DATETIME) AS DECIMAL(30,7)) +20060810101112.0123450 +Warnings: +Warning 1292 Truncated incorrect datetime value: '2006-08-10 10:11:12.0123450' +SELECT CAST(CAST('00000002006-000008-0000010 000010:0000011:00000012.0123450' AS DATETIME) AS DECIMAL(30,7)); +CAST(CAST('00000002006-000008-0000010 000010:0000011:00000012.0123450' AS DATETIME) AS DECIMAL(30,7)) +20060810101112.0123450 +Warnings: +Warning 1292 Truncated incorrect datetime value: '00000002006-000008-0000010 000010:0000011:00000012.0123450' +SELECT CAST(CAST('00000002006-000008-0000010 000010:0000011:00000012.012345' AS DATETIME) AS DECIMAL(30,7)); +CAST(CAST('00000002006-000008-0000010 000010:0000011:00000012.012345' AS DATETIME) AS DECIMAL(30,7)) +20060810101112.0123450 +SELECT CAST(CAST('2008-07-29T10:42:51.1234567' AS DateTime) AS DECIMAL(30,7)); +CAST(CAST('2008-07-29T10:42:51.1234567' AS DateTime) AS DECIMAL(30,7)) +20080729104251.1234560 +Warnings: +Warning 1292 Truncated incorrect datetime value: '2008-07-29T10:42:51.1234567' +End of 5.1 tests diff --git a/mysql-test/t/type_datetime.test b/mysql-test/t/type_datetime.test index eb1b7bde844..d4fa6bed186 100644 --- a/mysql-test/t/type_datetime.test +++ b/mysql-test/t/type_datetime.test @@ -427,3 +427,22 @@ create table t1 (da date default '1962-03-32 23:33:34', dt datetime default '196 --error 1067 create table t1 (t time default '916:00:00 a'); set @@sql_mode= @org_mode; + +# +# Bug #42146 - DATETIME fractional seconds parse error +# +# show we trucate microseconds from the right -- special case: leftmost is 0 +SELECT CAST(CAST('2006-08-10 10:11:12.0123450' AS DATETIME) AS DECIMAL(30,7)); + +# show that we ignore leading zeroes for all other fields +SELECT CAST(CAST('00000002006-000008-0000010 000010:0000011:00000012.0123450' AS DATETIME) AS DECIMAL(30,7)); +# once more with feeling (but no warnings) +SELECT CAST(CAST('00000002006-000008-0000010 000010:0000011:00000012.012345' AS DATETIME) AS DECIMAL(30,7)); + +# +# Bug #38435 - LONG Microseconds cause MySQL to fail a CAST to DATETIME or DATE +# +# show we truncate microseconds from the right +SELECT CAST(CAST('2008-07-29T10:42:51.1234567' AS DateTime) AS DECIMAL(30,7)); + +--echo End of 5.1 tests diff --git a/sql-common/my_time.c b/sql-common/my_time.c index 155e0237e3c..747c5797ed4 100644 --- a/sql-common/my_time.c +++ b/sql-common/my_time.c @@ -264,8 +264,19 @@ str_to_datetime(const char *str, uint length, MYSQL_TIME *l_time, { const char *start= str; ulong tmp_value= (uint) (uchar) (*str++ - '0'); + + /* + Internal format means no delimiters; every field has a fixed + width. Otherwise, we scan until we find a delimiter and discard + leading zeroes -- except for the microsecond part, where leading + zeroes are significant, and where we never process more than six + digits. + */ + my_bool scan_until_delim= !is_internal_format && + ((i != format_position[6])); + while (str != end && my_isdigit(&my_charset_latin1,str[0]) && - (!is_internal_format || --field_length)) + (scan_until_delim || --field_length)) { tmp_value=tmp_value*10 + (ulong) (uchar) (*str - '0'); str++; From 59c8a307fe59fb0822a1dbf8154688f12af415e3 Mon Sep 17 00:00:00 2001 From: Matthias Leich Date: Fri, 13 Feb 2009 19:07:56 +0100 Subject: [PATCH 080/219] Fix for Bug#42836 Funcs_1 storedproc and storedproc_08 tests failing --- .../funcs_1/r/innodb_storedproc_08.result | 213 +----------------- .../suite/funcs_1/r/innodb_trig_0102.result | 6 +- .../suite/funcs_1/r/innodb_trig_0407.result | 14 +- .../funcs_1/r/memory_storedproc_08.result | 213 +----------------- .../suite/funcs_1/r/memory_trig_0102.result | 6 +- .../suite/funcs_1/r/memory_trig_0407.result | 14 +- .../funcs_1/r/myisam_storedproc_08.result | 213 +----------------- .../suite/funcs_1/r/myisam_trig_0102.result | 6 +- .../suite/funcs_1/r/myisam_trig_0407.result | 14 +- .../suite/funcs_1/r/ndb_storedproc_08.result | 213 +----------------- .../suite/funcs_1/r/ndb_trig_0102.result | 6 +- .../suite/funcs_1/r/ndb_trig_0407.result | 14 +- mysql-test/suite/funcs_1/r/storedproc.result | 42 +--- .../funcs_1/storedproc/storedproc_08_show.inc | 9 +- mysql-test/suite/funcs_1/t/storedproc.test | 18 +- .../suite/funcs_1/triggers/triggers_0102.inc | 4 +- .../suite/funcs_1/triggers/triggers_0407.inc | 6 +- 17 files changed, 73 insertions(+), 938 deletions(-) diff --git a/mysql-test/suite/funcs_1/r/innodb_storedproc_08.result b/mysql-test/suite/funcs_1/r/innodb_storedproc_08.result index 7bffd77d9c6..2e504af6ed4 100644 --- a/mysql-test/suite/funcs_1/r/innodb_storedproc_08.result +++ b/mysql-test/suite/funcs_1/r/innodb_storedproc_08.result @@ -103,7 +103,7 @@ END// ... now check what is stored: ----------------------------- -SELECT * FROM information_schema.routines; +SELECT * FROM information_schema.routines where routine_schema = 'db_storedproc'; SPECIFIC_NAME fn_1 ROUTINE_CATALOG NULL ROUTINE_SCHEMA db_storedproc @@ -208,75 +208,6 @@ DEFINER root@localhost CHARACTER_SET_CLIENT latin1 COLLATION_CONNECTION latin1_swedish_ci DATABASE_COLLATION latin1_swedish_ci -SPECIFIC_NAME add_suppression -ROUTINE_CATALOG NULL -ROUTINE_SCHEMA mtr -ROUTINE_NAME add_suppression -ROUTINE_TYPE PROCEDURE -DTD_IDENTIFIER NULL -ROUTINE_BODY SQL -ROUTINE_DEFINITION BEGIN INSERT INTO test_suppressions (pattern) VALUES (pattern); END -EXTERNAL_NAME NULL -EXTERNAL_LANGUAGE NULL -PARAMETER_STYLE SQL -IS_DETERMINISTIC NO -SQL_DATA_ACCESS CONTAINS SQL -SQL_PATH NULL -SECURITY_TYPE DEFINER -CREATED -LAST_ALTERED -SQL_MODE -ROUTINE_COMMENT -DEFINER root@localhost -CHARACTER_SET_CLIENT latin1 -COLLATION_CONNECTION latin1_swedish_ci -DATABASE_COLLATION latin1_swedish_ci -SPECIFIC_NAME check_testcase -ROUTINE_CATALOG NULL -ROUTINE_SCHEMA mtr -ROUTINE_NAME check_testcase -ROUTINE_TYPE PROCEDURE -DTD_IDENTIFIER NULL -ROUTINE_BODY SQL -ROUTINE_DEFINITION BEGIN SELECT * FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES WHERE variable_name != 'timestamp' ORDER BY VARIABLE_NAME; SELECT * FROM INFORMATION_SCHEMA.SCHEMATA; SELECT table_name AS tables_in_test FROM INFORMATION_SCHEMA.TABLES WHERE table_schema='test'; SELECT CONCAT(table_schema, '.', table_name) AS tables_in_mysql FROM INFORMATION_SCHEMA.TABLES WHERE table_schema='mysql' AND table_name != 'ndb_apply_status' ORDER BY tables_in_mysql; SELECT CONCAT(table_schema, '.', table_name) AS columns_in_mysql, column_name, ordinal_position, column_default, is_nullable, data_type, character_maximum_length, character_octet_length, numeric_precision, numeric_scale, character_set_name, collation_name, column_type, column_key, extra, column_comment FROM INFORMATION_SCHEMA.COLUMNS WHERE table_schema='mysql' AND table_name != 'ndb_apply_status' ORDER BY columns_in_mysql; checksum table mysql.columns_priv, mysql.db, mysql.func, mysql.help_category, mysql.help_keyword, mysql.help_relation, mysql.host, mysql.proc, mysql.procs_priv, mysql.tables_priv, mysql.time_zone, mysql.time_zone_leap_second, mysql.time_zone_name, mysql.time_zone_transition, mysql.time_zone_transition_type, mysql.user; END -EXTERNAL_NAME NULL -EXTERNAL_LANGUAGE NULL -PARAMETER_STYLE SQL -IS_DETERMINISTIC NO -SQL_DATA_ACCESS CONTAINS SQL -SQL_PATH NULL -SECURITY_TYPE DEFINER -CREATED -LAST_ALTERED -SQL_MODE -ROUTINE_COMMENT -DEFINER root@localhost -CHARACTER_SET_CLIENT latin1 -COLLATION_CONNECTION latin1_swedish_ci -DATABASE_COLLATION latin1_swedish_ci -SPECIFIC_NAME check_warnings -ROUTINE_CATALOG NULL -ROUTINE_SCHEMA mtr -ROUTINE_NAME check_warnings -ROUTINE_TYPE PROCEDURE -DTD_IDENTIFIER NULL -ROUTINE_BODY SQL -ROUTINE_DEFINITION BEGIN DECLARE `pos` bigint unsigned; SET SQL_LOG_BIN=0; UPDATE error_log el, global_suppressions gs SET suspicious=0 WHERE el.suspicious=1 AND el.line REGEXP gs.pattern; UPDATE error_log el, test_suppressions ts SET suspicious=0 WHERE el.suspicious=1 AND el.line REGEXP ts.pattern; SELECT COUNT(*) INTO @num_warnings FROM error_log WHERE suspicious=1; IF @num_warnings > 0 THEN SELECT file_name, line FROM error_log WHERE suspicious=1; SELECT 2 INTO result; ELSE SELECT 0 INTO RESULT; END IF; TRUNCATE test_suppressions; DROP TABLE error_log; END -EXTERNAL_NAME NULL -EXTERNAL_LANGUAGE NULL -PARAMETER_STYLE SQL -IS_DETERMINISTIC NO -SQL_DATA_ACCESS CONTAINS SQL -SQL_PATH NULL -SECURITY_TYPE DEFINER -CREATED -LAST_ALTERED -SQL_MODE -ROUTINE_COMMENT -DEFINER root@localhost -CHARACTER_SET_CLIENT latin1 -COLLATION_CONNECTION latin1_swedish_ci -DATABASE_COLLATION latin1_swedish_ci SHOW CREATE FUNCTION fn_1; Function fn_1 sql_mode @@ -390,7 +321,7 @@ ALTER FUNCTION fn_2 MODIFIES SQL DATA; ... now check what is stored: ----------------------------- -SELECT * FROM information_schema.routines; +SELECT * FROM information_schema.routines where routine_schema = 'db_storedproc'; SPECIFIC_NAME fn_1 ROUTINE_CATALOG NULL ROUTINE_SCHEMA db_storedproc @@ -495,75 +426,6 @@ DEFINER root@localhost CHARACTER_SET_CLIENT latin1 COLLATION_CONNECTION latin1_swedish_ci DATABASE_COLLATION latin1_swedish_ci -SPECIFIC_NAME add_suppression -ROUTINE_CATALOG NULL -ROUTINE_SCHEMA mtr -ROUTINE_NAME add_suppression -ROUTINE_TYPE PROCEDURE -DTD_IDENTIFIER NULL -ROUTINE_BODY SQL -ROUTINE_DEFINITION BEGIN INSERT INTO test_suppressions (pattern) VALUES (pattern); END -EXTERNAL_NAME NULL -EXTERNAL_LANGUAGE NULL -PARAMETER_STYLE SQL -IS_DETERMINISTIC NO -SQL_DATA_ACCESS CONTAINS SQL -SQL_PATH NULL -SECURITY_TYPE DEFINER -CREATED -LAST_ALTERED -SQL_MODE -ROUTINE_COMMENT -DEFINER root@localhost -CHARACTER_SET_CLIENT latin1 -COLLATION_CONNECTION latin1_swedish_ci -DATABASE_COLLATION latin1_swedish_ci -SPECIFIC_NAME check_testcase -ROUTINE_CATALOG NULL -ROUTINE_SCHEMA mtr -ROUTINE_NAME check_testcase -ROUTINE_TYPE PROCEDURE -DTD_IDENTIFIER NULL -ROUTINE_BODY SQL -ROUTINE_DEFINITION BEGIN SELECT * FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES WHERE variable_name != 'timestamp' ORDER BY VARIABLE_NAME; SELECT * FROM INFORMATION_SCHEMA.SCHEMATA; SELECT table_name AS tables_in_test FROM INFORMATION_SCHEMA.TABLES WHERE table_schema='test'; SELECT CONCAT(table_schema, '.', table_name) AS tables_in_mysql FROM INFORMATION_SCHEMA.TABLES WHERE table_schema='mysql' AND table_name != 'ndb_apply_status' ORDER BY tables_in_mysql; SELECT CONCAT(table_schema, '.', table_name) AS columns_in_mysql, column_name, ordinal_position, column_default, is_nullable, data_type, character_maximum_length, character_octet_length, numeric_precision, numeric_scale, character_set_name, collation_name, column_type, column_key, extra, column_comment FROM INFORMATION_SCHEMA.COLUMNS WHERE table_schema='mysql' AND table_name != 'ndb_apply_status' ORDER BY columns_in_mysql; checksum table mysql.columns_priv, mysql.db, mysql.func, mysql.help_category, mysql.help_keyword, mysql.help_relation, mysql.host, mysql.proc, mysql.procs_priv, mysql.tables_priv, mysql.time_zone, mysql.time_zone_leap_second, mysql.time_zone_name, mysql.time_zone_transition, mysql.time_zone_transition_type, mysql.user; END -EXTERNAL_NAME NULL -EXTERNAL_LANGUAGE NULL -PARAMETER_STYLE SQL -IS_DETERMINISTIC NO -SQL_DATA_ACCESS CONTAINS SQL -SQL_PATH NULL -SECURITY_TYPE DEFINER -CREATED -LAST_ALTERED -SQL_MODE -ROUTINE_COMMENT -DEFINER root@localhost -CHARACTER_SET_CLIENT latin1 -COLLATION_CONNECTION latin1_swedish_ci -DATABASE_COLLATION latin1_swedish_ci -SPECIFIC_NAME check_warnings -ROUTINE_CATALOG NULL -ROUTINE_SCHEMA mtr -ROUTINE_NAME check_warnings -ROUTINE_TYPE PROCEDURE -DTD_IDENTIFIER NULL -ROUTINE_BODY SQL -ROUTINE_DEFINITION BEGIN DECLARE `pos` bigint unsigned; SET SQL_LOG_BIN=0; UPDATE error_log el, global_suppressions gs SET suspicious=0 WHERE el.suspicious=1 AND el.line REGEXP gs.pattern; UPDATE error_log el, test_suppressions ts SET suspicious=0 WHERE el.suspicious=1 AND el.line REGEXP ts.pattern; SELECT COUNT(*) INTO @num_warnings FROM error_log WHERE suspicious=1; IF @num_warnings > 0 THEN SELECT file_name, line FROM error_log WHERE suspicious=1; SELECT 2 INTO result; ELSE SELECT 0 INTO RESULT; END IF; TRUNCATE test_suppressions; DROP TABLE error_log; END -EXTERNAL_NAME NULL -EXTERNAL_LANGUAGE NULL -PARAMETER_STYLE SQL -IS_DETERMINISTIC NO -SQL_DATA_ACCESS CONTAINS SQL -SQL_PATH NULL -SECURITY_TYPE DEFINER -CREATED -LAST_ALTERED -SQL_MODE -ROUTINE_COMMENT -DEFINER root@localhost -CHARACTER_SET_CLIENT latin1 -COLLATION_CONNECTION latin1_swedish_ci -DATABASE_COLLATION latin1_swedish_ci SHOW CREATE FUNCTION fn_1; Function fn_1 sql_mode @@ -670,7 +532,7 @@ ALTER FUNCTION fn_2 CONTAINS SQL; ... now check what is stored: ----------------------------- -SELECT * FROM information_schema.routines; +SELECT * FROM information_schema.routines where routine_schema = 'db_storedproc'; SPECIFIC_NAME fn_1 ROUTINE_CATALOG NULL ROUTINE_SCHEMA db_storedproc @@ -775,75 +637,6 @@ DEFINER root@localhost CHARACTER_SET_CLIENT latin1 COLLATION_CONNECTION latin1_swedish_ci DATABASE_COLLATION latin1_swedish_ci -SPECIFIC_NAME add_suppression -ROUTINE_CATALOG NULL -ROUTINE_SCHEMA mtr -ROUTINE_NAME add_suppression -ROUTINE_TYPE PROCEDURE -DTD_IDENTIFIER NULL -ROUTINE_BODY SQL -ROUTINE_DEFINITION BEGIN INSERT INTO test_suppressions (pattern) VALUES (pattern); END -EXTERNAL_NAME NULL -EXTERNAL_LANGUAGE NULL -PARAMETER_STYLE SQL -IS_DETERMINISTIC NO -SQL_DATA_ACCESS CONTAINS SQL -SQL_PATH NULL -SECURITY_TYPE DEFINER -CREATED -LAST_ALTERED -SQL_MODE -ROUTINE_COMMENT -DEFINER root@localhost -CHARACTER_SET_CLIENT latin1 -COLLATION_CONNECTION latin1_swedish_ci -DATABASE_COLLATION latin1_swedish_ci -SPECIFIC_NAME check_testcase -ROUTINE_CATALOG NULL -ROUTINE_SCHEMA mtr -ROUTINE_NAME check_testcase -ROUTINE_TYPE PROCEDURE -DTD_IDENTIFIER NULL -ROUTINE_BODY SQL -ROUTINE_DEFINITION BEGIN SELECT * FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES WHERE variable_name != 'timestamp' ORDER BY VARIABLE_NAME; SELECT * FROM INFORMATION_SCHEMA.SCHEMATA; SELECT table_name AS tables_in_test FROM INFORMATION_SCHEMA.TABLES WHERE table_schema='test'; SELECT CONCAT(table_schema, '.', table_name) AS tables_in_mysql FROM INFORMATION_SCHEMA.TABLES WHERE table_schema='mysql' AND table_name != 'ndb_apply_status' ORDER BY tables_in_mysql; SELECT CONCAT(table_schema, '.', table_name) AS columns_in_mysql, column_name, ordinal_position, column_default, is_nullable, data_type, character_maximum_length, character_octet_length, numeric_precision, numeric_scale, character_set_name, collation_name, column_type, column_key, extra, column_comment FROM INFORMATION_SCHEMA.COLUMNS WHERE table_schema='mysql' AND table_name != 'ndb_apply_status' ORDER BY columns_in_mysql; checksum table mysql.columns_priv, mysql.db, mysql.func, mysql.help_category, mysql.help_keyword, mysql.help_relation, mysql.host, mysql.proc, mysql.procs_priv, mysql.tables_priv, mysql.time_zone, mysql.time_zone_leap_second, mysql.time_zone_name, mysql.time_zone_transition, mysql.time_zone_transition_type, mysql.user; END -EXTERNAL_NAME NULL -EXTERNAL_LANGUAGE NULL -PARAMETER_STYLE SQL -IS_DETERMINISTIC NO -SQL_DATA_ACCESS CONTAINS SQL -SQL_PATH NULL -SECURITY_TYPE DEFINER -CREATED -LAST_ALTERED -SQL_MODE -ROUTINE_COMMENT -DEFINER root@localhost -CHARACTER_SET_CLIENT latin1 -COLLATION_CONNECTION latin1_swedish_ci -DATABASE_COLLATION latin1_swedish_ci -SPECIFIC_NAME check_warnings -ROUTINE_CATALOG NULL -ROUTINE_SCHEMA mtr -ROUTINE_NAME check_warnings -ROUTINE_TYPE PROCEDURE -DTD_IDENTIFIER NULL -ROUTINE_BODY SQL -ROUTINE_DEFINITION BEGIN DECLARE `pos` bigint unsigned; SET SQL_LOG_BIN=0; UPDATE error_log el, global_suppressions gs SET suspicious=0 WHERE el.suspicious=1 AND el.line REGEXP gs.pattern; UPDATE error_log el, test_suppressions ts SET suspicious=0 WHERE el.suspicious=1 AND el.line REGEXP ts.pattern; SELECT COUNT(*) INTO @num_warnings FROM error_log WHERE suspicious=1; IF @num_warnings > 0 THEN SELECT file_name, line FROM error_log WHERE suspicious=1; SELECT 2 INTO result; ELSE SELECT 0 INTO RESULT; END IF; TRUNCATE test_suppressions; DROP TABLE error_log; END -EXTERNAL_NAME NULL -EXTERNAL_LANGUAGE NULL -PARAMETER_STYLE SQL -IS_DETERMINISTIC NO -SQL_DATA_ACCESS CONTAINS SQL -SQL_PATH NULL -SECURITY_TYPE DEFINER -CREATED -LAST_ALTERED -SQL_MODE -ROUTINE_COMMENT -DEFINER root@localhost -CHARACTER_SET_CLIENT latin1 -COLLATION_CONNECTION latin1_swedish_ci -DATABASE_COLLATION latin1_swedish_ci SHOW CREATE FUNCTION fn_1; Function fn_1 sql_mode diff --git a/mysql-test/suite/funcs_1/r/innodb_trig_0102.result b/mysql-test/suite/funcs_1/r/innodb_trig_0102.result index 86c2d2521ac..5ca24acf0bf 100644 --- a/mysql-test/suite/funcs_1/r/innodb_trig_0102.result +++ b/mysql-test/suite/funcs_1/r/innodb_trig_0102.result @@ -348,13 +348,13 @@ for each row set @test_var2='trig1_a'; create trigger trig_db2.trig2 before insert on trig_db2.t1 for each row set @test_var3='trig2'; select trigger_schema, trigger_name, event_object_table -from information_schema.triggers order by trigger_name; +from information_schema.triggers +where trigger_schema like 'trig_db%' + order by trigger_name; trigger_schema trigger_name event_object_table -mtr gs_insert global_suppressions trig_db1 trig1_a t1 trig_db1 trig1_b t1 trig_db2 trig2 t1 -mtr ts_insert test_suppressions set @test_var1= '', @test_var2= '', @test_var3= ''; insert into t1 (f1,f2) values ('insert to db1 t1 from db1',352); insert into trig_db2.t1 (f1,f2) values ('insert to db2 t1 from db1',352); diff --git a/mysql-test/suite/funcs_1/r/innodb_trig_0407.result b/mysql-test/suite/funcs_1/r/innodb_trig_0407.result index 62c8e0d06db..33e58f50ec1 100644 --- a/mysql-test/suite/funcs_1/r/innodb_trig_0407.result +++ b/mysql-test/suite/funcs_1/r/innodb_trig_0407.result @@ -90,10 +90,10 @@ f1 Trigger 3.5.4.1 drop trigger trg1; select trigger_schema, trigger_name, event_object_table -from information_schema.triggers order by trigger_name; +from information_schema.triggers +where trigger_schema = 'db_drop' + order by trigger_name; trigger_schema trigger_name event_object_table -mtr gs_insert global_suppressions -mtr ts_insert test_suppressions Insert into t1 values ('Insert no trigger 3.5.4.1'); Select * from t1 order by f1; f1 @@ -151,12 +151,8 @@ Select * from t1; f1 Trigger 3.5.4.4 Drop database db_drop4; -Show databases; -Database -information_schema -mtr -mysql -test +Show databases like 'db_drop4'; +Database (db_drop4) select trigger_schema, trigger_name, event_object_table from information_schema.triggers where information_schema.triggers.trigger_name='trg4'; diff --git a/mysql-test/suite/funcs_1/r/memory_storedproc_08.result b/mysql-test/suite/funcs_1/r/memory_storedproc_08.result index 2740a2cafa8..7f08a77ef09 100644 --- a/mysql-test/suite/funcs_1/r/memory_storedproc_08.result +++ b/mysql-test/suite/funcs_1/r/memory_storedproc_08.result @@ -104,7 +104,7 @@ END// ... now check what is stored: ----------------------------- -SELECT * FROM information_schema.routines; +SELECT * FROM information_schema.routines where routine_schema = 'db_storedproc'; SPECIFIC_NAME fn_1 ROUTINE_CATALOG NULL ROUTINE_SCHEMA db_storedproc @@ -209,75 +209,6 @@ DEFINER root@localhost CHARACTER_SET_CLIENT latin1 COLLATION_CONNECTION latin1_swedish_ci DATABASE_COLLATION latin1_swedish_ci -SPECIFIC_NAME add_suppression -ROUTINE_CATALOG NULL -ROUTINE_SCHEMA mtr -ROUTINE_NAME add_suppression -ROUTINE_TYPE PROCEDURE -DTD_IDENTIFIER NULL -ROUTINE_BODY SQL -ROUTINE_DEFINITION BEGIN INSERT INTO test_suppressions (pattern) VALUES (pattern); END -EXTERNAL_NAME NULL -EXTERNAL_LANGUAGE NULL -PARAMETER_STYLE SQL -IS_DETERMINISTIC NO -SQL_DATA_ACCESS CONTAINS SQL -SQL_PATH NULL -SECURITY_TYPE DEFINER -CREATED -LAST_ALTERED -SQL_MODE -ROUTINE_COMMENT -DEFINER root@localhost -CHARACTER_SET_CLIENT latin1 -COLLATION_CONNECTION latin1_swedish_ci -DATABASE_COLLATION latin1_swedish_ci -SPECIFIC_NAME check_testcase -ROUTINE_CATALOG NULL -ROUTINE_SCHEMA mtr -ROUTINE_NAME check_testcase -ROUTINE_TYPE PROCEDURE -DTD_IDENTIFIER NULL -ROUTINE_BODY SQL -ROUTINE_DEFINITION BEGIN SELECT * FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES WHERE variable_name != 'timestamp' ORDER BY VARIABLE_NAME; SELECT * FROM INFORMATION_SCHEMA.SCHEMATA; SELECT table_name AS tables_in_test FROM INFORMATION_SCHEMA.TABLES WHERE table_schema='test'; SELECT CONCAT(table_schema, '.', table_name) AS tables_in_mysql FROM INFORMATION_SCHEMA.TABLES WHERE table_schema='mysql' AND table_name != 'ndb_apply_status' ORDER BY tables_in_mysql; SELECT CONCAT(table_schema, '.', table_name) AS columns_in_mysql, column_name, ordinal_position, column_default, is_nullable, data_type, character_maximum_length, character_octet_length, numeric_precision, numeric_scale, character_set_name, collation_name, column_type, column_key, extra, column_comment FROM INFORMATION_SCHEMA.COLUMNS WHERE table_schema='mysql' AND table_name != 'ndb_apply_status' ORDER BY columns_in_mysql; checksum table mysql.columns_priv, mysql.db, mysql.func, mysql.help_category, mysql.help_keyword, mysql.help_relation, mysql.host, mysql.proc, mysql.procs_priv, mysql.tables_priv, mysql.time_zone, mysql.time_zone_leap_second, mysql.time_zone_name, mysql.time_zone_transition, mysql.time_zone_transition_type, mysql.user; END -EXTERNAL_NAME NULL -EXTERNAL_LANGUAGE NULL -PARAMETER_STYLE SQL -IS_DETERMINISTIC NO -SQL_DATA_ACCESS CONTAINS SQL -SQL_PATH NULL -SECURITY_TYPE DEFINER -CREATED -LAST_ALTERED -SQL_MODE -ROUTINE_COMMENT -DEFINER root@localhost -CHARACTER_SET_CLIENT latin1 -COLLATION_CONNECTION latin1_swedish_ci -DATABASE_COLLATION latin1_swedish_ci -SPECIFIC_NAME check_warnings -ROUTINE_CATALOG NULL -ROUTINE_SCHEMA mtr -ROUTINE_NAME check_warnings -ROUTINE_TYPE PROCEDURE -DTD_IDENTIFIER NULL -ROUTINE_BODY SQL -ROUTINE_DEFINITION BEGIN DECLARE `pos` bigint unsigned; SET SQL_LOG_BIN=0; UPDATE error_log el, global_suppressions gs SET suspicious=0 WHERE el.suspicious=1 AND el.line REGEXP gs.pattern; UPDATE error_log el, test_suppressions ts SET suspicious=0 WHERE el.suspicious=1 AND el.line REGEXP ts.pattern; SELECT COUNT(*) INTO @num_warnings FROM error_log WHERE suspicious=1; IF @num_warnings > 0 THEN SELECT file_name, line FROM error_log WHERE suspicious=1; SELECT 2 INTO result; ELSE SELECT 0 INTO RESULT; END IF; TRUNCATE test_suppressions; DROP TABLE error_log; END -EXTERNAL_NAME NULL -EXTERNAL_LANGUAGE NULL -PARAMETER_STYLE SQL -IS_DETERMINISTIC NO -SQL_DATA_ACCESS CONTAINS SQL -SQL_PATH NULL -SECURITY_TYPE DEFINER -CREATED -LAST_ALTERED -SQL_MODE -ROUTINE_COMMENT -DEFINER root@localhost -CHARACTER_SET_CLIENT latin1 -COLLATION_CONNECTION latin1_swedish_ci -DATABASE_COLLATION latin1_swedish_ci SHOW CREATE FUNCTION fn_1; Function fn_1 sql_mode NO_ENGINE_SUBSTITUTION @@ -391,7 +322,7 @@ ALTER FUNCTION fn_2 MODIFIES SQL DATA; ... now check what is stored: ----------------------------- -SELECT * FROM information_schema.routines; +SELECT * FROM information_schema.routines where routine_schema = 'db_storedproc'; SPECIFIC_NAME fn_1 ROUTINE_CATALOG NULL ROUTINE_SCHEMA db_storedproc @@ -496,75 +427,6 @@ DEFINER root@localhost CHARACTER_SET_CLIENT latin1 COLLATION_CONNECTION latin1_swedish_ci DATABASE_COLLATION latin1_swedish_ci -SPECIFIC_NAME add_suppression -ROUTINE_CATALOG NULL -ROUTINE_SCHEMA mtr -ROUTINE_NAME add_suppression -ROUTINE_TYPE PROCEDURE -DTD_IDENTIFIER NULL -ROUTINE_BODY SQL -ROUTINE_DEFINITION BEGIN INSERT INTO test_suppressions (pattern) VALUES (pattern); END -EXTERNAL_NAME NULL -EXTERNAL_LANGUAGE NULL -PARAMETER_STYLE SQL -IS_DETERMINISTIC NO -SQL_DATA_ACCESS CONTAINS SQL -SQL_PATH NULL -SECURITY_TYPE DEFINER -CREATED -LAST_ALTERED -SQL_MODE -ROUTINE_COMMENT -DEFINER root@localhost -CHARACTER_SET_CLIENT latin1 -COLLATION_CONNECTION latin1_swedish_ci -DATABASE_COLLATION latin1_swedish_ci -SPECIFIC_NAME check_testcase -ROUTINE_CATALOG NULL -ROUTINE_SCHEMA mtr -ROUTINE_NAME check_testcase -ROUTINE_TYPE PROCEDURE -DTD_IDENTIFIER NULL -ROUTINE_BODY SQL -ROUTINE_DEFINITION BEGIN SELECT * FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES WHERE variable_name != 'timestamp' ORDER BY VARIABLE_NAME; SELECT * FROM INFORMATION_SCHEMA.SCHEMATA; SELECT table_name AS tables_in_test FROM INFORMATION_SCHEMA.TABLES WHERE table_schema='test'; SELECT CONCAT(table_schema, '.', table_name) AS tables_in_mysql FROM INFORMATION_SCHEMA.TABLES WHERE table_schema='mysql' AND table_name != 'ndb_apply_status' ORDER BY tables_in_mysql; SELECT CONCAT(table_schema, '.', table_name) AS columns_in_mysql, column_name, ordinal_position, column_default, is_nullable, data_type, character_maximum_length, character_octet_length, numeric_precision, numeric_scale, character_set_name, collation_name, column_type, column_key, extra, column_comment FROM INFORMATION_SCHEMA.COLUMNS WHERE table_schema='mysql' AND table_name != 'ndb_apply_status' ORDER BY columns_in_mysql; checksum table mysql.columns_priv, mysql.db, mysql.func, mysql.help_category, mysql.help_keyword, mysql.help_relation, mysql.host, mysql.proc, mysql.procs_priv, mysql.tables_priv, mysql.time_zone, mysql.time_zone_leap_second, mysql.time_zone_name, mysql.time_zone_transition, mysql.time_zone_transition_type, mysql.user; END -EXTERNAL_NAME NULL -EXTERNAL_LANGUAGE NULL -PARAMETER_STYLE SQL -IS_DETERMINISTIC NO -SQL_DATA_ACCESS CONTAINS SQL -SQL_PATH NULL -SECURITY_TYPE DEFINER -CREATED -LAST_ALTERED -SQL_MODE -ROUTINE_COMMENT -DEFINER root@localhost -CHARACTER_SET_CLIENT latin1 -COLLATION_CONNECTION latin1_swedish_ci -DATABASE_COLLATION latin1_swedish_ci -SPECIFIC_NAME check_warnings -ROUTINE_CATALOG NULL -ROUTINE_SCHEMA mtr -ROUTINE_NAME check_warnings -ROUTINE_TYPE PROCEDURE -DTD_IDENTIFIER NULL -ROUTINE_BODY SQL -ROUTINE_DEFINITION BEGIN DECLARE `pos` bigint unsigned; SET SQL_LOG_BIN=0; UPDATE error_log el, global_suppressions gs SET suspicious=0 WHERE el.suspicious=1 AND el.line REGEXP gs.pattern; UPDATE error_log el, test_suppressions ts SET suspicious=0 WHERE el.suspicious=1 AND el.line REGEXP ts.pattern; SELECT COUNT(*) INTO @num_warnings FROM error_log WHERE suspicious=1; IF @num_warnings > 0 THEN SELECT file_name, line FROM error_log WHERE suspicious=1; SELECT 2 INTO result; ELSE SELECT 0 INTO RESULT; END IF; TRUNCATE test_suppressions; DROP TABLE error_log; END -EXTERNAL_NAME NULL -EXTERNAL_LANGUAGE NULL -PARAMETER_STYLE SQL -IS_DETERMINISTIC NO -SQL_DATA_ACCESS CONTAINS SQL -SQL_PATH NULL -SECURITY_TYPE DEFINER -CREATED -LAST_ALTERED -SQL_MODE -ROUTINE_COMMENT -DEFINER root@localhost -CHARACTER_SET_CLIENT latin1 -COLLATION_CONNECTION latin1_swedish_ci -DATABASE_COLLATION latin1_swedish_ci SHOW CREATE FUNCTION fn_1; Function fn_1 sql_mode NO_ENGINE_SUBSTITUTION @@ -671,7 +533,7 @@ ALTER FUNCTION fn_2 CONTAINS SQL; ... now check what is stored: ----------------------------- -SELECT * FROM information_schema.routines; +SELECT * FROM information_schema.routines where routine_schema = 'db_storedproc'; SPECIFIC_NAME fn_1 ROUTINE_CATALOG NULL ROUTINE_SCHEMA db_storedproc @@ -776,75 +638,6 @@ DEFINER root@localhost CHARACTER_SET_CLIENT latin1 COLLATION_CONNECTION latin1_swedish_ci DATABASE_COLLATION latin1_swedish_ci -SPECIFIC_NAME add_suppression -ROUTINE_CATALOG NULL -ROUTINE_SCHEMA mtr -ROUTINE_NAME add_suppression -ROUTINE_TYPE PROCEDURE -DTD_IDENTIFIER NULL -ROUTINE_BODY SQL -ROUTINE_DEFINITION BEGIN INSERT INTO test_suppressions (pattern) VALUES (pattern); END -EXTERNAL_NAME NULL -EXTERNAL_LANGUAGE NULL -PARAMETER_STYLE SQL -IS_DETERMINISTIC NO -SQL_DATA_ACCESS CONTAINS SQL -SQL_PATH NULL -SECURITY_TYPE DEFINER -CREATED -LAST_ALTERED -SQL_MODE -ROUTINE_COMMENT -DEFINER root@localhost -CHARACTER_SET_CLIENT latin1 -COLLATION_CONNECTION latin1_swedish_ci -DATABASE_COLLATION latin1_swedish_ci -SPECIFIC_NAME check_testcase -ROUTINE_CATALOG NULL -ROUTINE_SCHEMA mtr -ROUTINE_NAME check_testcase -ROUTINE_TYPE PROCEDURE -DTD_IDENTIFIER NULL -ROUTINE_BODY SQL -ROUTINE_DEFINITION BEGIN SELECT * FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES WHERE variable_name != 'timestamp' ORDER BY VARIABLE_NAME; SELECT * FROM INFORMATION_SCHEMA.SCHEMATA; SELECT table_name AS tables_in_test FROM INFORMATION_SCHEMA.TABLES WHERE table_schema='test'; SELECT CONCAT(table_schema, '.', table_name) AS tables_in_mysql FROM INFORMATION_SCHEMA.TABLES WHERE table_schema='mysql' AND table_name != 'ndb_apply_status' ORDER BY tables_in_mysql; SELECT CONCAT(table_schema, '.', table_name) AS columns_in_mysql, column_name, ordinal_position, column_default, is_nullable, data_type, character_maximum_length, character_octet_length, numeric_precision, numeric_scale, character_set_name, collation_name, column_type, column_key, extra, column_comment FROM INFORMATION_SCHEMA.COLUMNS WHERE table_schema='mysql' AND table_name != 'ndb_apply_status' ORDER BY columns_in_mysql; checksum table mysql.columns_priv, mysql.db, mysql.func, mysql.help_category, mysql.help_keyword, mysql.help_relation, mysql.host, mysql.proc, mysql.procs_priv, mysql.tables_priv, mysql.time_zone, mysql.time_zone_leap_second, mysql.time_zone_name, mysql.time_zone_transition, mysql.time_zone_transition_type, mysql.user; END -EXTERNAL_NAME NULL -EXTERNAL_LANGUAGE NULL -PARAMETER_STYLE SQL -IS_DETERMINISTIC NO -SQL_DATA_ACCESS CONTAINS SQL -SQL_PATH NULL -SECURITY_TYPE DEFINER -CREATED -LAST_ALTERED -SQL_MODE -ROUTINE_COMMENT -DEFINER root@localhost -CHARACTER_SET_CLIENT latin1 -COLLATION_CONNECTION latin1_swedish_ci -DATABASE_COLLATION latin1_swedish_ci -SPECIFIC_NAME check_warnings -ROUTINE_CATALOG NULL -ROUTINE_SCHEMA mtr -ROUTINE_NAME check_warnings -ROUTINE_TYPE PROCEDURE -DTD_IDENTIFIER NULL -ROUTINE_BODY SQL -ROUTINE_DEFINITION BEGIN DECLARE `pos` bigint unsigned; SET SQL_LOG_BIN=0; UPDATE error_log el, global_suppressions gs SET suspicious=0 WHERE el.suspicious=1 AND el.line REGEXP gs.pattern; UPDATE error_log el, test_suppressions ts SET suspicious=0 WHERE el.suspicious=1 AND el.line REGEXP ts.pattern; SELECT COUNT(*) INTO @num_warnings FROM error_log WHERE suspicious=1; IF @num_warnings > 0 THEN SELECT file_name, line FROM error_log WHERE suspicious=1; SELECT 2 INTO result; ELSE SELECT 0 INTO RESULT; END IF; TRUNCATE test_suppressions; DROP TABLE error_log; END -EXTERNAL_NAME NULL -EXTERNAL_LANGUAGE NULL -PARAMETER_STYLE SQL -IS_DETERMINISTIC NO -SQL_DATA_ACCESS CONTAINS SQL -SQL_PATH NULL -SECURITY_TYPE DEFINER -CREATED -LAST_ALTERED -SQL_MODE -ROUTINE_COMMENT -DEFINER root@localhost -CHARACTER_SET_CLIENT latin1 -COLLATION_CONNECTION latin1_swedish_ci -DATABASE_COLLATION latin1_swedish_ci SHOW CREATE FUNCTION fn_1; Function fn_1 sql_mode NO_ENGINE_SUBSTITUTION diff --git a/mysql-test/suite/funcs_1/r/memory_trig_0102.result b/mysql-test/suite/funcs_1/r/memory_trig_0102.result index a95702debcd..c39370dde69 100644 --- a/mysql-test/suite/funcs_1/r/memory_trig_0102.result +++ b/mysql-test/suite/funcs_1/r/memory_trig_0102.result @@ -349,13 +349,13 @@ for each row set @test_var2='trig1_a'; create trigger trig_db2.trig2 before insert on trig_db2.t1 for each row set @test_var3='trig2'; select trigger_schema, trigger_name, event_object_table -from information_schema.triggers order by trigger_name; +from information_schema.triggers +where trigger_schema like 'trig_db%' + order by trigger_name; trigger_schema trigger_name event_object_table -mtr gs_insert global_suppressions trig_db1 trig1_a t1 trig_db1 trig1_b t1 trig_db2 trig2 t1 -mtr ts_insert test_suppressions set @test_var1= '', @test_var2= '', @test_var3= ''; insert into t1 (f1,f2) values ('insert to db1 t1 from db1',352); insert into trig_db2.t1 (f1,f2) values ('insert to db2 t1 from db1',352); diff --git a/mysql-test/suite/funcs_1/r/memory_trig_0407.result b/mysql-test/suite/funcs_1/r/memory_trig_0407.result index feb0017b86b..2f76f5544b9 100644 --- a/mysql-test/suite/funcs_1/r/memory_trig_0407.result +++ b/mysql-test/suite/funcs_1/r/memory_trig_0407.result @@ -91,10 +91,10 @@ f1 Trigger 3.5.4.1 drop trigger trg1; select trigger_schema, trigger_name, event_object_table -from information_schema.triggers order by trigger_name; +from information_schema.triggers +where trigger_schema = 'db_drop' + order by trigger_name; trigger_schema trigger_name event_object_table -mtr gs_insert global_suppressions -mtr ts_insert test_suppressions Insert into t1 values ('Insert no trigger 3.5.4.1'); Select * from t1 order by f1; f1 @@ -152,12 +152,8 @@ Select * from t1; f1 Trigger 3.5.4.4 Drop database db_drop4; -Show databases; -Database -information_schema -mtr -mysql -test +Show databases like 'db_drop4'; +Database (db_drop4) select trigger_schema, trigger_name, event_object_table from information_schema.triggers where information_schema.triggers.trigger_name='trg4'; diff --git a/mysql-test/suite/funcs_1/r/myisam_storedproc_08.result b/mysql-test/suite/funcs_1/r/myisam_storedproc_08.result index 2740a2cafa8..7f08a77ef09 100644 --- a/mysql-test/suite/funcs_1/r/myisam_storedproc_08.result +++ b/mysql-test/suite/funcs_1/r/myisam_storedproc_08.result @@ -104,7 +104,7 @@ END// ... now check what is stored: ----------------------------- -SELECT * FROM information_schema.routines; +SELECT * FROM information_schema.routines where routine_schema = 'db_storedproc'; SPECIFIC_NAME fn_1 ROUTINE_CATALOG NULL ROUTINE_SCHEMA db_storedproc @@ -209,75 +209,6 @@ DEFINER root@localhost CHARACTER_SET_CLIENT latin1 COLLATION_CONNECTION latin1_swedish_ci DATABASE_COLLATION latin1_swedish_ci -SPECIFIC_NAME add_suppression -ROUTINE_CATALOG NULL -ROUTINE_SCHEMA mtr -ROUTINE_NAME add_suppression -ROUTINE_TYPE PROCEDURE -DTD_IDENTIFIER NULL -ROUTINE_BODY SQL -ROUTINE_DEFINITION BEGIN INSERT INTO test_suppressions (pattern) VALUES (pattern); END -EXTERNAL_NAME NULL -EXTERNAL_LANGUAGE NULL -PARAMETER_STYLE SQL -IS_DETERMINISTIC NO -SQL_DATA_ACCESS CONTAINS SQL -SQL_PATH NULL -SECURITY_TYPE DEFINER -CREATED -LAST_ALTERED -SQL_MODE -ROUTINE_COMMENT -DEFINER root@localhost -CHARACTER_SET_CLIENT latin1 -COLLATION_CONNECTION latin1_swedish_ci -DATABASE_COLLATION latin1_swedish_ci -SPECIFIC_NAME check_testcase -ROUTINE_CATALOG NULL -ROUTINE_SCHEMA mtr -ROUTINE_NAME check_testcase -ROUTINE_TYPE PROCEDURE -DTD_IDENTIFIER NULL -ROUTINE_BODY SQL -ROUTINE_DEFINITION BEGIN SELECT * FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES WHERE variable_name != 'timestamp' ORDER BY VARIABLE_NAME; SELECT * FROM INFORMATION_SCHEMA.SCHEMATA; SELECT table_name AS tables_in_test FROM INFORMATION_SCHEMA.TABLES WHERE table_schema='test'; SELECT CONCAT(table_schema, '.', table_name) AS tables_in_mysql FROM INFORMATION_SCHEMA.TABLES WHERE table_schema='mysql' AND table_name != 'ndb_apply_status' ORDER BY tables_in_mysql; SELECT CONCAT(table_schema, '.', table_name) AS columns_in_mysql, column_name, ordinal_position, column_default, is_nullable, data_type, character_maximum_length, character_octet_length, numeric_precision, numeric_scale, character_set_name, collation_name, column_type, column_key, extra, column_comment FROM INFORMATION_SCHEMA.COLUMNS WHERE table_schema='mysql' AND table_name != 'ndb_apply_status' ORDER BY columns_in_mysql; checksum table mysql.columns_priv, mysql.db, mysql.func, mysql.help_category, mysql.help_keyword, mysql.help_relation, mysql.host, mysql.proc, mysql.procs_priv, mysql.tables_priv, mysql.time_zone, mysql.time_zone_leap_second, mysql.time_zone_name, mysql.time_zone_transition, mysql.time_zone_transition_type, mysql.user; END -EXTERNAL_NAME NULL -EXTERNAL_LANGUAGE NULL -PARAMETER_STYLE SQL -IS_DETERMINISTIC NO -SQL_DATA_ACCESS CONTAINS SQL -SQL_PATH NULL -SECURITY_TYPE DEFINER -CREATED -LAST_ALTERED -SQL_MODE -ROUTINE_COMMENT -DEFINER root@localhost -CHARACTER_SET_CLIENT latin1 -COLLATION_CONNECTION latin1_swedish_ci -DATABASE_COLLATION latin1_swedish_ci -SPECIFIC_NAME check_warnings -ROUTINE_CATALOG NULL -ROUTINE_SCHEMA mtr -ROUTINE_NAME check_warnings -ROUTINE_TYPE PROCEDURE -DTD_IDENTIFIER NULL -ROUTINE_BODY SQL -ROUTINE_DEFINITION BEGIN DECLARE `pos` bigint unsigned; SET SQL_LOG_BIN=0; UPDATE error_log el, global_suppressions gs SET suspicious=0 WHERE el.suspicious=1 AND el.line REGEXP gs.pattern; UPDATE error_log el, test_suppressions ts SET suspicious=0 WHERE el.suspicious=1 AND el.line REGEXP ts.pattern; SELECT COUNT(*) INTO @num_warnings FROM error_log WHERE suspicious=1; IF @num_warnings > 0 THEN SELECT file_name, line FROM error_log WHERE suspicious=1; SELECT 2 INTO result; ELSE SELECT 0 INTO RESULT; END IF; TRUNCATE test_suppressions; DROP TABLE error_log; END -EXTERNAL_NAME NULL -EXTERNAL_LANGUAGE NULL -PARAMETER_STYLE SQL -IS_DETERMINISTIC NO -SQL_DATA_ACCESS CONTAINS SQL -SQL_PATH NULL -SECURITY_TYPE DEFINER -CREATED -LAST_ALTERED -SQL_MODE -ROUTINE_COMMENT -DEFINER root@localhost -CHARACTER_SET_CLIENT latin1 -COLLATION_CONNECTION latin1_swedish_ci -DATABASE_COLLATION latin1_swedish_ci SHOW CREATE FUNCTION fn_1; Function fn_1 sql_mode NO_ENGINE_SUBSTITUTION @@ -391,7 +322,7 @@ ALTER FUNCTION fn_2 MODIFIES SQL DATA; ... now check what is stored: ----------------------------- -SELECT * FROM information_schema.routines; +SELECT * FROM information_schema.routines where routine_schema = 'db_storedproc'; SPECIFIC_NAME fn_1 ROUTINE_CATALOG NULL ROUTINE_SCHEMA db_storedproc @@ -496,75 +427,6 @@ DEFINER root@localhost CHARACTER_SET_CLIENT latin1 COLLATION_CONNECTION latin1_swedish_ci DATABASE_COLLATION latin1_swedish_ci -SPECIFIC_NAME add_suppression -ROUTINE_CATALOG NULL -ROUTINE_SCHEMA mtr -ROUTINE_NAME add_suppression -ROUTINE_TYPE PROCEDURE -DTD_IDENTIFIER NULL -ROUTINE_BODY SQL -ROUTINE_DEFINITION BEGIN INSERT INTO test_suppressions (pattern) VALUES (pattern); END -EXTERNAL_NAME NULL -EXTERNAL_LANGUAGE NULL -PARAMETER_STYLE SQL -IS_DETERMINISTIC NO -SQL_DATA_ACCESS CONTAINS SQL -SQL_PATH NULL -SECURITY_TYPE DEFINER -CREATED -LAST_ALTERED -SQL_MODE -ROUTINE_COMMENT -DEFINER root@localhost -CHARACTER_SET_CLIENT latin1 -COLLATION_CONNECTION latin1_swedish_ci -DATABASE_COLLATION latin1_swedish_ci -SPECIFIC_NAME check_testcase -ROUTINE_CATALOG NULL -ROUTINE_SCHEMA mtr -ROUTINE_NAME check_testcase -ROUTINE_TYPE PROCEDURE -DTD_IDENTIFIER NULL -ROUTINE_BODY SQL -ROUTINE_DEFINITION BEGIN SELECT * FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES WHERE variable_name != 'timestamp' ORDER BY VARIABLE_NAME; SELECT * FROM INFORMATION_SCHEMA.SCHEMATA; SELECT table_name AS tables_in_test FROM INFORMATION_SCHEMA.TABLES WHERE table_schema='test'; SELECT CONCAT(table_schema, '.', table_name) AS tables_in_mysql FROM INFORMATION_SCHEMA.TABLES WHERE table_schema='mysql' AND table_name != 'ndb_apply_status' ORDER BY tables_in_mysql; SELECT CONCAT(table_schema, '.', table_name) AS columns_in_mysql, column_name, ordinal_position, column_default, is_nullable, data_type, character_maximum_length, character_octet_length, numeric_precision, numeric_scale, character_set_name, collation_name, column_type, column_key, extra, column_comment FROM INFORMATION_SCHEMA.COLUMNS WHERE table_schema='mysql' AND table_name != 'ndb_apply_status' ORDER BY columns_in_mysql; checksum table mysql.columns_priv, mysql.db, mysql.func, mysql.help_category, mysql.help_keyword, mysql.help_relation, mysql.host, mysql.proc, mysql.procs_priv, mysql.tables_priv, mysql.time_zone, mysql.time_zone_leap_second, mysql.time_zone_name, mysql.time_zone_transition, mysql.time_zone_transition_type, mysql.user; END -EXTERNAL_NAME NULL -EXTERNAL_LANGUAGE NULL -PARAMETER_STYLE SQL -IS_DETERMINISTIC NO -SQL_DATA_ACCESS CONTAINS SQL -SQL_PATH NULL -SECURITY_TYPE DEFINER -CREATED -LAST_ALTERED -SQL_MODE -ROUTINE_COMMENT -DEFINER root@localhost -CHARACTER_SET_CLIENT latin1 -COLLATION_CONNECTION latin1_swedish_ci -DATABASE_COLLATION latin1_swedish_ci -SPECIFIC_NAME check_warnings -ROUTINE_CATALOG NULL -ROUTINE_SCHEMA mtr -ROUTINE_NAME check_warnings -ROUTINE_TYPE PROCEDURE -DTD_IDENTIFIER NULL -ROUTINE_BODY SQL -ROUTINE_DEFINITION BEGIN DECLARE `pos` bigint unsigned; SET SQL_LOG_BIN=0; UPDATE error_log el, global_suppressions gs SET suspicious=0 WHERE el.suspicious=1 AND el.line REGEXP gs.pattern; UPDATE error_log el, test_suppressions ts SET suspicious=0 WHERE el.suspicious=1 AND el.line REGEXP ts.pattern; SELECT COUNT(*) INTO @num_warnings FROM error_log WHERE suspicious=1; IF @num_warnings > 0 THEN SELECT file_name, line FROM error_log WHERE suspicious=1; SELECT 2 INTO result; ELSE SELECT 0 INTO RESULT; END IF; TRUNCATE test_suppressions; DROP TABLE error_log; END -EXTERNAL_NAME NULL -EXTERNAL_LANGUAGE NULL -PARAMETER_STYLE SQL -IS_DETERMINISTIC NO -SQL_DATA_ACCESS CONTAINS SQL -SQL_PATH NULL -SECURITY_TYPE DEFINER -CREATED -LAST_ALTERED -SQL_MODE -ROUTINE_COMMENT -DEFINER root@localhost -CHARACTER_SET_CLIENT latin1 -COLLATION_CONNECTION latin1_swedish_ci -DATABASE_COLLATION latin1_swedish_ci SHOW CREATE FUNCTION fn_1; Function fn_1 sql_mode NO_ENGINE_SUBSTITUTION @@ -671,7 +533,7 @@ ALTER FUNCTION fn_2 CONTAINS SQL; ... now check what is stored: ----------------------------- -SELECT * FROM information_schema.routines; +SELECT * FROM information_schema.routines where routine_schema = 'db_storedproc'; SPECIFIC_NAME fn_1 ROUTINE_CATALOG NULL ROUTINE_SCHEMA db_storedproc @@ -776,75 +638,6 @@ DEFINER root@localhost CHARACTER_SET_CLIENT latin1 COLLATION_CONNECTION latin1_swedish_ci DATABASE_COLLATION latin1_swedish_ci -SPECIFIC_NAME add_suppression -ROUTINE_CATALOG NULL -ROUTINE_SCHEMA mtr -ROUTINE_NAME add_suppression -ROUTINE_TYPE PROCEDURE -DTD_IDENTIFIER NULL -ROUTINE_BODY SQL -ROUTINE_DEFINITION BEGIN INSERT INTO test_suppressions (pattern) VALUES (pattern); END -EXTERNAL_NAME NULL -EXTERNAL_LANGUAGE NULL -PARAMETER_STYLE SQL -IS_DETERMINISTIC NO -SQL_DATA_ACCESS CONTAINS SQL -SQL_PATH NULL -SECURITY_TYPE DEFINER -CREATED -LAST_ALTERED -SQL_MODE -ROUTINE_COMMENT -DEFINER root@localhost -CHARACTER_SET_CLIENT latin1 -COLLATION_CONNECTION latin1_swedish_ci -DATABASE_COLLATION latin1_swedish_ci -SPECIFIC_NAME check_testcase -ROUTINE_CATALOG NULL -ROUTINE_SCHEMA mtr -ROUTINE_NAME check_testcase -ROUTINE_TYPE PROCEDURE -DTD_IDENTIFIER NULL -ROUTINE_BODY SQL -ROUTINE_DEFINITION BEGIN SELECT * FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES WHERE variable_name != 'timestamp' ORDER BY VARIABLE_NAME; SELECT * FROM INFORMATION_SCHEMA.SCHEMATA; SELECT table_name AS tables_in_test FROM INFORMATION_SCHEMA.TABLES WHERE table_schema='test'; SELECT CONCAT(table_schema, '.', table_name) AS tables_in_mysql FROM INFORMATION_SCHEMA.TABLES WHERE table_schema='mysql' AND table_name != 'ndb_apply_status' ORDER BY tables_in_mysql; SELECT CONCAT(table_schema, '.', table_name) AS columns_in_mysql, column_name, ordinal_position, column_default, is_nullable, data_type, character_maximum_length, character_octet_length, numeric_precision, numeric_scale, character_set_name, collation_name, column_type, column_key, extra, column_comment FROM INFORMATION_SCHEMA.COLUMNS WHERE table_schema='mysql' AND table_name != 'ndb_apply_status' ORDER BY columns_in_mysql; checksum table mysql.columns_priv, mysql.db, mysql.func, mysql.help_category, mysql.help_keyword, mysql.help_relation, mysql.host, mysql.proc, mysql.procs_priv, mysql.tables_priv, mysql.time_zone, mysql.time_zone_leap_second, mysql.time_zone_name, mysql.time_zone_transition, mysql.time_zone_transition_type, mysql.user; END -EXTERNAL_NAME NULL -EXTERNAL_LANGUAGE NULL -PARAMETER_STYLE SQL -IS_DETERMINISTIC NO -SQL_DATA_ACCESS CONTAINS SQL -SQL_PATH NULL -SECURITY_TYPE DEFINER -CREATED -LAST_ALTERED -SQL_MODE -ROUTINE_COMMENT -DEFINER root@localhost -CHARACTER_SET_CLIENT latin1 -COLLATION_CONNECTION latin1_swedish_ci -DATABASE_COLLATION latin1_swedish_ci -SPECIFIC_NAME check_warnings -ROUTINE_CATALOG NULL -ROUTINE_SCHEMA mtr -ROUTINE_NAME check_warnings -ROUTINE_TYPE PROCEDURE -DTD_IDENTIFIER NULL -ROUTINE_BODY SQL -ROUTINE_DEFINITION BEGIN DECLARE `pos` bigint unsigned; SET SQL_LOG_BIN=0; UPDATE error_log el, global_suppressions gs SET suspicious=0 WHERE el.suspicious=1 AND el.line REGEXP gs.pattern; UPDATE error_log el, test_suppressions ts SET suspicious=0 WHERE el.suspicious=1 AND el.line REGEXP ts.pattern; SELECT COUNT(*) INTO @num_warnings FROM error_log WHERE suspicious=1; IF @num_warnings > 0 THEN SELECT file_name, line FROM error_log WHERE suspicious=1; SELECT 2 INTO result; ELSE SELECT 0 INTO RESULT; END IF; TRUNCATE test_suppressions; DROP TABLE error_log; END -EXTERNAL_NAME NULL -EXTERNAL_LANGUAGE NULL -PARAMETER_STYLE SQL -IS_DETERMINISTIC NO -SQL_DATA_ACCESS CONTAINS SQL -SQL_PATH NULL -SECURITY_TYPE DEFINER -CREATED -LAST_ALTERED -SQL_MODE -ROUTINE_COMMENT -DEFINER root@localhost -CHARACTER_SET_CLIENT latin1 -COLLATION_CONNECTION latin1_swedish_ci -DATABASE_COLLATION latin1_swedish_ci SHOW CREATE FUNCTION fn_1; Function fn_1 sql_mode NO_ENGINE_SUBSTITUTION diff --git a/mysql-test/suite/funcs_1/r/myisam_trig_0102.result b/mysql-test/suite/funcs_1/r/myisam_trig_0102.result index a95702debcd..c39370dde69 100644 --- a/mysql-test/suite/funcs_1/r/myisam_trig_0102.result +++ b/mysql-test/suite/funcs_1/r/myisam_trig_0102.result @@ -349,13 +349,13 @@ for each row set @test_var2='trig1_a'; create trigger trig_db2.trig2 before insert on trig_db2.t1 for each row set @test_var3='trig2'; select trigger_schema, trigger_name, event_object_table -from information_schema.triggers order by trigger_name; +from information_schema.triggers +where trigger_schema like 'trig_db%' + order by trigger_name; trigger_schema trigger_name event_object_table -mtr gs_insert global_suppressions trig_db1 trig1_a t1 trig_db1 trig1_b t1 trig_db2 trig2 t1 -mtr ts_insert test_suppressions set @test_var1= '', @test_var2= '', @test_var3= ''; insert into t1 (f1,f2) values ('insert to db1 t1 from db1',352); insert into trig_db2.t1 (f1,f2) values ('insert to db2 t1 from db1',352); diff --git a/mysql-test/suite/funcs_1/r/myisam_trig_0407.result b/mysql-test/suite/funcs_1/r/myisam_trig_0407.result index feb0017b86b..2f76f5544b9 100644 --- a/mysql-test/suite/funcs_1/r/myisam_trig_0407.result +++ b/mysql-test/suite/funcs_1/r/myisam_trig_0407.result @@ -91,10 +91,10 @@ f1 Trigger 3.5.4.1 drop trigger trg1; select trigger_schema, trigger_name, event_object_table -from information_schema.triggers order by trigger_name; +from information_schema.triggers +where trigger_schema = 'db_drop' + order by trigger_name; trigger_schema trigger_name event_object_table -mtr gs_insert global_suppressions -mtr ts_insert test_suppressions Insert into t1 values ('Insert no trigger 3.5.4.1'); Select * from t1 order by f1; f1 @@ -152,12 +152,8 @@ Select * from t1; f1 Trigger 3.5.4.4 Drop database db_drop4; -Show databases; -Database -information_schema -mtr -mysql -test +Show databases like 'db_drop4'; +Database (db_drop4) select trigger_schema, trigger_name, event_object_table from information_schema.triggers where information_schema.triggers.trigger_name='trg4'; diff --git a/mysql-test/suite/funcs_1/r/ndb_storedproc_08.result b/mysql-test/suite/funcs_1/r/ndb_storedproc_08.result index 7bffd77d9c6..2e504af6ed4 100644 --- a/mysql-test/suite/funcs_1/r/ndb_storedproc_08.result +++ b/mysql-test/suite/funcs_1/r/ndb_storedproc_08.result @@ -103,7 +103,7 @@ END// ... now check what is stored: ----------------------------- -SELECT * FROM information_schema.routines; +SELECT * FROM information_schema.routines where routine_schema = 'db_storedproc'; SPECIFIC_NAME fn_1 ROUTINE_CATALOG NULL ROUTINE_SCHEMA db_storedproc @@ -208,75 +208,6 @@ DEFINER root@localhost CHARACTER_SET_CLIENT latin1 COLLATION_CONNECTION latin1_swedish_ci DATABASE_COLLATION latin1_swedish_ci -SPECIFIC_NAME add_suppression -ROUTINE_CATALOG NULL -ROUTINE_SCHEMA mtr -ROUTINE_NAME add_suppression -ROUTINE_TYPE PROCEDURE -DTD_IDENTIFIER NULL -ROUTINE_BODY SQL -ROUTINE_DEFINITION BEGIN INSERT INTO test_suppressions (pattern) VALUES (pattern); END -EXTERNAL_NAME NULL -EXTERNAL_LANGUAGE NULL -PARAMETER_STYLE SQL -IS_DETERMINISTIC NO -SQL_DATA_ACCESS CONTAINS SQL -SQL_PATH NULL -SECURITY_TYPE DEFINER -CREATED -LAST_ALTERED -SQL_MODE -ROUTINE_COMMENT -DEFINER root@localhost -CHARACTER_SET_CLIENT latin1 -COLLATION_CONNECTION latin1_swedish_ci -DATABASE_COLLATION latin1_swedish_ci -SPECIFIC_NAME check_testcase -ROUTINE_CATALOG NULL -ROUTINE_SCHEMA mtr -ROUTINE_NAME check_testcase -ROUTINE_TYPE PROCEDURE -DTD_IDENTIFIER NULL -ROUTINE_BODY SQL -ROUTINE_DEFINITION BEGIN SELECT * FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES WHERE variable_name != 'timestamp' ORDER BY VARIABLE_NAME; SELECT * FROM INFORMATION_SCHEMA.SCHEMATA; SELECT table_name AS tables_in_test FROM INFORMATION_SCHEMA.TABLES WHERE table_schema='test'; SELECT CONCAT(table_schema, '.', table_name) AS tables_in_mysql FROM INFORMATION_SCHEMA.TABLES WHERE table_schema='mysql' AND table_name != 'ndb_apply_status' ORDER BY tables_in_mysql; SELECT CONCAT(table_schema, '.', table_name) AS columns_in_mysql, column_name, ordinal_position, column_default, is_nullable, data_type, character_maximum_length, character_octet_length, numeric_precision, numeric_scale, character_set_name, collation_name, column_type, column_key, extra, column_comment FROM INFORMATION_SCHEMA.COLUMNS WHERE table_schema='mysql' AND table_name != 'ndb_apply_status' ORDER BY columns_in_mysql; checksum table mysql.columns_priv, mysql.db, mysql.func, mysql.help_category, mysql.help_keyword, mysql.help_relation, mysql.host, mysql.proc, mysql.procs_priv, mysql.tables_priv, mysql.time_zone, mysql.time_zone_leap_second, mysql.time_zone_name, mysql.time_zone_transition, mysql.time_zone_transition_type, mysql.user; END -EXTERNAL_NAME NULL -EXTERNAL_LANGUAGE NULL -PARAMETER_STYLE SQL -IS_DETERMINISTIC NO -SQL_DATA_ACCESS CONTAINS SQL -SQL_PATH NULL -SECURITY_TYPE DEFINER -CREATED -LAST_ALTERED -SQL_MODE -ROUTINE_COMMENT -DEFINER root@localhost -CHARACTER_SET_CLIENT latin1 -COLLATION_CONNECTION latin1_swedish_ci -DATABASE_COLLATION latin1_swedish_ci -SPECIFIC_NAME check_warnings -ROUTINE_CATALOG NULL -ROUTINE_SCHEMA mtr -ROUTINE_NAME check_warnings -ROUTINE_TYPE PROCEDURE -DTD_IDENTIFIER NULL -ROUTINE_BODY SQL -ROUTINE_DEFINITION BEGIN DECLARE `pos` bigint unsigned; SET SQL_LOG_BIN=0; UPDATE error_log el, global_suppressions gs SET suspicious=0 WHERE el.suspicious=1 AND el.line REGEXP gs.pattern; UPDATE error_log el, test_suppressions ts SET suspicious=0 WHERE el.suspicious=1 AND el.line REGEXP ts.pattern; SELECT COUNT(*) INTO @num_warnings FROM error_log WHERE suspicious=1; IF @num_warnings > 0 THEN SELECT file_name, line FROM error_log WHERE suspicious=1; SELECT 2 INTO result; ELSE SELECT 0 INTO RESULT; END IF; TRUNCATE test_suppressions; DROP TABLE error_log; END -EXTERNAL_NAME NULL -EXTERNAL_LANGUAGE NULL -PARAMETER_STYLE SQL -IS_DETERMINISTIC NO -SQL_DATA_ACCESS CONTAINS SQL -SQL_PATH NULL -SECURITY_TYPE DEFINER -CREATED -LAST_ALTERED -SQL_MODE -ROUTINE_COMMENT -DEFINER root@localhost -CHARACTER_SET_CLIENT latin1 -COLLATION_CONNECTION latin1_swedish_ci -DATABASE_COLLATION latin1_swedish_ci SHOW CREATE FUNCTION fn_1; Function fn_1 sql_mode @@ -390,7 +321,7 @@ ALTER FUNCTION fn_2 MODIFIES SQL DATA; ... now check what is stored: ----------------------------- -SELECT * FROM information_schema.routines; +SELECT * FROM information_schema.routines where routine_schema = 'db_storedproc'; SPECIFIC_NAME fn_1 ROUTINE_CATALOG NULL ROUTINE_SCHEMA db_storedproc @@ -495,75 +426,6 @@ DEFINER root@localhost CHARACTER_SET_CLIENT latin1 COLLATION_CONNECTION latin1_swedish_ci DATABASE_COLLATION latin1_swedish_ci -SPECIFIC_NAME add_suppression -ROUTINE_CATALOG NULL -ROUTINE_SCHEMA mtr -ROUTINE_NAME add_suppression -ROUTINE_TYPE PROCEDURE -DTD_IDENTIFIER NULL -ROUTINE_BODY SQL -ROUTINE_DEFINITION BEGIN INSERT INTO test_suppressions (pattern) VALUES (pattern); END -EXTERNAL_NAME NULL -EXTERNAL_LANGUAGE NULL -PARAMETER_STYLE SQL -IS_DETERMINISTIC NO -SQL_DATA_ACCESS CONTAINS SQL -SQL_PATH NULL -SECURITY_TYPE DEFINER -CREATED -LAST_ALTERED -SQL_MODE -ROUTINE_COMMENT -DEFINER root@localhost -CHARACTER_SET_CLIENT latin1 -COLLATION_CONNECTION latin1_swedish_ci -DATABASE_COLLATION latin1_swedish_ci -SPECIFIC_NAME check_testcase -ROUTINE_CATALOG NULL -ROUTINE_SCHEMA mtr -ROUTINE_NAME check_testcase -ROUTINE_TYPE PROCEDURE -DTD_IDENTIFIER NULL -ROUTINE_BODY SQL -ROUTINE_DEFINITION BEGIN SELECT * FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES WHERE variable_name != 'timestamp' ORDER BY VARIABLE_NAME; SELECT * FROM INFORMATION_SCHEMA.SCHEMATA; SELECT table_name AS tables_in_test FROM INFORMATION_SCHEMA.TABLES WHERE table_schema='test'; SELECT CONCAT(table_schema, '.', table_name) AS tables_in_mysql FROM INFORMATION_SCHEMA.TABLES WHERE table_schema='mysql' AND table_name != 'ndb_apply_status' ORDER BY tables_in_mysql; SELECT CONCAT(table_schema, '.', table_name) AS columns_in_mysql, column_name, ordinal_position, column_default, is_nullable, data_type, character_maximum_length, character_octet_length, numeric_precision, numeric_scale, character_set_name, collation_name, column_type, column_key, extra, column_comment FROM INFORMATION_SCHEMA.COLUMNS WHERE table_schema='mysql' AND table_name != 'ndb_apply_status' ORDER BY columns_in_mysql; checksum table mysql.columns_priv, mysql.db, mysql.func, mysql.help_category, mysql.help_keyword, mysql.help_relation, mysql.host, mysql.proc, mysql.procs_priv, mysql.tables_priv, mysql.time_zone, mysql.time_zone_leap_second, mysql.time_zone_name, mysql.time_zone_transition, mysql.time_zone_transition_type, mysql.user; END -EXTERNAL_NAME NULL -EXTERNAL_LANGUAGE NULL -PARAMETER_STYLE SQL -IS_DETERMINISTIC NO -SQL_DATA_ACCESS CONTAINS SQL -SQL_PATH NULL -SECURITY_TYPE DEFINER -CREATED -LAST_ALTERED -SQL_MODE -ROUTINE_COMMENT -DEFINER root@localhost -CHARACTER_SET_CLIENT latin1 -COLLATION_CONNECTION latin1_swedish_ci -DATABASE_COLLATION latin1_swedish_ci -SPECIFIC_NAME check_warnings -ROUTINE_CATALOG NULL -ROUTINE_SCHEMA mtr -ROUTINE_NAME check_warnings -ROUTINE_TYPE PROCEDURE -DTD_IDENTIFIER NULL -ROUTINE_BODY SQL -ROUTINE_DEFINITION BEGIN DECLARE `pos` bigint unsigned; SET SQL_LOG_BIN=0; UPDATE error_log el, global_suppressions gs SET suspicious=0 WHERE el.suspicious=1 AND el.line REGEXP gs.pattern; UPDATE error_log el, test_suppressions ts SET suspicious=0 WHERE el.suspicious=1 AND el.line REGEXP ts.pattern; SELECT COUNT(*) INTO @num_warnings FROM error_log WHERE suspicious=1; IF @num_warnings > 0 THEN SELECT file_name, line FROM error_log WHERE suspicious=1; SELECT 2 INTO result; ELSE SELECT 0 INTO RESULT; END IF; TRUNCATE test_suppressions; DROP TABLE error_log; END -EXTERNAL_NAME NULL -EXTERNAL_LANGUAGE NULL -PARAMETER_STYLE SQL -IS_DETERMINISTIC NO -SQL_DATA_ACCESS CONTAINS SQL -SQL_PATH NULL -SECURITY_TYPE DEFINER -CREATED -LAST_ALTERED -SQL_MODE -ROUTINE_COMMENT -DEFINER root@localhost -CHARACTER_SET_CLIENT latin1 -COLLATION_CONNECTION latin1_swedish_ci -DATABASE_COLLATION latin1_swedish_ci SHOW CREATE FUNCTION fn_1; Function fn_1 sql_mode @@ -670,7 +532,7 @@ ALTER FUNCTION fn_2 CONTAINS SQL; ... now check what is stored: ----------------------------- -SELECT * FROM information_schema.routines; +SELECT * FROM information_schema.routines where routine_schema = 'db_storedproc'; SPECIFIC_NAME fn_1 ROUTINE_CATALOG NULL ROUTINE_SCHEMA db_storedproc @@ -775,75 +637,6 @@ DEFINER root@localhost CHARACTER_SET_CLIENT latin1 COLLATION_CONNECTION latin1_swedish_ci DATABASE_COLLATION latin1_swedish_ci -SPECIFIC_NAME add_suppression -ROUTINE_CATALOG NULL -ROUTINE_SCHEMA mtr -ROUTINE_NAME add_suppression -ROUTINE_TYPE PROCEDURE -DTD_IDENTIFIER NULL -ROUTINE_BODY SQL -ROUTINE_DEFINITION BEGIN INSERT INTO test_suppressions (pattern) VALUES (pattern); END -EXTERNAL_NAME NULL -EXTERNAL_LANGUAGE NULL -PARAMETER_STYLE SQL -IS_DETERMINISTIC NO -SQL_DATA_ACCESS CONTAINS SQL -SQL_PATH NULL -SECURITY_TYPE DEFINER -CREATED -LAST_ALTERED -SQL_MODE -ROUTINE_COMMENT -DEFINER root@localhost -CHARACTER_SET_CLIENT latin1 -COLLATION_CONNECTION latin1_swedish_ci -DATABASE_COLLATION latin1_swedish_ci -SPECIFIC_NAME check_testcase -ROUTINE_CATALOG NULL -ROUTINE_SCHEMA mtr -ROUTINE_NAME check_testcase -ROUTINE_TYPE PROCEDURE -DTD_IDENTIFIER NULL -ROUTINE_BODY SQL -ROUTINE_DEFINITION BEGIN SELECT * FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES WHERE variable_name != 'timestamp' ORDER BY VARIABLE_NAME; SELECT * FROM INFORMATION_SCHEMA.SCHEMATA; SELECT table_name AS tables_in_test FROM INFORMATION_SCHEMA.TABLES WHERE table_schema='test'; SELECT CONCAT(table_schema, '.', table_name) AS tables_in_mysql FROM INFORMATION_SCHEMA.TABLES WHERE table_schema='mysql' AND table_name != 'ndb_apply_status' ORDER BY tables_in_mysql; SELECT CONCAT(table_schema, '.', table_name) AS columns_in_mysql, column_name, ordinal_position, column_default, is_nullable, data_type, character_maximum_length, character_octet_length, numeric_precision, numeric_scale, character_set_name, collation_name, column_type, column_key, extra, column_comment FROM INFORMATION_SCHEMA.COLUMNS WHERE table_schema='mysql' AND table_name != 'ndb_apply_status' ORDER BY columns_in_mysql; checksum table mysql.columns_priv, mysql.db, mysql.func, mysql.help_category, mysql.help_keyword, mysql.help_relation, mysql.host, mysql.proc, mysql.procs_priv, mysql.tables_priv, mysql.time_zone, mysql.time_zone_leap_second, mysql.time_zone_name, mysql.time_zone_transition, mysql.time_zone_transition_type, mysql.user; END -EXTERNAL_NAME NULL -EXTERNAL_LANGUAGE NULL -PARAMETER_STYLE SQL -IS_DETERMINISTIC NO -SQL_DATA_ACCESS CONTAINS SQL -SQL_PATH NULL -SECURITY_TYPE DEFINER -CREATED -LAST_ALTERED -SQL_MODE -ROUTINE_COMMENT -DEFINER root@localhost -CHARACTER_SET_CLIENT latin1 -COLLATION_CONNECTION latin1_swedish_ci -DATABASE_COLLATION latin1_swedish_ci -SPECIFIC_NAME check_warnings -ROUTINE_CATALOG NULL -ROUTINE_SCHEMA mtr -ROUTINE_NAME check_warnings -ROUTINE_TYPE PROCEDURE -DTD_IDENTIFIER NULL -ROUTINE_BODY SQL -ROUTINE_DEFINITION BEGIN DECLARE `pos` bigint unsigned; SET SQL_LOG_BIN=0; UPDATE error_log el, global_suppressions gs SET suspicious=0 WHERE el.suspicious=1 AND el.line REGEXP gs.pattern; UPDATE error_log el, test_suppressions ts SET suspicious=0 WHERE el.suspicious=1 AND el.line REGEXP ts.pattern; SELECT COUNT(*) INTO @num_warnings FROM error_log WHERE suspicious=1; IF @num_warnings > 0 THEN SELECT file_name, line FROM error_log WHERE suspicious=1; SELECT 2 INTO result; ELSE SELECT 0 INTO RESULT; END IF; TRUNCATE test_suppressions; DROP TABLE error_log; END -EXTERNAL_NAME NULL -EXTERNAL_LANGUAGE NULL -PARAMETER_STYLE SQL -IS_DETERMINISTIC NO -SQL_DATA_ACCESS CONTAINS SQL -SQL_PATH NULL -SECURITY_TYPE DEFINER -CREATED -LAST_ALTERED -SQL_MODE -ROUTINE_COMMENT -DEFINER root@localhost -CHARACTER_SET_CLIENT latin1 -COLLATION_CONNECTION latin1_swedish_ci -DATABASE_COLLATION latin1_swedish_ci SHOW CREATE FUNCTION fn_1; Function fn_1 sql_mode diff --git a/mysql-test/suite/funcs_1/r/ndb_trig_0102.result b/mysql-test/suite/funcs_1/r/ndb_trig_0102.result index 86c2d2521ac..5ca24acf0bf 100644 --- a/mysql-test/suite/funcs_1/r/ndb_trig_0102.result +++ b/mysql-test/suite/funcs_1/r/ndb_trig_0102.result @@ -348,13 +348,13 @@ for each row set @test_var2='trig1_a'; create trigger trig_db2.trig2 before insert on trig_db2.t1 for each row set @test_var3='trig2'; select trigger_schema, trigger_name, event_object_table -from information_schema.triggers order by trigger_name; +from information_schema.triggers +where trigger_schema like 'trig_db%' + order by trigger_name; trigger_schema trigger_name event_object_table -mtr gs_insert global_suppressions trig_db1 trig1_a t1 trig_db1 trig1_b t1 trig_db2 trig2 t1 -mtr ts_insert test_suppressions set @test_var1= '', @test_var2= '', @test_var3= ''; insert into t1 (f1,f2) values ('insert to db1 t1 from db1',352); insert into trig_db2.t1 (f1,f2) values ('insert to db2 t1 from db1',352); diff --git a/mysql-test/suite/funcs_1/r/ndb_trig_0407.result b/mysql-test/suite/funcs_1/r/ndb_trig_0407.result index 62c8e0d06db..33e58f50ec1 100644 --- a/mysql-test/suite/funcs_1/r/ndb_trig_0407.result +++ b/mysql-test/suite/funcs_1/r/ndb_trig_0407.result @@ -90,10 +90,10 @@ f1 Trigger 3.5.4.1 drop trigger trg1; select trigger_schema, trigger_name, event_object_table -from information_schema.triggers order by trigger_name; +from information_schema.triggers +where trigger_schema = 'db_drop' + order by trigger_name; trigger_schema trigger_name event_object_table -mtr gs_insert global_suppressions -mtr ts_insert test_suppressions Insert into t1 values ('Insert no trigger 3.5.4.1'); Select * from t1 order by f1; f1 @@ -151,12 +151,8 @@ Select * from t1; f1 Trigger 3.5.4.4 Drop database db_drop4; -Show databases; -Database -information_schema -mtr -mysql -test +Show databases like 'db_drop4'; +Database (db_drop4) select trigger_schema, trigger_name, event_object_table from information_schema.triggers where information_schema.triggers.trigger_name='trg4'; diff --git a/mysql-test/suite/funcs_1/r/storedproc.result b/mysql-test/suite/funcs_1/r/storedproc.result index fd5b090e6fb..7e21ddf1544 100644 --- a/mysql-test/suite/funcs_1/r/storedproc.result +++ b/mysql-test/suite/funcs_1/r/storedproc.result @@ -92,11 +92,8 @@ END// ERROR 42000: Identifier name 'sp1_thisisaveryverylongname234872934_thisisaveryverylongnameabcde' is too long CALL sp1_thisisaveryverylongname234872934_thisisaveryverylongnameabcde( 'abc' ); ERROR 42000: Identifier name 'sp1_thisisaveryverylongname234872934_thisisaveryverylongnameabcde' is too long -SHOW PROCEDURE STATUS; +SHOW PROCEDURE STATUS WHERE db = 'db_storedproc'; Db Name Type Definer Modified Created Security_type Comment character_set_client collation_connection Database Collation -mtr add_suppression PROCEDURE root@localhost DEFINER latin1 latin1_swedish_ci latin1_swedish_ci -mtr check_testcase PROCEDURE root@localhost DEFINER latin1 latin1_swedish_ci latin1_swedish_ci -mtr check_warnings PROCEDURE root@localhost DEFINER latin1 latin1_swedish_ci latin1_swedish_ci DROP PROCEDURE IF EXISTS sp1; CREATE PROCEDURE sp1( f1 BINARY ) LANGUAGE SQL DETERMINISTIC SQL SECURITY INVOKER COMMENT 'this is simple' @@ -109,12 +106,9 @@ CALL sp1( 34 ); 3 Warnings: Warning 1265 Data truncated for column 'f1' at row 1 -SHOW PROCEDURE STATUS; +SHOW PROCEDURE STATUS WHERE db = 'db_storedproc'; Db Name Type Definer Modified Created Security_type Comment character_set_client collation_connection Database Collation db_storedproc sp1 PROCEDURE root@localhost INVOKER this is simple latin1 latin1_swedish_ci latin1_swedish_ci -mtr add_suppression PROCEDURE root@localhost DEFINER latin1 latin1_swedish_ci latin1_swedish_ci -mtr check_testcase PROCEDURE root@localhost DEFINER latin1 latin1_swedish_ci latin1_swedish_ci -mtr check_warnings PROCEDURE root@localhost DEFINER latin1 latin1_swedish_ci latin1_swedish_ci DROP PROCEDURE IF EXISTS sp1; CREATE PROCEDURE sp1( f1 BLOB ) LANGUAGE SQL NOT DETERMINISTIC SQL SECURITY INVOKER COMMENT 'this is simple' @@ -125,12 +119,9 @@ END// CALL sp1( 34 ); @v1 34 -SHOW PROCEDURE STATUS; +SHOW PROCEDURE STATUS WHERE db = 'db_storedproc'; Db Name Type Definer Modified Created Security_type Comment character_set_client collation_connection Database Collation db_storedproc sp1 PROCEDURE root@localhost INVOKER this is simple latin1 latin1_swedish_ci latin1_swedish_ci -mtr add_suppression PROCEDURE root@localhost DEFINER latin1 latin1_swedish_ci latin1_swedish_ci -mtr check_testcase PROCEDURE root@localhost DEFINER latin1 latin1_swedish_ci latin1_swedish_ci -mtr check_warnings PROCEDURE root@localhost DEFINER latin1 latin1_swedish_ci latin1_swedish_ci DROP PROCEDURE IF EXISTS sp1; CREATE PROCEDURE sp1( f1 INT ) LANGUAGE SQL NOT DETERMINISTIC SQL SECURITY INVOKER COMMENT 'this is simple' @@ -141,12 +132,9 @@ END// CALL sp1( 34 ); @v1 34 -SHOW PROCEDURE STATUS; +SHOW PROCEDURE STATUS WHERE db = 'db_storedproc'; Db Name Type Definer Modified Created Security_type Comment character_set_client collation_connection Database Collation db_storedproc sp1 PROCEDURE root@localhost INVOKER this is simple latin1 latin1_swedish_ci latin1_swedish_ci -mtr add_suppression PROCEDURE root@localhost DEFINER latin1 latin1_swedish_ci latin1_swedish_ci -mtr check_testcase PROCEDURE root@localhost DEFINER latin1 latin1_swedish_ci latin1_swedish_ci -mtr check_warnings PROCEDURE root@localhost DEFINER latin1 latin1_swedish_ci latin1_swedish_ci DROP PROCEDURE IF EXISTS sp1; CREATE PROCEDURE sp1( f1 DECIMAL(256, 30) ) LANGUAGE SQL NOT DETERMINISTIC SQL SECURITY INVOKER COMMENT 'this is simple' @@ -185,13 +173,10 @@ LANGUAGE SQL NOT DETERMINISTIC SQL SECURITY INVOKER COMMENT 'this is simple' BEGIN RETURN f1; END// -SHOW PROCEDURE STATUS; +SHOW PROCEDURE STATUS WHERE db = 'db_storedproc'; Db Name Type Definer Modified Created Security_type Comment character_set_client collation_connection Database Collation db_storedproc sproc_1 PROCEDURE root@localhost INVOKER this is simple latin1 latin1_swedish_ci latin1_swedish_ci -mtr add_suppression PROCEDURE root@localhost DEFINER latin1 latin1_swedish_ci latin1_swedish_ci -mtr check_testcase PROCEDURE root@localhost DEFINER latin1 latin1_swedish_ci latin1_swedish_ci -mtr check_warnings PROCEDURE root@localhost DEFINER latin1 latin1_swedish_ci latin1_swedish_ci -SHOW FUNCTION STATUS; +SHOW FUNCTION STATUS WHERE db = 'db_storedproc'; Db Name Type Definer Modified Created Security_type Comment character_set_client collation_connection Database Collation db_storedproc func_1 FUNCTION root@localhost INVOKER this is simple latin1 latin1_swedish_ci latin1_swedish_ci UPDATE t1_aux SET f1 = NULL; @@ -1431,12 +1416,9 @@ f1 value1 Warnings: Note 1291 Column '' has duplicated value 'value1' in ENUM -SHOW PROCEDURE STATUS; +SHOW PROCEDURE STATUS WHERE db = 'db_storedproc'; Db Name Type Definer Modified Created Security_type Comment character_set_client collation_connection Database Collation db_storedproc sp1 PROCEDURE root@localhost INVOKER this is simple latin1 latin1_swedish_ci latin1_swedish_ci -mtr add_suppression PROCEDURE root@localhost DEFINER latin1 latin1_swedish_ci latin1_swedish_ci -mtr check_testcase PROCEDURE root@localhost DEFINER latin1 latin1_swedish_ci latin1_swedish_ci -mtr check_warnings PROCEDURE root@localhost DEFINER latin1 latin1_swedish_ci latin1_swedish_ci DROP PROCEDURE IF EXISTS sp1; CREATE PROCEDURE sp1( f1 SET("value1", "value1") ) LANGUAGE SQL NOT DETERMINISTIC SQL SECURITY INVOKER COMMENT 'this is simple' @@ -1451,12 +1433,9 @@ value1 Warnings: Note 1291 Column '' has duplicated value 'value1' in SET Warning 1265 Data truncated for column 'f1' at row 1 -SHOW PROCEDURE STATUS; +SHOW PROCEDURE STATUS WHERE db = 'db_storedproc'; Db Name Type Definer Modified Created Security_type Comment character_set_client collation_connection Database Collation db_storedproc sp1 PROCEDURE root@localhost INVOKER this is simple latin1 latin1_swedish_ci latin1_swedish_ci -mtr add_suppression PROCEDURE root@localhost DEFINER latin1 latin1_swedish_ci latin1_swedish_ci -mtr check_testcase PROCEDURE root@localhost DEFINER latin1 latin1_swedish_ci latin1_swedish_ci -mtr check_warnings PROCEDURE root@localhost DEFINER latin1 latin1_swedish_ci latin1_swedish_ci DROP PROCEDURE IF EXISTS sp1; CREATE PROCEDURE sp1( f1 ENUM("value1", "value1") ) LANGUAGE SQL NOT DETERMINISTIC SQL SECURITY INVOKER COMMENT 'this is simple' @@ -1470,12 +1449,9 @@ f1 value1 Warnings: Note 1291 Column '' has duplicated value 'value1' in ENUM -SHOW PROCEDURE STATUS; +SHOW PROCEDURE STATUS WHERE db = 'db_storedproc'; Db Name Type Definer Modified Created Security_type Comment character_set_client collation_connection Database Collation db_storedproc sp1 PROCEDURE root@localhost INVOKER this is simple latin1 latin1_swedish_ci latin1_swedish_ci -mtr add_suppression PROCEDURE root@localhost DEFINER latin1 latin1_swedish_ci latin1_swedish_ci -mtr check_testcase PROCEDURE root@localhost DEFINER latin1 latin1_swedish_ci latin1_swedish_ci -mtr check_warnings PROCEDURE root@localhost DEFINER latin1 latin1_swedish_ci latin1_swedish_ci DROP PROCEDURE IF EXISTS sp1; CREATE PROCEDURE sp1( f1 TEXT ) LANGUAGE SQL SELECT f1; CALL sp1( 'abc' ); diff --git a/mysql-test/suite/funcs_1/storedproc/storedproc_08_show.inc b/mysql-test/suite/funcs_1/storedproc/storedproc_08_show.inc index 962d9242675..d6fd397561c 100644 --- a/mysql-test/suite/funcs_1/storedproc/storedproc_08_show.inc +++ b/mysql-test/suite/funcs_1/storedproc/storedproc_08_show.inc @@ -2,15 +2,14 @@ # # used from .../storedproc_08.inc to show all created / altered routines -let $message= ... now check what is stored:; ---source include/show_msg.inc +--echo +--echo ... now check what is stored: +--echo ----------------------------- --vertical_results -#--replace_column 16 "YYYY-MM-DD hh:mm:ss" 17 "YYYY-MM-DD hh:mm:ss" - --replace_column 16 17 -SELECT * FROM information_schema.routines; +SELECT * FROM information_schema.routines where routine_schema = 'db_storedproc'; SHOW CREATE FUNCTION fn_1; diff --git a/mysql-test/suite/funcs_1/t/storedproc.test b/mysql-test/suite/funcs_1/t/storedproc.test index cc45101fbed..6877b751ed2 100644 --- a/mysql-test/suite/funcs_1/t/storedproc.test +++ b/mysql-test/suite/funcs_1/t/storedproc.test @@ -72,7 +72,7 @@ delimiter ;// CALL sp1_thisisaveryverylongname234872934_thisisaveryverylongnameabcde( 'abc' ); --replace_column 5 6 -SHOW PROCEDURE STATUS; +SHOW PROCEDURE STATUS WHERE db = 'db_storedproc'; --disable_warnings DROP PROCEDURE IF EXISTS sp1; @@ -90,7 +90,7 @@ delimiter ;// CALL sp1( 34 ); --replace_column 5 6 -SHOW PROCEDURE STATUS; +SHOW PROCEDURE STATUS WHERE db = 'db_storedproc'; --disable_warnings DROP PROCEDURE IF EXISTS sp1; @@ -108,7 +108,7 @@ delimiter ;// CALL sp1( 34 ); --replace_column 5 6 -SHOW PROCEDURE STATUS; +SHOW PROCEDURE STATUS WHERE db = 'db_storedproc'; --disable_warnings DROP PROCEDURE IF EXISTS sp1; @@ -126,7 +126,7 @@ delimiter ;// CALL sp1( 34 ); --replace_column 5 6 -SHOW PROCEDURE STATUS; +SHOW PROCEDURE STATUS WHERE db = 'db_storedproc'; --disable_warnings DROP PROCEDURE IF EXISTS sp1; @@ -191,9 +191,9 @@ BEGIN END// delimiter ;// --replace_column 5 6 -SHOW PROCEDURE STATUS; +SHOW PROCEDURE STATUS WHERE db = 'db_storedproc'; --replace_column 5 6 -SHOW FUNCTION STATUS; +SHOW FUNCTION STATUS WHERE db = 'db_storedproc'; let $test_value = 1.7976931348623157493578e+308; --source suite/funcs_1/storedproc/param_check.inc @@ -245,7 +245,7 @@ delimiter ;// CALL sp1( "value1" ); --replace_column 5 6 -SHOW PROCEDURE STATUS; +SHOW PROCEDURE STATUS WHERE db = 'db_storedproc'; --disable_warnings DROP PROCEDURE IF EXISTS sp1; @@ -262,7 +262,7 @@ delimiter ;// CALL sp1( "value1, value1" ); --replace_column 5 6 -SHOW PROCEDURE STATUS; +SHOW PROCEDURE STATUS WHERE db = 'db_storedproc'; --disable_warnings DROP PROCEDURE IF EXISTS sp1; @@ -279,7 +279,7 @@ delimiter ;// CALL sp1( "value1" ); --replace_column 5 6 -SHOW PROCEDURE STATUS; +SHOW PROCEDURE STATUS WHERE db = 'db_storedproc'; --disable_warnings DROP PROCEDURE IF EXISTS sp1; diff --git a/mysql-test/suite/funcs_1/triggers/triggers_0102.inc b/mysql-test/suite/funcs_1/triggers/triggers_0102.inc index 3afbc3f7aa9..e49bcead9f1 100644 --- a/mysql-test/suite/funcs_1/triggers/triggers_0102.inc +++ b/mysql-test/suite/funcs_1/triggers/triggers_0102.inc @@ -458,7 +458,9 @@ let $message= Testcase 3.5.2.1/2/3:; create trigger trig_db2.trig2 before insert on trig_db2.t1 for each row set @test_var3='trig2'; select trigger_schema, trigger_name, event_object_table - from information_schema.triggers order by trigger_name; + from information_schema.triggers + where trigger_schema like 'trig_db%' + order by trigger_name; set @test_var1= '', @test_var2= '', @test_var3= ''; insert into t1 (f1,f2) values ('insert to db1 t1 from db1',352); diff --git a/mysql-test/suite/funcs_1/triggers/triggers_0407.inc b/mysql-test/suite/funcs_1/triggers/triggers_0407.inc index a5e3c180a71..af45017ae6a 100644 --- a/mysql-test/suite/funcs_1/triggers/triggers_0407.inc +++ b/mysql-test/suite/funcs_1/triggers/triggers_0407.inc @@ -60,7 +60,9 @@ let $message= Testcase 3.5.4.1:; connection con1_super; drop trigger trg1; select trigger_schema, trigger_name, event_object_table - from information_schema.triggers order by trigger_name; + from information_schema.triggers + where trigger_schema = 'db_drop' + order by trigger_name; connection con1_general; Insert into t1 values ('Insert no trigger 3.5.4.1'); Select * from t1 order by f1; @@ -160,7 +162,7 @@ let $message= Testcase 3.5.4.4:; Select * from t1; connection con1_super; Drop database db_drop4; - Show databases; + Show databases like 'db_drop4'; select trigger_schema, trigger_name, event_object_table from information_schema.triggers where information_schema.triggers.trigger_name='trg4'; From f29aa74aa125990461b8db6e51740026125c8c45 Mon Sep 17 00:00:00 2001 From: Davi Arnaut Date: Fri, 13 Feb 2009 17:26:20 -0200 Subject: [PATCH 081/219] Remove test case for bug 40264. Dirty close tricky does not work on Windows. mysql-test/r/query_cache_notembedded.result: Remove test case result. mysql-test/t/query_cache_notembedded.test: Remove test case. --- mysql-test/r/query_cache_notembedded.result | 16 ------------ mysql-test/t/query_cache_notembedded.test | 29 --------------------- 2 files changed, 45 deletions(-) diff --git a/mysql-test/r/query_cache_notembedded.result b/mysql-test/r/query_cache_notembedded.result index bf582bfaec6..8e5df012cfb 100644 --- a/mysql-test/r/query_cache_notembedded.result +++ b/mysql-test/r/query_cache_notembedded.result @@ -345,19 +345,3 @@ id drop table t1; drop function f1; set GLOBAL query_cache_size=0; -DROP TABLE IF EXISTS t1; -FLUSH STATUS; -SET GLOBAL query_cache_size=1048576; -CREATE TABLE t1 (a INT); -INSERT INTO t1 VALUES (1),(2),(3),(4),(5); -SHOW STATUS LIKE 'Qcache_queries_in_cache'; -Variable_name Value -Qcache_queries_in_cache 0 -LOCK TABLES t1 WRITE; -SELECT * FROM t1; -UNLOCK TABLES; -SHOW STATUS LIKE 'Qcache_queries_in_cache'; -Variable_name Value -Qcache_queries_in_cache 0 -DROP TABLE t1; -SET GLOBAL query_cache_size= default; diff --git a/mysql-test/t/query_cache_notembedded.test b/mysql-test/t/query_cache_notembedded.test index d98ed691c7b..112856117ce 100644 --- a/mysql-test/t/query_cache_notembedded.test +++ b/mysql-test/t/query_cache_notembedded.test @@ -230,35 +230,6 @@ connection default; set GLOBAL query_cache_size=0; -# -# Bug#40264: Aborted cached query causes query to hang indefinitely on next cache hit -# - ---disable_warnings -DROP TABLE IF EXISTS t1; ---enable_warnings - -FLUSH STATUS; -SET GLOBAL query_cache_size=1048576; -CREATE TABLE t1 (a INT); -INSERT INTO t1 VALUES (1),(2),(3),(4),(5); -SHOW STATUS LIKE 'Qcache_queries_in_cache'; -LOCK TABLES t1 WRITE; -connect(con1,localhost,root,,); ---send SELECT * FROM t1 -connection default; -let $show_type= open tables where `table`='t1' and in_use=2; -let $show_pattern= '%t1%2%'; ---source include/wait_show_pattern.inc -dirty_close con1; -UNLOCK TABLES; -let $show_type= open tables where `table`='t1' and in_use=0; -let $show_pattern= '%t1%0%'; ---source include/wait_show_pattern.inc -SHOW STATUS LIKE 'Qcache_queries_in_cache'; -DROP TABLE t1; -SET GLOBAL query_cache_size= default; - # End of 5.0 tests # Wait till we reached the initial number of concurrent sessions From aedef27a85bb21826f35f3ce9e1ff6e1cb471a19 Mon Sep 17 00:00:00 2001 From: Patrick Crews Date: Fri, 13 Feb 2009 16:12:59 -0500 Subject: [PATCH 082/219] BUG#32667: lowercase_table3.test reports to error log Cleaned up SQL code in the test. Needed to move the FLUSH TABLES statement prior to the DROP TABLE t1 to prevent a warning of Table open on delete and a test fail. --- mysql-test/r/lowercase_table3.result | 16 ++++++++-------- mysql-test/t/lowercase_table3.test | 19 +++++++++---------- 2 files changed, 17 insertions(+), 18 deletions(-) diff --git a/mysql-test/r/lowercase_table3.result b/mysql-test/r/lowercase_table3.result index 880a203a15f..1ef7d04bb1d 100644 --- a/mysql-test/r/lowercase_table3.result +++ b/mysql-test/r/lowercase_table3.result @@ -1,11 +1,11 @@ -call mtr.add_suppression("Cannot find or open table test/BUG29839 from"); +call mtr.add_suppression("Cannot find or open table test/BUG29839 from .*"); DROP TABLE IF EXISTS t1,T1; -CREATE TABLE t1 (a int); -SELECT * from T1; +CREATE TABLE t1 (a INT); +SELECT * FROM T1; a -drop table t1; -flush tables; -CREATE TABLE bug29839 (a int) ENGINE=INNODB; -SELECT * from BUG29839; +FLUSH TABLES; +DROP TABLE t1; +CREATE TABLE bug29839 (a INT) ENGINE=INNODB; +SELECT * FROM BUG29839; ERROR 42S02: Table 'test.BUG29839' doesn't exist -drop table bug29839; +DROP TABLE bug29839; diff --git a/mysql-test/t/lowercase_table3.test b/mysql-test/t/lowercase_table3.test index e71d9029606..4748953fe95 100644 --- a/mysql-test/t/lowercase_table3.test +++ b/mysql-test/t/lowercase_table3.test @@ -9,7 +9,7 @@ --source include/have_case_insensitive_file_system.inc --source include/not_windows.inc -call mtr.add_suppression("Cannot find or open table test/BUG29839 from"); +call mtr.add_suppression("Cannot find or open table test/BUG29839 from .*"); --disable_warnings DROP TABLE IF EXISTS t1,T1; @@ -18,11 +18,10 @@ DROP TABLE IF EXISTS t1,T1; # # This is actually an error, but ok as the user has forced this # by using --lower-case-table-names=0 - -CREATE TABLE t1 (a int); -SELECT * from T1; -drop table t1; -flush tables; +CREATE TABLE t1 (a INT); +SELECT * FROM T1; +FLUSH TABLES; +DROP TABLE t1; # # InnoDB should in this case be case sensitive @@ -30,9 +29,9 @@ flush tables; # storing things in lower case. # -CREATE TABLE bug29839 (a int) ENGINE=INNODB; ---error 1146 -SELECT * from BUG29839; -drop table bug29839; +CREATE TABLE bug29839 (a INT) ENGINE=INNODB; +--error ER_NO_SUCH_TABLE +SELECT * FROM BUG29839; +DROP TABLE bug29839; # End of 4.1 tests From 60f7f87abba10cee407e866356ea0f6f145052ba Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 14 Feb 2009 01:43:21 +0100 Subject: [PATCH 083/219] Disabled libedit use of '__weak_reference' on FreeBSD, doesn't compile --- cmd-line-utils/libedit/vi.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cmd-line-utils/libedit/vi.c b/cmd-line-utils/libedit/vi.c index 602383f3231..00a9f493a9b 100644 --- a/cmd-line-utils/libedit/vi.c +++ b/cmd-line-utils/libedit/vi.c @@ -914,14 +914,14 @@ vi_comment_out(EditLine *el, int c) * NB: posix implies that we should enter insert mode, however * this is against historical precedent... */ -#ifdef __weak_reference +#if defined(__weak_reference) && !defined(__FreeBSD__) extern char *get_alias_text(const char *) __weak_reference(get_alias_text); #endif protected el_action_t /*ARGSUSED*/ vi_alias(EditLine *el, int c) { -#ifdef __weak_reference +#if defined(__weak_reference) && !defined(__FreeBSD__) char alias_name[3]; char *alias_text; From 0e4333f6ccb5fb2f0fc2797745b9d8bffc2e75c0 Mon Sep 17 00:00:00 2001 From: Ramil Kalimullin Date: Sat, 14 Feb 2009 14:40:22 +0400 Subject: [PATCH 084/219] Fix for bug#21476: stack overflow crashes server; error-message stack reservation too small Problem: some tests fail on HP-UX due to insufficient stack reservation. Fix: increase stack reservation. sql/mysql_priv.h: Fix for bug#21476: stack overflow crashes server; error-message stack reservation too small - raised STACK_MIN_SIZE to pass execution_constants.test on HP-UX. --- sql/mysql_priv.h | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index 015128cda1f..3fba9248940 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -282,16 +282,12 @@ protected: */ #define TABLE_DEF_CACHE_MIN 256 -/* - Value of 9236 discovered through binary search 2006-09-26 on Ubuntu Dapper - Drake, libc6 2.3.6-0ubuntu2, Linux kernel 2.6.15-27-686, on x86. (Added - 100 bytes as reasonable buffer against growth and other environments' - requirements.) - - Feel free to raise this by the smallest amount you can to get the - "execution_constants" test to pass. - */ -#define STACK_MIN_SIZE 12000 ///< Abort if less stack during eval. +/* + Stack reservation. + Feel free to raise this by the smallest amount you can to get the + "execution_constants" test to pass. +*/ +#define STACK_MIN_SIZE 16000 // Abort if less stack during eval. #define STACK_MIN_SIZE_FOR_OPEN 1024*80 #define STACK_BUFF_ALLOC 352 ///< For stack overrun checks From b41215add2ee2bffb8ba00716afa20a478f03f37 Mon Sep 17 00:00:00 2001 From: Alexey Kopytov Date: Sat, 14 Feb 2009 18:36:57 +0300 Subject: [PATCH 085/219] Fixed bdb_gis and ndb_gis test failures in PB introduced by the patch for bug #21205. mysql-test/r/bdb_gis.result: Take additional precision into account. mysql-test/r/ndb_gis.result: Take additional precision into account. mysql-test/t/type_float.test: Added missing DROP TABLE. --- mysql-test/r/bdb_gis.result | 6 +++--- mysql-test/r/ndb_gis.result | 12 ++++++------ mysql-test/t/type_float.test | 1 + 3 files changed, 10 insertions(+), 9 deletions(-) diff --git a/mysql-test/r/bdb_gis.result b/mysql-test/r/bdb_gis.result index 6651421b51c..3187d7bef99 100644 --- a/mysql-test/r/bdb_gis.result +++ b/mysql-test/r/bdb_gis.result @@ -291,7 +291,7 @@ Note 1003 select astext(startpoint(`test`.`gis_line`.`g`)) AS `AsText(StartPoint SELECT fid, AsText(Centroid(g)) FROM gis_polygon ORDER by fid; fid AsText(Centroid(g)) 108 POINT(15 15) -109 POINT(25.416666666667 25.416666666667) +109 POINT(25.4166666666667 25.4166666666667) 110 POINT(20 10) SELECT fid, Area(g) FROM gis_polygon ORDER by fid; fid Area(g) @@ -325,8 +325,8 @@ fid IsClosed(g) 116 0 SELECT fid, AsText(Centroid(g)) FROM gis_multi_polygon ORDER by fid; fid AsText(Centroid(g)) -117 POINT(55.588527753042 17.426536064114) -118 POINT(55.588527753042 17.426536064114) +117 POINT(55.5885277530424 17.426536064114) +118 POINT(55.5885277530424 17.426536064114) 119 POINT(2 2) SELECT fid, Area(g) FROM gis_multi_polygon ORDER by fid; fid Area(g) diff --git a/mysql-test/r/ndb_gis.result b/mysql-test/r/ndb_gis.result index ec064ace651..0625128195b 100644 --- a/mysql-test/r/ndb_gis.result +++ b/mysql-test/r/ndb_gis.result @@ -291,7 +291,7 @@ Note 1003 select astext(startpoint(`test`.`gis_line`.`g`)) AS `AsText(StartPoint SELECT fid, AsText(Centroid(g)) FROM gis_polygon ORDER by fid; fid AsText(Centroid(g)) 108 POINT(15 15) -109 POINT(25.416666666667 25.416666666667) +109 POINT(25.4166666666667 25.4166666666667) 110 POINT(20 10) SELECT fid, Area(g) FROM gis_polygon ORDER by fid; fid Area(g) @@ -325,8 +325,8 @@ fid IsClosed(g) 116 0 SELECT fid, AsText(Centroid(g)) FROM gis_multi_polygon ORDER by fid; fid AsText(Centroid(g)) -117 POINT(55.588527753042 17.426536064114) -118 POINT(55.588527753042 17.426536064114) +117 POINT(55.5885277530424 17.426536064114) +118 POINT(55.5885277530424 17.426536064114) 119 POINT(2 2) SELECT fid, Area(g) FROM gis_multi_polygon ORDER by fid; fid Area(g) @@ -835,7 +835,7 @@ Note 1003 select astext(startpoint(`test`.`gis_line`.`g`)) AS `AsText(StartPoint SELECT fid, AsText(Centroid(g)) FROM gis_polygon ORDER by fid; fid AsText(Centroid(g)) 108 POINT(15 15) -109 POINT(25.416666666667 25.416666666667) +109 POINT(25.4166666666667 25.4166666666667) 110 POINT(20 10) SELECT fid, Area(g) FROM gis_polygon ORDER by fid; fid Area(g) @@ -869,8 +869,8 @@ fid IsClosed(g) 116 0 SELECT fid, AsText(Centroid(g)) FROM gis_multi_polygon ORDER by fid; fid AsText(Centroid(g)) -117 POINT(55.588527753042 17.426536064114) -118 POINT(55.588527753042 17.426536064114) +117 POINT(55.5885277530424 17.426536064114) +118 POINT(55.5885277530424 17.426536064114) 119 POINT(2 2) SELECT fid, Area(g) FROM gis_multi_polygon ORDER by fid; fid Area(g) diff --git a/mysql-test/t/type_float.test b/mysql-test/t/type_float.test index 42703e11863..3b7b30db6f8 100644 --- a/mysql-test/t/type_float.test +++ b/mysql-test/t/type_float.test @@ -274,5 +274,6 @@ drop table t1; CREATE TABLE t1 (f1 DOUBLE); INSERT INTO t1 VALUES(-1.79769313486231e+308); SELECT f1 FROM t1; +DROP TABLE t1; --echo End of 5.0 tests From 9665fcfff31fc3b13a838f20e0ab362074eb947b Mon Sep 17 00:00:00 2001 From: Alexey Kopytov Date: Sat, 14 Feb 2009 18:58:07 +0300 Subject: [PATCH 086/219] Fixed several test failures in the funcs_1 suite introduced by the patch for bug #21205. mysql-test/suite/funcs_1/r/memory_func_view.result: Take additional precision into account. mysql-test/suite/funcs_1/r/memory_views.result: Take additional precision into account. mysql-test/suite/funcs_1/r/myisam_func_view.result: Take additional precision into account. mysql-test/suite/funcs_1/r/myisam_views.result: Take additional precision into account. --- mysql-test/suite/funcs_1/r/memory_func_view.result | 4 ++-- mysql-test/suite/funcs_1/r/memory_views.result | 6 +++--- mysql-test/suite/funcs_1/r/myisam_func_view.result | 4 ++-- mysql-test/suite/funcs_1/r/myisam_views.result | 6 +++--- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/mysql-test/suite/funcs_1/r/memory_func_view.result b/mysql-test/suite/funcs_1/r/memory_func_view.result index c2689a36801..0bd83c81bcf 100644 --- a/mysql-test/suite/funcs_1/r/memory_func_view.result +++ b/mysql-test/suite/funcs_1/r/memory_func_view.result @@ -5245,7 +5245,7 @@ WHERE select_id = 1 OR select_id IS NULL order by id; sqrt(my_bigint) my_bigint id NULL NULL 1 NULL -9223372036854775808 2 -3037000499.976 9223372036854775807 3 +3037000499.97605 9223372036854775807 3 0 0 4 NULL -1 5 2 4 6 @@ -5259,7 +5259,7 @@ WHERE select_id = 1 OR select_id IS NULL) order by id; sqrt(my_bigint) my_bigint id NULL NULL 1 NULL -9223372036854775808 2 -3037000499.976 9223372036854775807 3 +3037000499.97605 9223372036854775807 3 0 0 4 NULL -1 5 2 4 6 diff --git a/mysql-test/suite/funcs_1/r/memory_views.result b/mysql-test/suite/funcs_1/r/memory_views.result index 7bd674b8d76..d24d72473fd 100644 --- a/mysql-test/suite/funcs_1/r/memory_views.result +++ b/mysql-test/suite/funcs_1/r/memory_views.result @@ -22825,7 +22825,7 @@ f1 f2 ABC 3 SELECT * FROM v1 order by 2; f1 my_sqrt -ABC 1.7320508075689 +ABC 1.73205080756888 ALTER TABLE t1 CHANGE COLUMN f2 f2 VARCHAR(30); INSERT INTO t1 SET f1 = 'ABC', f2 = 'DEF'; DESCRIBE t1; @@ -22843,7 +22843,7 @@ ABC DEF SELECT * FROM v1 order by 2; f1 my_sqrt ABC 0 -ABC 1.7320508075689 +ABC 1.73205080756888 SELECT SQRT('DEF'); SQRT('DEF') 0 @@ -22863,7 +22863,7 @@ my_sqrt double YES NULL SELECT * FROM v2 order by 2; f1 my_sqrt ABC 0 -ABC 1.7320508075689 +ABC 1.73205080756888 CREATE TABLE t2 AS SELECT f1, SQRT(f2) my_sqrt FROM t1; SELECT * FROM t2 order by 2; f1 ABC diff --git a/mysql-test/suite/funcs_1/r/myisam_func_view.result b/mysql-test/suite/funcs_1/r/myisam_func_view.result index c2689a36801..0bd83c81bcf 100644 --- a/mysql-test/suite/funcs_1/r/myisam_func_view.result +++ b/mysql-test/suite/funcs_1/r/myisam_func_view.result @@ -5245,7 +5245,7 @@ WHERE select_id = 1 OR select_id IS NULL order by id; sqrt(my_bigint) my_bigint id NULL NULL 1 NULL -9223372036854775808 2 -3037000499.976 9223372036854775807 3 +3037000499.97605 9223372036854775807 3 0 0 4 NULL -1 5 2 4 6 @@ -5259,7 +5259,7 @@ WHERE select_id = 1 OR select_id IS NULL) order by id; sqrt(my_bigint) my_bigint id NULL NULL 1 NULL -9223372036854775808 2 -3037000499.976 9223372036854775807 3 +3037000499.97605 9223372036854775807 3 0 0 4 NULL -1 5 2 4 6 diff --git a/mysql-test/suite/funcs_1/r/myisam_views.result b/mysql-test/suite/funcs_1/r/myisam_views.result index bde591c13bf..e4d6dd4cf8e 100644 --- a/mysql-test/suite/funcs_1/r/myisam_views.result +++ b/mysql-test/suite/funcs_1/r/myisam_views.result @@ -24527,7 +24527,7 @@ f1 f2 ABC 3 SELECT * FROM v1 order by 2; f1 my_sqrt -ABC 1.7320508075689 +ABC 1.73205080756888 ALTER TABLE t1 CHANGE COLUMN f2 f2 VARCHAR(30); INSERT INTO t1 SET f1 = 'ABC', f2 = 'DEF'; DESCRIBE t1; @@ -24545,7 +24545,7 @@ ABC DEF SELECT * FROM v1 order by 2; f1 my_sqrt ABC 0 -ABC 1.7320508075689 +ABC 1.73205080756888 SELECT SQRT('DEF'); SQRT('DEF') 0 @@ -24565,7 +24565,7 @@ my_sqrt double YES NULL SELECT * FROM v2 order by 2; f1 my_sqrt ABC 0 -ABC 1.7320508075689 +ABC 1.73205080756888 CREATE TABLE t2 AS SELECT f1, SQRT(f2) my_sqrt FROM t1; SELECT * FROM t2 order by 2; f1 ABC From 6d1dc3270b11b71b83acf6cc1ead73224c68d3b1 Mon Sep 17 00:00:00 2001 From: Alexey Kopytov Date: Sat, 14 Feb 2009 19:04:16 +0300 Subject: [PATCH 087/219] Fixed parser test failure introduced by the patch for bug #21205. mysql-test/r/parser.result: Take additional precision into account. --- mysql-test/r/parser.result | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mysql-test/r/parser.result b/mysql-test/r/parser.result index 270c1ec5670..002fbd02c2a 100644 --- a/mysql-test/r/parser.result +++ b/mysql-test/r/parser.result @@ -522,7 +522,7 @@ select conv(255 AS p1, 10 AS p2, 16 AS p3); ERROR 42000: Incorrect parameters in the call to native function 'conv' select atan(10); atan(10) -1.4711276743037 +1.47112767430373 select atan(10 AS p1); ERROR 42000: Incorrect parameters in the call to native function 'atan' select atan(10 p1); @@ -533,7 +533,7 @@ select atan(10 "p1"); ERROR 42000: Incorrect parameters in the call to native function 'atan' select atan(10, 20); atan(10, 20) -0.46364760900081 +0.463647609000806 select atan(10 AS p1, 20); ERROR 42000: Incorrect parameters in the call to native function 'atan' select atan(10 p1, 20); From 4e356b1fe3b4cd228fbca64c1b89e5914a0ed6aa Mon Sep 17 00:00:00 2001 From: Alexey Kopytov Date: Sat, 14 Feb 2009 20:12:14 +0300 Subject: [PATCH 088/219] Added missing DROP TABLE to type_float.result. mysql-test/r/type_float.result: Added missing DROP TABLE. --- mysql-test/r/type_float.result | 1 + 1 file changed, 1 insertion(+) diff --git a/mysql-test/r/type_float.result b/mysql-test/r/type_float.result index 757cd6f5d71..d3a136d53d2 100644 --- a/mysql-test/r/type_float.result +++ b/mysql-test/r/type_float.result @@ -406,4 +406,5 @@ INSERT INTO t1 VALUES(-1.79769313486231e+308); SELECT f1 FROM t1; f1 -1.79769313486231e+308 +DROP TABLE t1; End of 5.0 tests From 338aefcb386a4011fcbd671f717b9bd973c94745 Mon Sep 17 00:00:00 2001 From: Timothy Smith Date: Sun, 15 Feb 2009 03:18:30 +0100 Subject: [PATCH 089/219] Add the IBM DB2 for i storage engine. Modify plugins.m4 configuration framework so that plugins which are not built still get added to the source distribution during make dist. This came up now because we can only build ibmdb2i on i5/OS, and we can't bootstrap our source dist on that platform. The solution is to specify DIST_SUBDIRS containing all plugins, separate from SUBDIRS which contains the plugins which are actually built. This ibmdb2i code is from the ibmdb2i-ga3-src.zip file, with a patch to plug.in to disable the plugin if the PASE environment isn't available. --- config/ac-macros/plugins.m4 | 72 +- plugin/Makefile.am | 2 +- storage/Makefile.am | 1 + storage/ibmdb2i/CMakeLists.txt | 25 + storage/ibmdb2i/Makefile.am | 53 + storage/ibmdb2i/db2i_blobCollection.cc | 107 + storage/ibmdb2i/db2i_blobCollection.h | 146 + storage/ibmdb2i/db2i_charsetSupport.cc | 793 +++++ storage/ibmdb2i/db2i_charsetSupport.h | 65 + storage/ibmdb2i/db2i_collationSupport.cc | 360 +++ storage/ibmdb2i/db2i_collationSupport.h | 45 + storage/ibmdb2i/db2i_constraints.cc | 699 +++++ storage/ibmdb2i/db2i_conversion.cc | 1168 +++++++ storage/ibmdb2i/db2i_errors.cc | 296 ++ storage/ibmdb2i/db2i_errors.h | 91 + storage/ibmdb2i/db2i_file.cc | 513 ++++ storage/ibmdb2i/db2i_file.h | 441 +++ storage/ibmdb2i/db2i_global.h | 138 + storage/ibmdb2i/db2i_iconv.h | 51 + storage/ibmdb2i/db2i_ileBridge.cc | 1331 ++++++++ storage/ibmdb2i/db2i_ileBridge.h | 488 +++ storage/ibmdb2i/db2i_ioBuffers.cc | 332 ++ storage/ibmdb2i/db2i_ioBuffers.h | 411 +++ storage/ibmdb2i/db2i_misc.h | 95 + storage/ibmdb2i/db2i_myconv.cc | 1498 +++++++++ storage/ibmdb2i/db2i_myconv.h | 3200 ++++++++++++++++++++ storage/ibmdb2i/db2i_rir.cc | 441 +++ storage/ibmdb2i/db2i_safeString.h | 98 + storage/ibmdb2i/db2i_sqlStatementStream.cc | 86 + storage/ibmdb2i/db2i_sqlStatementStream.h | 151 + storage/ibmdb2i/db2i_validatedPointer.h | 162 + storage/ibmdb2i/ha_ibmdb2i.cc | 3171 +++++++++++++++++++ storage/ibmdb2i/ha_ibmdb2i.h | 727 +++++ storage/ibmdb2i/plug.in | 12 + 34 files changed, 17247 insertions(+), 22 deletions(-) create mode 100644 storage/ibmdb2i/CMakeLists.txt create mode 100644 storage/ibmdb2i/Makefile.am create mode 100644 storage/ibmdb2i/db2i_blobCollection.cc create mode 100644 storage/ibmdb2i/db2i_blobCollection.h create mode 100644 storage/ibmdb2i/db2i_charsetSupport.cc create mode 100644 storage/ibmdb2i/db2i_charsetSupport.h create mode 100644 storage/ibmdb2i/db2i_collationSupport.cc create mode 100644 storage/ibmdb2i/db2i_collationSupport.h create mode 100644 storage/ibmdb2i/db2i_constraints.cc create mode 100644 storage/ibmdb2i/db2i_conversion.cc create mode 100644 storage/ibmdb2i/db2i_errors.cc create mode 100644 storage/ibmdb2i/db2i_errors.h create mode 100644 storage/ibmdb2i/db2i_file.cc create mode 100644 storage/ibmdb2i/db2i_file.h create mode 100644 storage/ibmdb2i/db2i_global.h create mode 100644 storage/ibmdb2i/db2i_iconv.h create mode 100644 storage/ibmdb2i/db2i_ileBridge.cc create mode 100644 storage/ibmdb2i/db2i_ileBridge.h create mode 100644 storage/ibmdb2i/db2i_ioBuffers.cc create mode 100644 storage/ibmdb2i/db2i_ioBuffers.h create mode 100644 storage/ibmdb2i/db2i_misc.h create mode 100644 storage/ibmdb2i/db2i_myconv.cc create mode 100644 storage/ibmdb2i/db2i_myconv.h create mode 100644 storage/ibmdb2i/db2i_rir.cc create mode 100644 storage/ibmdb2i/db2i_safeString.h create mode 100644 storage/ibmdb2i/db2i_sqlStatementStream.cc create mode 100644 storage/ibmdb2i/db2i_sqlStatementStream.h create mode 100644 storage/ibmdb2i/db2i_validatedPointer.h create mode 100644 storage/ibmdb2i/ha_ibmdb2i.cc create mode 100644 storage/ibmdb2i/ha_ibmdb2i.h create mode 100644 storage/ibmdb2i/plug.in diff --git a/config/ac-macros/plugins.m4 b/config/ac-macros/plugins.m4 index 8dfb698709f..e1da6fd11f5 100644 --- a/config/ac-macros/plugins.m4 +++ b/config/ac-macros/plugins.m4 @@ -302,7 +302,9 @@ AC_DEFUN([MYSQL_CONFIGURE_PLUGINS],[ _MYSQL_CONFIGURE_PLUGINS(m4_bpatsubst(__mysql_plugin_list__, :, [,])) _MYSQL_EMIT_PLUGIN_ACTIONS(m4_bpatsubst(__mysql_plugin_list__, :, [,])) AC_SUBST([mysql_se_dirs]) + AC_SUBST([mysql_se_distdirs]) AC_SUBST([mysql_pg_dirs]) + AC_SUBST([mysql_pg_distdirs]) AC_SUBST([mysql_se_unittest_dirs]) AC_SUBST([mysql_pg_unittest_dirs]) AC_SUBST([condition_dependent_plugin_modules]) @@ -354,6 +356,24 @@ AC_DEFUN([__MYSQL_EMIT_CHECK_PLUGIN],[ fi AC_MSG_RESULT([no]) ],[ + + # Plugin is not disabled, determine if it should be built, + # or only distributed + + m4_ifdef([$6], [ + if test ! -d "$srcdir/$6"; then + # Plugin directory was removed after autoconf was run; treat + # this as a disabled plugin + if test "X[$with_plugin_]$2" = Xyes; then + AC_MSG_RESULT([error]) + AC_MSG_ERROR([disabled]) + fi + + # The result message will be printed below + [with_plugin_]$2=no + fi + ]) + m4_ifdef([$9],[ if test "X[$with_plugin_]$2" = Xno; then AC_MSG_RESULT([error]) @@ -372,6 +392,8 @@ AC_DEFUN([__MYSQL_EMIT_CHECK_PLUGIN],[ ;; esac ]) + + if test "X[$with_plugin_]$2" = Xno; then AC_MSG_RESULT([no]) else @@ -448,28 +470,36 @@ dnl Although this is "pretty", it breaks libmysqld build condition_dependent_plugin_includes="$condition_dependent_plugin_includes -I[\$(top_srcdir)]/$6/m4_bregexp($11, [^.+[/$]], [\&])" ]) fi - m4_ifdef([$6],[ - if test -n "$mysql_use_plugin_dir" ; then - mysql_plugin_dirs="$mysql_plugin_dirs $6" - m4_syscmd(test -f "$6/configure") - ifelse(m4_sysval, 0, - [AC_CONFIG_SUBDIRS($6)], - [AC_CONFIG_FILES($6/Makefile)] - ) - ifelse(m4_substr($6, 0, 8), [storage/], - [ - [mysql_se_dirs="$mysql_se_dirs ]m4_substr($6, 8)" - mysql_se_unittest_dirs="$mysql_se_unittest_dirs ../$6" - ], - m4_substr($6, 0, 7), [plugin/], - [ - [mysql_pg_dirs="$mysql_pg_dirs ]m4_substr($6, 7)" - mysql_pg_unittest_dirs="$mysql_pg_unittest_dirs ../$6" - ], - [AC_FATAL([don't know how to handle plugin dir ]$6)]) - fi - ]) fi + + m4_ifdef([$6], [ + if test -d "$srcdir/$6"; then + # Even if we don't build a plugin, we bundle its source into the dist + # file. So its Makefile (and Makefiles for any subdirs) must be + # generated for 'make dist' to work. + m4_syscmd(test -f "$6/configure") + ifelse(m4_sysval, 0, + [AC_CONFIG_SUBDIRS($6)], + [AC_CONFIG_FILES($6/Makefile)] + ) + + ifelse( + m4_substr($6, 0, 8), [storage/], [ + mysql_se_distdirs="$mysql_se_distdirs m4_substr($6, 8)" + if test -n "$mysql_use_plugin_dir" ; then + mysql_se_dirs="$mysql_se_dirs m4_substr($6, 8)" + mysql_se_unittest_dirs="$mysql_se_unittest_dirs ../$6" + fi], + + m4_substr($6, 0, 7), [plugin/], [ + mysql_pg_distdirs="$mysql_pg_distdirs m4_substr($6, 7)" + if test -n "$mysql_use_plugin_dir" ; then + mysql_pg_dirs="$mysql_pg_dirs m4_substr($6, 7)" + mysql_pg_unittest_dirs="$mysql_pg_unittest_dirs ../$6" + fi], + [AC_FATAL([don't know how to handle plugin dir ]$6)]) + fi + ]) ]) ]) diff --git a/plugin/Makefile.am b/plugin/Makefile.am index 22f6bfd88b2..68f1f939836 100644 --- a/plugin/Makefile.am +++ b/plugin/Makefile.am @@ -22,7 +22,7 @@ AUTOMAKE_OPTIONS = foreign EXTRA_DIST = fulltext/configure.in SUBDIRS = @mysql_pg_dirs@ -DIST_SUBDIRS = daemon_example fulltext +DIST_SUBDIRS = @mysql_pg_distdirs@ # Don't update the files from bitkeeper %::SCCS/s.% diff --git a/storage/Makefile.am b/storage/Makefile.am index b978453d29d..4f19be3a361 100644 --- a/storage/Makefile.am +++ b/storage/Makefile.am @@ -20,6 +20,7 @@ AUTOMAKE_OPTIONS = foreign # These are built from source in the Docs directory EXTRA_DIST = SUBDIRS = @mysql_se_dirs@ +DIST_SUBDIRS = @mysql_se_distdirs@ # Don't update the files from bitkeeper %::SCCS/s.% diff --git a/storage/ibmdb2i/CMakeLists.txt b/storage/ibmdb2i/CMakeLists.txt new file mode 100644 index 00000000000..11cc4300569 --- /dev/null +++ b/storage/ibmdb2i/CMakeLists.txt @@ -0,0 +1,25 @@ +# Copyright (C) 2006 MySQL AB +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; version 2 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DSAFEMALLOC -DSAFE_MUTEX") +SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -DSAFEMALLOC -DSAFE_MUTEX") + +INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include ${CMAKE_SOURCE_DIR}/sql + ${CMAKE_SOURCE_DIR}/regex + ${CMAKE_SOURCE_DIR}/extra/yassl/include) +ADD_LIBRARY(ibmdb2i ha_ibmdb2i.cc db2i_ileBridge.cc db2i_conversion.cc + db2i_blobCollection.cc db2i_file.cc db2i_charsetSupport.cc + db2i_collationSupport.cc db2i_errors.cc db2i_constraints.cc + db2i_rir.cc db2i_sqlStatementStream.cc db2i_ioBuffers.cc db2i_myconv.cc) diff --git a/storage/ibmdb2i/Makefile.am b/storage/ibmdb2i/Makefile.am new file mode 100644 index 00000000000..2436a764429 --- /dev/null +++ b/storage/ibmdb2i/Makefile.am @@ -0,0 +1,53 @@ +# +# Copyright (c) 2007, 2008, IBM Corporation. +# All rights reserved. +# +# + +#called from the top level Makefile + +MYSQLDATAdir = $(localstatedir) +MYSQLSHAREdir = $(pkgdatadir) +MYSQLBASEdir= $(prefix) +MYSQLLIBdir= $(pkglibdir) +pkgplugindir = $(pkglibdir)/plugin +INCLUDES = -I$(top_srcdir)/include -I$(top_builddir)/include \ + -I$(top_srcdir)/regex \ + -I$(top_srcdir)/sql \ + -I$(srcdir) \ + -I$ /afs/rchland.ibm.com/lande/shadow/dev2000/osxpf/v5r4m0f.xpf/cur/cmvc/base.pgm/my.xpf/apis \ + -I$ /afs/rchland.ibm.com/lande/shadow/dev2000/osxpf/v5r4m0.xpf/bld/cmvc/base.pgm/lg.xpf \ + -I$ /afs/rchland.ibm.com/lande/shadow/dev2000/osxpf/v5r4m0.xpf/bld/cmvc/base.pgm/tq.xpf +WRAPLIBS= + +LDADD = + +DEFS = @DEFS@ + +noinst_HEADERS = ha_ibmdb2i.h db2i_collationSupport.h db2i_file.h \ + db2i_ioBuffers.h db2i_blobCollection.h \ + db2i_global.h db2i_misc.h db2i_charsetSupport.h db2i_errors.h \ + db2i_ileBridge.h db2i_validatedPointer.h + +EXTRA_LTLIBRARIES = ha_ibmdb2i.la +pkgplugin_LTLIBRARIES = @plugin_ibmdb2i_shared_target@ +ha_ibmdb2i_la_LIBADD = -liconv +ha_ibmdb2i_la_LDFLAGS = -module -rpath $(MYSQLLIBdir) +ha_ibmdb2i_la_CXXFLAGS= $(AM_CFLAGS) -DMYSQL_DYNAMIC_PLUGIN +ha_ibmdb2i_la_CFLAGS = $(AM_CFLAGS) -DMYSQL_DYNAMIC_PLUGIN +ha_ibmdb2i_la_SOURCES = ha_ibmdb2i.cc db2i_ileBridge.cc db2i_conversion.cc \ + db2i_blobCollection.cc db2i_file.cc db2i_charsetSupport.cc \ + db2i_collationSupport.cc db2i_errors.cc db2i_constraints.cc \ + db2i_rir.cc db2i_sqlStatementStream.cc db2i_ioBuffers.cc \ + db2i_myconv.cc + +EXTRA_LIBRARIES = libibmdb2i.a +noinst_LIBRARIES = @plugin_ibmdb2i_static_target@ +libibmdb2i_a_CXXFLAGS = $(AM_CFLAGS) +libibmdb2i_a_CFLAGS = $(AM_CFLAGS) +libibmdb2i_a_SOURCES= $(ha_ibmdb2i_la_SOURCES) + + +EXTRA_DIST = CMakeLists.txt plug.in +# Don't update the files from bitkeeper +%::SCCS/s.% diff --git a/storage/ibmdb2i/db2i_blobCollection.cc b/storage/ibmdb2i/db2i_blobCollection.cc new file mode 100644 index 00000000000..17101c9c0a4 --- /dev/null +++ b/storage/ibmdb2i/db2i_blobCollection.cc @@ -0,0 +1,107 @@ +/* +Licensed Materials - Property of IBM +DB2 Storage Engine Enablement +Copyright IBM Corporation 2007,2008 +All rights reserved + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + (a) Redistributions of source code must retain this list of conditions, the + copyright notice in section {d} below, and the disclaimer following this + list of conditions. + (b) Redistributions in binary form must reproduce this list of conditions, the + copyright notice in section (d) below, and the disclaimer following this + list of conditions, in the documentation and/or other materials provided + with the distribution. + (c) The name of IBM may not be used to endorse or promote products derived from + this software without specific prior written permission. + (d) The text of the required copyright notice is: + Licensed Materials - Property of IBM + DB2 Storage Engine Enablement + Copyright IBM Corporation 2007,2008 + All rights reserved + +THIS SOFTWARE IS PROVIDED BY IBM CORPORATION "AS IS" AND ANY EXPRESS OR IMPLIED +WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT +SHALL IBM CORPORATION BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT +OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT INCLUDING NEGLIGENCE OR OTHERWISE) ARISING +IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + + +#include "db2i_blobCollection.h" + +/** + Return the size to use when allocating space for blob reads. + + @param fieldIndex The field to allocate for + @param[out] shouldProtect Indicates whether storage protection should be + applied to the space, because the size returned is + smaller than the maximum possible size. +*/ + +uint32 +BlobCollection::getSizeToAllocate(int fieldIndex, bool& shouldProtect) +{ + Field* field = table->getMySQLTable()->field[fieldIndex]; + uint fieldLength = field->max_display_length(); + + if (fieldLength <= MAX_FULL_ALLOCATE_BLOB_LENGTH) + { + shouldProtect = false; + return fieldLength; + } + + shouldProtect = true; + + uint curMaxSize = table->getBlobFieldActualSize(fieldIndex); + + uint defaultAllocSize = min(defaultAllocation, fieldLength); + + return max(defaultAllocSize, curMaxSize); + +} + +void +BlobCollection::generateBuffer(int fieldIndex) +{ + DBUG_ASSERT(table->db2Field(fieldIndex).isBlob()); + + bool protect; + buffers[table->getBlobIdFromField(fieldIndex)].Malloc(getSizeToAllocate(fieldIndex, protect), protect); + + return; +} + +/** + Realloc the read buffer associated with a blob field. + + This is used when the previous allocation for a blob field is found to be + too small (this is discovered when QMY_READ trips over the protected boundary + page). + + @param fieldIndex The field to be reallocated + @param size The size of buffer to allocate for this field. +*/ + +ValidatedPointer& +BlobCollection::reallocBuffer(int fieldIndex, size_t size) +{ + ProtectedBuffer& buf = buffers[table->getBlobIdFromField(fieldIndex)]; + if (size <= buf.allocLen()) + return buf.ptr(); + + table->updateBlobFieldActualSize(fieldIndex, size); + + DBUG_PRINT("BlobCollection::reallocBuffer",("PERF: reallocing %d to %d: ", fieldIndex, size)); + + bool protect; + buf.Free(); + buf.Malloc(getSizeToAllocate(fieldIndex, protect), protect); + return buf.ptr(); +} diff --git a/storage/ibmdb2i/db2i_blobCollection.h b/storage/ibmdb2i/db2i_blobCollection.h new file mode 100644 index 00000000000..35cfacbf42a --- /dev/null +++ b/storage/ibmdb2i/db2i_blobCollection.h @@ -0,0 +1,146 @@ +/* +Licensed Materials - Property of IBM +DB2 Storage Engine Enablement +Copyright IBM Corporation 2007,2008 +All rights reserved + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + (a) Redistributions of source code must retain this list of conditions, the + copyright notice in section {d} below, and the disclaimer following this + list of conditions. + (b) Redistributions in binary form must reproduce this list of conditions, the + copyright notice in section (d) below, and the disclaimer following this + list of conditions, in the documentation and/or other materials provided + with the distribution. + (c) The name of IBM may not be used to endorse or promote products derived from + this software without specific prior written permission. + (d) The text of the required copyright notice is: + Licensed Materials - Property of IBM + DB2 Storage Engine Enablement + Copyright IBM Corporation 2007,2008 + All rights reserved + +THIS SOFTWARE IS PROVIDED BY IBM CORPORATION "AS IS" AND ANY EXPRESS OR IMPLIED +WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT +SHALL IBM CORPORATION BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT +OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT INCLUDING NEGLIGENCE OR OTHERWISE) ARISING +IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + + +#ifndef DB2I_BLOBCOLLECTION_H +#define DB2I_BLOBCOLLECTION_H + +#include "db2i_global.h" +#include "db2i_file.h" + +/** + @class ProtectedBuffer + @brief Implements memory management for (optionally) protected buffers. + + Buffers created with the protection option will have a guard page set on the + page following requested allocation size. The side effect is that the actual + allocation is up to 2*4096-1 bytes larger than the size requested by the + using code. +*/ + +class ProtectedBuffer +{ +public: + ProtectedBuffer() : protectBuf(false) + {;} + + void Malloc(size_t size, bool protect = false) + { + protectBuf = protect; + bufptr.alloc(size + (protectBuf ? 0x1fff : 0x0)); + if ((void*)bufptr != NULL) + { + len = size; + if (protectBuf) + mprotect(protectedPage(), 0x1000, PROT_NONE); + } + } + + void Free() + { + if ((void*)bufptr != NULL) + { + if (protectBuf) + mprotect(protectedPage(), 0x1000, PROT_READ | PROT_WRITE); + bufptr.dealloc(); + } + } + + ~ProtectedBuffer() + { + Free(); + } + + ValidatedPointer& ptr() {return bufptr;} + bool isProtected() const {return protectBuf;} + size_t allocLen() const {return len;} +private: + void* protectedPage() + { + return (void*)(((address64_t)(void*)bufptr + len + 0x1000) & ~0xfff); + } + + ValidatedPointer bufptr; + size_t len; + bool protectBuf; + +}; + + +/** + @class BlobCollection + @brief Manages memory allocation for reading blobs associated with a table. + + Allocations are done on-demand and are protected with a guard page if less + than the max possible size is allocated. +*/ +class BlobCollection +{ + public: + BlobCollection(db2i_table* db2Table, uint32 defaultAllocSize) : + defaultAllocation(defaultAllocSize), table(db2Table) + { + buffers = new ProtectedBuffer[table->getBlobCount()]; + } + + ~BlobCollection() + { + delete[] buffers; + } + + ValidatedPointer& getBufferPtr(int fieldIndex) + { + int blobIndex = table->getBlobIdFromField(fieldIndex); + if ((char*)buffers[blobIndex].ptr() == NULL) + generateBuffer(fieldIndex); + + return buffers[blobIndex].ptr(); + } + + ValidatedPointer& reallocBuffer(int fieldIndex, size_t size); + + + private: + + uint32 getSizeToAllocate(int fieldIndex, bool& shouldProtect); + void generateBuffer(int fieldIndex); + + db2i_table* table; // The table being read + ProtectedBuffer* buffers; // The buffers + uint32 defaultAllocation; + /* The default size to use when first allocating a buffer */ +}; + +#endif diff --git a/storage/ibmdb2i/db2i_charsetSupport.cc b/storage/ibmdb2i/db2i_charsetSupport.cc new file mode 100644 index 00000000000..41f7ef0e32f --- /dev/null +++ b/storage/ibmdb2i/db2i_charsetSupport.cc @@ -0,0 +1,793 @@ +/* +Licensed Materials - Property of IBM +DB2 Storage Engine Enablement +Copyright IBM Corporation 2007,2008 +All rights reserved + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + (a) Redistributions of source code must retain this list of conditions, the + copyright notice in section {d} below, and the disclaimer following this + list of conditions. + (b) Redistributions in binary form must reproduce this list of conditions, the + copyright notice in section (d) below, and the disclaimer following this + list of conditions, in the documentation and/or other materials provided + with the distribution. + (c) The name of IBM may not be used to endorse or promote products derived from + this software without specific prior written permission. + (d) The text of the required copyright notice is: + Licensed Materials - Property of IBM + DB2 Storage Engine Enablement + Copyright IBM Corporation 2007,2008 + All rights reserved + +THIS SOFTWARE IS PROVIDED BY IBM CORPORATION "AS IS" AND ANY EXPRESS OR IMPLIED +WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT +SHALL IBM CORPORATION BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT +OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT INCLUDING NEGLIGENCE OR OTHERWISE) ARISING +IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + + + +#include "db2i_charsetSupport.h" +#include "as400_types.h" +#include "as400_protos.h" +#include "db2i_ileBridge.h" +#include "qlgusr.h" +#include "db2i_errors.h" + + +/* + The following arrays define a mapping between IANA-style text descriptors and + IBM i CCSID text descriptors. The mapping is a 1-to-1 correlation between + corresponding array slots. +*/ +#define MAX_IANASTRING 23 +static const char ianaStringType[MAX_IANASTRING][10] = +{ + {"ascii"}, + {"Big5"}, //big5 + {"cp1250"}, + {"cp1251"}, + {"cp1256"}, + {"cp850"}, + {"cp852"}, + {"cp866"}, + {"IBM943"}, //cp932 + {"EUC-KR"}, //euckr + {"IBM1381"}, //gb2312 + {"IBM1386"}, //gbk + {"greek"}, + {"hebrew"}, + {"latin1"}, + {"latin2"}, + {"latin5"}, + {"macce"}, + {"tis620"}, + {"Shift_JIS"}, //sjis + {"ucs2"}, + {"EUC-JP"}, //ujis + {"utf8"} +}; +static const char ccsidType[MAX_IANASTRING][6] = +{ + {"367"}, //ascii + {"950"}, //big5 + {"1250"}, //cp1250 + {"1251"}, //cp1251 + {"1256"}, //cp1256 + {"850"}, //cp850 + {"852"}, //cp852 + {"866"}, //cp866 + {"943"}, //cp932 + {"970"}, //euckr + {"1381"}, //gb2312 + {"1386"}, //gbk + {"813"}, //greek + {"916"}, //hebrew + {"923"}, //latin1 + {"912"}, //latin2 + {"920"}, //latin5 + {"1282"}, //macce + {"874"}, //tis620 + {"943"}, //sjis + {"13488"},//ucs2 + {"5050"}, //ujis + {"1208"} //utf8 +}; + +static _ILEpointer *QlgCvtTextDescToDesc_sym; + +/* We keep a cache of the mapping for text descriptions obtained via + QlgTextDescToDesc. The following structures implement this cache. */ +static HASH textDescMapHash; +static MEM_ROOT textDescMapMemroot; +static pthread_mutex_t textDescMapHashMutex; +struct TextDescMap +{ + struct HashKey + { + int32 inType; + int32 outType; + char inDesc[Qlg_MaxDescSize]; + } hashKey; + char outDesc[Qlg_MaxDescSize]; +}; + +/* We keep a cache of the mapping for open iconv descriptors. The following + structures implement this cache. */ +static HASH iconvMapHash; +static MEM_ROOT iconvMapMemroot; +static pthread_mutex_t iconvMapHashMutex; +struct IconvMap +{ + struct HashKey + { + uint16 direction; // This is a uint16 instead of a uchar to avoid garbage data in the key from compiler padding + uint16 db2CCSID; + const CHARSET_INFO* myCharset; + } hashKey; + iconv_t iconvDesc; +}; + + +/** + Initialize the static structures used by this module. + + This must only be called once per plugin instantiation. + + @return 0 if successful. Failure otherwise +*/ +int32 initCharsetSupport() +{ + DBUG_ENTER("initCharsetSupport"); + + int actmark = _ILELOAD("QSYS/QLGUSR", ILELOAD_LIBOBJ); + if ( actmark == -1 ) + { + DBUG_PRINT("initCharsetSupport", ("conversion srvpgm activation failed")); + DBUG_RETURN(1); + } + + QlgCvtTextDescToDesc_sym = (ILEpointer*)malloc_aligned(sizeof(ILEpointer)); + if (_ILESYM(QlgCvtTextDescToDesc_sym, actmark, "QlgCvtTextDescToDesc") == -1) + { + DBUG_PRINT("initCharsetSupport", + ("resolve of QlgCvtTextDescToDesc failed")); + DBUG_RETURN(errno); + } + + VOID(pthread_mutex_init(&textDescMapHashMutex,MY_MUTEX_INIT_FAST)); + hash_init(&textDescMapHash, &my_charset_bin, 10, offsetof(TextDescMap, hashKey), sizeof(TextDescMap::hashKey), 0, 0, HASH_UNIQUE); + + VOID(pthread_mutex_init(&iconvMapHashMutex,MY_MUTEX_INIT_FAST)); + hash_init(&iconvMapHash, &my_charset_bin, 10, offsetof(IconvMap, hashKey), sizeof(IconvMap::hashKey), 0, 0, HASH_UNIQUE); + + init_alloc_root(&textDescMapMemroot, 2048, 0); + init_alloc_root(&iconvMapMemroot, 256, 0); + + initMyconv(); + + DBUG_RETURN(0); +} + +/** + Cleanup the static structures used by this module. + + This must only be called once per plugin instantiation and only if + initCharsetSupport() was successful. +*/ +void doneCharsetSupport() +{ + cleanupMyconv(); + + free_root(&textDescMapMemroot, 0); + free_root(&iconvMapMemroot, 0); + + pthread_mutex_destroy(&textDescMapHashMutex); + hash_free(&textDescMapHash); + pthread_mutex_destroy(&iconvMapHashMutex); + hash_free(&iconvMapHash); + free_aligned(QlgCvtTextDescToDesc_sym); +} + + +/** + Convert a text description from one type to another. + + This function is just a wrapper for the IBM i QlgTextDescToDesc function plus + some overrides for conversions that the API does not handle correctly and + support for caching the computed conversion. + + @param inType The type of descriptor pointed to by "in". + @param outType The type of descriptor requested for "out". + @param in The descriptor to be convereted. + @param[out] out The equivalent descriptor + @param hashKey The hash key to be used for caching the conversion result. + + @return 0 if successful. Failure otherwise +*/ +static int32 getNewTextDesc(const int32 inType, + const int32 outType, + const char* in, + char* out, + const TextDescMap::HashKey* hashKey) +{ + DBUG_ENTER("db2i_charsetSupport::getNewTextDesc"); + const arg_type_t signature[] = { ARG_INT32, ARG_INT32, ARG_MEMPTR, ARG_INT32, ARG_MEMPTR, ARG_INT32, ARG_INT32, ARG_END }; + struct ArgList + { + ILEarglist_base base; + int32 CRDIInType; + int32 CRDIOutType; + ILEpointer CRDIDesc; + int32 CRDIDescSize; + ILEpointer CRDODesc; + int32 CRDODescSize; + int32 CTDCCSID; + } *arguments; + + if ((inType == Qlg_TypeIANA) && (outType == Qlg_TypeAix41)) + { + // Override non-standard charsets + if (unlikely(strcmp("IBM1381", in) == 0)) + { + strcpy(out, "IBM-1381"); + DBUG_RETURN(0); + } + } + else if ((inType == Qlg_TypeAS400CCSID) && (outType == Qlg_TypeAix41)) + { + // Override non-standard charsets + if (unlikely(strcmp("1148", in) == 0)) + { + strcpy(out, "IBM-1148"); + DBUG_RETURN(0); + } + } + + char argBuf[sizeof(ArgList)+15]; + arguments = (ArgList*)roundToQuadWordBdy(argBuf); + + arguments->CRDIInType = inType; + arguments->CRDIOutType = outType; + arguments->CRDIDesc.s.addr = (address64_t) in; + arguments->CRDIDescSize = Qlg_MaxDescSize; + arguments->CRDODesc.s.addr = (address64_t) out; + arguments->CRDODescSize = Qlg_MaxDescSize; + arguments->CTDCCSID = 819; + _ILECALL(QlgCvtTextDescToDesc_sym, + &arguments->base, + signature, + RESULT_INT32); + if (unlikely(arguments->base.result.s_int32.r_int32 < 0)) + { + getErrTxt(DB2I_ERR_ILECALL,"QlgCvtTextDescToDesc",arguments->base.result.s_int32.r_int32); + DBUG_RETURN(DB2I_ERR_ILECALL); + } + + // Store the conversion information into a cache entry + TextDescMap* mapping = (TextDescMap*)alloc_root(&textDescMapMemroot, sizeof(TextDescMap)); + if (unlikely(!mapping)) + DBUG_RETURN(HA_ERR_OUT_OF_MEM); + memcpy(&(mapping->hashKey), hashKey, sizeof(hashKey)); + strcpy(mapping->outDesc, out); + pthread_mutex_lock(&textDescMapHashMutex); + my_hash_insert(&textDescMapHash, (const uchar*)mapping); + pthread_mutex_unlock(&textDescMapHashMutex); + + DBUG_RETURN(0); +} + + +/** + Convert a text description from one type to another. + + This function takes a text description in one representation and converts + it into another representation. Although the OS provides some facilities for + doing this, the support is not complete, nor does MySQL always use standard + identifiers. Therefore, there are a lot of hardcoded overrides required. + There is probably some room for optimization here, but this should not be + called frequently under most circumstances. + + @param inType The type of descriptor pointed to by "in". + @param outType The type of descriptor requested for "out". + @param in The descriptor to be convereted. + @param[out] out The equivalent descriptor + + @return 0 if successful. Failure otherwise +*/ +static int32 convertTextDesc(const int32 inType, const int32 outType, const char* inDesc, char* outDesc) +{ + DBUG_ENTER("db2i_charsetSupport::convertTextDesc"); + const char* inDescOverride; + + if (inType == Qlg_TypeIANA) + { + // Override non-standard charsets + if (strcmp("big5", inDesc) == 0) + inDescOverride = "Big5"; + else if (strcmp("cp932", inDesc) == 0) + inDescOverride = "IBM943"; + else if (strcmp("euckr", inDesc) == 0) + inDescOverride = "EUC-KR"; + else if (strcmp("gb2312", inDesc) == 0) + inDescOverride = "IBM1381"; + else if (strcmp("gbk", inDesc) == 0) + inDescOverride = "IBM1386"; + else if (strcmp("sjis", inDesc) == 0) + inDescOverride = "Shift_JIS"; + else if (strcmp("ujis", inDesc) == 0) + inDescOverride = "EUC-JP"; + else + inDescOverride = inDesc; + + // Hardcode non-standard charsets + if (outType == Qlg_TypeAix41) + { + if (strcmp("Big5", inDescOverride) == 0) + { + strcpy(outDesc,"big5"); + DBUG_RETURN(0); + } + else if (strcmp("IBM1386", inDescOverride) == 0) + { + strcpy(outDesc,"GBK"); + DBUG_RETURN(0); + } + else if (strcmp("Shift_JIS", inDescOverride) == 0 || + strcmp("IBM943", inDescOverride) == 0) + { + strcpy(outDesc,"IBM-943"); + DBUG_RETURN(0); + } + else if (strcmp("tis620", inDescOverride) == 0) + { + strcpy(outDesc,"TIS-620"); + DBUG_RETURN(0); + } + else if (strcmp("ucs2", inDescOverride) == 0) + { + strcpy(outDesc,"UCS-2"); + DBUG_RETURN(0); + } + else if (strcmp("cp1250", inDescOverride) == 0) + { + strcpy(outDesc,"IBM-1250"); + DBUG_RETURN(0); + } + else if (strcmp("cp1251", inDescOverride) == 0) + { + strcpy(outDesc,"IBM-1251"); + DBUG_RETURN(0); + } + else if (strcmp("cp1256", inDescOverride) == 0) + { + strcpy(outDesc,"IBM-1256"); + DBUG_RETURN(0); + } + } + else if (outType == Qlg_TypeAS400CCSID) + { + // See if we can fast path the convert + for (int loopCnt = 0; loopCnt < MAX_IANASTRING; ++loopCnt) + { + if (strcmp((char*)ianaStringType[loopCnt],inDescOverride) == 0) + { + strcpy(outDesc,ccsidType[loopCnt]); + DBUG_RETURN(0); + } + } + } + } + else + inDescOverride = inDesc; + + // We call getNewTextDesc for all other conversions and cache the result. + TextDescMap *mapping; + TextDescMap::HashKey hashKey; + hashKey.inType= inType; + hashKey.outType= outType; + uint32 len = strlen(inDescOverride); + memcpy(hashKey.inDesc, inDescOverride, len); + memset(hashKey.inDesc+len, 0, sizeof(hashKey.inDesc) - len); + + if (!(mapping=(TextDescMap *) hash_search(&textDescMapHash, + (const uchar*)&hashKey, + sizeof(hashKey)))) + { + DBUG_RETURN(getNewTextDesc(inType, outType, inDescOverride, outDesc, &hashKey)); + } + else + { + strcpy(outDesc, mapping->outDesc); + } + DBUG_RETURN(0); +} + + +/** + Convert an IANA character set name into a DB2 for i CCSID value. + + @param parmIANADesc An IANA character set name + @param[out] db2Ccsid The equivalent CCSID value + + @return 0 if successful. Failure otherwise +*/ +int32 convertIANAToDb2Ccsid(const char* parmIANADesc, uint16* db2Ccsid) +{ + int32 rc; + uint16 aixCcsid; + char aixCcsidString[Qlg_MaxDescSize]; + int aixEncodingScheme; + int db2EncodingScheme; + rc = convertTextDesc(Qlg_TypeIANA, Qlg_TypeAS400CCSID, parmIANADesc, aixCcsidString); + if (rc != 0) + return rc; + aixCcsid = atoi(aixCcsidString); + rc = getEncodingScheme(aixCcsid, aixEncodingScheme); + if (rc != 0) + return rc; + switch(aixEncodingScheme) { // Select on encoding scheme + case 0x1100: // EDCDIC SBCS + case 0x2100: // ASCII SBCS + case 0x4100: // AIX SBCS + case 0x4105: // MS Windows + case 0x5100: // ISO 7 bit ASCII + db2EncodingScheme = 0x1100; + break; + case 0x1200: // EDCDIC DBCS + case 0x2200: // ASCII DBCS + db2EncodingScheme = 0x1200; + break; + case 0x1301: // EDCDIC Mixed + case 0x2300: // ASCII Mixed + case 0x4403: // EUC (ISO 2022) + db2EncodingScheme = 0x1301; + break; + case 0x7200: // UCS2 + db2EncodingScheme = 0x7200; + break; + case 0x7807: // UTF-8 + db2EncodingScheme = 0x7807; + break; + case 0x7500: // UTF-32 + db2EncodingScheme = 0x7500; + break; + default: // Unknown + { + getErrTxt(DB2I_ERR_UNKNOWN_ENCODING,aixEncodingScheme); + return DB2I_ERR_UNKNOWN_ENCODING; + } + break; + } + if (aixEncodingScheme == db2EncodingScheme) + { + *db2Ccsid = aixCcsid; + } + else + { + rc = getAssociatedCCSID(aixCcsid, db2EncodingScheme, db2Ccsid); // EDCDIC SBCS + if (rc != 0) + return rc; + } + + return 0; +} + + +/** + Obtain the encoding scheme of a CCSID. + + @param inCcsid An IBM i CCSID + @param[out] outEncodingScheme The associated encoding scheme + + @return 0 if successful. Failure otherwise +*/ +int32 getEncodingScheme(const uint16 inCcsid, int32& outEncodingScheme) +{ + DBUG_ENTER("db2i_charsetSupport::getEncodingScheme"); + + static bool ptrInited = FALSE; + static char ptrSpace[sizeof(ILEpointer) + 15]; + static ILEpointer* ptrToPtr = (ILEpointer*)roundToQuadWordBdy(ptrSpace); + int rc; + + if (!ptrInited) + { + rc = _RSLOBJ2(ptrToPtr, RSLOBJ_TS_PGM, "QTQGESP", "QSYS"); + + if (rc) + { + getErrTxt(DB2I_ERR_RESOLVE_OBJ,"QTQGESP","QSYS","*PGM",errno); + DBUG_RETURN(DB2I_ERR_RESOLVE_OBJ); + } + ptrInited = TRUE; + } + + DBUG_ASSERT(inCcsid != 0); + + int GESPCCSID = inCcsid; + int GESPLen = 32; + int GESPNbrVal = 0; + int32 GESPES; + int GESPCSCPL[32]; + int GESPFB[3]; + void* ILEArgv[7]; + ILEArgv[0] = &GESPCCSID; + ILEArgv[1] = &GESPLen; + ILEArgv[2] = &GESPNbrVal; + ILEArgv[3] = &GESPES; + ILEArgv[4] = &GESPCSCPL; + ILEArgv[5] = &GESPFB; + ILEArgv[6] = NULL; + + rc = _PGMCALL(ptrToPtr, (void**)&ILEArgv, 0); + + if (rc) + { + getErrTxt(DB2I_ERR_PGMCALL,"QTQGESP","QSYS",rc); + DBUG_RETURN(DB2I_ERR_PGMCALL); + } + if (GESPFB[0] != 0 || + GESPFB[1] != 0 || + GESPFB[2] != 0) + { + getErrTxt(DB2I_ERR_QTQGESP,GESPFB[0],GESPFB[1],GESPFB[2]); + DBUG_RETURN(DB2I_ERR_QTQGESP); + } + outEncodingScheme = GESPES; + + DBUG_RETURN(0); +} + + +/** + Get the best fit equivalent CCSID. (Wrapper for QTQGRDC API) + + @param inCcsid An IBM i CCSID + @param inEncodingScheme The encoding scheme + @param[out] outCcsid The equivalent CCSID + + @return 0 if successful. Failure otherwise +*/ +int32 getAssociatedCCSID(const uint16 inCcsid, const int inEncodingScheme, uint16* outCcsid) +{ + DBUG_ENTER("db2i_charsetSupport::getAssociatedCCSID"); + static bool ptrInited = FALSE; + static char ptrSpace[sizeof(ILEpointer) + 15]; + static ILEpointer* ptrToPtr = (ILEpointer*)roundToQuadWordBdy(ptrSpace); + int rc; + + // Override non-standard charsets + if ((inCcsid == 923) && (inEncodingScheme == 0x1100)) + { + *outCcsid = 1148; + DBUG_RETURN(0); + } + + if (!ptrInited) + { + rc = _RSLOBJ2(ptrToPtr, RSLOBJ_TS_PGM, "QTQGRDC", "QSYS"); + + if (rc) + { + getErrTxt(DB2I_ERR_RESOLVE_OBJ,"QTQGRDC","QSYS","*PGM",errno); + DBUG_RETURN(DB2I_ERR_RESOLVE_OBJ); + } + ptrInited = TRUE; + } + + int GRDCCCSID = inCcsid; + int GRDCES = inEncodingScheme; + int GRDCSel = 0; + int GRDCAssCCSID; + int GRDCFB[3]; + void* ILEArgv[7]; + ILEArgv[0] = &GRDCCCSID; + ILEArgv[1] = &GRDCES; + ILEArgv[2] = &GRDCSel; + ILEArgv[3] = &GRDCAssCCSID; + ILEArgv[4] = &GRDCFB; + ILEArgv[5] = NULL; + + rc = _PGMCALL(ptrToPtr, (void**)&ILEArgv, 0); + + if (rc) + { + getErrTxt(DB2I_ERR_PGMCALL,"QTQGRDC","QSYS",rc); + DBUG_RETURN(DB2I_ERR_PGMCALL); + } + if (GRDCFB[0] != 0 || + GRDCFB[1] != 0 || + GRDCFB[2] != 0) + { + getErrTxt(DB2I_ERR_QTQGRDC,GRDCFB[0],GRDCFB[1],GRDCFB[2]); + DBUG_RETURN(DB2I_ERR_QTQGRDC); + } + + *outCcsid = GRDCAssCCSID; + + DBUG_RETURN(0); +} + +/** + Open an iconv conversion between a MySQL charset and the respective IBM i CCSID + + @param direction The direction of the conversion + @param mysqlCSName Name of the MySQL character set + @param db2CCSID The IBM i CCSID + @param hashKey The key to use for inserting the opened conversion into the cache + @param[out] newConversion The iconv descriptor + + @return 0 if successful. Failure otherwise +*/ +static int32 openNewConversion(enum_conversionDirection direction, + const char* mysqlCSName, + uint16 db2CCSID, + IconvMap::HashKey* hashKey, + iconv_t& newConversion) +{ + DBUG_ENTER("db2i_charsetSupport::openNewConversion"); + + char mysqlAix41Desc[Qlg_MaxDescSize]; + char db2Aix41Desc[Qlg_MaxDescSize]; + char db2CcsidString[6] = ""; + int32 rc; + + /* + First we have to convert the MySQL IANA-like name and the DB2 CCSID into + there equivalent iconv descriptions. + */ + rc = convertTextDesc(Qlg_TypeIANA, Qlg_TypeAix41, mysqlCSName, mysqlAix41Desc); + if (rc) + DBUG_RETURN(rc); + CHARSET_INFO *cs= &my_charset_bin; + (uint)(cs->cset->long10_to_str)(cs,db2CcsidString,sizeof(db2CcsidString), 10, db2CCSID); + rc = convertTextDesc(Qlg_TypeAS400CCSID, Qlg_TypeAix41, db2CcsidString, db2Aix41Desc); + if (rc) + DBUG_RETURN(rc); + + /* Call iconv to open the conversion. */ + if (direction == toDB2) + { + newConversion = iconv_open(db2Aix41Desc, mysqlAix41Desc); + if (newConversion == (iconv_t) -1) + { + getErrTxt(DB2I_ERR_ICONV_OPEN, mysqlAix41Desc, db2Aix41Desc, errno); + DBUG_RETURN(DB2I_ERR_ICONV_OPEN); + } + } + else + { + newConversion = iconv_open(mysqlAix41Desc, db2Aix41Desc); + if (newConversion == (iconv_t) -1) + { + getErrTxt(DB2I_ERR_ICONV_OPEN, db2Aix41Desc, mysqlAix41Desc, errno); + DBUG_RETURN(DB2I_ERR_ICONV_OPEN); + } + } + + /* Insert the new conversion into the cache. */ + IconvMap* mapping = (IconvMap*)alloc_root(&iconvMapMemroot, sizeof(IconvMap)); + if (!mapping) + { + my_error(ER_OUTOFMEMORY, MYF(0), sizeof(IconvMap)); + DBUG_RETURN( HA_ERR_OUT_OF_MEM); + } + memcpy(&(mapping->hashKey), hashKey, sizeof(mapping->hashKey)); + mapping->iconvDesc = newConversion; + pthread_mutex_lock(&iconvMapHashMutex); + my_hash_insert(&iconvMapHash, (const uchar*)mapping); + pthread_mutex_unlock(&iconvMapHashMutex); + + DBUG_RETURN(0); +} + + +/** + Open an iconv conversion between a MySQL charset and the respective IBM i CCSID + + @param direction The direction of the conversion + @param cs The MySQL character set + @param db2CCSID The IBM i CCSID + @param[out] newConversion The iconv descriptor + + @return 0 if successful. Failure otherwise +*/ +int32 getConversion(enum_conversionDirection direction, const CHARSET_INFO* cs, uint16 db2CCSID, iconv_t& conversion) +{ + DBUG_ENTER("db2i_charsetSupport::convChars"); + + int32 rc; + + /* Build the hash key */ + IconvMap::HashKey hashKey; + hashKey.direction= direction; + hashKey.myCharset= cs; + hashKey.db2CCSID= db2CCSID; + + /* Look for the conversion in the cache and add it if it is not there. */ + IconvMap *mapping; + if (!(mapping= (IconvMap *) hash_search(&iconvMapHash, + (const uchar*)&hashKey, + sizeof(hashKey)))) + { + DBUG_PRINT("getConversion", ("Hash miss for direction=%d, cs=%s, ccsid=%d", direction, cs->name, db2CCSID)); + rc= openNewConversion(direction, cs->csname, db2CCSID, &hashKey, conversion); + if (rc) + DBUG_RETURN(rc); + } + else + { + conversion= mapping->iconvDesc; + } + + DBUG_RETURN(0); +} + +/** + Fast-path conversion from ASCII to EBCDIC for use in converting + identifiers to be sent to the QMY APIs. + + @param input ASCII data + @param[out] ouput EBCDIC data + @param ilen Size of input buffer and output buffer +*/ +int convToEbcdic(const char* input, char* output, size_t ilen) +{ + static bool inited = FALSE; + static iconv_t ic; + + if (ilen == 0) + return 0; + + if (!inited) + { + ic = iconv_open( "IBM-037", "ISO8859-1" ); + inited = TRUE; + } + size_t substitutedChars; + size_t olen = ilen; + if (iconv( ic, (char**)&input, &ilen, &output, &olen, &substitutedChars ) == -1) + return errno; + + return 0; +} + + +/** + Fast-path conversion from EBCDIC to ASCII for use in converting + data received from the QMY APIs. + + @param input EBCDIC data + @param[out] ouput ASCII data + @param ilen Size of input buffer and output buffer +*/ +int convFromEbcdic(const char* input, char* output, size_t ilen) +{ + static bool inited = FALSE; + static iconv_t ic; + + if (ilen == 0) + return 0; + + if (!inited) + { + ic = iconv_open("ISO8859-1", "IBM-037"); + inited = TRUE; + } + + size_t substitutedChars; + size_t olen = ilen; + if (iconv( ic, (char**)&input, &ilen, &output, &olen, &substitutedChars) == -1) + return errno; + + return 0; +} diff --git a/storage/ibmdb2i/db2i_charsetSupport.h b/storage/ibmdb2i/db2i_charsetSupport.h new file mode 100644 index 00000000000..77051e1e0db --- /dev/null +++ b/storage/ibmdb2i/db2i_charsetSupport.h @@ -0,0 +1,65 @@ +/* +Licensed Materials - Property of IBM +DB2 Storage Engine Enablement +Copyright IBM Corporation 2007,2008 +All rights reserved + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + (a) Redistributions of source code must retain this list of conditions, the + copyright notice in section {d} below, and the disclaimer following this + list of conditions. + (b) Redistributions in binary form must reproduce this list of conditions, the + copyright notice in section (d) below, and the disclaimer following this + list of conditions, in the documentation and/or other materials provided + with the distribution. + (c) The name of IBM may not be used to endorse or promote products derived from + this software without specific prior written permission. + (d) The text of the required copyright notice is: + Licensed Materials - Property of IBM + DB2 Storage Engine Enablement + Copyright IBM Corporation 2007,2008 + All rights reserved + +THIS SOFTWARE IS PROVIDED BY IBM CORPORATION "AS IS" AND ANY EXPRESS OR IMPLIED +WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT +SHALL IBM CORPORATION BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT +OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT INCLUDING NEGLIGENCE OR OTHERWISE) ARISING +IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + + +#ifndef DB2I_CHARSETSUPPORT_H +#define DB2I_CHARSETSUPPORT_H + +#include "db2i_global.h" +#include "mysql_priv.h" +#include +#include "db2i_iconv.h" + +/** + @enum enum_conversionDirection + + Conversion directions for getConversion() +*/ +enum enum_conversionDirection +{ + toMySQL, + toDB2 +}; + +int initCharsetSupport(); +void doneCharsetSupport(); +int32 convertIANAToDb2Ccsid(const char* parmIANADesc, uint16* db2Ccsid); +int32 getEncodingScheme(const uint16 inCcsid, int32& outEncodingScheme); +int32 getAssociatedCCSID(const uint16 inCcsid, const int inEncodingScheme, uint16* outCcsid); +int convToEbcdic(const char* input, char* output, size_t ilen); +int convFromEbcdic(const char* input, char* output, size_t ilen); +int32 getConversion(enum_conversionDirection direction, const CHARSET_INFO* cs, uint16 db2CCSID, iconv_t& conversion); + +#endif diff --git a/storage/ibmdb2i/db2i_collationSupport.cc b/storage/ibmdb2i/db2i_collationSupport.cc new file mode 100644 index 00000000000..a6ffd661b81 --- /dev/null +++ b/storage/ibmdb2i/db2i_collationSupport.cc @@ -0,0 +1,360 @@ +/* +Licensed Materials - Property of IBM +DB2 Storage Engine Enablement +Copyright IBM Corporation 2007,2008 +All rights reserved + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + (a) Redistributions of source code must retain this list of conditions, the + copyright notice in section {d} below, and the disclaimer following this + list of conditions. + (b) Redistributions in binary form must reproduce this list of conditions, the + copyright notice in section (d) below, and the disclaimer following this + list of conditions, in the documentation and/or other materials provided + with the distribution. + (c) The name of IBM may not be used to endorse or promote products derived from + this software without specific prior written permission. + (d) The text of the required copyright notice is: + Licensed Materials - Property of IBM + DB2 Storage Engine Enablement + Copyright IBM Corporation 2007,2008 + All rights reserved + +THIS SOFTWARE IS PROVIDED BY IBM CORPORATION "AS IS" AND ANY EXPRESS OR IMPLIED +WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT +SHALL IBM CORPORATION BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT +OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT INCLUDING NEGLIGENCE OR OTHERWISE) ARISING +IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + + +#include "db2i_collationSupport.h" +#include "db2i_errors.h" + + +/* + The following arrays define a mapping between MySQL collation names and + corresponding IBM i sort sequences. The mapping is a 1-to-1 correlation + between corresponding array slots but is incomplete without case-sensitivity + markers dynamically added to the mySqlSortSequence names. +*/ +#define MAX_COLLATION 89 +static const char* mySQLCollation[MAX_COLLATION] = +{ + {"ascii_general"}, + {"ascii"}, + {"big5_chinese"}, + {"big5"}, + {"cp1250_croatian"}, + {"cp1250_czech"}, + {"cp1250_general"}, + {"cp1250_polish"}, + {"cp1250"}, + {"cp1251_bulgarian"}, + {"cp1251_general"}, + {"cp1251"}, + {"cp1256_general"}, + {"cp1256"}, + {"cp850_general"}, + {"cp850"}, + {"cp852_general"}, + {"cp852"}, + {"cp932_japanese"}, + {"cp932"}, + {"euckr_korean"}, + {"euckr"}, + {"gb2312_chinese"}, + {"gb2312"}, + {"gbk_chinese"}, + {"gbk"}, + {"greek_general"}, + {"greek"}, + {"hebrew_general"}, + {"hebrew"}, + {"latin1_danish"}, + {"latin1_general"}, + {"latin1_german1"}, + {"latin1_spanish"}, + {"latin1_swedish"}, + {"latin1"}, + {"latin2_croatian"}, + {"latin2_czech"}, + {"latin2_general"}, + {"latin2_hungarian"}, + {"latin2"}, + {"latin5_turkish"}, + {"latin5"}, + {"macce_general"}, + {"macce"}, + {"sjis_japanese"}, + {"sjis"}, + {"tis620_thai"}, + {"tis620"}, + {"ucs2_czech"}, + {"ucs2_danish"}, + {"ucs2_esperanto"}, + {"ucs2_estonian"}, + {"ucs2_general"}, + {"ucs2_hungarian"}, + {"ucs2_icelandic"}, + {"ucs2_latvian"}, + {"ucs2_lithuanian"}, + {"ucs2_persian"}, + {"ucs2_polish"}, + {"ucs2_romanian"}, + {"ucs2_slovak"}, + {"ucs2_slovenian"}, + {"ucs2_spanish"}, + {"ucs2_spanish2"}, + {"ucs2_turkish"}, + {"ucs2_unicode"}, + {"ucs2"}, + {"ujis_japanese"}, + {"ujis"}, + {"utf8_czech"}, + {"utf8_danish"}, + {"utf8_esperanto"}, + {"utf8_estonian"}, + {"utf8_general"}, + {"utf8_hungarian"}, + {"utf8_icelandic"}, + {"utf8_latvian"}, + {"utf8_lithuanian"}, + {"utf8_persian"}, + {"utf8_polish"}, + {"utf8_romanian"}, + {"utf8_slovak"}, + {"utf8_slovenian"}, + {"utf8_spanish"}, + {"utf8_spanish2"}, + {"utf8_turkish"}, + {"utf8_unicode"}, + {"utf8"} +}; + + +static const char* mySqlSortSequence[MAX_COLLATION] = +{ + {"QALA101F4"}, + {"QBLA101F4"}, + {"QACHT04B0"}, + {"QBCHT04B0"}, + {"QALA20481"}, + {"QBLA20481"}, + {"QCLA20481"}, + {"QDLA20481"}, + {"QELA20481"}, + {"QACYR0401"}, + {"QBCYR0401"}, + {"QCCYR0401"}, + {"QAARA01A4"}, + {"QBARA01A4"}, + {"QCLA101F4"}, + {"QDLA101F4"}, + {"QALA20366"}, + {"QBLA20366"}, + {"QAJPN04B0"}, + {"QBJPN04B0"}, + {"QAKOR04B0"}, + {"QBKOR04B0"}, + {"QACHS04B0"}, + {"QBCHS04B0"}, + {"QCCHS04B0"}, + {"QDCHS04B0"}, + {"QAELL036B"}, + {"QBELL036B"}, + {"QAHEB01A8"}, + {"QBHEB01A8"}, + {"QALA1047C"}, + {"QBLA1047C"}, + {"QCLA1047C"}, + {"QDLA1047C"}, + {"QELA1047C"}, + {"QFLA1047C"}, + {"QCLA20366"}, + {"QDLA20366"}, + {"QELA20366"}, + {"QFLA20366"}, + {"QGLA20366"}, + {"QATRK0402"}, + {"QBTRK0402"}, + {"QHLA20366"}, + {"QILA20366"}, + {"QCJPN04B0"}, + {"QDJPN04B0"}, + {"QATHA0346"}, + {"QBTHA0346"}, + {"ACS"}, + {"ADA"}, + {"AEO"}, + {"AET"}, + {"QAUCS04B0"}, + {"AHU"}, + {"AIS"}, + {"ALV"}, + {"ALT"}, + {"AFA"}, + {"APL"}, + {"ARO"}, + {"ASK"}, + {"ASL"}, + {"AES"}, + {"AES__TRADIT"}, + {"ATR"}, + {"AEN"}, + {"*HEX"}, + {"QEJPN04B0"}, + {"QFJPN04B0"}, + {"ACS"}, + {"ADA"}, + {"AEO"}, + {"AET"}, + {"QAUCS04B0"}, + {"AHU"}, + {"AIS"}, + {"ALV"}, + {"ALT"}, + {"AFA"}, + {"APL"}, + {"ARO"}, + {"ASK"}, + {"ASL"}, + {"AES"}, + {"AES__TRADIT"}, + {"ATR"}, + {"AEN"}, + {"*HEX"} +}; + + +/** + Get the IBM i sort sequence that corresponds to the given MySQL collation. + + @param fieldCharSet The collated character set + @param[out] rtnSortSequence The corresponding sort sequence + + @return 0 if successful. Failure otherwise +*/ +static int32 getAssociatedSortSequence(const CHARSET_INFO *fieldCharSet, const char** rtnSortSequence) +{ + DBUG_ENTER("ha_ibmdb2i::getAssociatedSortSequence"); + + if (strcmp(fieldCharSet->csname,"binary") != 0) + { + int collationSearchLen = strlen(fieldCharSet->name); + if (fieldCharSet->state & MY_CS_BINSORT) + collationSearchLen -= 4; + else + collationSearchLen -= 3; + + uint16 loopCnt = 0; + for (loopCnt; loopCnt < MAX_COLLATION; ++loopCnt) + { + if ((strlen(mySQLCollation[loopCnt]) == collationSearchLen) && + (strncmp((char*)mySQLCollation[loopCnt], fieldCharSet->name, collationSearchLen) == 0)) + break; + } + if (loopCnt == MAX_COLLATION) // Did not find associated sort sequence + { + getErrTxt(DB2I_ERR_SRTSEQ); + DBUG_RETURN(DB2I_ERR_SRTSEQ); + } + *rtnSortSequence = mySqlSortSequence[loopCnt]; + } + + DBUG_RETURN(0); +} + + +/** + Update sort sequence information for a key. + + This function accumulates information about a key as it is called for each + field composing the key. The caller should invoke the function for each field + and (with the exception of the curField parm) preserve the values for the + parms across invocations, until a particular key has been evaluated. Once + the last field in the key has been evaluated, the fileSortSequence and + fileSortSequenceLibrary parms will contain the correct information for + creating the corresponding DB2 key. + + @param curField The field under consideration + @param[in, out] fileSortSequenceType The type of the current key's sort seq + @param[in, out] fileSortSequence The IBM i identifier for the DB2 sort sequence + that corresponds + + @return 0 if successful. Failure otherwise +*/ +int32 updateAssociatedSortSequence(const Field *curField, + char* fileSortSequenceType, + char* fileSortSequence, + char* fileSortSequenceLibrary) +{ + DBUG_ENTER("ha_ibmdb2i::updateAssociatedSortSequence"); + DBUG_ASSERT(curField); + CHARSET_INFO* fieldCharSet = curField->charset(); + if (strcmp(fieldCharSet->csname,"binary") != 0) + { + char newSortSequence[11] = ""; + char newSortSequenceType = ' '; + const char* foundSortSequence; + int rc = getAssociatedSortSequence(fieldCharSet, &foundSortSequence); + if (rc) DBUG_RETURN (rc); + switch(foundSortSequence[0]) + { + case '*': // Binary + strcat(newSortSequence,foundSortSequence); + newSortSequenceType = 'B'; + break; + case 'Q': // Non-ICU sort sequence + strcat(newSortSequence,foundSortSequence); + if ((fieldCharSet->state & MY_CS_BINSORT) != 0) + { + strcat(newSortSequence,"U"); + } + else if ((fieldCharSet->state & MY_CS_CSSORT) != 0) + { + strcat(newSortSequence,"U"); + } + else + { + strcat(newSortSequence,"S"); + } + newSortSequenceType = 'N'; + break; + default: // ICU sort sequence + { + if ((fieldCharSet->state & MY_CS_CSSORT) == 0) + { + if (osVersion.v >= 6) + strcat(newSortSequence,"I34"); // ICU 3.4 + else + strcat(newSortSequence,"I26"); // ICU 2.6.1 + } + strcat(newSortSequence,foundSortSequence); + newSortSequenceType = 'I'; + } + break; + } + if (*fileSortSequenceType == ' ') // If no sort sequence has been set yet + { + // Set associated sort sequence + strcpy(fileSortSequence,newSortSequence); + strcpy(fileSortSequenceLibrary,"QSYS"); + *fileSortSequenceType = newSortSequenceType; + } + else if (strcmp(fileSortSequence,newSortSequence) != 0) + { + // Only one sort sequence/collation is supported for each DB2 index. + getErrTxt(DB2I_ERR_MIXED_COLLATIONS); + DBUG_RETURN(DB2I_ERR_MIXED_COLLATIONS); + } + } + + DBUG_RETURN(0); +} diff --git a/storage/ibmdb2i/db2i_collationSupport.h b/storage/ibmdb2i/db2i_collationSupport.h new file mode 100644 index 00000000000..315d6ae4403 --- /dev/null +++ b/storage/ibmdb2i/db2i_collationSupport.h @@ -0,0 +1,45 @@ +/* +Licensed Materials - Property of IBM +DB2 Storage Engine Enablement +Copyright IBM Corporation 2007,2008 +All rights reserved + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + (a) Redistributions of source code must retain this list of conditions, the + copyright notice in section {d} below, and the disclaimer following this + list of conditions. + (b) Redistributions in binary form must reproduce this list of conditions, the + copyright notice in section (d) below, and the disclaimer following this + list of conditions, in the documentation and/or other materials provided + with the distribution. + (c) The name of IBM may not be used to endorse or promote products derived from + this software without specific prior written permission. + (d) The text of the required copyright notice is: + Licensed Materials - Property of IBM + DB2 Storage Engine Enablement + Copyright IBM Corporation 2007,2008 + All rights reserved + +THIS SOFTWARE IS PROVIDED BY IBM CORPORATION "AS IS" AND ANY EXPRESS OR IMPLIED +WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT +SHALL IBM CORPORATION BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT +OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT INCLUDING NEGLIGENCE OR OTHERWISE) ARISING +IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + + +#ifndef DB2I_COLLATIONSUPPORT_H +#define DB2I_COLLATIONSUPPORT_H + +#include "db2i_global.h" +#include "mysql_priv.h" + +int32 updateAssociatedSortSequence(const Field *curField, char* fileSortSequenceType, char* fileSortSequence, char* fileSortSequenceLibrary); + +#endif diff --git a/storage/ibmdb2i/db2i_constraints.cc b/storage/ibmdb2i/db2i_constraints.cc new file mode 100644 index 00000000000..d219aa05737 --- /dev/null +++ b/storage/ibmdb2i/db2i_constraints.cc @@ -0,0 +1,699 @@ +/* +Licensed Materials - Property of IBM +DB2 Storage Engine Enablement +Copyright IBM Corporation 2007,2008 +All rights reserved + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + (a) Redistributions of source code must retain this list of conditions, the + copyright notice in section {d} below, and the disclaimer following this + list of conditions. + (b) Redistributions in binary form must reproduce this list of conditions, the + copyright notice in section (d) below, and the disclaimer following this + list of conditions, in the documentation and/or other materials provided + with the distribution. + (c) The name of IBM may not be used to endorse or promote products derived from + this software without specific prior written permission. + (d) The text of the required copyright notice is: + Licensed Materials - Property of IBM + DB2 Storage Engine Enablement + Copyright IBM Corporation 2007,2008 + All rights reserved + +THIS SOFTWARE IS PROVIDED BY IBM CORPORATION "AS IS" AND ANY EXPRESS OR IMPLIED +WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT +SHALL IBM CORPORATION BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT +OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT INCLUDING NEGLIGENCE OR OTHERWISE) ARISING +IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + + + +#include "ha_ibmdb2i.h" +#include "db2i_safeString.h" + +// This function is called when building the CREATE TABLE information for +// foreign key constraints. It converts a constraint, table, schema, or +// field name from EBCDIC to ASCII. If the DB2 name is quoted, it removes +// those quotes. It then adds the appropriate quotes for a MySQL identifier. + +static void convNameForCreateInfo(THD *thd, SafeString& info, char* fromName, int len) +{ + int quote; + char cquote; // Quote character + char convName[MAX_DB2_FILENAME_LENGTH]; // Converted name + + memset(convName, 0, sizeof(convName)); + convFromEbcdic(fromName, convName, len); + quote = get_quote_char_for_identifier(thd, convName, len); + cquote = (char) quote; + if (quote != EOF) + info.strcat(cquote); + if (convName[0] == '"') // If DB2 name was quoted, remove quotes + { + if (strstr(convName, "\"\"")) + stripExtraQuotes(convName+1, len-1); + info.strncat((char*)(convName+1), len-2); + } + else // DB2 name was not quoted + info.strncat(convName, len); + if (quote != EOF) + info.strcat(cquote); +} + +/** + Evaluate the parse tree to build foreign key constraint clauses + + @parm lex The parse tree + @parm appendHere The DB2 string to receive the constraint clauses + @parm path The path to the table under consideration + @parm fields Pointer to the table's list of field pointers + @parm[in, out] fileSortSequenceType The sort sequence type associated with the table + @parm[in, out] fileSortSequence The sort sequence associated with the table + @parm[in, out] fileSortSequenceLibrary The sort sequence library associated with the table + + @return 0 if successful; HA_ERR_CANNOT_ADD_FOREIGN otherwise +*/ +int ha_ibmdb2i::buildDB2ConstraintString(LEX* lex, + String& appendHere, + const char* path, + Field** fields, + char* fileSortSequenceType, + char* fileSortSequence, + char* fileSortSequenceLibrary) +{ + List_iterator keyIter(lex->alter_info.key_list); + char colName[MAX_DB2_COLNAME_LENGTH+1]; + + Key* curKey; + + while (curKey = keyIter++) + { + if (curKey->type == Key::FOREIGN_KEY) + { + appendHere.append(STRING_WITH_LEN(", ")); + + Foreign_key* fk = (Foreign_key*)curKey; + + char db2LibName[MAX_DB2_SCHEMANAME_LENGTH+1]; + if (fk->name) + { + char db2FKName[MAX_DB2_FILENAME_LENGTH+1]; + appendHere.append(STRING_WITH_LEN("CONSTRAINT ")); + if (fk->ref_table->db.str) + { + convertMySQLNameToDB2Name(fk->ref_table->db.str, db2LibName, sizeof(db2LibName)); + } + else + { + db2i_table::getDB2LibNameFromPath(path, db2LibName); + } + if (lower_case_table_names == 1) + my_casedn_str(files_charset_info, db2LibName); + appendHere.append(db2LibName); + + appendHere.append('.'); + + convertMySQLNameToDB2Name(fk->name, db2FKName, sizeof(db2FKName)); + appendHere.append(db2FKName); + } + + appendHere.append(STRING_WITH_LEN(" FOREIGN KEY (")); + + bool firstTime = true; + + List_iterator column(fk->columns); + Key_part_spec* curColumn; + + while (curColumn = column++) + { + if (!firstTime) + { + appendHere.append(','); + } + firstTime = false; + + convertMySQLNameToDB2Name(curColumn->field_name, colName, sizeof(colName)); + appendHere.append(colName); + + // DB2 requires that the sort sequence on the child table match the parent table's + // sort sequence. We ensure that happens by updating the sort sequence according + // to the constrained fields. + Field** field = fields; + do + { + if (strcmp((*field)->field_name, curColumn->field_name) == 0) + { + int rc = updateAssociatedSortSequence((*field), + fileSortSequenceType, + fileSortSequence, + fileSortSequenceLibrary); + + if (unlikely(rc)) return rc; + } + } while (*(++field)); + } + + firstTime = true; + + appendHere.append(STRING_WITH_LEN(") REFERENCES ")); + + if (fk->ref_table->db.str) + { + convertMySQLNameToDB2Name(fk->ref_table->db.str, db2LibName, sizeof(db2LibName)); + } + else + { + db2i_table::getDB2LibNameFromPath(path, db2LibName); + } + if (lower_case_table_names == 1) + my_casedn_str(files_charset_info, db2LibName); + appendHere.append(db2LibName); + appendHere.append('.'); + + char db2FileName[MAX_DB2_FILENAME_LENGTH+1]; + convertMySQLNameToDB2Name(fk->ref_table->table.str, db2FileName, sizeof(db2FileName)); + if (lower_case_table_names) + my_casedn_str(files_charset_info, db2FileName); + appendHere.append(db2FileName); + + + if (!fk->ref_columns.is_empty()) + { + List_iterator ref(fk->ref_columns); + Key_part_spec* curRef; + appendHere.append(STRING_WITH_LEN(" (")); + + + while (curRef = ref++) + { + if (!firstTime) + { + appendHere.append(','); + } + firstTime = false; + + convertMySQLNameToDB2Name(curRef->field_name, colName, sizeof(colName)); + appendHere.append(colName); + } + + appendHere.append(STRING_WITH_LEN(") ")); + } + + if (fk->delete_opt != Foreign_key::FK_OPTION_UNDEF) + { + appendHere.append(STRING_WITH_LEN("ON DELETE ")); + switch (fk->delete_opt) + { + case Foreign_key::FK_OPTION_RESTRICT: + appendHere.append(STRING_WITH_LEN("RESTRICT ")); break; + case Foreign_key::FK_OPTION_CASCADE: + appendHere.append(STRING_WITH_LEN("CASCADE ")); break; + case Foreign_key::FK_OPTION_SET_NULL: + appendHere.append(STRING_WITH_LEN("SET NULL ")); break; + case Foreign_key::FK_OPTION_NO_ACTION: + appendHere.append(STRING_WITH_LEN("NO ACTION ")); break; + case Foreign_key::FK_OPTION_DEFAULT: + appendHere.append(STRING_WITH_LEN("SET DEFAULT ")); break; + default: + return HA_ERR_CANNOT_ADD_FOREIGN; break; + } + } + + if (fk->update_opt != Foreign_key::FK_OPTION_UNDEF) + { + appendHere.append(STRING_WITH_LEN("ON UPDATE ")); + switch (fk->update_opt) + { + case Foreign_key::FK_OPTION_RESTRICT: + appendHere.append(STRING_WITH_LEN("RESTRICT ")); break; + case Foreign_key::FK_OPTION_NO_ACTION: + appendHere.append(STRING_WITH_LEN("NO ACTION ")); break; + default: + return HA_ERR_CANNOT_ADD_FOREIGN; break; + } + } + + } + + } + + return 0; +} + + +/*********************************************************************** +Get the foreign key information in the form of a character string so +that it can be inserted into a CREATE TABLE statement. This is used by +the SHOW CREATE TABLE statement. The string will later be freed by the +free_foreign_key_create_info() method. +************************************************************************/ + +char* ha_ibmdb2i::get_foreign_key_create_info(void) +{ + DBUG_ENTER("ha_ibmdb2i::get_foreign_key_create_info"); + int rc = 0; + char* infoBuffer = NULL; // Pointer to string returned to MySQL + uint32 constraintSpaceLength;// Length of space passed to DB2 + ValidatedPointer constraintSpace; // Space pointer passed to DB2 + uint32 neededLen; // Length returned from DB2 + uint32 cstCnt; // Number of foreign key constraints from DB2 + uint32 fld; // + constraint_hdr* cstHdr; // Pointer to constraint header structure + FK_constraint* FKCstDef; // Pointer to constraint definition structure + cst_name* fieldName; // Pointer to field name structure + char* tempPtr; // Temp pointer for traversing constraint space + char convName[128]; + + /* Allocate space to retrieve the DB2 constraint information. */ + + if (!(share = get_share(table_share->path.str, table))) + DBUG_RETURN(NULL); + + constraintSpaceLength = 5000; // Try allocating 5000 bytes and see if enough. + + initBridge(); + + constraintSpace.alloc(constraintSpaceLength); + rc = bridge()->expectErrors(QMY_ERR_NEED_MORE_SPACE) + ->constraints(db2Table->dataFile()->getMasterDefnHandle(), + constraintSpace, + constraintSpaceLength, + &neededLen, + &cstCnt); + + if (unlikely(rc == QMY_ERR_NEED_MORE_SPACE)) + { + constraintSpaceLength = neededLen; // Get length of space that's needed + constraintSpace.realloc(constraintSpaceLength); + rc = bridge()->expectErrors(QMY_ERR_NEED_MORE_SPACE) + ->constraints(db2Table->dataFile()->getMasterDefnHandle(), + constraintSpace, + constraintSpaceLength, + &neededLen, + &cstCnt); + } + + /* If constraint information was returned by DB2, build a text string */ + /* to return to MySQL. */ + + if ((rc == 0) && (cstCnt > 0)) + { + THD* thd = ha_thd(); + infoBuffer = (char*) my_malloc(MAX_FOREIGN_LEN + 1, MYF(MY_WME)); + if (infoBuffer == NULL) + { + free_share(share); + DBUG_RETURN(NULL); + } + + SafeString info(infoBuffer, MAX_FOREIGN_LEN + 1); + + /* Loop through the DB2 constraints and build a text string for each foreign */ + /* key constraint that is found. */ + + tempPtr = constraintSpace; + cstHdr = (constraint_hdr_t*)(void*)constraintSpace; // Address first constraint definition + for (int i = 0; i < cstCnt && !info.overflowed(); ++i) + { + if (cstHdr->CstType[0] == QMY_CST_FK) // If this is a foreign key constraint + { + tempPtr = (char*)(tempPtr + cstHdr->CstDefOff); + FKCstDef = (FK_constraint_t*)tempPtr; + + /* Process the constraint name. */ + + info.strncat(STRING_WITH_LEN(" CONSTRAINT ")); + convNameForCreateInfo(thd, info, + FKCstDef->CstName.Name, FKCstDef->CstName.Len); + + /* Process the names of the foreign keys. */ + + info.strncat(STRING_WITH_LEN(" FOREIGN KEY (")); + tempPtr = (char*)(tempPtr + FKCstDef->KeyColOff); + fieldName= (cst_name_t*)tempPtr; + for (fld = 0; fld < FKCstDef->KeyCnt; ++fld) + { + convNameForCreateInfo(thd, info, fieldName->Name, fieldName->Len); + if ((fld + 1) < FKCstDef->KeyCnt) + { + info.strncat(STRING_WITH_LEN(", ")); + fieldName = fieldName + 1; + } + } + + /* Process the schema-name and name of the referenced table. */ + + info.strncat(STRING_WITH_LEN(") REFERENCES ")); + convNameForCreateInfo(thd, info, + FKCstDef->RefSchema.Name, FKCstDef->RefSchema.Len); + info.strcat('.'); + convNameForCreateInfo(thd, info, + FKCstDef->RefTable.Name, FKCstDef->RefTable.Len); + info.strncat(STRING_WITH_LEN(" (")); + + /* Process the names of the referenced keys. */ + + tempPtr = (char*)FKCstDef; + tempPtr = (char*)(tempPtr + FKCstDef->RefColOff); + fieldName= (cst_name_t*)tempPtr; + for (fld = 0; fld < FKCstDef->RefCnt; ++fld) + { + convNameForCreateInfo(thd, info, fieldName->Name, fieldName->Len); + if ((fld + 1) < FKCstDef->RefCnt) + { + info.strncat(STRING_WITH_LEN(", ")); + fieldName = fieldName + 1; + } + } + + /* Process the ON UPDATE and ON DELETE rules. */ + + info.strncat(STRING_WITH_LEN(") ON UPDATE ")); + switch(FKCstDef->UpdMethod) + { + case QMY_NOACTION: info.strncat(STRING_WITH_LEN("NO ACTION")); break; + case QMY_RESTRICT: info.strncat(STRING_WITH_LEN("RESTRICT")); break; + default: break; + } + info.strncat(STRING_WITH_LEN(" ON DELETE ")); + switch(FKCstDef->DltMethod) + { + case QMY_CASCADE: info.strncat(STRING_WITH_LEN("CASCADE")); break; + case QMY_SETDFT: info.strncat(STRING_WITH_LEN("SET DEFAULT")); break; + case QMY_SETNULL: info.strncat(STRING_WITH_LEN("SET NULL")); break; + case QMY_NOACTION: info.strncat(STRING_WITH_LEN("NO ACTION")); break; + case QMY_RESTRICT: info.strncat(STRING_WITH_LEN("RESTRICT")); break; + default: break; + } + } + + /* Address the next constraint, if any. */ + + if ((i+1) < cstCnt) + { + info.strcat(','); + tempPtr = (char*)cstHdr + cstHdr->CstLen; + cstHdr = (constraint_hdr_t*)(tempPtr); + } + } + } + + /* Cleanup and return */ + free_share(share); + + DBUG_RETURN(infoBuffer); +} + +/*********************************************************************** +Free the foreign key create info (for a table) that was acquired by the +get_foreign_key_create_info() method. +***********************************************************************/ + +void ha_ibmdb2i::free_foreign_key_create_info(char* info) +{ + DBUG_ENTER("ha_ibmdb2i::free_foreign_key_create_info"); + + if (info) + { + my_free(info, MYF(0)); + } + DBUG_VOID_RETURN; +} + +/*********************************************************************** +This method returns to MySQL a list, with one entry in the list describing +each foreign key constraint. +***********************************************************************/ + +int ha_ibmdb2i::get_foreign_key_list(THD *thd, List *f_key_list) +{ + DBUG_ENTER("ha_ibmdb2i::get_foreign_key_list"); + int rc = 0; + uint32 constraintSpaceLength; // Length of space passed to DB2 + ValidatedPointer constraintSpace; // Space pointer passed to DB2 + uint16 rtnCode; // Return code from DB2 + uint32 neededLen; // Bytes needed to contain DB2 constraint info + uint32 cstCnt; // Number of constraints returned by DB2 + uint32 fld; + constraint_hdr* cstHdr; // Pointer to a cst header structure + FK_constraint* FKCstDef; // Pointer to definition of foreign key constraint + cst_name* fieldName; // Pointer to field name structure + const char *method; + ulong methodLen; + bool gotShare = FALSE; // Indicator for local get_share + char* tempPtr; // Temp pointer for traversing constraint space + char convName[128]; + + // Allocate space to retrieve the DB2 constraint information. + if (!(share = get_share(table_share->path.str, table))) + DBUG_RETURN(0); + + constraintSpaceLength = 5000; // Try allocating 5000 bytes and see if enough. + + constraintSpace.alloc(constraintSpaceLength); + rc = bridge()->expectErrors(QMY_ERR_NEED_MORE_SPACE) + ->constraints(db2Table->dataFile()->getMasterDefnHandle(), + constraintSpace, + constraintSpaceLength, + &neededLen, + &cstCnt); + + if (unlikely(rc == QMY_ERR_NEED_MORE_SPACE)) + { + constraintSpaceLength = neededLen; // Get length of space that's needed + constraintSpace.realloc(constraintSpaceLength); + rc = bridge()->expectErrors(QMY_ERR_NEED_MORE_SPACE) + ->constraints(db2Table->dataFile()->getMasterDefnHandle(), + constraintSpace, + constraintSpaceLength, + &neededLen, + &cstCnt); + } + + /* If constraint information was returned by DB2, build a text string */ + /* to return to MySQL. */ + if ((rc == 0) && (cstCnt > 0)) + { + tempPtr = constraintSpace; + cstHdr = (constraint_hdr_t*)(void*)constraintSpace; // Address first constraint definition + for (int i = 0; i < cstCnt; ++i) + { + if (cstHdr->CstType[0] == QMY_CST_FK) // If this is a foreign key constraint + { + FOREIGN_KEY_INFO f_key_info; + LEX_STRING *name= 0; + tempPtr = (char*)(tempPtr + cstHdr->CstDefOff); + FKCstDef = (FK_constraint_t*)tempPtr; + + /* Process the constraint name. */ + + convFromEbcdic(FKCstDef->CstName.Name, convName,FKCstDef->CstName.Len); + if (convName[0] == '"') // If quoted, exclude quotes. + f_key_info.forein_id = thd_make_lex_string(thd, 0, + convName + 1, (uint) (FKCstDef->CstName.Len - 2), 1); + else // Not quoted + f_key_info.forein_id = thd_make_lex_string(thd, 0, + convName, (uint) FKCstDef->CstName.Len, 1); + + /* Process the names of the foreign keys. */ + + + tempPtr = (char*)(tempPtr + FKCstDef->KeyColOff); + fieldName = (cst_name_t*)tempPtr; + for (fld = 0; fld < FKCstDef->KeyCnt; ++fld) + { + convFromEbcdic(fieldName->Name, convName, fieldName->Len); + if (convName[0] == '"') // If quoted, exclude quotes. + name = thd_make_lex_string(thd, name, + convName + 1, (uint) (fieldName->Len - 2), 1); + else + name = thd_make_lex_string(thd, name, convName, (uint) fieldName->Len, 1); + f_key_info.foreign_fields.push_back(name); + if ((fld + 1) < FKCstDef->KeyCnt) + fieldName = fieldName + 1; + } + + /* Process the schema and name of the referenced table. */ + + convFromEbcdic(FKCstDef->RefSchema.Name, convName, FKCstDef->RefSchema.Len); + if (convName[0] == '"') // If quoted, exclude quotes. + f_key_info.referenced_db = thd_make_lex_string(thd, 0, + convName + 1, (uint) (FKCstDef->RefSchema.Len -2), 1); + else + f_key_info.referenced_db = thd_make_lex_string(thd, 0, + convName, (uint) FKCstDef->RefSchema.Len, 1); + convFromEbcdic(FKCstDef->RefTable.Name, convName, FKCstDef->RefTable.Len); + if (convName[0] == '"') // If quoted, exclude quotes. + f_key_info.referenced_table = thd_make_lex_string(thd, 0, + convName +1, (uint) (FKCstDef->RefTable.Len -2), 1); + else + f_key_info.referenced_table = thd_make_lex_string(thd, 0, + convName, (uint) FKCstDef->RefTable.Len, 1); + + /* Process the names of the referenced keys. */ + + tempPtr = (char*)FKCstDef; + tempPtr = (char*)(tempPtr + FKCstDef->RefColOff); + fieldName= (cst_name_t*)tempPtr; + for (fld = 0; fld < FKCstDef->RefCnt; ++fld) + { + convFromEbcdic(fieldName->Name, convName, fieldName->Len); + if (convName[0] == '"') // If quoted, exclude quotes. + name = thd_make_lex_string(thd, name, + convName + 1, (uint) (fieldName->Len -2), 1); + else + name = thd_make_lex_string(thd, name, convName, (uint) fieldName->Len, 1); + f_key_info.referenced_fields.push_back(name); + if ((fld + 1) < FKCstDef->RefCnt) + fieldName = fieldName + 1; + } + + /* Process the ON UPDATE and ON DELETE rules. */ + + switch(FKCstDef->UpdMethod) + { + case QMY_NOACTION: + { + method = "NO ACTION"; + methodLen=9; + } + break; + case QMY_RESTRICT: + { + method = "RESTRICT"; + methodLen = 8; + } + break; + default: break; + } + f_key_info.update_method = thd_make_lex_string( + thd, f_key_info.update_method, method, methodLen, 1); + switch(FKCstDef->DltMethod) + { + case QMY_CASCADE: + { + method = "CASCADE"; + methodLen = 7; + } + break; + case QMY_SETDFT: + { + method = "SET DEFAULT"; + methodLen = 11; + } + break; + case QMY_SETNULL: + { + method = "SET NULL"; + methodLen = 8; + } + break; + case QMY_NOACTION: + { + method = "NO ACTION"; + methodLen = 9; + } + break; + case QMY_RESTRICT: + { + method = "RESTRICT"; + methodLen = 8; + } + break; + default: break; + } + f_key_info.delete_method = thd_make_lex_string( + thd, f_key_info.delete_method, method, methodLen, 1); + f_key_info.referenced_key_name= thd_make_lex_string(thd, 0, (char *)"", 1, 1); + FOREIGN_KEY_INFO *pf_key_info = (FOREIGN_KEY_INFO *) + thd_memdup(thd, &f_key_info, sizeof(FOREIGN_KEY_INFO)); + f_key_list->push_back(pf_key_info); + } + + /* Address the next constraint, if any. */ + + if ((i+1) < cstCnt) + { + tempPtr = (char*)cstHdr + cstHdr->CstLen; + cstHdr = (constraint_hdr_t*)(tempPtr); + } + } + } + + /* Cleanup and return. */ + + free_share(share); + DBUG_RETURN(0); +} + +/*********************************************************************** +Checks if the table is referenced by a foreign key. +Returns: 0 if not referenced (or error occurs), + > 0 if is referenced +***********************************************************************/ + +uint ha_ibmdb2i::referenced_by_foreign_key(void) +{ + DBUG_ENTER("ha_ibmdb2i::referenced_by_foreign_key"); + + int rc = 0; + FILE_HANDLE queryFile = 0; + uint32 resultRowLen; + uint32 count = 0; + + const char* libName = db2Table->getDB2LibName(db2i_table::ASCII_SQL); + const char* fileName = db2Table->getDB2TableName(db2i_table::ASCII_SQL); + + String query(128); + query.append(STRING_WITH_LEN(" SELECT COUNT(*) FROM SYSIBM.SQLFOREIGNKEYS WHERE PKTABLE_SCHEM = '")); + query.append(libName+1, strlen(libName)-2); // parent library name + query.append(STRING_WITH_LEN("' AND PKTABLE_NAME = '")); + query.append(fileName+1, strlen(fileName)-2); // parent file name + query.append(STRING_WITH_LEN("'")); + + SqlStatementStream sqlStream(query); + + rc = bridge()->prepOpen(sqlStream.getPtrToData(), + &queryFile, + &resultRowLen); + if (rc == 0) + { + IOReadBuffer rowBuffer(1, resultRowLen); + rc = bridge()->read(queryFile, rowBuffer.ptr(), QMY_READ_ONLY, QMY_NONE, QMY_FIRST); + if (!rc) count = *((uint32*)rowBuffer.getRowN(0)); + bridge()->deallocateFile(queryFile); + } + DBUG_RETURN(count); +} + + +bool ha_ibmdb2i::check_if_incompatible_data(HA_CREATE_INFO *info, + uint table_changes) +{ + DBUG_ENTER("ha_ibmdb2i::check_if_incompatible_data"); + uint i; + /* Check that auto_increment value and field definitions were + not changed. */ + if ((info->used_fields & HA_CREATE_USED_AUTO && + info->auto_increment_value != 0) || + table_changes != IS_EQUAL_YES) + DBUG_RETURN(COMPATIBLE_DATA_NO); + /* Check if any fields were renamed. */ + for (i= 0; i < table->s->fields; i++) + { + Field *field= table->field[i]; + if (field->flags & FIELD_IS_RENAMED) + { + DBUG_PRINT("info", ("Field has been renamed, copy table")); + DBUG_RETURN(COMPATIBLE_DATA_NO); + } + } + DBUG_RETURN(COMPATIBLE_DATA_YES); +} diff --git a/storage/ibmdb2i/db2i_conversion.cc b/storage/ibmdb2i/db2i_conversion.cc new file mode 100644 index 00000000000..229d84c3b40 --- /dev/null +++ b/storage/ibmdb2i/db2i_conversion.cc @@ -0,0 +1,1168 @@ +/* +Licensed Materials - Property of IBM +DB2 Storage Engine Enablement +Copyright IBM Corporation 2007,2008 +All rights reserved + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + (a) Redistributions of source code must retain this list of conditions, the + copyright notice in section {d} below, and the disclaimer following this + list of conditions. + (b) Redistributions in binary form must reproduce this list of conditions, the + copyright notice in section (d) below, and the disclaimer following this + list of conditions, in the documentation and/or other materials provided + with the distribution. + (c) The name of IBM may not be used to endorse or promote products derived from + this software without specific prior written permission. + (d) The text of the required copyright notice is: + Licensed Materials - Property of IBM + DB2 Storage Engine Enablement + Copyright IBM Corporation 2007,2008 + All rights reserved + +THIS SOFTWARE IS PROVIDED BY IBM CORPORATION "AS IS" AND ANY EXPRESS OR IMPLIED +WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT +SHALL IBM CORPORATION BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT +OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT INCLUDING NEGLIGENCE OR OTHERWISE) ARISING +IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + + + +#include "db2i_ileBridge.h" +#include "mysql_priv.h" +#include "db2i_charsetSupport.h" +#include "ctype.h" +#include "ha_ibmdb2i.h" +#include "db2i_errors.h" +#include "wchar.h" + +/** + Put a BCD digit into a BCD string. + + @param[out] bcdString The BCD string to be modified + @param pos The position within the string to be updated. + @param val The value to be assigned into the string at pos. +*/ +static inline void bcdAssign(char* bcdString, uint pos, uint val) +{ + bcdString[pos/2] |= val << ((pos % 2) ? 0 : 4); +} + +/** + Read a BCD digit from a BCD string. + + @param[out] bcdString The BCD string to be read + @param pos The position within the string to be read. + + @return bcdGet The value of the BCD digit at pos. +*/ +static inline uint bcdGet(const char* bcdString, uint pos) +{ + return (bcdString[pos/2] >> ((pos % 2) ? 0 : 4)) & 0xf; +} + +/** + In-place convert a number in ASCII represenation to EBCDIC representation. + + @param string The string of ASCII characters + @param len The length of string +*/ +static inline void convertNumericToEbcdicFast(char* string, int len) +{ + for (int i = 0; i < len; ++i, ++string) + { + switch(*string) + { + case '-': + *string = 0x60; break; + case ':': + *string = 0x7A; break; + case '.': + *string = 0x4B; break; + default: + DBUG_ASSERT(isdigit(*string)); + *string += 0xF0 - '0'; + break; + } + } +} + + +/** + atoi()-like function for a 4-character EBCDIC string. + + @param string The EBCDIC string + @return a4toi_ebcdic The decimal value of the EBCDIC string +*/ +static inline uint16 a4toi_ebcdic(const uchar* string) +{ + return ((string[0]-0xF0) * 1000 + + (string[1]-0xF0) * 100 + + (string[2]-0xF0) * 10 + + (string[3]-0xF0)); +}; + + +/** + atoi()-like function for a 4-character EBCDIC string. + + @param string The EBCDIC string + @return a4toi_ebcdic The decimal value of the EBCDIC string +*/ +static inline uint8 a2toi_ebcdic(const uchar* string) +{ + return ((string[0]-0xF0) * 10 + + (string[1]-0xF0)); +}; + +/** + Perform character conversion for textual field data. +*/ +int ha_ibmdb2i::convertFieldChars(enum_conversionDirection direction, + uint16 fieldID, + const char* input, + char* output, + size_t ilen, + size_t olen, + size_t* outDataLen) +{ + DBUG_PRINT("ha_ibmdb2i::convertFieldChars",("Direction: %d; length = %d", direction, ilen)); + + if (unlikely(ilen == 0)) + { + if (outDataLen) *outDataLen = 0; + return (0); + } + + iconv_t& conversion = db2Table->getConversionDefinition(direction, fieldID); + + if (unlikely(conversion == (iconv_t)(-1))) + { + return (DB2I_ERR_ICONV_OPEN); + } + + size_t initOLen= olen; + ilen = min(ilen, olen); // Handle partial translation + size_t substitutedChars = 0; + int rc = iconv(conversion, (char**)&input, &ilen, &output, &olen, &substitutedChars ); + if (unlikely(rc < 0)) + { + int er = errno; + if (er == EILSEQ) + { + getErrTxt(DB2I_ERR_ILL_CHAR, table->field[fieldID]->field_name); + return (DB2I_ERR_ILL_CHAR); + } + else + { + getErrTxt(DB2I_ERR_ICONV,er); + return (DB2I_ERR_ICONV); + } + } + if (unlikely(substitutedChars)) + { + warning(ha_thd(), DB2I_ERR_SUB_CHARS, table->field[fieldID]->field_name); + } + + if (outDataLen) *outDataLen = initOLen - olen; + + return (0); +} + + +/** + Convert a MySQL field definition into its corresponding DB2 type. + + The result will be appended to mapping as a DB2 SQL phrase. + + @param field The MySQL field to be evaluated + @param[out] mapping The receiver for the DB2 SQL syntax + @param timeFormat The format to be used for mapping the TIME type +*/ +int ha_ibmdb2i::getFieldTypeMapping(Field* field, + String& mapping, + enum_TimeFormat timeFormat, + enum_BlobMapping blobMapping) +{ + char stringBuildBuffer[257]; + uint32 fieldLength; + + CHARSET_INFO* fieldCharSet = field->charset(); + switch (field->type()) + { + case MYSQL_TYPE_NEWDECIMAL: + { + uint precision= ((Field_new_decimal*)field)->precision; + uint scale= field->decimals(); + + if (precision <= MAX_DEC_PRECISION) + { + sprintf(stringBuildBuffer,"DECIMAL(%d, %d)",precision,scale); + } + else + { + if (scale > precision - MAX_DEC_PRECISION) + { + scale = scale - (precision - MAX_DEC_PRECISION); + precision = MAX_DEC_PRECISION; + sprintf(stringBuildBuffer,"DECIMAL(%d, %d)",precision,scale); + } + else + { + return HA_ERR_UNSUPPORTED; + } + warning(ha_thd(), DB2I_ERR_PRECISION); + } + + mapping.append(stringBuildBuffer); + } + break; + case MYSQL_TYPE_TINY: + mapping.append(STRING_WITH_LEN("SMALLINT")); + break; + case MYSQL_TYPE_SHORT: + if (((Field_num*)field)->unsigned_flag) + mapping.append(STRING_WITH_LEN("INT")); + else + mapping.append(STRING_WITH_LEN("SMALLINT")); + break; + case MYSQL_TYPE_LONG: + if (((Field_num*)field)->unsigned_flag) + mapping.append(STRING_WITH_LEN("BIGINT")); + else + mapping.append(STRING_WITH_LEN("INT")); + break; + case MYSQL_TYPE_FLOAT: + mapping.append(STRING_WITH_LEN("REAL")); + break; + case MYSQL_TYPE_DOUBLE: + mapping.append(STRING_WITH_LEN("DOUBLE")); + break; + case MYSQL_TYPE_LONGLONG: + if (((Field_num*)field)->unsigned_flag) + mapping.append(STRING_WITH_LEN("DECIMAL(20,0)")); + else + mapping.append(STRING_WITH_LEN("BIGINT")); + break; + case MYSQL_TYPE_INT24: + mapping.append(STRING_WITH_LEN("INTEGER")); + break; + case MYSQL_TYPE_DATE: + case MYSQL_TYPE_NEWDATE: + mapping.append(STRING_WITH_LEN("DATE")); + break; + case MYSQL_TYPE_TIME: + if (timeFormat == TIME_OF_DAY) + mapping.append(STRING_WITH_LEN("TIME")); + else + mapping.append(STRING_WITH_LEN("INTEGER")); + break; + case MYSQL_TYPE_TIMESTAMP: + case MYSQL_TYPE_DATETIME: + mapping.append(STRING_WITH_LEN("TIMESTAMP")); + break; + case MYSQL_TYPE_YEAR: + mapping.append(STRING_WITH_LEN("CHAR(4) CCSID 1208")); + break; + case MYSQL_TYPE_BIT: + sprintf(stringBuildBuffer, "BINARY(%d)", (field->max_display_length() / 8) + 1); + mapping.append(stringBuildBuffer); + break; + case MYSQL_TYPE_BLOB: + case MYSQL_TYPE_VARCHAR: + case MYSQL_TYPE_STRING: + { + if (field->real_type() == MYSQL_TYPE_ENUM || + field->real_type() == MYSQL_TYPE_SET) + { + mapping.append(STRING_WITH_LEN("BIGINT")); + } + else + { + fieldLength = field->max_display_length(); // Get field byte length + + if (fieldCharSet == &my_charset_bin) + { + if (field->type() == MYSQL_TYPE_STRING) + { + sprintf(stringBuildBuffer, "BINARY(%d)", max(fieldLength, 1)); + } + else + { + if (fieldLength <= MAX_VARCHAR_LENGTH) + { + sprintf(stringBuildBuffer, "VARBINARY(%d)", max(fieldLength, 1)); + } +/* else if (blobMapping == AS_VARCHAR && + get_blob_type_from_length(fieldLength) == MYSQL_TYPE_BLOB) + { + sprintf(stringBuildBuffer, "LONG VARBINARY ", max(fieldLength, 1)); + } +*/ + else + { + fieldLength = min(MAX_BLOB_LENGTH, fieldLength); + sprintf(stringBuildBuffer, "BLOB(%d)", max(fieldLength, 1)); + } + } + mapping.append(stringBuildBuffer); + } + else + { + uint16 db2Ccsid = 0; // No override CCSID + if (field->type() == MYSQL_TYPE_STRING) + { + if (fieldLength > MAX_CHAR_LENGTH) + return 1; + if (fieldCharSet->mbmaxlen > 1) + { + if (strncmp(fieldCharSet->name, "ucs2_", sizeof("ucs2_")) == 0 ) // UCS2 + { + sprintf(stringBuildBuffer, "GRAPHIC(%d)", max(fieldLength / fieldCharSet->mbmaxlen, 1)); // Number of characters + db2Ccsid = 13488; + } + else if (strncmp(fieldCharSet->name, "utf8_", sizeof("utf8_")) == 0 && + strcmp(fieldCharSet->name, "utf8_general_ci") != 0) + { + sprintf(stringBuildBuffer, "CHAR(%d)", max(fieldLength, 1)); // Number of bytes + db2Ccsid = 1208; + } + else + { + sprintf(stringBuildBuffer, "GRAPHIC(%d)", max(fieldLength / fieldCharSet->mbmaxlen, 1)); // Number of characters + db2Ccsid = 1200; + } + } + else + { + sprintf(stringBuildBuffer, "CHAR(%d)", max(fieldLength, 1)); + } + mapping.append(stringBuildBuffer); + } + else + { + if (fieldLength <= MAX_VARCHAR_LENGTH) + { + if (fieldCharSet->mbmaxlen > 1) + { + if (strncmp(fieldCharSet->name, "ucs2_", sizeof("ucs2_")) == 0 ) // UCS2 + { + sprintf(stringBuildBuffer, "VARGRAPHIC(%d)", max(fieldLength / fieldCharSet->mbmaxlen, 1)); // Number of characters + db2Ccsid = 13488; + } + else if (strncmp(fieldCharSet->name, "utf8_", sizeof("utf8_")) == 0 && + strcmp(fieldCharSet->name, "utf8_general_ci") != 0) + { + sprintf(stringBuildBuffer, "VARCHAR(%d)", max(fieldLength, 1)); // Number of bytes + db2Ccsid = 1208; + } + else + { + sprintf(stringBuildBuffer, "VARGRAPHIC(%d)", max(fieldLength / fieldCharSet->mbmaxlen, 1)); // Number of characters + db2Ccsid = 1200; + } + } + else + { + sprintf(stringBuildBuffer, "VARCHAR(%d)", max(fieldLength, 1)); + } + } + else if (blobMapping == AS_VARCHAR && + get_blob_type_from_length(fieldLength) == MYSQL_TYPE_BLOB) + { + if (fieldCharSet->mbmaxlen > 1) + { + if (strncmp(fieldCharSet->name, "ucs2_", sizeof("ucs2_")) == 0 ) // UCS2 + { + sprintf(stringBuildBuffer, "LONG VARGRAPHIC "); + db2Ccsid = 13488; + } + else if (strncmp(fieldCharSet->name, "utf8_", sizeof("utf8_")) == 0 && + strcmp(fieldCharSet->name, "utf8_general_ci") != 0) + { + sprintf(stringBuildBuffer, "LONG VARCHAR "); + db2Ccsid = 1208; + } + else + { + sprintf(stringBuildBuffer, "LONG VARGRAPHIC "); + db2Ccsid = 1200; + } + } + else + { + sprintf(stringBuildBuffer, "LONG VARCHAR "); + } + } + else + { + fieldLength = min(MAX_BLOB_LENGTH, fieldLength); + + if (fieldCharSet->mbmaxlen > 1) + { + if (strncmp(fieldCharSet->name, "ucs2_", sizeof("ucs2_")) == 0 ) // UCS2 + { + sprintf(stringBuildBuffer, "DBCLOB(%d)", max(fieldLength / fieldCharSet->mbmaxlen, 1)); // Number of characters + db2Ccsid = 13488; + } + else if (strncmp(fieldCharSet->name, "utf8_", sizeof("utf8_")) == 0 && + strcmp(fieldCharSet->name, "utf8_general_ci") != 0) + { + sprintf(stringBuildBuffer, "CLOB(%d)", max(fieldLength, 1)); // Number of bytes + db2Ccsid = 1208; + } + else + { + sprintf(stringBuildBuffer, "DBCLOB(%d)", max(fieldLength / fieldCharSet->mbmaxlen, 1)); // Number of characters + db2Ccsid = 1200; + } + } + else + { + sprintf(stringBuildBuffer, "CLOB(%d)", max(fieldLength, 1)); // Number of characters + } + } + + mapping.append(stringBuildBuffer); + } + if (db2Ccsid == 0) // If not overriding CCSID + { + int32 rtnCode = convertIANAToDb2Ccsid(fieldCharSet->csname, &db2Ccsid); + if (rtnCode) + return rtnCode; + } + sprintf(stringBuildBuffer, " CCSID %d ", db2Ccsid); + mapping.append(stringBuildBuffer); + } + } + } + break; + + } + + return 0; +} + + +/** + Convert MySQL field data into the equivalent DB2 format + + @param field The MySQL field to be converted + @param db2Field The corresponding DB2 field definition + @param db2Buf The buffer to receive the converted data + @param data NULL if field points to the correct data; otherwise, + the data to be converted (for use with keys) +*/ +int32 ha_ibmdb2i::convertMySQLtoDB2(Field* field, const DB2Field& db2Field, char* db2Buf, const uchar* data) +{ + enum_field_types fieldType = field->type(); + switch (fieldType) + { + case MYSQL_TYPE_NEWDECIMAL: + { + uint precision= ((Field_new_decimal*)field)->precision; + uint scale= field->decimals(); + uint db2Precision = min(precision, MAX_DEC_PRECISION); + uint truncationAmount = precision - db2Precision; + + if (scale >= truncationAmount) + { + String tempString(precision+2); + + if (data == NULL) + { + field->val_str((String*)&tempString, (String*)(NULL)); + } + else + { + field->val_str(&tempString, data); + } + const char* temp = tempString.ptr(); + char packed[32]; + memset(&packed, 0, sizeof(packed)); + + int bcdPos = db2Precision - (db2Precision % 2 ? 1 : 0); + bcdAssign(packed, bcdPos+1, (temp[0] == '-' ? 0xD : 0xF)); + + int strPos=tempString.length() - 1 - truncationAmount; + + for (;strPos >= 0 && bcdPos >= 0; strPos--) + { + if (my_isdigit(&my_charset_latin1, temp[strPos])) + { + bcdAssign(packed, bcdPos, temp[strPos]-'0'); + --bcdPos; + } + } + memcpy(db2Buf, &packed, (db2Precision/2)+1); + } + + } + break; + case MYSQL_TYPE_TINY: + { + int16 temp = (data == NULL ? field->val_int() : field->val_int(data)); + memcpy(db2Buf , &temp, sizeof(temp)); + } + break; + case MYSQL_TYPE_SHORT: + { + if (((Field_num*)field)->unsigned_flag) + { + memset(db2Buf, 0, 2); + memcpy(db2Buf+2, (data == NULL ? field->ptr : data), 2); + } + else + { + memcpy(db2Buf, (data == NULL ? field->ptr : data), 2); + } + } + break; + case MYSQL_TYPE_LONG: + { + if (((Field_num*)field)->unsigned_flag) + { + memset(db2Buf, 0, 4); + memcpy(db2Buf+4, (data == NULL ? field->ptr : data), 4); + } + else + { + memcpy(db2Buf, (data == NULL ? field->ptr : data), 4); + } + } + break; + case MYSQL_TYPE_FLOAT: + { + memcpy(db2Buf, (data == NULL ? field->ptr : data), 4); + } + break; + case MYSQL_TYPE_DOUBLE: + { + memcpy(db2Buf, (data == NULL ? field->ptr : data), 8); + } + break; + case MYSQL_TYPE_TIMESTAMP: + case MYSQL_TYPE_DATETIME: + { + String tempString(27); + const char* ZERO_VALUE = "0000-00-00 00:00:00"; + if (data == NULL) + { + field->val_str(&tempString, &tempString); + } + else + { + field->val_str(&tempString, data); + } + memset(db2Buf, '0', 26); + memcpy(db2Buf, tempString.ptr(), tempString.length()); + if (strncmp(db2Buf,ZERO_VALUE,strlen(ZERO_VALUE)) == 0) + { + getErrTxt(DB2I_ERR_INVALID_COL_VALUE,ZERO_VALUE,field->field_name); + return(DB2I_ERR_INVALID_COL_VALUE); + } + (db2Buf)[10] = '-'; + (db2Buf)[13] = (db2Buf)[16] = (db2Buf)[19] = '.'; + + convertNumericToEbcdicFast(db2Buf, 26); + } + break; + case MYSQL_TYPE_LONGLONG: + { + if (((Field_num*)field)->unsigned_flag) + { + char temp[23]; + String tempString(temp, sizeof(temp), &my_charset_latin1); + + if (data == NULL) + { + field->val_str((String*)&tempString, (String*)(NULL)); + } + else + { + field->val_str(&tempString, data); + } + char packed[11]; + memset(packed, 0, sizeof(packed)); + bcdAssign(packed, 21, (temp[0] == '-' ? 0xD : 0xF)); + int strPos=tempString.length()-1; + int bcdPos=20; + + for (;strPos >= 0; strPos--) + { + if (my_isdigit(&my_charset_latin1, temp[strPos])) + { + bcdAssign(packed, bcdPos, temp[strPos]-'0'); + --bcdPos; + } + } + memcpy(db2Buf, &packed, 11); + } + else + { + *(uint64*)db2Buf = *(uint64*)(data == NULL ? field->ptr : data); + } + } + break; + case MYSQL_TYPE_INT24: + { + int32 temp= (data == NULL ? field->val_int() : field->val_int(data)); + memcpy(db2Buf , &temp, sizeof(temp)); + } + break; + case MYSQL_TYPE_DATE: + case MYSQL_TYPE_NEWDATE: + { + const char* ZERO_VALUE = "0000-00-00"; + String tempString(11); + if (data == NULL) + { + field->val_str(&tempString, (String*)NULL); + } + else + { + field->val_str(&tempString, data); + } + memcpy(db2Buf, tempString.ptr(), 10); + if (strncmp(db2Buf,ZERO_VALUE,strlen(ZERO_VALUE)) == 0) + { + getErrTxt(DB2I_ERR_INVALID_COL_VALUE,ZERO_VALUE,field->field_name); + return(DB2I_ERR_INVALID_COL_VALUE); + } + + convertNumericToEbcdicFast(db2Buf,10); + } + break; + case MYSQL_TYPE_TIME: + { + if (db2Field.getType() == QMY_TIME) + { + String tempString(10); + if (data == NULL) + { + field->val_str(&tempString, (String*)NULL); + } + else + { + field->val_str(&tempString, data); + } + memcpy(db2Buf, tempString.ptr(), 8); + (db2Buf)[2]=(db2Buf)[5] = '.'; + + convertNumericToEbcdicFast(db2Buf, 8); + } + else + { + int32 temp = sint3korr(data == NULL ? field->ptr : data); + memcpy(db2Buf, &temp, sizeof(temp)); + } + } + break; + case MYSQL_TYPE_YEAR: + { + String tempString(5); + if (data == NULL) + { + field->val_str(&tempString, (String*)NULL); + } + else + { + field->val_str(&tempString, data); + } + memcpy(db2Buf, tempString.ptr(), 4); + } + break; + case MYSQL_TYPE_BIT: + { + int bytesToCopy = (db2Field.getByteLengthInRecord()-1) / 8 + 1; + + if (data == NULL) + { + uint64 temp = field->val_int(); + memcpy(db2Buf, + ((char*)&temp) + (sizeof(temp) - bytesToCopy), + bytesToCopy); + } + else + { + memcpy(db2Buf, + data, + bytesToCopy); + } + } + break; + case MYSQL_TYPE_VARCHAR: + case MYSQL_TYPE_STRING: + case MYSQL_TYPE_BLOB: + { + if (field->real_type() == MYSQL_TYPE_ENUM || + field->real_type() == MYSQL_TYPE_SET) + { + int64 temp= (data == NULL ? field->val_int() : field->val_int(data)); + *(int64*)db2Buf = temp; + } + else + { + const uchar* dataToStore; + uint32 bytesToStore; + uint32 bytesToPad = 0; + CHARSET_INFO* fieldCharSet = field->charset(); + uint32 maxDisplayLength = field->max_display_length(); + switch (fieldType) + { + case MYSQL_TYPE_STRING: + { + bytesToStore = maxDisplayLength; + if (data == NULL) + dataToStore = field->ptr; + else + dataToStore = data; + } + break; + case MYSQL_TYPE_VARCHAR: + { + + if (data == NULL) + { + bytesToStore = field->data_length(); + dataToStore = field->ptr + ((Field_varstring*)field)->length_bytes; + } + else + { + // Key lens are stored little-endian + bytesToStore = *(uint8*)data + ((*(uint8*)(data+1)) << 8); + dataToStore = data + 2; + } + bytesToPad = maxDisplayLength - bytesToStore; + } + break; + case MYSQL_TYPE_BLOB: + { + DBUG_ASSERT(data == NULL); + bytesToStore = ((Field_blob*)field)->get_length(); + bytesToPad = maxDisplayLength - bytesToStore; + ((Field_blob*)field)->get_ptr((uchar**)&dataToStore); + } + break; + } + + int32 rc; + uint16 db2FieldType = db2Field.getType(); + switch(db2FieldType) + { + case QMY_CHAR: + if (maxDisplayLength == 0) + bytesToPad = 1; + case QMY_VARCHAR: + if (db2FieldType == QMY_VARCHAR) + { + db2Buf += sizeof(uint16); + bytesToPad = 0; + } + + if (bytesToStore > db2Field.getDataLengthInRecord()) + { + bytesToStore = db2Field.getDataLengthInRecord(); + field->set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, WARN_DATA_TRUNCATED, 1); + } + + if (fieldCharSet == &my_charset_bin) // If binary + { + if (bytesToStore) + memcpy(db2Buf, dataToStore, bytesToStore); + if (bytesToPad) + memset(db2Buf + bytesToStore, 0x00, bytesToPad); + } + else if (db2Field.getCCSID() == 1208) // utf8 + { + if (bytesToStore) + memcpy(db2Buf, dataToStore, bytesToStore); + if (bytesToPad) + memset(db2Buf + bytesToStore, ' ', bytesToPad); + } + else // single-byte ASCII to EBCDIC + { + DBUG_ASSERT(fieldCharSet->mbmaxlen == 1); + if (bytesToStore) + { + rc = convertFieldChars(toDB2, field->field_index, (char*)dataToStore, db2Buf, bytesToStore, bytesToStore, NULL); + if (rc) + return rc; + } + if (bytesToPad) + memset(db2Buf + bytesToStore, 0x40, bytesToPad); + } + + if (db2FieldType == QMY_VARCHAR) + *(uint16*)(db2Buf - sizeof(uint16)) = bytesToStore; + break; + case QMY_VARGRAPHIC: + db2Buf += sizeof(uint16); + bytesToPad = 0; + case QMY_GRAPHIC: + if (maxDisplayLength == 0 && db2FieldType == QMY_GRAPHIC) + bytesToPad = 2; + + if (db2Field.getCCSID() == 13488) + { + if (bytesToStore) + memcpy(db2Buf, dataToStore, bytesToStore); + if (bytesToPad) + wmemset((wchar_t*)(db2Buf + bytesToStore), 0x0020, bytesToPad/2); + } + else + { + size_t db2BytesToStore; + size_t maxDb2BytesToStore; + + if (maxDisplayLength == 0 && db2FieldType == QMY_GRAPHIC) + maxDb2BytesToStore = 2; + else + maxDb2BytesToStore = min(((bytesToStore * 2) / fieldCharSet->mbminlen), + ((maxDisplayLength * 2) / fieldCharSet->mbmaxlen)); + + if (bytesToStore == 0) + db2BytesToStore = 0; + else + { + rc = convertFieldChars(toDB2, field->field_index, (char*)dataToStore, db2Buf, bytesToStore, maxDb2BytesToStore, &db2BytesToStore); + if (rc) + return rc; + bytesToStore = db2BytesToStore; + } + if (db2BytesToStore < maxDb2BytesToStore) // If need to pad + wmemset((wchar_t*)(db2Buf + db2BytesToStore), 0x0020, (maxDb2BytesToStore - db2BytesToStore)/2); + } + + if (db2FieldType == QMY_VARGRAPHIC) + *(uint16*)(db2Buf-sizeof(uint16)) = bytesToStore/2; + break; + case QMY_BLOBCLOB: + case QMY_DBCLOB: + { + DBUG_ASSERT(data == NULL); + DB2LobField* lobField = (DB2LobField*)(db2Buf + db2Field.calcBlobPad()); + + if ((fieldCharSet == &my_charset_bin) || // binary or + (db2Field.getCCSID()==13488) || + (db2Field.getCCSID()==1208)) // binary UTF8 + { + } + else + { + char* temp; + int32 rc; + size_t db2BytesToStore; + if (fieldCharSet->mbmaxlen == 1) // single-byte ASCII to EBCDIC + { + temp = getCharacterConversionBuffer(field->field_index, bytesToStore); + rc = convertFieldChars(toDB2, field->field_index, (char*)dataToStore,temp,bytesToStore, bytesToStore, NULL); + if (rc) + return (rc); + } + else // Else Far East, special UTF8 or non-special UTF8/UCS2 + { + size_t maxDb2BytesToStore; + maxDb2BytesToStore = min(((bytesToStore * 2) / fieldCharSet->mbminlen), + ((maxDisplayLength * 2) / fieldCharSet->mbmaxlen)); + temp = getCharacterConversionBuffer(field->field_index, maxDb2BytesToStore); + rc = convertFieldChars(toDB2, field->field_index, (char*)dataToStore,temp,bytesToStore, maxDb2BytesToStore, &db2BytesToStore); + if (rc) + return (rc); + bytesToStore = db2BytesToStore; + } + dataToStore = (uchar*)temp; + } + + uint16 blobID = db2Table->getBlobIdFromField(field->field_index); + if (blobWriteBuffers[blobID] != (char*)dataToStore) + blobWriteBuffers[blobID].reassign((char*)dataToStore); + if ((void*)blobWriteBuffers[blobID]) + lobField->dataHandle = (ILEMemHandle)blobWriteBuffers[blobID]; + else + lobField->dataHandle = 0; + lobField->length = bytesToStore / (db2FieldType == QMY_DBCLOB ? 2 : 1); + } + break; + } + } + } + break; + default: + DBUG_ASSERT(0); + break; + } + + return (ha_thd()->is_error()); +} + + +/** + Convert DB2 field data into the equivalent MySQL format + + @param db2Field The DB2 field definition + @param field The MySQL field to receive the converted data + @param buf The DB2 data to be converted +*/ +int32 ha_ibmdb2i::convertDB2toMySQL(const DB2Field& db2Field, Field* field, const char* buf) +{ + int32 storeRC = 0; // Result of the field->store() operation + + const char* bufPtr = buf + db2Field.getBufferOffset(); + + switch (field->type()) + { + case MYSQL_TYPE_NEWDECIMAL: + { + uint precision= ((Field_new_decimal*)field)->precision; + uint scale= field->decimals(); + uint db2Precision = min(precision, MAX_DEC_PRECISION); + uint decimalPlace = precision-scale+1; + char temp[80]; + + if (precision <= MAX_DEC_PRECISION || + scale > precision - MAX_DEC_PRECISION) + { + uint numNibbles = db2Precision + (db2Precision % 2 ? 0 : 1); + + temp[0] = (bcdGet(bufPtr, numNibbles) == 0xD ? '-' : ' '); + int strPos=1; + int bcdPos=(db2Precision % 2 ? 0 : 1); + + for (;bcdPos < numNibbles; bcdPos++, strPos++) + { + if (strPos == decimalPlace) + { + temp[strPos] = '.'; + strPos++; + } + + temp[strPos] = bcdGet(bufPtr, bcdPos) + '0'; + } + + temp[strPos] = 0; + + storeRC = field->store(temp, strPos, &my_charset_latin1); + } + } + break; + case MYSQL_TYPE_TINY: + { + storeRC = field->store(*(int16*)bufPtr, ((Field_num*)field)->unsigned_flag); + } + break; + case MYSQL_TYPE_SHORT: + { + if (((Field_num*)field)->unsigned_flag) + { + storeRC = field->store(*(int32*)bufPtr, TRUE); + } + else + { + storeRC = field->store(*(int16*)bufPtr, FALSE); + } + } + break; + case MYSQL_TYPE_LONG: + { + if (((Field_num*)field)->unsigned_flag) + { + storeRC = field->store(*(int64*)bufPtr, TRUE); + } + else + { + storeRC = field->store(*(int32*)bufPtr, FALSE); + } + } + break; + case MYSQL_TYPE_FLOAT: + { + storeRC = field->store(*(float*)bufPtr); + } + break; + case MYSQL_TYPE_DOUBLE: + { + storeRC = field->store(*(double*)bufPtr); + } + break; + case MYSQL_TYPE_LONGLONG: + { + char temp[23]; + if (((Field_num*)field)->unsigned_flag) + { + temp[0] = (bcdGet(bufPtr, 21) == 0xD ? '-' : ' '); + int strPos=1; + int bcdPos=0; + + for (;bcdPos <= 20; bcdPos++, strPos++) + { + temp[strPos] = bcdGet(bufPtr, bcdPos) + '0'; + } + + temp[strPos] = 0; + + storeRC = field->store(temp, strPos, &my_charset_latin1); + } + else + { + storeRC = field->store(*(int64*)bufPtr, FALSE); + } + } + break; + case MYSQL_TYPE_INT24: + { + storeRC = field->store(*(int32*)bufPtr, ((Field_num*)field)->unsigned_flag); + } + break; + case MYSQL_TYPE_DATE: + case MYSQL_TYPE_NEWDATE: + { + longlong value= a4toi_ebcdic((uchar*)bufPtr) * 10000 + + a2toi_ebcdic((uchar*)bufPtr+5) * 100 + + a2toi_ebcdic((uchar*)bufPtr+8); + + storeRC = field->store(value); + } + break; + case MYSQL_TYPE_TIME: + { + if (db2Field.getType() == QMY_TIME) + { + longlong value= a2toi_ebcdic((uchar*)bufPtr) * 10000 + + a2toi_ebcdic((uchar*)bufPtr+3) * 100 + + a2toi_ebcdic((uchar*)bufPtr+6); + + storeRC = field->store(value); + } + else + storeRC = field->store(*((int32*)bufPtr)); + } + break; + case MYSQL_TYPE_TIMESTAMP: + case MYSQL_TYPE_DATETIME: + { + longlong value= (a4toi_ebcdic((uchar*)bufPtr) * 10000 + + a2toi_ebcdic((uchar*)bufPtr+5) * 100 + + a2toi_ebcdic((uchar*)bufPtr+8)) * 1000000LL + + (a2toi_ebcdic((uchar*)bufPtr+11) * 10000 + + a2toi_ebcdic((uchar*)bufPtr+14) * 100 + + a2toi_ebcdic((uchar*)bufPtr+17)); + + storeRC = field->store(value); + } + break; + case MYSQL_TYPE_YEAR: + { + storeRC = field->store(bufPtr, 4, &my_charset_bin); + } + break; + case MYSQL_TYPE_BIT: + { + uint64 temp= 0; + int bytesToCopy= (db2Field.getByteLengthInRecord()-1) / 8 + 1; + memcpy(((char*)&temp) + (sizeof(temp) - bytesToCopy), bufPtr, bytesToCopy); + storeRC = field->store(temp, TRUE); + } + break; + case MYSQL_TYPE_VARCHAR: + case MYSQL_TYPE_STRING: + case MYSQL_TYPE_BLOB: + { + if (field->real_type() == MYSQL_TYPE_ENUM || + field->real_type() == MYSQL_TYPE_SET) + { + storeRC = field->store(*(int64*)bufPtr); + } + else + { + + const char* dataToStore = NULL; + uint32 bytesToStore = 0; + CHARSET_INFO* fieldCharSet = field->charset(); + switch(db2Field.getType()) + { + case QMY_CHAR: + case QMY_GRAPHIC: + { + bytesToStore = db2Field.getByteLengthInRecord(); + if (bytesToStore == 0) + bytesToStore = 1; + dataToStore = bufPtr; + } + break; + case QMY_VARCHAR: + { + bytesToStore = *(uint16*)bufPtr; + dataToStore = bufPtr+sizeof(uint16); + } + break; + case QMY_VARGRAPHIC: + { + /* For VARGRAPHIC, convert the number of double-byte characters + to the number of bytes. */ + bytesToStore = (*(uint16*)bufPtr)*2; + dataToStore = bufPtr+sizeof(uint16); + } + break; + case QMY_DBCLOB: + case QMY_BLOBCLOB: + { + DB2LobField* lobField = (DB2LobField* )(bufPtr + db2Field.calcBlobPad()); + bytesToStore = lobField->length * (db2Field.getType() == QMY_DBCLOB ? 2 : 1); + dataToStore = (char*)blobReadBuffers->getBufferPtr(field->field_index); + } + break; + + } + + if ((fieldCharSet != &my_charset_bin) && // not binary & + (db2Field.getCCSID() != 13488) && // not UCS2 & + (db2Field.getCCSID() != 1208)) + { + char* temp; + size_t db2BytesToStore; + int rc; + if (fieldCharSet->mbmaxlen > 1) + { + size_t maxDb2BytesToStore = ((bytesToStore / 2) * fieldCharSet->mbmaxlen); // Worst case for number of bytes + temp = getCharacterConversionBuffer(field->field_index, maxDb2BytesToStore); + rc = convertFieldChars(toMySQL, field->field_index, dataToStore, temp, bytesToStore, maxDb2BytesToStore, &db2BytesToStore); + bytesToStore = db2BytesToStore; + } + else // single-byte ASCII to EBCDIC + { + temp = getCharacterConversionBuffer(field->field_index, bytesToStore); + rc = convertFieldChars(toMySQL, field->field_index, dataToStore, temp, bytesToStore, bytesToStore, NULL); + } + if (rc) + return (rc); + dataToStore = temp; + } + + if ((field)->flags & BLOB_FLAG) + ((Field_blob*)(field))->set_ptr(bytesToStore, (uchar*)dataToStore); + else + storeRC = field->store(dataToStore, bytesToStore, &my_charset_bin); + } + } + break; + default: + DBUG_ASSERT(0); + break; + + } + + if (storeRC) + { + invalidDataFound = true; + } + + return 0; +} diff --git a/storage/ibmdb2i/db2i_errors.cc b/storage/ibmdb2i/db2i_errors.cc new file mode 100644 index 00000000000..cb8b4986099 --- /dev/null +++ b/storage/ibmdb2i/db2i_errors.cc @@ -0,0 +1,296 @@ +/* +Licensed Materials - Property of IBM +DB2 Storage Engine Enablement +Copyright IBM Corporation 2007,2008 +All rights reserved + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + (a) Redistributions of source code must retain this list of conditions, the + copyright notice in section {d} below, and the disclaimer following this + list of conditions. + (b) Redistributions in binary form must reproduce this list of conditions, the + copyright notice in section (d) below, and the disclaimer following this + list of conditions, in the documentation and/or other materials provided + with the distribution. + (c) The name of IBM may not be used to endorse or promote products derived from + this software without specific prior written permission. + (d) The text of the required copyright notice is: + Licensed Materials - Property of IBM + DB2 Storage Engine Enablement + Copyright IBM Corporation 2007,2008 + All rights reserved + +THIS SOFTWARE IS PROVIDED BY IBM CORPORATION "AS IS" AND ANY EXPRESS OR IMPLIED +WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT +SHALL IBM CORPORATION BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT +OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT INCLUDING NEGLIGENCE OR OTHERWISE) ARISING +IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + + +#include "db2i_errors.h" +#include "db2i_ileBridge.h" +#include "db2i_charsetSupport.h" +#include "mysql_priv.h" +#include "stdarg.h" + +#define MAX_MSGSTRING 109 + +/* + The following strings are associated with errors that can be produced + within the storage engine proper. +*/ +static const char* engineErrors[MAX_MSGSTRING] = +{ + {""}, + {"Error opening codeset conversion from %.64s to %.64s (errno = %d)"}, + {"Invalid %-.10s name '%-.128s'"}, + {"Unsupported move from '%-.128s' to '%-.128s' on RENAME TABLE statement"}, + {"Unsupported schema '%-.128s' specified on RENAME TABLE statement"}, + {"Auto_increment is not allowed for a partitioned table"}, + {"Character set conversion error due to unknown encoding scheme %d"}, + {""}, + {"Table '%-.128s' was not found by the storage engine"}, + {"Could not resolve to %-.128s in library %-.10s type %-.10s (errno = %d)"}, + {"Error on _PGMCALL for program %-.10s in library %-.10s (error = %d)"}, + {"Error on _ILECALL for API '%.128s' (error = %d)"}, + {"Error in iconv() function during character set conversion (errno = %d)"}, + {"Error from Get Encoding Scheme (QTQGESP) API: %d, %d, %d"}, + {"Error from Get Related Default CCSID (QTQGRDC) API: %d, %d, %d"}, + {"Invalid value '%-.128s' for column '%.192s'"}, + {"Schema name '%.128s' exceeds maximum length of %d characters"}, + {"Multiple collations not supported in a single index"}, + {"Sort sequence was not found"}, + {"One or more characters in column %.128s were substituted during conversion"}, + {"A decimal column exceeded the maximum precision. Data may be truncated."}, + {"Some data returned by DB2 for table %s could not be converted for MySQL"}, + {""}, + {"Column %.128s contains characters that cannot be converted"}, + {"An invalid name was specified for ibmdb2i_rdb_name."}, + {"A duplicate key was encountered for index '%.128s'"}, + {"A table with the same name exists but has incompatible column definitions."}, + {"The created table was discovered as an existing DB2 object."}, +}; + +/* + The following strings are associated with errors that can be returned + by the operating system via the QMY_* APIs. Most are very uncommon and + indicate a bug somewhere. +*/ +static const char* systemErrors[MAX_MSGSTRING] = +{ + {"Thread ID is too long"}, + {"Error creating a SPACE memory object"}, + {"Error creating a FILE memory object"}, + {"Error creating a SPACE synchronization token"}, + {"Error creating a FILE synchronization token"}, + {"See message %-.7s in joblog for job %-.6s/%-.10s/%-.10s."}, + {"Error unlocking a synchronization token when closing a connection"}, + {"Invalid action specified for an 'object lock' request"}, + {"Invalid action specified for a savepoint request"}, + {"Partial keys are not supported with an ICU sort sequence"}, + {"Error retrieving an ICU sort key"}, + {"Error converting single-byte sort sequence to UCS-2"}, + {"An unsupported collation was specified"}, + {"Validation failed for referenced table of foreign key constraint"}, + {"Error extracting table for constraint information"}, + {"Error extracting referenced table for constraint information"}, + {"Invalid action specified for a 'commitment control' request"}, + {"Invalid commitment control isolation level specified on 'open' request"}, + {"Invalid file handle"}, + {" "}, + {"Invalid option specified for returning data on 'read' request"}, + {"Invalid orientation specified for 'read' request"}, + {"Invalid option type specified for 'read' request"}, + {"Invalid isolation level for starting commitment control"}, + {"Error unlocking a synchronization token in module QMYALC"}, + {"Length of space for returned format is not long enough"}, + {"SQL XA transactions are currently unsupported by this interface"}, + {"The associated QSQSRVR job was killed or ended unexpectedly."}, + {"Error unlocking a synchronization token in module QMYSEI"}, + {"Error unlocking a synchronization token in module QMYSPO"}, + {"Error converting input CCSID from short form to long form"}, + {" "}, + {"Error getting associated CCSID for CCSID conversion"}, + {"Error converting a string from one CCSID to another"}, + {"Error unlocking a synchronization token"}, + {"Error destroying a synchronization token"}, + {"Error locking a synchronization token"}, + {"Error recreating a synchronization token"}, + {"A space handle was not specified for a constraint request"}, + {"An SQL cursor was specified for a delete request"}, + {" "}, + {"Error on delete request because current UFCB for connection is not open"}, + {"An SQL cursor was specified for an object initialization request"}, + {"An SQL cursor was specified for an object override request"}, + {"A space handle was not specified for an object override request"}, + {"An SQL cursor was specified for an information request"}, + {"An SQL cursor was specified for an object lock request"}, + {"An SQL cursor was specified for an optimize request"}, + {"A data handle was not specified for a read request"}, + {"A row number handle was not specified for a read request"}, + {"A key handle was not specified for a read request"}, + {"An SQL cursor was specified for an row estimation request"}, + {"A space handle was not specified for a row estimation request"}, + {"An SQL cursor was specified for a release record request"}, + {"A statement handle was not specified for an 'execute immediate' request"}, + {"A statement handle was not specified for a 'prepare open' request"}, + {"An SQL cursor was specified for an update request"}, + {"The UFCB was not open for read"}, + {"Error on update request because current UFCB for connection is not open"}, + {"A data handle was not specified for an update request"}, + {"An SQL cursor was specified for a write request"}, + {"A data handle was not specified for a write request"}, + {"An unknown function was specified on a process request"}, + {"A share definition was not specified for an 'allocate share' request"}, + {"A share handle was not specified for an 'allocate share' request"}, + {"A use count handle was not specified for an 'allocate share' request"}, + {"A 'records per key' handle was not specified for an information request"}, + {"Error resolving LOB addresss"}, + {"Length of a LOB space is too small"}, + {"An unknown function was specified for a server request"}, + {"Object authorization failed. See message %-.7s in joblog for job %-.6s/%-.10s/%-.10s. for more information."}, + {" "}, + {"Error locking mutex on server"}, + {"Error unlocking mutex on server"}, + {"Error checking for RDB name in RDB Directory"}, + {"Error creating mutex on server"}, + {"A table with that name already exists"}, + {" "}, + {"Error unlocking mutex"}, + {"Error connecting to server job"}, + {"Error connecting to server job"}, + {" "}, + {"Function check occurred while registering parameter spaces. See joblog."}, + {" "}, + {" "}, + {"End of block"}, + {"The file has changed and might not be compatible with the MySQL table definition"}, + {"Error giving pipe to server job"}, + {"There are open object locks when attempting to deallocate"}, + {"There is no open lock"}, + {" "}, + {" "}, + {"The maximum value for the auto_increment data type was exceeded"}, + {"Error occurred closing the pipe "}, + {"Error occurred taking a descriptor for the pipe"}, + {"Error writing to pipe "}, + {"Server was interrupted "}, + {"No pipe descriptor exists for reuse "}, + {"Error occurred during an SQL prepare statement "}, + {"Error occurred during an SQL open "}, + {" "}, + {" "}, + {" "}, + {" "}, + {" "}, + {" "}, + {"An unspecified error was returned from the system."}, + {" "} +}; + +/** + This function builds the text string for an error code, and substitutes + a variable number of replacement variables into the string. +*/ +void getErrTxt(int errCode, ...) +{ + va_list args; + va_start(args,errCode); + char* buffer = db2i_ileBridge::getBridgeForThread()->getErrorStorage(); + const char* msg; + + if (errCode >= QMY_ERR_MIN && errCode <= QMY_ERR_SQ_OPEN) + msg = systemErrors[errCode - QMY_ERR_MIN]; + else + { + DBUG_ASSERT(errCode >= DB2I_FIRST_ERR && errCode <= DB2I_LAST_ERR); + msg = engineErrors[errCode - DB2I_FIRST_ERR]; + } + + (void) my_vsnprintf (buffer, MYSQL_ERRMSG_SIZE, msg, args); + va_end(args); + fprintf(stderr,"ibmdb2i error %d: %s\n",errCode,buffer); + DBUG_PRINT("error", ("ibmdb2i error %d: %s",errCode,buffer)); +} + +static inline void trimSpace(char* str) +{ + char* end = strchr(str, ' '); + if (end) *end = 0; +} + + +/** + Generate the error text specific to an API error returned by a QMY_* API. + + @parm errCode The error value + @parm errInfo The structure containing the message and job identifiers. +*/ +void reportSystemAPIError(int errCode, const Qmy_Error_output *errInfo) +{ + if (errCode >= QMY_ERR_MIN && errCode <= QMY_ERR_SQ_OPEN) + { + switch(errCode) + { + case QMY_ERR_MSGID: + case QMY_ERR_NOT_AUTH: + { + DBUG_ASSERT(errInfo); + char jMsg[8]; // Error message ID + char jName[11]; // Job name + char jUser[11]; // Job user + char jNbr[7]; // Job number + memset(jMsg, 0, sizeof(jMsg)); + memset(jName, 0, sizeof(jMsg)); + memset(jUser, 0, sizeof(jMsg)); + memset(jMsg, 0, sizeof(jMsg)); + + convFromEbcdic(errInfo->MsgId,jMsg,sizeof(jMsg)-1); + convFromEbcdic(errInfo->JobName,jName,sizeof(jName)-1); + trimSpace(jName); + convFromEbcdic(errInfo->JobUser,jUser,sizeof(jUser)-1); + trimSpace(jUser); + convFromEbcdic(errInfo->JobNbr,jNbr,sizeof(jNbr)-1); + getErrTxt(errCode,jMsg,jNbr,jUser,jName); + } + break; + case QMY_ERR_RTNFMT: + { + getErrTxt(QMY_ERR_LVLID_MISMATCH); + } + break; + default: + getErrTxt(errCode); + break; + } + } +} + + +/** + Generate a warning for the specified error. +*/ +void warning(THD *thd, int errCode, ...) +{ + va_list args; + va_start(args,errCode); + char buffer[MYSQL_ERRMSG_SIZE]; + const char* msg; + + DBUG_ASSERT(errCode >= DB2I_FIRST_ERR && errCode <= DB2I_LAST_ERR); + msg = engineErrors[errCode - DB2I_FIRST_ERR]; + + (void) my_vsnprintf (buffer, MYSQL_ERRMSG_SIZE, msg, args); + va_end(args); + DBUG_PRINT("warning", ("ibmdb2i warning %d: %s",errCode,buffer)); + push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, errCode, buffer); +} + + diff --git a/storage/ibmdb2i/db2i_errors.h b/storage/ibmdb2i/db2i_errors.h new file mode 100644 index 00000000000..9be2364a7b5 --- /dev/null +++ b/storage/ibmdb2i/db2i_errors.h @@ -0,0 +1,91 @@ +/* +Licensed Materials - Property of IBM +DB2 Storage Engine Enablement +Copyright IBM Corporation 2007,2008 +All rights reserved + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + (a) Redistributions of source code must retain this list of conditions, the + copyright notice in section {d} below, and the disclaimer following this + list of conditions. + (b) Redistributions in binary form must reproduce this list of conditions, the + copyright notice in section (d) below, and the disclaimer following this + list of conditions, in the documentation and/or other materials provided + with the distribution. + (c) The name of IBM may not be used to endorse or promote products derived from + this software without specific prior written permission. + (d) The text of the required copyright notice is: + Licensed Materials - Property of IBM + DB2 Storage Engine Enablement + Copyright IBM Corporation 2007,2008 + All rights reserved + +THIS SOFTWARE IS PROVIDED BY IBM CORPORATION "AS IS" AND ANY EXPRESS OR IMPLIED +WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT +SHALL IBM CORPORATION BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT +OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT INCLUDING NEGLIGENCE OR OTHERWISE) ARISING +IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + + +#ifndef DB2I_ERRORS_H +#define DB2I_ERRORS_H + +#include "qmyse.h" +class THD; + +/** + @enum DB2I_errors + + @brief These are the errors that can be returned by the storage engine proper + and that are specific to the engine. Refer to db2i_errors.cc for text + descriptions of the errors. +*/ + +enum DB2I_errors +{ + DB2I_FIRST_ERR = 2500, + DB2I_ERR_ICONV_OPEN, + DB2I_ERR_INVALID_NAME, + DB2I_ERR_RENAME_MOVE, + DB2I_ERR_RENAME_QTEMP, + DB2I_ERR_PART_AUTOINC, + DB2I_ERR_UNKNOWN_ENCODING, + DB2I_ERR_RESERVED, + DB2I_ERR_TABLE_NOT_FOUND, + DB2I_ERR_RESOLVE_OBJ, + DB2I_ERR_PGMCALL, + DB2I_ERR_ILECALL, + DB2I_ERR_ICONV, + DB2I_ERR_QTQGESP, + DB2I_ERR_QTQGRDC, + DB2I_ERR_INVALID_COL_VALUE, + DB2I_ERR_TOO_LONG_SCHEMA, + DB2I_ERR_MIXED_COLLATIONS, + DB2I_ERR_SRTSEQ, + DB2I_ERR_SUB_CHARS, + DB2I_ERR_PRECISION, + DB2I_ERR_INVALID_DATA, + DB2I_ERR_RESERVED2, + DB2I_ERR_ILL_CHAR, + DB2I_ERR_BAD_RDB_NAME, + DB2I_ERR_UNKNOWN_IDX, + DB2I_ERR_DISCOVERY_MISMATCH, + DB2I_ERR_WARN_CREATE_DISCOVER, + DB2I_LAST_ERR = DB2I_ERR_WARN_CREATE_DISCOVER +}; + +void getErrTxt(int errcode, ...); +void reportSystemAPIError(int errCode, const Qmy_Error_output *errInfo); +void warning(THD *thd, int errCode, ...); + +const char* DB2I_SQL0350 = "\xE2\xD8\xD3\xF0\xF3\xF5\xF0"; // SQL0350 in EBCDIC + + +#endif diff --git a/storage/ibmdb2i/db2i_file.cc b/storage/ibmdb2i/db2i_file.cc new file mode 100644 index 00000000000..2ce78f18d21 --- /dev/null +++ b/storage/ibmdb2i/db2i_file.cc @@ -0,0 +1,513 @@ +/* +Licensed Materials - Property of IBM +DB2 Storage Engine Enablement +Copyright IBM Corporation 2007,2008 +All rights reserved + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + (a) Redistributions of source code must retain this list of conditions, the + copyright notice in section {d} below, and the disclaimer following this + list of conditions. + (b) Redistributions in binary form must reproduce this list of conditions, the + copyright notice in section (d) below, and the disclaimer following this + list of conditions, in the documentation and/or other materials provided + with the distribution. + (c) The name of IBM may not be used to endorse or promote products derived from + this software without specific prior written permission. + (d) The text of the required copyright notice is: + Licensed Materials - Property of IBM + DB2 Storage Engine Enablement + Copyright IBM Corporation 2007,2008 + All rights reserved + +THIS SOFTWARE IS PROVIDED BY IBM CORPORATION "AS IS" AND ANY EXPRESS OR IMPLIED +WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT +SHALL IBM CORPORATION BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT +OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT INCLUDING NEGLIGENCE OR OTHERWISE) ARISING +IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + + + +#include "db2i_file.h" +#include "db2i_charsetSupport.h" +#include "db2i_collationSupport.h" +#include "db2i_misc.h" +#include "db2i_errors.h" +#include "my_dir.h" + +db2i_table::db2i_table(const TABLE_SHARE* myTable, const char* path) : + mysqlTable(myTable), + db2StartId(0), + blobFieldCount(0), + blobFields(NULL), + blobFieldActualSizes(NULL), + logicalFiles(NULL), + physicalFile(NULL), + db2TableNameSQLAscii(NULL), + db2LibNameSQLAscii(NULL) +{ + char asciiLibName[MAX_DB2_SCHEMANAME_LENGTH + 1]; + getDB2LibNameFromPath(path, asciiLibName, ASCII_NATIVE); + + char asciiFileName[MAX_DB2_FILENAME_LENGTH + 1]; + getDB2FileNameFromPath(path, asciiFileName, ASCII_NATIVE); + + size_t libNameLen = strlen(asciiLibName); + size_t fileNameLen = strlen(asciiFileName); + + db2LibNameEbcdic=(char *) + my_multi_malloc(MYF(MY_WME | MY_ZEROFILL), + &db2LibNameEbcdic, libNameLen+1, + &db2LibNameAscii, libNameLen+1, + &db2LibNameSQLAscii, libNameLen*2 + 1, + &db2TableNameEbcdic, fileNameLen+1, + &db2TableNameAscii, fileNameLen+1, + &db2TableNameSQLAscii, fileNameLen*2 + 1, + NullS); + + if (likely(db2LibNameEbcdic)) + { + memcpy(db2LibNameAscii, asciiLibName, libNameLen); + convertNativeToSQLName(db2LibNameAscii, db2LibNameSQLAscii); + convToEbcdic(db2LibNameAscii, db2LibNameEbcdic, libNameLen); + memcpy(db2TableNameAscii, asciiFileName, fileNameLen); + convertNativeToSQLName(db2TableNameAscii, db2TableNameSQLAscii); + convToEbcdic(db2TableNameAscii, db2TableNameEbcdic, fileNameLen); + } + + conversionDefinitions[toMySQL] = NULL; + conversionDefinitions[toDB2] = NULL; + + isTemporaryTable = (strstr(mysqlTable->path.str, mysql_tmpdir) == mysqlTable->path.str); +} + + +int32 db2i_table::initDB2Objects(const char* path) +{ + uint fileObjects = 1 + mysqlTable->keys; + ValidatedPointer fileDefnSpace(sizeof(ShrDef) * fileObjects); + + physicalFile = new db2i_file(this); + physicalFile->fillILEDefn(&fileDefnSpace[0], true); + + if (fileObjects > 1) + { + logicalFiles = new db2i_file*[fileObjects - 1]; + for (int k = 0; k < mysqlTable->keys; k++) + { + logicalFiles[k] = new db2i_file(this, k); + logicalFiles[k]->fillILEDefn(&fileDefnSpace[k+1], false); + } + } + + ValidatedPointer fileDefnHandles(sizeof(FILE_HANDLE) * fileObjects); + size_t formatSpaceLen = sizeof(format_hdr_t) + mysqlTable->fields * sizeof(DB2Field); + formatSpace.alloc(formatSpaceLen); + + int rc = db2i_ileBridge::getBridgeForThread()->allocateFileDefn(fileDefnSpace, + fileDefnHandles, + fileObjects, + db2LibNameEbcdic, + strlen(db2LibNameEbcdic), + formatSpace, + formatSpaceLen); + + if (rc) + return rc; + + convFromEbcdic(((format_hdr_t*)formatSpace)->FilLvlId, fileLevelID, sizeof(fileLevelID)); + + if (!doFileIDsMatch(path)) + { + getErrTxt(QMY_ERR_LVLID_MISMATCH); + return QMY_ERR_LVLID_MISMATCH; + } + + physicalFile->setMasterDefnHandle(fileDefnHandles[0]); + for (int k = 0; k < mysqlTable->keys; k++) + { + logicalFiles[k]->setMasterDefnHandle(fileDefnHandles[k+1]); + } + + db2StartId = (uint64)(((format_hdr_t*)formatSpace)->StartIdVal); + db2Fields = (DB2Field*)((char*)(void*)formatSpace + ((format_hdr_t*)formatSpace)->ColDefOff); + + uint fields = mysqlTable->fields; + for (int i = 0; i < fields; ++i) + { + if (db2Field(i).isBlob()) + { + blobFieldCount++; + } + } + + if (blobFieldCount) + { + blobFieldActualSizes = (uint*)my_multi_malloc(MYF(MY_WME | MY_ZEROFILL), + &blobFieldActualSizes, blobFieldCount * sizeof(uint), + &blobFields, blobFieldCount * sizeof(uint16), + NullS); + + int b = 0; + for (int i = 0; i < fields; ++i) + { + if (db2Field(i).isBlob()) + { + blobFields[b++] = i; + } + } + } + + my_multi_malloc(MYF(MY_WME), + &conversionDefinitions[toMySQL], fields * sizeof(iconv_t), + &conversionDefinitions[toDB2], fields * sizeof(iconv_t), + NullS); + for (int i = 0; i < fields; ++i) + { + conversionDefinitions[toMySQL][i] = (iconv_t)(-1); + conversionDefinitions[toDB2][i] = (iconv_t)(-1); + } + + return 0; +} + +int db2i_table::fastInitForCreate(const char* path) +{ + ValidatedPointer fileDefnSpace(sizeof(ShrDef)); + + physicalFile = new db2i_file(this); + physicalFile->fillILEDefn(fileDefnSpace, true); + + ValidatedPointer fileDefnHandles(sizeof(FILE_HANDLE)); + + size_t formatSpaceLen = sizeof(format_hdr_t) + + mysqlTable->fields * sizeof(DB2Field); + formatSpace.alloc(formatSpaceLen); + + int rc = db2i_ileBridge::getBridgeForThread()->allocateFileDefn(fileDefnSpace, + fileDefnHandles, + 1, + db2LibNameEbcdic, + strlen(db2LibNameEbcdic), + formatSpace, + formatSpaceLen); + + if (rc) + return rc; + + convFromEbcdic(((format_hdr_t*)formatSpace)->FilLvlId, fileLevelID, sizeof(fileLevelID)); + doFileIDsMatch(path); + + return 0; +} + +bool db2i_table::doFileIDsMatch(const char* path) +{ + char name_buff[FN_REFLEN]; + + fn_format(name_buff, path, "", FID_EXT, (MY_REPLACE_EXT | MY_UNPACK_FILENAME)); + + File fd = my_open(name_buff, O_RDONLY, MYF(0)); + + if (fd == -1) + { + if (errno == ENOENT) + { + fd = my_create(name_buff, 0, O_WRONLY, MYF(MY_WME)); + + if (fd == -1) + { + // TODO: Report errno here + return false; + } + my_write(fd, (uchar*)fileLevelID, sizeof(fileLevelID), MYF(MY_WME)); + my_close(fd, MYF(0)); + return true; + } + else + { + // TODO: Report errno here + return false; + } + } + + char diskFID[sizeof(fileLevelID)]; + + bool match = false; + + if (my_read(fd, (uchar*)diskFID, sizeof(diskFID), MYF(MY_WME)) == sizeof(diskFID) && + (memcmp(diskFID, fileLevelID, sizeof(diskFID)) == 0)) + match = true; + + my_close(fd, MYF(0)); + + return match; +} + +void db2i_table::deleteAssocFiles(const char* name) +{ + char name_buff[FN_REFLEN]; + fn_format(name_buff, name, "", FID_EXT, (MY_REPLACE_EXT | MY_UNPACK_FILENAME)); + my_delete(name_buff, MYF(0)); +} + +void db2i_table::renameAssocFiles(const char* from, const char* to) +{ + rename_file_ext(from, to, FID_EXT); +} + + +db2i_table::~db2i_table() +{ + if (blobFieldActualSizes) + my_free(blobFieldActualSizes, MYF(0)); + + if (conversionDefinitions[toMySQL]) + my_free(conversionDefinitions[toMySQL], MYF(0)); + + if (logicalFiles) + { + for (int k = 0; k < mysqlTable->keys; ++k) + { + delete logicalFiles[k]; + } + + delete[] logicalFiles; + } + delete physicalFile; + + my_free(db2LibNameEbcdic, 0); +} + +void db2i_table::getDB2QualifiedName(char* to) +{ + strcat(to, getDB2LibName(ASCII_SQL)); + strcat(to, "."); + strcat(to, getDB2TableName(ASCII_SQL)); +} + + +void db2i_table::getDB2QualifiedNameFromPath(const char* path, char* to) +{ + getDB2LibNameFromPath(path, to); + strcat(to, "."); + getDB2FileNameFromPath(path, strend(to)); +} + + +void db2i_table::filenameToTablename(const char* in, char* out, size_t outlen) +{ + if (strchr(in, '#') == NULL) + { + filename_to_tablename(in, out, outlen); + return; + } + + char* temp = (char*)sql_alloc(outlen); + + const char* part1, *part2, *part3, *part4; + part1 = in; + part2 = strstr(part1, "#P#"); + if (part2); + { + part3 = part2 + 3; + part4 = strchr(part3, '#'); + if (!part4) + part4 = strend(in); + } + + memcpy(temp, part1, min(outlen, part2 - part1)); + temp[min(outlen-1, part2-part1)] = 0; + + int32 accumLen = filename_to_tablename(temp, out, outlen); + + if (part2 && (accumLen + 4 < outlen)) + { + strcat(out, "#P#"); + accumLen += 4; + + memset(temp, 0, min(outlen, part2-part1)); + memcpy(temp, part3, min(outlen, part4-part3)); + temp[min(outlen-1, part4-part3)] = 0; + + accumLen += filename_to_tablename(temp, strend(out), outlen-accumLen); + + if (part4 && (accumLen + (strend(in) - part4 + 1) < outlen)) + { + strcat(out, part4); + } + } +} + +void db2i_table::getDB2LibNameFromPath(const char* path, char* lib, NameFormatFlags format) +{ + if (strstr(path, mysql_tmpdir) == path) + { + strcpy(lib, DB2I_TEMP_TABLE_SCHEMA); + } + else + { + const char* c = strend(path) - 1; + while (c > path && *c != '\\' && *c != '/') + --c; + + if (c != path) + { + const char* dbEnd = c; + do { + --c; + } while (c >= path && *c != '\\' && *c != '/'); + + if (c >= path) + { + const char* dbStart = c+1; + char fileName[FN_REFLEN]; + memcpy(fileName, dbStart, dbEnd - dbStart); + fileName[dbEnd-dbStart] = 0; + + char dbName[MAX_DB2_SCHEMANAME_LENGTH+1]; + filenameToTablename(fileName, dbName , sizeof(dbName)); + + convertMySQLNameToDB2Name(dbName, lib, sizeof(dbName), true, (format==ASCII_SQL) ); + } + else + DBUG_ASSERT(0); // This should never happen! + } + } +} + +void db2i_table::getDB2FileNameFromPath(const char* path, char* file, NameFormatFlags format) +{ + const char* fileEnd = strend(path); + const char* c = fileEnd; + while (c > path && *c != '\\' && *c != '/') + --c; + + if (c != path) + { + const char* fileStart = c+1; + char fileName[FN_REFLEN]; + memcpy(fileName, fileStart, fileEnd - fileStart); + fileName[fileEnd - fileStart] = 0; + char db2Name[MAX_DB2_FILENAME_LENGTH+1]; + filenameToTablename(fileName, db2Name, sizeof(db2Name)); + convertMySQLNameToDB2Name(db2Name, file, sizeof(db2Name), true, (format==ASCII_SQL) ); + } +} + +// Generates the DB2 index name when given the MySQL index and table names. +int32 db2i_table::appendQualifiedIndexFileName(const char* indexName, + const char* tableName, + String& to, + NameFormatFlags format, + enum_DB2I_INDEX_TYPE type) +{ + char generatedName[MAX_DB2_FILENAME_LENGTH+1]; + strncpy(generatedName, indexName, DB2I_INDEX_NAME_LENGTH_TO_PRESERVE); + generatedName[DB2I_INDEX_NAME_LENGTH_TO_PRESERVE] = 0; + char* endOfGeneratedName; + + if (type == typeDefault) + { + strcat(generatedName, DB2I_DEFAULT_INDEX_NAME_DELIMITER); + endOfGeneratedName = strend(generatedName); + } + else if (type != typeNone) + { + strcat(generatedName, DB2I_ADDL_INDEX_NAME_DELIMITER); + endOfGeneratedName = strend(generatedName); + *(endOfGeneratedName-2) = char(type); + } + + uint lenWithoutFile = endOfGeneratedName - generatedName; + + char strippedTableName[MAX_DB2_FILENAME_LENGTH+1]; + if (format == ASCII_SQL) + { + strcpy(strippedTableName, tableName); + stripExtraQuotes(strippedTableName+1, sizeof(strippedTableName)); + tableName = strippedTableName; + } + + if (strlen(tableName) > (MAX_DB2_FILENAME_LENGTH-lenWithoutFile)) + return -1; + + strncat(generatedName, + tableName+1, + min(strlen(tableName), (MAX_DB2_FILENAME_LENGTH-lenWithoutFile))-2 ); + + char finalName[MAX_DB2_FILENAME_LENGTH+1]; + convertMySQLNameToDB2Name(generatedName, finalName, sizeof(finalName), true, (format==ASCII_SQL)); + to.append(finalName); + + return 0; +} + + +void db2i_table::findConversionDefinition(enum_conversionDirection direction, uint16 fieldID) +{ + getConversion(direction, + mysqlTable->field[fieldID]->charset(), + db2Field(fieldID).getCCSID(), + conversionDefinitions[direction][fieldID]); +} + + +db2i_file::db2i_file(db2i_table* table) : db2Table(table) +{ + commonCtorInit(); + + DBUG_ASSERT(table->getMySQLTable()->table_name.length <= MAX_DB2_FILENAME_LENGTH-2); + + db2FileName = (char*)table->getDB2TableName(db2i_table::EBCDIC_NATIVE); +} + +db2i_file::db2i_file(db2i_table* table, int index) : db2Table(table) +{ + commonCtorInit(); + + if ((index == table->getMySQLTable()->primary_key) && !table->isTemporary()) + { + db2FileName = (char*)table->getDB2TableName(db2i_table::EBCDIC_NATIVE); + } + else + { + // Generate the index name (in index___table form); quote and EBCDICize it. + String qualifiedPath; + qualifiedPath.length(0); + + const char* asciiFileName = table->getDB2TableName(db2i_table::ASCII_NATIVE); + + db2i_table::appendQualifiedIndexFileName(table->getMySQLTable()->key_info[index].name, + asciiFileName, + qualifiedPath, + db2i_table::ASCII_NATIVE, + typeDefault); + + db2FileName = (char*)my_malloc(qualifiedPath.length()+1, MYF(MY_WME | MY_ZEROFILL)); + convToEbcdic(qualifiedPath.ptr(), db2FileName, qualifiedPath.length()); + } +} + +void db2i_file::commonCtorInit() +{ + masterDefn = 0; + memset(&formats, 0, maxRowFormats*sizeof(RowFormat)); +} + + +void db2i_file::fillILEDefn(ShrDef* defn, bool readInArrivalSeq) +{ + defn->ObjNamLen = strlen(db2FileName); + DBUG_ASSERT(defn->ObjNamLen <= sizeof(defn->ObjNam)); + memcpy(defn->ObjNam, db2FileName, defn->ObjNamLen); + defn->ArrSeq[0] = (readInArrivalSeq ? QMY_YES : QMY_NO); +} + diff --git a/storage/ibmdb2i/db2i_file.h b/storage/ibmdb2i/db2i_file.h new file mode 100644 index 00000000000..4be6558a95d --- /dev/null +++ b/storage/ibmdb2i/db2i_file.h @@ -0,0 +1,441 @@ +/* +Licensed Materials - Property of IBM +DB2 Storage Engine Enablement +Copyright IBM Corporation 2007,2008 +All rights reserved + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + (a) Redistributions of source code must retain this list of conditions, the + copyright notice in section {d} below, and the disclaimer following this + list of conditions. + (b) Redistributions in binary form must reproduce this list of conditions, the + copyright notice in section (d) below, and the disclaimer following this + list of conditions, in the documentation and/or other materials provided + with the distribution. + (c) The name of IBM may not be used to endorse or promote products derived from + this software without specific prior written permission. + (d) The text of the required copyright notice is: + Licensed Materials - Property of IBM + DB2 Storage Engine Enablement + Copyright IBM Corporation 2007,2008 + All rights reserved + +THIS SOFTWARE IS PROVIDED BY IBM CORPORATION "AS IS" AND ANY EXPRESS OR IMPLIED +WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT +SHALL IBM CORPORATION BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT +OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT INCLUDING NEGLIGENCE OR OTHERWISE) ARISING +IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + + +#ifndef DB2I_FILE_H +#define DB2I_FILE_H + +#include "db2i_global.h" +#include "db2i_ileBridge.h" +#include "db2i_validatedPointer.h" +#include "my_atomic.h" +#include "db2i_iconv.h" +#include "db2i_charsetSupport.h" + +const char FID_EXT[] = ".FID"; + +class db2i_file; + +#pragma pack(1) +struct DB2LobField +{ + char reserved1; + uint32 length; + char reserved2[4]; + uint32 ordinal; + ILEMemHandle dataHandle; + char reserved3[8]; +}; +#pragma pack(pop) + +class DB2Field +{ + public: + uint16 getType() const { return *(uint16*)(&definition.ColType); } + uint16 getByteLengthInRecord() const { return definition.ColLen; } + uint16 getDataLengthInRecord() const + { + return (getType() == QMY_VARCHAR || getType() == QMY_VARGRAPHIC ? definition.ColLen - 2 : definition.ColLen); + } + uint16 getCCSID() const { return *(uint16*)(&definition.ColCCSID); } + bool isBlob() const + { + uint16 type = getType(); + return (type == QMY_BLOBCLOB || type == QMY_DBCLOB); + } + uint16 getBufferOffset() const { return definition.ColBufOff; } + uint16 calcBlobPad() const + { + DBUG_ASSERT(isBlob()); + return getByteLengthInRecord() - sizeof (DB2LobField); + } + DB2LobField* asBlobField(char* buf) const + { + DBUG_ASSERT(isBlob()); + return (DB2LobField*)(buf + getBufferOffset() + calcBlobPad()); + } + private: + col_def_t definition; +}; + + +/** + @class db2i_table + + @details + This class describes the logical SQL table provided by DB2. + It stores "table-scoped" information such as the name of the + DB2 schema, BLOB descriptions, and the corresponding MySQL table definition. + Only one instance exists per SQL table. +*/ +class db2i_table +{ + public: + enum NameFormatFlags + { + ASCII_SQL, + ASCII_NATIVE, + EBCDIC_NATIVE + }; + + db2i_table(const TABLE_SHARE* myTable, const char* path = NULL); + + ~db2i_table(); + + int32 initDB2Objects(const char* path); + + const TABLE_SHARE* getMySQLTable() const + { + return mysqlTable; + } + + uint64 getStartId() const + { + return db2StartId; + } + + void updateStartId(uint64 newStartId) + { + db2StartId = newStartId; + } + + bool hasBlobs() const + { + return (blobFieldCount > 0); + } + + uint16 getBlobCount() const + { + return blobFieldCount; + } + + uint getBlobFieldActualSize(uint fieldIndex) const + { + return blobFieldActualSizes[getBlobIdFromField(fieldIndex)]; + } + + void updateBlobFieldActualSize(uint fieldIndex, uint32 newSize) + { + // It's OK that this isn't threadsafe, since this is just an advisory + // value. If a race condition causes the lesser of two values to be stored, + // that's OK. + uint16 blobID = getBlobIdFromField(fieldIndex); + DBUG_ASSERT(blobID < blobFieldCount); + + if (blobFieldActualSizes[blobID] < newSize) + { + blobFieldActualSizes[blobID] = newSize; + } + } + + + + const char* getDB2LibName(NameFormatFlags format = EBCDIC_NATIVE) + { + switch (format) + { + case EBCDIC_NATIVE: + return db2LibNameEbcdic; break; + case ASCII_NATIVE: + return db2LibNameAscii; break; + case ASCII_SQL: + return db2LibNameSQLAscii; break; + default: + DBUG_ASSERT(0); + } + return NULL; + } + + const char* getDB2TableName(NameFormatFlags format = EBCDIC_NATIVE) const + { + switch (format) + { + case EBCDIC_NATIVE: + return db2TableNameEbcdic; break; + case ASCII_NATIVE: + return db2TableNameAscii; break; + case ASCII_SQL: + return db2TableNameAscii; break; + break; + default: + DBUG_ASSERT(0); + } + return NULL; + } + + DB2Field& db2Field(int fieldID) const { return db2Fields[fieldID]; } + DB2Field& db2Field(const Field* field) const { return db2Field(field->field_index); } + + void processFormatSpace(); + + void* getFormatSpace(size_t& spaceNeeded) + { + DBUG_ASSERT(formatSpace == NULL); + spaceNeeded = sizeof(format_hdr_t) + mysqlTable->fields * sizeof(DB2Field); + formatSpace.alloc(spaceNeeded); + return (void*)formatSpace; + } + + bool isTemporary() const + { + return isTemporaryTable; + } + + void getDB2QualifiedName(char* to); + static void getDB2LibNameFromPath(const char* path, char* lib, NameFormatFlags format=ASCII_SQL); + static void getDB2FileNameFromPath(const char* path, char* file, NameFormatFlags format=ASCII_SQL); + static void getDB2QualifiedNameFromPath(const char* path, char* to); + static int32 appendQualifiedIndexFileName(const char* indexName, + const char* tableName, + String& to, + NameFormatFlags format=ASCII_SQL, + enum_DB2I_INDEX_TYPE type=typeDefault); + + uint16 getBlobIdFromField(uint16 fieldID) const + { + for (int i = 0; i < blobFieldCount; ++i) + { + if (blobFields[i] == fieldID) + return i; + } + DBUG_ASSERT(0); + return 0; + } + + iconv_t& getConversionDefinition(enum_conversionDirection direction, + uint16 fieldID) + { + if (conversionDefinitions[direction][fieldID] == (iconv_t)(-1)) + findConversionDefinition(direction, fieldID); + + return conversionDefinitions[direction][fieldID]; + } + + const db2i_file* dataFile() const + { + return physicalFile; + } + + const db2i_file* indexFile(uint idx) const + { + return logicalFiles[idx]; + } + + const char* getFileLevelID() const + { + return fileLevelID; + } + + static void deleteAssocFiles(const char* name); + static void renameAssocFiles(const char* from, const char* to); + + int fastInitForCreate(const char* path); + int initDiscoveredTable(const char* path); + + uint16* blobFields; + +private: + + void findConversionDefinition(enum_conversionDirection direction, uint16 fieldID); + static void filenameToTablename(const char* in, char* out, size_t outlen); + void convertNativeToSQLName(const char* input, + char* output) + { + + output[0] = input[0]; + + uint o = 1; + uint i = 1; + do + { + output[o++] = input[i]; + if (input[i] == '"' && input[i+1]) + output[o++] = '"'; + } while (input[++i]); + + output[o] = 0; // This isn't the most user-friendly way to handle overflows, + // but at least its safe. + } + + bool doFileIDsMatch(const char* path); + + ValidatedPointer formatSpace; + DB2Field* db2Fields; + uint64 db2StartId; // Starting value for identity column + uint16 blobFieldCount; // Count of LOB fields in the DB2 table + uint* blobFieldActualSizes; // Array of LOB field lengths (actual vs. allocated). + // This is updated as LOBs are read and will contain + // the length of the longest known LOB in that field. + iconv_t* conversionDefinitions[2]; + + const TABLE_SHARE* mysqlTable; + char* db2LibNameEbcdic; // Quoted and in EBCDIC + char* db2LibNameAscii; + char* db2TableNameEbcdic; + char* db2TableNameAscii; + char* db2TableNameSQLAscii; + char* db2LibNameSQLAscii; + + db2i_file* physicalFile; + db2i_file** logicalFiles; + + bool isTemporaryTable; + char fileLevelID[13]; +}; + +/** + @class db2i_file + + @details This class describes a file object underlaying a particular SQL + table. Both "physical files" (data) and "logical files" (indices) are + described by this class. Only one instance of the class exists per DB2 file + object. The single instance is responsible for de/allocating the multiple + handles used by the handlers. +*/ +class db2i_file +{ + enum RowFormats + { + readOnly = 0, + readWrite, + maxRowFormats + }; + +public: + mutable struct RowFormat + { + uint16 readRowLen; + uint16 readRowNullOffset; + uint16 writeRowLen; + uint16 writeRowNullOffset; + char inited; + } formats[maxRowFormats]; + + // Construct an instance for a physical file. + db2i_file(db2i_table* table); + + // Construct an instance for a logical file. + db2i_file(db2i_table* table, int index); + + ~db2i_file() + { + if (masterDefn) + db2i_ileBridge::getBridgeForThread()->deallocateFile(masterDefn); + + if (db2FileName != (char*)db2Table->getDB2TableName(db2i_table::EBCDIC_NATIVE)) + my_free(db2FileName, MYF(0)); + } + + // This is roughly equivalent to an "open". It tells ILE to allocate a descriptor + // for the file. The associated handle is returned to the caller. + int allocateNewInstance(FILE_HANDLE* newHandle, ILEMemHandle inuseSpace) const + { + int rc; + + rc = db2i_ileBridge::getBridgeForThread()->allocateFileInstance(masterDefn, + inuseSpace, + newHandle); + + if (rc) *newHandle = 0; + + return rc; + } + + // This obtains the row layout associated with a particular access intent for + // an open instance of the file. + int useFile(FILE_HANDLE instanceHandle, + char intent, + char commitLevel, + const RowFormat** activeFormat) const + { + DBUG_ENTER("db2i_file::useFile"); + RowFormat* rowFormat; + + if (intent == QMY_UPDATABLE) + rowFormat = &(formats[readWrite]); + else if (intent == QMY_READ_ONLY) + rowFormat = &(formats[readOnly]); + else + DBUG_ASSERT(0); + + if (!rowFormat->inited) + { + int rc; + rc = db2i_ileBridge::getBridgeForThread()->initFileForIO(instanceHandle, + intent, + commitLevel, + &(rowFormat->writeRowLen), + &(rowFormat->writeRowNullOffset), + &(rowFormat->readRowLen), + &(rowFormat->readRowNullOffset)); + if (rc) DBUG_RETURN(rc); + rowFormat->inited = 1; + } + + *activeFormat = rowFormat; + DBUG_RETURN(0); + } + + const char* getDB2FileName() const + { + return db2FileName; + } + + void fillILEDefn(ShrDef* defn, bool readInArrivalSeq); + + void setMasterDefnHandle(FILE_HANDLE handle) + { + masterDefn = handle; + } + + FILE_HANDLE getMasterDefnHandle() const + { + return masterDefn; + } + +private: + void commonCtorInit(); + + char* db2FileName; // Quoted and in EBCDIC + + db2i_table* db2Table; // The logical SQL table contained by this file. + + bool db2CanSort; + + FILE_HANDLE masterDefn; +}; + + +#endif diff --git a/storage/ibmdb2i/db2i_global.h b/storage/ibmdb2i/db2i_global.h new file mode 100644 index 00000000000..d201fbd8124 --- /dev/null +++ b/storage/ibmdb2i/db2i_global.h @@ -0,0 +1,138 @@ +/* +Licensed Materials - Property of IBM +DB2 Storage Engine Enablement +Copyright IBM Corporation 2007,2008 +All rights reserved + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + (a) Redistributions of source code must retain this list of conditions, the + copyright notice in section {d} below, and the disclaimer following this + list of conditions. + (b) Redistributions in binary form must reproduce this list of conditions, the + copyright notice in section (d) below, and the disclaimer following this + list of conditions, in the documentation and/or other materials provided + with the distribution. + (c) The name of IBM may not be used to endorse or promote products derived from + this software without specific prior written permission. + (d) The text of the required copyright notice is: + Licensed Materials - Property of IBM + DB2 Storage Engine Enablement + Copyright IBM Corporation 2007,2008 + All rights reserved + +THIS SOFTWARE IS PROVIDED BY IBM CORPORATION "AS IS" AND ANY EXPRESS OR IMPLIED +WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT +SHALL IBM CORPORATION BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT +OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT INCLUDING NEGLIGENCE OR OTHERWISE) ARISING +IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + + +#ifndef DB2I_GLOBAL_H +#define DB2I_GLOBAL_H + +#define MYSQL_SERVER 1 + +#include "my_global.h" +#include "my_sys.h" + +const uint MAX_DB2_KEY_PARTS=120; +const int MAX_DB2_V5R4_LIBNAME_LENGTH = 10; +const int MAX_DB2_V6R1_LIBNAME_LENGTH = 30; +const int MAX_DB2_SCHEMANAME_LENGTH=258; +const int MAX_DB2_FILENAME_LENGTH=258; +const int MAX_DB2_COLNAME_LENGTH=128; +const int MAX_DB2_SAVEPOINTNAME_LENGTH=128; +const int MAX_DB2_QUALIFIEDNAME_LENGTH=MAX_DB2_V6R1_LIBNAME_LENGTH + 1 + MAX_DB2_FILENAME_LENGTH; +const uint32 MAX_CHAR_LENGTH = 32765; +const uint32 MAX_VARCHAR_LENGTH = 32739; +const uint32 MAX_DEC_PRECISION = 63; +const uint32 MAX_BLOB_LENGTH = 2147483646; +const uint32 MAX_BINARY_LENGTH = MAX_CHAR_LENGTH; +const uint32 MAX_VARBINARY_LENGTH = MAX_VARCHAR_LENGTH; +const uint32 MAX_FULL_ALLOCATE_BLOB_LENGTH = 65536; +const uint32 MAX_FOREIGN_LEN = 64000; +const char* DB2I_TEMP_TABLE_SCHEMA = "QTEMP"; +const char DB2I_ADDL_INDEX_NAME_DELIMITER[5] = {'_','_','_','_','_'}; +const char DB2I_DEFAULT_INDEX_NAME_DELIMITER[3] = {'_','_','_'}; +const int DB2I_INDEX_NAME_LENGTH_TO_PRESERVE = 110; + +enum enum_DB2I_INDEX_TYPE +{ + typeNone = 0, + typeDefault = 'D', + typeHex = 'H', + typeAscii = 'A' +}; + +void* roundToQuadWordBdy(void* ptr) +{ + return (void*)(((uint64)(ptr)+0xf) & ~0xf); +} + +typedef uint64_t ILEMemHandle; + +struct OSVersion +{ + uint8 v; + uint8 r; +}; +extern OSVersion osVersion; + + +/** + Allocate 16-byte aligned space using the MySQL heap allocator + + @details Many of the spaces used by the QMY_* APIS are required to be + aligned on 16 byte boundaries. The standard system malloc will do this + alignment by default. However, in order to use the heap debug and tracking + features of the mysql allocator, we chose to implement an aligning wrapper + around my_malloc. Essentially, we overallocate the storage space, find the + first aligned address in the space, store a pointer to the true malloc + allocation in the bytes immediately preceding the aligned address, and return + the aligned address to the caller. + + @parm size The size of heap storage needed + + @return A 16-byte aligned pointer to the storage requested. +*/ +void* malloc_aligned(size_t size) +{ + char* p; + char* base; + base = (char*)my_malloc(size + sizeof(void*) + 15, MYF(MY_WME)); + if (likely(base)) + { + p = (char*)roundToQuadWordBdy(base + sizeof(void*)); + char** p2 = (char**)(p - sizeof(void*)); + *p2 = base; + } + else + p = NULL; + + return p; +} + +/** + Free a 16-byte aligned space alloced by malloc_aligned + + @details We know that a pointer to the true malloced storage immediately + precedes the aligned address, so we pull that out and call my_free(). + + @parm p A 16-byte aligned pointer generated by malloc_aligned +*/ +void free_aligned(void* p) +{ + if (likely(p)) + { + my_free(*(char**)((char*)p-sizeof(void*)), MYF(0)); + } +} + +#endif diff --git a/storage/ibmdb2i/db2i_iconv.h b/storage/ibmdb2i/db2i_iconv.h new file mode 100644 index 00000000000..9fc6e4ed636 --- /dev/null +++ b/storage/ibmdb2i/db2i_iconv.h @@ -0,0 +1,51 @@ +/* +Licensed Materials - Property of IBM +DB2 Storage Engine Enablement +Copyright IBM Corporation 2007,2008 +All rights reserved + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + (a) Redistributions of source code must retain this list of conditions, the + copyright notice in section {d} below, and the disclaimer following this + list of conditions. + (b) Redistributions in binary form must reproduce this list of conditions, the + copyright notice in section (d) below, and the disclaimer following this + list of conditions, in the documentation and/or other materials provided + with the distribution. + (c) The name of IBM may not be used to endorse or promote products derived from + this software without specific prior written permission. + (d) The text of the required copyright notice is: + Licensed Materials - Property of IBM + DB2 Storage Engine Enablement + Copyright IBM Corporation 2007,2008 + All rights reserved + +THIS SOFTWARE IS PROVIDED BY IBM CORPORATION "AS IS" AND ANY EXPRESS OR IMPLIED +WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT +SHALL IBM CORPORATION BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT +OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT INCLUDING NEGLIGENCE OR OTHERWISE) ARISING +IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +/** + @file + + @brief Used to redefine iconv symbols to the optimized "myconv" ones +*/ + +#ifndef DB2I_ICONV_H +#define DB2I_ICONV_H + +#include "db2i_myconv.h" +#define iconv_open(A, B) myconv_open(A, B, CONVERTER_DMAP) +#define iconv_close myconv_close +#define iconv myconv_dmap +#define iconv_t myconv_t + +#endif diff --git a/storage/ibmdb2i/db2i_ileBridge.cc b/storage/ibmdb2i/db2i_ileBridge.cc new file mode 100644 index 00000000000..356c837cd00 --- /dev/null +++ b/storage/ibmdb2i/db2i_ileBridge.cc @@ -0,0 +1,1331 @@ +/* +Licensed Materials - Property of IBM +DB2 Storage Engine Enablement +Copyright IBM Corporation 2007,2008 +All rights reserved + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + (a) Redistributions of source code must retain this list of conditions, the + copyright notice in section {d} below, and the disclaimer following this + list of conditions. + (b) Redistributions in binary form must reproduce this list of conditions, the + copyright notice in section (d) below, and the disclaimer following this + list of conditions, in the documentation and/or other materials provided + with the distribution. + (c) The name of IBM may not be used to endorse or promote products derived from + this software without specific prior written permission. + (d) The text of the required copyright notice is: + Licensed Materials - Property of IBM + DB2 Storage Engine Enablement + Copyright IBM Corporation 2007,2008 + All rights reserved + +THIS SOFTWARE IS PROVIDED BY IBM CORPORATION "AS IS" AND ANY EXPRESS OR IMPLIED +WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT +SHALL IBM CORPORATION BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT +OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT INCLUDING NEGLIGENCE OR OTHERWISE) ARISING +IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + + + +#include "db2i_ileBridge.h" +#include "my_dbug.h" +#include "db2i_global.h" +#include "db2i_charsetSupport.h" +#include "db2i_errors.h" + + +// static class member data +ILEpointer* db2i_ileBridge::functionSymbols; +db2i_ileBridge* db2i_ileBridge::globalBridge; +#ifndef DBUG_OFF +uint32 db2i_ileBridge::registeredPtrs; +#endif + +pthread_key(IleParms*, THR_ILEPARMS); + +static void ileParmsDtor(void* parmsToFree) +{ + if (parmsToFree) + { + free_aligned(parmsToFree); + DBUG_PRINT("db2i_ileBridge", ("Freeing space for parms")); + } +} + + +/** + Convert a timestamp in ILE time format into a unix time_t +*/ +static inline time_t convertILEtime(const ILE_time_t& input) +{ + tm temp; + + temp.tm_sec = input.Second; + temp.tm_min = input.Minute; + temp.tm_hour = input.Hour; + temp.tm_mday = input.Day; + temp.tm_mon = input.Month-1; + temp.tm_year = input.Year - 1900; + temp.tm_isdst = -1; + + return mktime(&temp); +} + +/** + Allocate and intialize a new bridge structure +*/ +db2i_ileBridge* db2i_ileBridge::createNewBridge(CONNECTION_HANDLE connID) +{ + DBUG_PRINT("db2i_ileBridge::createNewBridge",("Building new bridge...")); + db2i_ileBridge* newBridge = (db2i_ileBridge*)my_malloc(sizeof(db2i_ileBridge), MYF(MY_WME)); + + if (unlikely(newBridge == NULL)) + return NULL; + + newBridge->stmtTxActive = false; + newBridge->connErrText = NULL; + newBridge->pendingLockedHandles.head = NULL; + newBridge->cachedConnectionID = connID; + + return newBridge; +} + + +void db2i_ileBridge::destroyBridge(db2i_ileBridge* bridge) +{ + bridge->freeErrorStorage(); + my_free(bridge, MYF(0)); +} + + +void db2i_ileBridge::destroyBridgeForThread(const THD* thd) +{ + void* thdData = *thd_ha_data(thd, ibmdb2i_hton); + if (thdData != NULL) + { + destroyBridge((db2i_ileBridge*)thdData); + } +} + + +void db2i_ileBridge::registerPtr(const void* ptr, ILEMemHandle* receiver) +{ + static const arg_type_t ileSignature[] = { ARG_MEMPTR, ARG_END }; + + if (unlikely(ptr == NULL)) + { + *receiver = 0; + return; + } + + struct ArgList + { + ILEarglist_base base; + ILEpointer ptr; + } *arguments; + + char argBuf[sizeof(ArgList)+15]; + arguments = (ArgList*)roundToQuadWordBdy(argBuf); + + arguments->ptr.s.addr = (address64_t)(ptr); + + _ILECALL(&functionSymbols[funcRegisterSpace], + &arguments->base, + ileSignature, + RESULT_INT64); + +#ifndef DBUG_OFF + uint32 truncHandle = arguments->base.result.r_uint64; + DBUG_PRINT("db2i_ileBridge::registerPtr",("Register 0x%p with handle %d", ptr, truncHandle)); + getBridgeForThread()->registeredPtrs++; +#endif + + *receiver = arguments->base.result.r_uint64; + return; +} + +void db2i_ileBridge::unregisterPtr(ILEMemHandle handle) +{ + static const arg_type_t ileSignature[] = { ARG_UINT64, ARG_END }; + + if (unlikely(handle == NULL)) + return; + + struct ArgList + { + ILEarglist_base base; + uint64 handle; + } *arguments; + + char argBuf[sizeof(ArgList)+15]; + arguments = (ArgList*)roundToQuadWordBdy(argBuf); + + arguments->handle = (uint64)(handle); + + _ILECALL(&functionSymbols[funcUnregisterSpace], + &arguments->base, + ileSignature, + RESULT_VOID); + +#ifndef DBUG_OFF + DBUG_PRINT("db2i_ileBridge::unregisterPtr",("Unregister handle %d", (uint32)handle)); + getBridgeForThread()->registeredPtrs--; +#endif +} + + + +/** + Initialize the bridge component + + @details Resolves srvpgm and function names of the APIs. If this fails, + the approrpiate operating system support (PTFs) is probably not installed. + + WARNING: + Must be called before any other functions in this class are used!!!! + Can only be called by a single thread! +*/ +int db2i_ileBridge::setup() +{ + static const char funcNames[db2i_ileBridge::funcListEnd][32] = + { + {"QmyRegisterParameterSpaces"}, + {"QmyRegisterSpace"}, + {"QmyUnregisterSpace"}, + {"QmyProcessRequest"} + }; + + DBUG_ENTER("db2i_ileBridge::setup"); + + int actmark = _ILELOAD("QSYS/QMYSE", ILELOAD_LIBOBJ); + if ( actmark == -1 ) + { + DBUG_PRINT("db2i_ileBridge::setup", ("srvpgm activation failed")); + DBUG_RETURN(1); + } + + functionSymbols = (ILEpointer*)malloc_aligned(sizeof(ILEpointer) * db2i_ileBridge::funcListEnd); + + for (int i = 0; i < db2i_ileBridge::funcListEnd; i++) + { + if (_ILESYM(&functionSymbols[i], actmark, funcNames[i]) == -1) + { + DBUG_PRINT("db2i_ileBridge::setup", + ("resolve of %s failed", funcNames[i])); + DBUG_RETURN(errno); + } + } + + pthread_key_create(&THR_ILEPARMS, &ileParmsDtor); + +#ifndef DBUG_OFF + registeredPtrs = 0; +#endif + + globalBridge = createNewBridge(0); + + DBUG_RETURN(0); +} + +/** + Cleanup any resources before shutting down plug-in +*/ +void db2i_ileBridge::takedown() +{ + if (globalBridge) + destroyBridge(globalBridge); + free_aligned(functionSymbols); +} + +/** + Call off to QmyProcessRequest to perform the API that the caller prepared +*/ +inline int32 db2i_ileBridge::doIt() +{ + static const arg_type_t ileSignature[] = {ARG_END}; + + struct ArgList + { + ILEarglist_base base; + } *arguments; + + char argBuf[sizeof(ArgList)+15]; + arguments = (ArgList*)roundToQuadWordBdy(argBuf); + + _ILECALL(&functionSymbols[funcProcessRequest], + &arguments->base, + ileSignature, + RESULT_INT32); + + return translateErrorCode(arguments->base.result.s_int32.r_int32); +} + +/** + Call off to QmyProcessRequest to perform the API that the caller prepared and + log any errors that may occur. +*/ +inline int32 db2i_ileBridge::doItWithLog() +{ + int32 rc = doIt(); + + if (unlikely(rc)) + { + // Only report errors that we weren't expecting + if (rc != tacitErrors[0] && + rc != tacitErrors[1] && + rc != QMY_ERR_END_OF_BLOCK) + reportSystemAPIError(rc, (Qmy_Error_output_t*)parms()->outParms); + } + memset(tacitErrors, 0, sizeof(tacitErrors)); + + return rc; +} + + +/** + Interface to QMY_ALLOCATE_SHARE API + + See QMY_ALLOCATE_SHARE documentation for more information about + parameters and return codes. +*/ +int32 db2i_ileBridge::allocateFileDefn(ILEMemHandle definitionSpace, + ILEMemHandle handleSpace, + uint16 fileCount, + const char* schemaName, + uint16 schemaNameLength, + ILEMemHandle formatSpace, + uint32 formatSpaceLen) +{ + DBUG_ASSERT(cachedStateIsCoherent()); + + IleParms* parmBlock = parms(); + Qmy_MAOS0100 *input = (Qmy_MAOS0100*)&(parmBlock->inParms); + memset(input, 0, sizeof(*input)); + + input->Format = QMY_ALLOCATE_SHARE; + input->ShrDefSpcHnd = definitionSpace; + input->ShrHndSpcHnd = handleSpace; + input->ShrDefCnt = fileCount; + input->FmtSpcHnd = formatSpace; + input->FmtSpcLen = formatSpaceLen; + + if (schemaNameLength > sizeof(input->SchNam)) + { + // This should never happen! + DBUG_ASSERT(0); + return HA_ERR_GENERIC; + } + + memcpy(input->SchNam, schemaName, schemaNameLength); + input->SchNamLen = schemaNameLength; + + input->CnnHnd = cachedConnectionID; + + int32 rc = doItWithLog(); + + return rc; +} + + +/** + Interface to QMY_ALLOCATE_INSTANCE API + + See QMY_ALLOCATE_INSTANCE documentation for more information about + parameters and return codes. +*/ +int32 db2i_ileBridge::allocateFileInstance(FILE_HANDLE defnHandle, + ILEMemHandle inuseSpace, + FILE_HANDLE* instance) +{ + DBUG_ASSERT(cachedStateIsCoherent()); + + IleParms* parmBlock = parms(); + Qmy_MAOI0100 *input = (Qmy_MAOI0100*)&(parmBlock->inParms); + memset(input, 0, sizeof(*input)); + + input->Format = QMY_ALLOCATE_INSTANCE; + input->ShrHnd = defnHandle; + input->CnnHnd = cachedConnectionID; + input->UseSpcHnd = inuseSpace; + + int32 rc = doItWithLog(); + + if (likely(rc == 0)) + { + Qmy_MAOI0100_output* output = (Qmy_MAOI0100_output*)parmBlock->outParms; + DBUG_ASSERT(instance); + *instance = output->ObjHnd; + } + + return rc; +} + + +/** + Interface to QMY_DEALLOCATE_OBJECT API + + See QMY_DEALLOCATE_OBJECT documentation for more information about + parameters and return codes. +*/ +int32 db2i_ileBridge::deallocateFile(FILE_HANDLE rfileHandle, + bool postDropTable) +{ + IleParms* parmBlock = parms(); + Qmy_MDLC0100 *input = (Qmy_MDLC0100*)&(parmBlock->inParms); + memset(input, 0, sizeof(*input)); + + input->Format = QMY_DEALLOCATE_OBJECT; + input->ObjHnd = rfileHandle; + input->ObjDrp[0] = (postDropTable ? QMY_YES : QMY_NO); + + DBUG_PRINT("db2i_ileBridge::deallocateFile", ("Deallocating %d", (uint32)rfileHandle)); + + int32 rc = doItWithLog(); + + return rc; +} + + +/** + Interface to QMY_OBJECT_INITIALIZATION API + + See QMY_OBJECT_INITIALIZATION documentation for more information about + parameters and return codes. +*/ +int32 db2i_ileBridge::initFileForIO(FILE_HANDLE rfileHandle, + char accessIntent, + char commitLevel, + uint16* inRecSize, + uint16* inRecNullOffset, + uint16* outRecSize, + uint16* outRecNullOffset) +{ + DBUG_ASSERT(cachedStateIsCoherent()); + IleParms* parmBlock = parms(); + Qmy_MOIX0100 *input = (Qmy_MOIX0100*)&(parmBlock->inParms); + memset(input, 0, sizeof(*input)); + + input->Format = QMY_OBJECT_INITIALIZATION; + input->CmtLvl[0] = commitLevel; + input->Intent[0] = accessIntent; + input->ObjHnd = rfileHandle; + input->CnnHnd = cachedConnectionID; + + int32 rc = doItWithLog(); + + if (likely(rc == 0)) + { + Qmy_MOIX0100_output* output = (Qmy_MOIX0100_output*)parmBlock->outParms; + *inRecSize = output->InNxtRowOff; + *inRecNullOffset = output->InNullMapOff; + *outRecSize = output->OutNxtRowOff; + *outRecNullOffset = output->OutNullMapOff; + } + + return rc; +} + + +/** + Interface to QMY_READ_ROWS API for reading a row with a specific RRN. + + See QMY_READ_ROWS documentation for more information about + parameters and return codes. +*/ +int32 db2i_ileBridge::readByRRN(FILE_HANDLE rfileHandle, + ILEMemHandle buf, + uint32 inRRN, + char accessIntent, + char commitLevel) +{ + DBUG_ASSERT(cachedStateIsCoherent()); + IleParms* parmBlock = parms(); + Qmy_MRDX0100 *input = (Qmy_MRDX0100*)&(parmBlock->inParms); + memset(input, 0, sizeof(*input)); + + input->Format = QMY_READ_ROWS; + input->CmtLvl[0] = commitLevel; + input->ObjHnd = rfileHandle; + input->Intent[0] = accessIntent; + input->OutSpcHnd = (uint64)buf; + input->RelRowNbr = inRRN; + input->CnnHnd = cachedConnectionID; + + int32 rc = doItWithLog(); + + if (rc == QMY_ERR_END_OF_BLOCK) + { + rc = 0; + DBUG_PRINT("db2i_ileBridge::readByRRN", ("End of block signalled")); + } + + return rc; +} + + +/** + Interface to QMY_WRITE_ROWS API. + + See QMY_WRITE_ROWS documentation for more information about + parameters and return codes. +*/ +int32 db2i_ileBridge::writeRows(FILE_HANDLE rfileHandle, + ILEMemHandle buf, + char commitLevel, + int64* outIdVal, + bool* outIdGen, + uint32* dupKeyRRN, + char** dupKeyName, + uint32* dupKeyNameLen, + uint32* outIdIncrement) +{ + DBUG_ASSERT(cachedStateIsCoherent()); + IleParms* parmBlock = parms(); + Qmy_MWRT0100 *input = (Qmy_MWRT0100*)&(parmBlock->inParms); + memset(input, 0, sizeof(*input)); + + input->Format = QMY_WRITE_ROWS; + input->CmtLvl[0] = commitLevel; + + input->ObjHnd = rfileHandle; + input->InSpcHnd = (uint64_t) buf; + input->CnnHnd = cachedConnectionID; + + int32 rc = doItWithLog(); + + Qmy_MWRT0100_output_t* output = (Qmy_MWRT0100_output_t*)parmBlock->outParms; + if (likely(rc == 0 || rc == HA_ERR_FOUND_DUPP_KEY)) + { + DBUG_ASSERT(dupKeyRRN && dupKeyName && dupKeyNameLen && outIdGen && outIdIncrement && outIdVal); + *dupKeyRRN = output->DupRRN; + *dupKeyName = (char*)parmBlock->outParms + output->DupObjNamOff; + *dupKeyNameLen = output->DupObjNamLen; + *outIdGen = (output->NewIdGen[0] == QMY_YES ? TRUE : FALSE); + if (*outIdGen == TRUE) + { + *outIdIncrement = output->IdIncrement; + *outIdVal = output->NewIdVal; + } + } + + return rc; + +} + +/** + Interface to QMY_EXECUTE_IMMEDIATE API. + + See QMY_EXECUTE_IMMEDIATE documentation for more information about + parameters and return codes. +*/ +uint32 db2i_ileBridge::execSQL(const char* statement, + uint32 statementCount, + uint8 commitLevel, + bool autoCreateSchema, + bool dropSchema, + bool noCommit, + FILE_HANDLE fileHandle) + +{ + IleParms* parmBlock = parms(); + Qmy_MSEI0100 *input = (Qmy_MSEI0100*)&(parmBlock->inParms); + memset(input, 0, sizeof(*input)); + + input->Format = QMY_EXECUTE_IMMEDIATE; + + registerPtr(statement, &input->StmtsSpcHnd); + + input->NbrStmts = statementCount; + *(uint16*)(&input->StmtCCSID) = 850; + input->AutoCrtSchema[0] = (autoCreateSchema == TRUE ? QMY_YES : QMY_NO); + input->DropSchema[0] = (dropSchema == TRUE ? QMY_YES : QMY_NO); + input->CmtLvl[0] = commitLevel; + if ((commitLevel == QMY_NONE && statementCount == 1) || noCommit) + { + input->CmtBefore[0] = QMY_NO; + input->CmtAfter[0] = QMY_NO; + } + else + { + input->CmtBefore[0] = QMY_YES; + input->CmtAfter[0] = QMY_YES; + } + input->CnnHnd = current_thd->thread_id; + input->ObjHnd = fileHandle; + + int32 rc = doItWithLog(); + + unregisterPtr(input->StmtsSpcHnd); + + return rc; +} + +/** + Interface to QMY_PREPARE_OPEN_CURSOR API. + + See QMY_PREPARE_OPEN_CURSOR documentation for more information about + parameters and return codes. +*/ +int32 db2i_ileBridge::prepOpen(const char* statement, + FILE_HANDLE* rfileHandle, + uint32* recLength) +{ + IleParms* parmBlock = parms(); + Qmy_MSPO0100 *input = (Qmy_MSPO0100*)&(parmBlock->inParms); + memset(input, 0, sizeof(*input)); + + input->Format = QMY_PREPARE_OPEN_CURSOR; + + registerPtr(statement, &input->StmtsSpcHnd ); + *(uint16*)(&input->StmtCCSID) = 850; + input->CnnHnd = current_thd->thread_id; + + int32 rc = doItWithLog(); + + if (likely(rc == 0)) + { + Qmy_MSPO0100_output* output = (Qmy_MSPO0100_output*)parmBlock->outParms; + *rfileHandle = output->ObjHnd; + *recLength = max(output->InNxtRowOff, output->OutNxtRowOff); + } + + + unregisterPtr(input->StmtsSpcHnd); + + return rc; +} + + +/** + Interface to QMY_DELETE_ROW API. + + See QMY_DELETE_ROW documentation for more information about + parameters and return codes. +*/ +int32 db2i_ileBridge::deleteRow(FILE_HANDLE rfileHandle, + uint32 rrn) +{ + DBUG_ASSERT(cachedStateIsCoherent()); + IleParms* parmBlock = parms(); + Qmy_MDLT0100 *input = (Qmy_MDLT0100*)&(parmBlock->inParms); + memset(input, 0, sizeof(*input)); + + input->Format = QMY_DELETE_ROW; + input->ObjHnd = rfileHandle; + input->RelRowNbr = rrn; + input->CnnHnd = cachedConnectionID; + + int32 rc = doItWithLog(); + + return rc; +} + + +/** + Interface to QMY_UPDATE_ROW API. + + See QMY_UPDATE_ROW documentation for more information about + parameters and return codes. +*/ +int32 db2i_ileBridge::updateRow(FILE_HANDLE rfileHandle, + uint32 rrn, + ILEMemHandle buf, + uint32* dupKeyRRN, + char** dupKeyName, + uint32* dupKeyNameLen) +{ + DBUG_ASSERT(cachedStateIsCoherent()); + IleParms* parmBlock = parms(); + Qmy_MUPD0100 *input = (Qmy_MUPD0100*)&(parmBlock->inParms); + memset(input, 0, sizeof(*input)); + + input->Format = QMY_UPDATE_ROW; + input->ObjHnd = rfileHandle; + input->InSpcHnd = (uint64)buf; + input->RelRowNbr = rrn; + input->CnnHnd = cachedConnectionID; + + int32 rc = doItWithLog(); + + if (rc == HA_ERR_FOUND_DUPP_KEY) + { + Qmy_MUPD0100_output* output = (Qmy_MUPD0100_output*)parmBlock->outParms; + DBUG_ASSERT(dupKeyRRN && dupKeyName && dupKeyNameLen); + *dupKeyRRN = output->DupRRN; + *dupKeyName = (char*)parmBlock->outParms + output->DupObjNamOff; + *dupKeyNameLen = output->DupObjNamLen; + } + + return rc; +} + +/** + Interface to QMY_DESCRIBE_RANGE API. + + See QMY_DESCRIBE_RANGE documentation for more information about + parameters and return codes. +*/ +int32 db2i_ileBridge::recordsInRange(FILE_HANDLE defnHandle, + ILEMemHandle inSpc, + uint32 inKeyCnt, + uint32 inLiteralCnt, + uint32 inBoundsOff, + uint32 inLitDefOff, + uint32 inLiteralsOff, + uint32 inCutoff, + uint32 inSpcLen, + uint16 inEndByte, + uint64* outRecCnt, + uint16* outRtnCode) +{ + DBUG_ASSERT(cachedStateIsCoherent()); + + IleParms* parmBlock = parms(); + Qmy_MDRG0100 *input = (Qmy_MDRG0100*)&(parmBlock->inParms); + memset(input, 0, sizeof(*input)); + + input->Format = QMY_DESCRIBE_RANGE; + input->ShrHnd = defnHandle; + input->SpcHnd = (uint64)inSpc; + input->KeyCnt = inKeyCnt; + input->LiteralCnt = inLiteralCnt; + input->BoundsOff = inBoundsOff; + input->LitDefOff = inLitDefOff; + input->LiteralsOff = inLiteralsOff; + input->Cutoff = inCutoff; + input->SpcLen = inSpcLen; + input->EndByte = inEndByte; + input->CnnHnd = cachedConnectionID; + + int rc = doItWithLog(); + + if (likely(rc == 0)) + { + Qmy_MDRG0100_output* output = (Qmy_MDRG0100_output*)parmBlock->outParms; + DBUG_ASSERT(outRecCnt && outRtnCode); + *outRecCnt = output->RecCnt; + *outRtnCode = output->RtnCode; + } + + return rc; +} + + +/** + Interface to QMY_RELEASE_ROW API. + + See QMY_RELEASE_ROW documentation for more information about + parameters and return codes. +*/ +int32 db2i_ileBridge::rrlslck(FILE_HANDLE rfileHandle, char accessIntent) +{ + DBUG_ASSERT(cachedStateIsCoherent()); + + IleParms* parmBlock = parms(); + Qmy_MRRX0100 *input = (Qmy_MRRX0100*)&(parmBlock->inParms); + memset(input, 0, sizeof(*input)); + + input->Format = QMY_RELEASE_ROW; + + input->ObjHnd = rfileHandle; + input->CnnHnd = cachedConnectionID; + input->Intent[0] = accessIntent; + + int32 rc = doItWithLog(); + + return rc; +} + +/** + Interface to QMY_LOCK_OBJECT API. + + See QMY_LOCK_OBJECT documentation for more information about + parameters and return codes. +*/ +int32 db2i_ileBridge::lockObj(FILE_HANDLE defnHandle, + uint64 lockVal, + char lockAction, + char lockType, + char lockTimeout) +{ + DBUG_ASSERT(cachedStateIsCoherent()); + IleParms* parmBlock = parms(); + Qmy_MOLX0100 *input = (Qmy_MOLX0100*)&(parmBlock->inParms); + memset(input, 0, sizeof(*input)); + + input->Format = QMY_LOCK_OBJECT; + input->ShrHnd = defnHandle; + input->LckTimeoutVal = lockVal; + input->Action[0] = lockAction; + input->LckTyp[0] = lockType; + input->LckTimeout[0] = lockTimeout; + input->CnnHnd = cachedConnectionID; + + int32 rc = doItWithLog(); + + return rc; +} + +/** + Interface to QMY_DESCRIBE_CONSTRAINTS API. + + See QMY_DESCRIBE_CONSTRAINTS documentation for more information about + parameters and return codes. +*/ +int32 db2i_ileBridge::constraints(FILE_HANDLE defnHandle, + ILEMemHandle inSpc, + uint32 inSpcLen, + uint32* outLen, + uint32* outCnt) +{ + DBUG_ASSERT(cachedStateIsCoherent()); + IleParms* parmBlock = parms(); + Qmy_MDCT0100 *input = (Qmy_MDCT0100*)&(parmBlock->inParms); + memset(input, 0, sizeof(*input)); + + input->Format = QMY_DESCRIBE_CONSTRAINTS; + input->ShrHnd = defnHandle; + input->CstSpcHnd = (uint64)inSpc; + input->CstSpcLen = inSpcLen; + input->CnnHnd = cachedConnectionID; + + int32 rc = doItWithLog(); + + if (likely(rc == 0)) + { + Qmy_MDCT0100_output* output = (Qmy_MDCT0100_output*)parmBlock->outParms; + DBUG_ASSERT(outLen && outCnt); + *outLen = output->NeededLen; + *outCnt = output->CstCnt; + } + + return rc; +} + + +/** + Interface to QMY_REORGANIZE_TABLE API. + + See QMY_REORGANIZE_TABLE documentation for more information about + parameters and return codes. +*/ +int32 db2i_ileBridge::optimizeTable(FILE_HANDLE defnHandle) +{ + DBUG_ASSERT(cachedStateIsCoherent()); + IleParms* parmBlock = parms(); + Qmy_MRGX0100 *input = (Qmy_MRGX0100*)&(parmBlock->inParms); + memset(input, 0, sizeof(*input)); + + input->Format = QMY_REORGANIZE_TABLE; + input->ShrHnd = defnHandle; + input->CnnHnd = cachedConnectionID; + + int32 rc = doItWithLog(); + + return rc; +} + + +/** + Interface to QMY_PROCESS_COMMITMENT_CONTROL API. + + See QMY_PROCESS_COMMITMENT_CONTROL documentation for more information about + parameters and return codes. +*/ +int32 db2i_ileBridge::commitmentControl(uint8 function) +{ + DBUG_ASSERT(cachedStateIsCoherent()); + IleParms* parmBlock = parms(); + Qmy_MCCX0100 *input = (Qmy_MCCX0100*)&(parmBlock->inParms); + memset(input, 0, sizeof(*input)); + + input->Format = QMY_PROCESS_COMMITMENT_CONTROL; + input->Function[0] = function; + input->CnnHnd = cachedConnectionID; + + int32 rc = doItWithLog(); + + return rc; +} + + +/** + Interface to QMY_PROCESS_SAVEPOINT API. + + See QMY_PROCESS_SAVEPOINT documentation for more information about parameters and + return codes. +*/ +int32 db2i_ileBridge::savepoint(uint8 function, + const char* savepointName) +{ + DBUG_ASSERT(cachedStateIsCoherent()); + DBUG_PRINT("db2i_ileBridge::savepoint",("%d %s", (uint32)function, savepointName)); + + IleParms* parmBlock = parms(); + Qmy_MSPX0100 *input = (Qmy_MSPX0100*)&(parmBlock->inParms); + memset(input, 0, sizeof(*input)); + + char* savPtNam = (char*)(input+1); + + input->Format = QMY_PROCESS_SAVEPOINT; + + if (strlen(savepointName) > MAX_DB2_SAVEPOINTNAME_LENGTH) + { + DBUG_ASSERT(0); + return HA_ERR_GENERIC; + } + strcpy(savPtNam, savepointName); + + input->Function[0] = function; + input->SavPtNamOff = savPtNam - (char*)(input); + input->SavPtNamLen = strlen(savepointName); + input->CnnHnd = cachedConnectionID; + + int32 rc = doItWithLog(); + + return rc; +} + +/** + Do initialization for the QMY_* APIs. + + @parm aspName The name of the relational database to use for all + connections. + + @return 0 if successful; error otherwise +*/ +int32 db2i_ileBridge::initILE(const char* aspName) +{ + // We forego the typical thread-based parms space because MySQL doesn't + // allow us to clean it up before checking for memory leaks. As a result + // we get a complaint about leaked memory on server shutdown. + int32 rc; + char inParms[db2i_ileBridge_MAX_INPARM_SIZE]; + char outParms[db2i_ileBridge_MAX_OUTPARM_SIZE]; + if (rc = registerParmSpace(inParms, outParms)) + { + reportSystemAPIError(rc, NULL); + return rc; + } + + struct ParmBlock + { + Qmy_MINI0100 parms; + } *parmBlock = (ParmBlock*)inParms; + + memset(inParms, 0, sizeof(ParmBlock)); + + parmBlock->parms.Format = QMY_INITIALIZATION; + + char paddedName[18]; + if (strlen(aspName) > sizeof(paddedName)) + { + getErrTxt(DB2I_ERR_BAD_RDB_NAME); + return DB2I_ERR_BAD_RDB_NAME; + } + + memset(paddedName, ' ', sizeof(paddedName)); + memcpy(paddedName, aspName, strlen(aspName)); + convToEbcdic(paddedName, parmBlock->parms.RDBName, strlen(paddedName)); + + rc = doIt(); + + if (rc) + { + reportSystemAPIError(rc, (Qmy_Error_output_t*)outParms); + } + + return rc; +} + +/** + Signal to the QMY_ APIs to perform any cleanup they need to do. +*/ +int32 db2i_ileBridge::exitILE() +{ + IleParms* parmBlock = parms(); + Qmy_MCLN0100 *input = (Qmy_MCLN0100*)&(parmBlock->inParms); + memset(input, 0, sizeof(*input)); + + input->Format = QMY_CLEANUP; + + int32 rc = doIt(); + + if (rc) + { + reportSystemAPIError(rc, (Qmy_Error_output_t*)parmBlock->outParms); + } + + DBUG_PRINT("db2i_ileBridge::exitILE", ("Registered ptrs remaining: %d", registeredPtrs)); +#ifndef DBUG_OFF + if (registeredPtrs != 0) + printf("Oh no! IBMDB2I left some pointers registered. Count was %d.\n", registeredPtrs); +#endif + + // This is needed to prevent SAFE_MALLOC from complaining at process termination. + my_pthread_setspecific_ptr(THR_ILEPARMS, NULL); + free_aligned(parmBlock); + + return rc; + +} + + +/** + Designate the specified addresses as parameter passing buffers. + + @parm in Input to the API will go here; format is defined by the individual API + @parm out Output from the API will be; format is defined by the individual API + + @return 0 if success; error otherwise +*/ +int db2i_ileBridge::registerParmSpace(char* in, char* out) +{ + static const arg_type_t ileSignature[] = { ARG_MEMPTR, ARG_MEMPTR, ARG_END }; + + struct ArgList + { + ILEarglist_base base; + ILEpointer input; + ILEpointer output; + } *arguments; + + char argBuf[sizeof(ArgList)+15]; + arguments = (ArgList*)roundToQuadWordBdy(argBuf); + + arguments->input.s.addr = (address64_t)(in); + arguments->output.s.addr = (address64_t)(out); + + _ILECALL(&functionSymbols[funcRegisterParameterSpaces], + &arguments->base, + ileSignature, + RESULT_INT32); + + return arguments->base.result.s_int32.r_int32; +} + + +/** + Interface to QMY_OBJECT_OVERRIDE API. + + See QMY_OBJECT_OVERRIDE documentation for more information about parameters and + return codes. +*/ +int32 db2i_ileBridge::objectOverride(FILE_HANDLE rfileHandle, + ILEMemHandle buf, + uint32 recordWidth) +{ + DBUG_ASSERT(cachedStateIsCoherent()); + IleParms* parmBlock = parms(); + Qmy_MOOX0100 *input = (Qmy_MOOX0100*)&(parmBlock->inParms); + memset(input, 0, sizeof(*input)); + + input->Format = QMY_OBJECT_OVERRIDE; + input->ObjHnd = rfileHandle; + input->OutSpcHnd = (uint64)buf; + input->NxtRowOff = recordWidth; + input->CnnHnd = cachedConnectionID; + + int32 rc = doItWithLog(); + + return rc; +} + +/** + Interface to QMY_DESCRIBE_OBJECT API for obtaining table stats. + + See QMY_DESCRIBE_OBJECT documentation for more information about parameters and + return codes. +*/ +int32 db2i_ileBridge::retrieveTableInfo(FILE_HANDLE defnHandle, + uint16 dataRequested, + ha_statistics& stats, + ILEMemHandle inSpc) +{ + DBUG_ASSERT(cachedStateIsCoherent()); + IleParms* parmBlock = parms(); + Qmy_MDSO0100 *input = (Qmy_MDSO0100*)&(parmBlock->inParms); + memset(input, 0, sizeof(*input)); + + input->Format = QMY_DESCRIBE_OBJECT; + input->ShrHnd = defnHandle; + input->CnnHnd = cachedConnectionID; + + if (dataRequested & objLength) + input->RtnObjLen[0] = QMY_YES; + if (dataRequested & rowCount) + input->RtnRowCnt[0] = QMY_YES; + if (dataRequested & deletedRowCount) + input->RtnDltRowCnt[0] = QMY_YES; + if (dataRequested & rowsPerKey) + { + input->RowKeyHnd = (uint64)inSpc; + input->RtnRowKey[0] = QMY_YES; + } + if (dataRequested & meanRowLen) + input->RtnMeanRowLen[0] = QMY_YES; + if (dataRequested & lastModTime) + input->RtnModTim[0] = QMY_YES; + if (dataRequested & createTime) + input->RtnCrtTim[0] = QMY_YES; + if (dataRequested & ioCount) + input->RtnEstIoCnt[0] = QMY_YES; + + int32 rc = doItWithLog(); + + if (likely(rc == 0)) + { + Qmy_MDSO0100_output* output = (Qmy_MDSO0100_output*)parmBlock->outParms; + if (dataRequested & objLength) + stats.data_file_length = output->ObjLen; + if (dataRequested & rowCount) + stats.records= output->RowCnt; + if (dataRequested & deletedRowCount) + stats.deleted = output->DltRowCnt; + if (dataRequested & meanRowLen) + stats.mean_rec_length = output->MeanRowLen; + if (dataRequested & lastModTime) + stats.update_time = convertILEtime(output->ModTim); + if (dataRequested & createTime) + stats.create_time = convertILEtime(output->CrtTim); + if (dataRequested & ioCount) + stats.data_file_length = output->EstIoCnt; + } + + return rc; +} + +/** + Interface to QMY_DESCRIBE_OBJECT API for finding index size. + + See QMY_DESCRIBE_OBJECT documentation for more information about parameters and + return codes. +*/ +int32 db2i_ileBridge::retrieveIndexInfo(FILE_HANDLE defnHandle, + uint64* outPageCnt) +{ + DBUG_ASSERT(cachedStateIsCoherent()); + IleParms* parmBlock = parms(); + Qmy_MDSO0100 *input = (Qmy_MDSO0100*)&(parmBlock->inParms); + memset(input, 0, sizeof(*input)); + + input->Format = QMY_DESCRIBE_OBJECT; + input->ShrHnd = defnHandle; + input->CnnHnd = cachedConnectionID; + input->RtnPageCnt[0] = QMY_YES; + + int32 rc = doItWithLog(); + + if (likely(rc == 0)) + { + Qmy_MDSO0100_output* output = (Qmy_MDSO0100_output*)parmBlock->outParms; + *outPageCnt = output->PageCnt; + } + + return rc; +} + + +/** + Interface to QMY_CLOSE_CONNECTION API + + See QMY_CLOSE_CONNECTION documentation for more information about parameters and + return codes. +*/ +int32 db2i_ileBridge::closeConnection(CONNECTION_HANDLE conn) +{ + IleParms* parmBlock = parms(); + Qmy_MCCN0100 *input = (Qmy_MCCN0100*)&(parmBlock->inParms); + memset(input, 0, sizeof(*input)); + + input->Format = QMY_CLOSE_CONNECTION; + input->CnnHnd = conn; + + int32 rc = doItWithLog(); + + return rc; +} + + +/** + Interface to QMY_INTERRUPT API + + See QMY_INTERRUPT documentation for more information about parameters and + return codes. +*/ +int32 db2i_ileBridge::readInterrupt(FILE_HANDLE fileHandle) +{ + DBUG_ASSERT(cachedStateIsCoherent()); + IleParms* parmBlock = parms(); + Qmy_MINT0100 *input = (Qmy_MINT0100*)&(parmBlock->inParms); + memset(input, 0, sizeof(*input)); + + input->Format = QMY_INTERRUPT; + input->CnnHnd = cachedConnectionID; + input->ObjHnd = fileHandle; + + int32 rc = doItWithLog(); + + if (rc == QMY_ERR_END_OF_BLOCK) + { + rc = 0; + DBUG_PRINT("db2i_ileBridge::readInterrupt", ("End of block signalled")); + } + + return rc; +} + +/** + Interface to QMY_READ_ROWS API + + See QMY_READ_ROWS documentation for more information about parameters and + return codes. +*/ +int32 db2i_ileBridge::read(FILE_HANDLE rfileHandle, + ILEMemHandle buf, + char accessIntent, + char commitLevel, + char orientation, + bool asyncRead, + ILEMemHandle rrn, + ILEMemHandle key, + uint32 keylen, + uint16 keyParts, + int pipeFD) +{ + DBUG_ASSERT(cachedStateIsCoherent()); + IleParms* parmBlock = parms(); + Qmy_MRDX0100 *input = (Qmy_MRDX0100*)&(parmBlock->inParms); + memset(input, 0, sizeof(*input)); + + input->Format = QMY_READ_ROWS; + input->CmtLvl[0] = commitLevel; + + input->ObjHnd = rfileHandle; + input->Intent[0] = accessIntent; + input->OutSpcHnd = (uint64)buf; + input->OutRRNSpcHnd = (uint64)rrn; + input->RtnData[0] = QMY_RETURN_DATA; + + if (key) + { + input->KeySpcHnd = (uint64)key; + input->KeyColsLen = keylen; + input->KeyColsNbr = keyParts; + } + + input->Async[0] = (asyncRead ? QMY_YES : QMY_NO); + input->PipeDesc = pipeFD; + input->Orientation[0] = orientation; + input->CnnHnd = cachedConnectionID; + + int32 rc = doItWithLog(); + + // QMY_ERR_END_OF_BLOCK is informational only, so we ignore it. + if (rc == QMY_ERR_END_OF_BLOCK) + { + rc = 0; + DBUG_PRINT("db2i_ileBridge::read", ("End of block signalled")); + } + + return rc; +} + + +/** + Interface to QMY_QUIESCE_OBJECT API + + See QMY_QUIESCE_OBJECT documentation for more information about parameters and + return codes. +*/ +int32 db2i_ileBridge::quiesceFileInstance(FILE_HANDLE rfileHandle) +{ + IleParms* parmBlock = parms(); + Qmy_MQSC0100 *input = (Qmy_MQSC0100*)&(parmBlock->inParms); + memset(input, 0, sizeof(*input)); + + input->Format = QMY_QUIESCE_OBJECT; + input->ObjHnd = rfileHandle; + + int32 rc = doItWithLog(); + +#ifndef DBUG_OFF + if (unlikely(rc)) + { + DBUG_ASSERT(0); + } +#endif + + return rc; +} + +void db2i_ileBridge::PreservedHandleList::add(const char* newname, FILE_HANDLE newhandle) +{ + NameHandlePair *newPair = (NameHandlePair*)my_malloc(sizeof(NameHandlePair), MYF(MY_WME)); + + newPair->next = head; + head = newPair; + + strcpy(newPair->name, newname); + newPair->handle = newhandle; + DBUG_PRINT("db2i_ileBridge", ("Added handle %d for %s", uint32(newhandle), newname)); +} + + +FILE_HANDLE db2i_ileBridge::PreservedHandleList::findAndRemove(const char* fileName) +{ + NameHandlePair* current = head; + NameHandlePair* prev = NULL; + + while (current) + { + NameHandlePair* next = current->next; + if (strcmp(fileName, current->name) == 0) + { + FILE_HANDLE tmp = current->handle; + if (prev) + prev->next = next; + if (current == head) + head = next; + my_free(current, MYF(0)); + DBUG_PRINT("db2i_ileBridge", ("Found handle %d for %s", uint32(tmp), fileName)); + return tmp; + } + prev = current; + current = next; + } + + return 0; +} + + +IleParms* db2i_ileBridge::initParmsForThread() +{ + + IleParms* p = (IleParms*)malloc_aligned(sizeof(IleParms)); + DBUG_ASSERT((uint64)(&(p->outParms))% 16 == 0); // Guarantee that outParms are aligned correctly + + if (likely(p)) + { + int32 rc = registerParmSpace((p->inParms), (p->outParms)); + if (likely(rc == 0)) + { + my_pthread_setspecific_ptr(THR_ILEPARMS, p); + DBUG_PRINT("db2i_ileBridge", ("Inited space for parms")); + return p; + } + else + reportSystemAPIError(rc, NULL); + } + + return NULL; +} + diff --git a/storage/ibmdb2i/db2i_ileBridge.h b/storage/ibmdb2i/db2i_ileBridge.h new file mode 100644 index 00000000000..7e4e8216cfc --- /dev/null +++ b/storage/ibmdb2i/db2i_ileBridge.h @@ -0,0 +1,488 @@ +/* +Licensed Materials - Property of IBM +DB2 Storage Engine Enablement +Copyright IBM Corporation 2007,2008 +All rights reserved + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + (a) Redistributions of source code must retain this list of conditions, the + copyright notice in section {d} below, and the disclaimer following this + list of conditions. + (b) Redistributions in binary form must reproduce this list of conditions, the + copyright notice in section (d) below, and the disclaimer following this + list of conditions, in the documentation and/or other materials provided + with the distribution. + (c) The name of IBM may not be used to endorse or promote products derived from + this software without specific prior written permission. + (d) The text of the required copyright notice is: + Licensed Materials - Property of IBM + DB2 Storage Engine Enablement + Copyright IBM Corporation 2007,2008 + All rights reserved + +THIS SOFTWARE IS PROVIDED BY IBM CORPORATION "AS IS" AND ANY EXPRESS OR IMPLIED +WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT +SHALL IBM CORPORATION BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT +OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT INCLUDING NEGLIGENCE OR OTHERWISE) ARISING +IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + + +#ifndef DB2I_ILEBRIDGE_H +#define DB2I_ILEBRIDGE_H + +#include "db2i_global.h" +#include "mysql_priv.h" +#include "as400_types.h" +#include "as400_protos.h" +#include "qmyse.h" +#include "db2i_errors.h" + +typedef uint64_t FILE_HANDLE; +typedef my_thread_id CONNECTION_HANDLE; +const char SAVEPOINT_NAME[] = {0xD4,0xE2,0xD7,0xC9,0xD5,0xE3,0xC5,0xD9,0xD5,0x0}; +const uint32 TACIT_ERRORS_SIZE=2; + +enum db2i_InfoRequestSpec +{ + objLength = 1, + rowCount = 2, + deletedRowCount = 4, + rowsPerKey = 8, + meanRowLen = 16, + lastModTime = 32, + createTime = 64, + ioCount = 128 +}; + +extern handlerton *ibmdb2i_hton; + +const uint32 db2i_ileBridge_MAX_INPARM_SIZE = 512; +const uint32 db2i_ileBridge_MAX_OUTPARM_SIZE = 512; + +extern pthread_key(IleParms*, THR_ILEPARMS); +struct IleParms +{ + char inParms[db2i_ileBridge_MAX_INPARM_SIZE]; + char outParms[db2i_ileBridge_MAX_OUTPARM_SIZE]; +}; + +/** + @class db2i_ileBridge + + Implements a connection-based interface to the QMY_* APIs + + @details Each client connection that touches an IBMDB2I table has a "bridge" + associated with it. This bridge is constructed on first use and provides a + more C-like interface to the APIs. As well, it is reponsible for tracking + connection scoped information such as statement transaction state and error + message text. The bridge is destroyed when the connection ends. +*/ +class db2i_ileBridge +{ + enum ileFuncs + { + funcRegisterParameterSpaces, + funcRegisterSpace, + funcUnregisterSpace, + funcProcessRequest, + funcListEnd + }; + + static db2i_ileBridge* globalBridge; +public: + + + static int setup(); + static void takedown(); + + /** + Obtain a pointer to the bridge for the current connection. + + If a MySQL client connection is on the stack, we get the associated brideg. + Otherwise, we use the globalBridge. + */ + static db2i_ileBridge* getBridgeForThread() + { + THD* thd = current_thd; + if (likely(thd)) + return getBridgeForThread(thd); + + return globalBridge; + } + + /** + Obtain a pointer to the bridge for the specified connection. + + If a bridge exists already, we return it immediately. Otherwise, prepare + a new bridge for the connection. + */ + static db2i_ileBridge* getBridgeForThread(const THD* thd) + { + void* thdData = *thd_ha_data(thd, ibmdb2i_hton); + if (likely(thdData != NULL)) + return (db2i_ileBridge*)(thdData); + + db2i_ileBridge* newBridge = createNewBridge(thd->thread_id); + *thd_ha_data(thd, ibmdb2i_hton) = (void*)newBridge; + return newBridge; + } + + static void destroyBridgeForThread(const THD* thd); + static void registerPtr(const void* ptr, ILEMemHandle* receiver); + static void unregisterPtr(ILEMemHandle handle); + int32 allocateFileDefn(ILEMemHandle definitionSpace, + ILEMemHandle handleSpace, + uint16 fileCount, + const char* schemaName, + uint16 schemaNameLength, + ILEMemHandle formatSpace, + uint32 formatSpaceLen); + int32 allocateFileInstance(FILE_HANDLE defnHandle, + ILEMemHandle inuseSpace, + FILE_HANDLE* instance); + int32 deallocateFile(FILE_HANDLE fileHandle, + bool postDropTable=FALSE); + int32 read(FILE_HANDLE rfileHandle, + ILEMemHandle buf, + char accessIntent, + char commitLevel, + char orientation, + bool asyncRead = FALSE, + ILEMemHandle rrn = 0, + ILEMemHandle key = 0, + uint32 keylen = 0, + uint16 keyParts = 0, + int pipeFD = -1); + int32 readByRRN(FILE_HANDLE rfileHandle, + ILEMemHandle buf, + uint32 inRRN, + char accessIntent, + char commitLevel); + int32 writeRows(FILE_HANDLE rfileHandle, + ILEMemHandle buf, + char commitLevel, + int64* outIdVal, + bool* outIdGen, + uint32* dupKeyRRN, + char** dupKeyName, + uint32* dupKeyNameLen, + uint32* outIdIncrement); + uint32 execSQL(const char* statement, + uint32 statementCount, + uint8 commitLevel, + bool autoCreateSchema = FALSE, + bool dropSchema = FALSE, + bool noCommit = FALSE, + FILE_HANDLE fileHandle = 0); + int32 prepOpen(const char* statement, + FILE_HANDLE* rfileHandle, + uint32* recLength); + int32 deleteRow(FILE_HANDLE rfileHandle, + uint32 rrn); + int32 updateRow(FILE_HANDLE rfileHandle, + uint32 rrn, + ILEMemHandle buf, + uint32* dupKeyRRN, + char** dupKeyName, + uint32* dupKeyNameLen); + int32 commitmentControl(uint8 function); + int32 savepoint(uint8 function, + const char* savepointName); + int32 recordsInRange(FILE_HANDLE rfileHandle, + ILEMemHandle inSpc, + uint32 inKeyCnt, + uint32 inLiteralCnt, + uint32 inBoundsOff, + uint32 inLitDefOff, + uint32 inLiteralsOff, + uint32 inCutoff, + uint32 inSpcLen, + uint16 inEndByte, + uint64* outRecCnt, + uint16* outRtnCode); + int32 rrlslck(FILE_HANDLE rfileHandle, + char accessIntent); + int32 lockObj(FILE_HANDLE rfileHandle, + uint64 inTimeoutVal, + char inAction, + char inLockType, + char inTimeout); + int32 constraints(FILE_HANDLE rfileHandle, + ILEMemHandle inSpc, + uint32 inSpcLen, + uint32* outLen, + uint32* outCnt); + int32 optimizeTable(FILE_HANDLE rfileHandle); + static int32 initILE(const char* aspName); + int32 initFileForIO(FILE_HANDLE rfileHandle, + char accessIntent, + char commitLevel, + uint16* inRecSize, + uint16* inRecNullOffset, + uint16* outRecSize, + uint16* outRecNullOffset); + int32 readInterrupt(FILE_HANDLE fileHandle); + static int32 exitILE(); + + int32 objectOverride(FILE_HANDLE rfileHandle, + ILEMemHandle buf, + uint32 recordWidth = 0); + + int32 retrieveTableInfo(FILE_HANDLE rfileHandle, + uint16 dataRequested, + ha_statistics& stats, + ILEMemHandle inSpc = NULL); + + int32 retrieveIndexInfo(FILE_HANDLE rfileHandle, + uint64* outPageCnt); + + int32 closeConnection(CONNECTION_HANDLE conn); + int32 quiesceFileInstance(FILE_HANDLE rfileHandle); + + /** + Mark the beginning of a "statement transaction" + + @detail MySQL "statement transactions" (see sql/handler.cc) are implemented + as DB2 savepoints having a predefined name. + + @return 0 if successful; error otherwise + */ + uint32 beginStmtTx() + { + DBUG_ENTER("db2i_ileBridge::beginStmtTx"); + if (stmtTxActive) + DBUG_RETURN(0); + + stmtTxActive = true; + + DBUG_RETURN(savepoint(QMY_SET_SAVEPOINT, SAVEPOINT_NAME)); + } + + /** + Commit a "statement transaction" + + @return 0 if successful; error otherwise + */ + uint32 commitStmtTx() + { + DBUG_ENTER("db2i_ileBridge::commitStmtTx"); + DBUG_ASSERT(stmtTxActive); + stmtTxActive = false; + DBUG_RETURN(savepoint(QMY_RELEASE_SAVEPOINT, SAVEPOINT_NAME)); + } + + /** + Roll back a "statement transaction" + + @return 0 if successful; error otherwise + */ + uint32 rollbackStmtTx() + { + DBUG_ENTER("db2i_ileBridge::rollbackStmtTx"); + DBUG_ASSERT(stmtTxActive); + stmtTxActive = false; + DBUG_RETURN(savepoint(QMY_ROLLBACK_SAVEPOINT, SAVEPOINT_NAME)); + } + + + /** + Provide storage for generating error messages. + + This storage must persist until the error message is retrieved from the + handler instance. It is for this reason that we associate it with the bridge. + + @return Pointer to heap storage of MYSQL_ERRMSG_SIZE bytes + */ + char* getErrorStorage() + { + if (!connErrText) + { + connErrText = (char*)my_malloc(MYSQL_ERRMSG_SIZE, MYF(MY_WME)); + if (connErrText) connErrText[0] = 0; + } + + return connErrText; + } + + /** + Free storage for generating error messages. + */ + void freeErrorStorage() + { + if (likely(connErrText)) + { + my_free(connErrText, MYF(0)); + connErrText = NULL; + } + } + + + /** + Store a file handle for later retrieval. + + If deallocateFile encounters a lock when trying to perform its operation, + the file remains allocated but must be deallocated later. This function + provides a way for the connection to "remember" that this deallocation is + still needed. + + @param newname The name of the file to be added + @param newhandle The handle associated with newname + + */ + void preserveHandle(const char* newname, FILE_HANDLE newhandle) + { + pendingLockedHandles.add(newname, newhandle); + } + + /** + Retrieve a file handle stored by preserveHandle(). + + @param name The name of the file to be retrieved. + + @return The handle associated with name + */ + FILE_HANDLE findAndRemovePreservedHandle(const char* name) + { + return pendingLockedHandles.findAndRemove(name); + } + + /** + Indicate which error messages should be suppressed on the next API call + + These functions are useful for ensuring that the provided error numbers + are returned if a failure occurs but do not cause a spurious error message + to be returned. + + @return A pointer to this instance + */ + db2i_ileBridge* expectErrors(int32 er1) + { + tacitErrors[0]=er1; + return this; + } + + db2i_ileBridge* expectErrors(int32 er1, int32 er2) + { + tacitErrors[0]=er1; + tacitErrors[1]=er2; + return this; + } + + /** + Obtain the IBM i system message that accompanied the last API failure. + + @return A pointer to the 7 character message ID. + */ + const char* getErrorMsgID() + { + return ((Qmy_Error_output_t*)parms()->outParms)->MsgId; + } + + /** + Convert an API error code into the equivalent MySQL error code (if any) + + @param rc The QMYSE API error code + + @return If an equivalent exists, the MySQL error code; else rc + */ + static int32 translateErrorCode(int32 rc) + { + if (likely(rc == 0)) + return 0; + + switch (rc) + { + case QMY_ERR_KEY_NOT_FOUND: + return HA_ERR_KEY_NOT_FOUND; + case QMY_ERR_DUP_KEY: + return HA_ERR_FOUND_DUPP_KEY; + case QMY_ERR_END_OF_FILE: + return HA_ERR_END_OF_FILE; + case QMY_ERR_LOCK_TIMEOUT: + return HA_ERR_LOCK_WAIT_TIMEOUT; + case QMY_ERR_CST_VIOLATION: + return HA_ERR_NO_REFERENCED_ROW; + case QMY_ERR_TABLE_NOT_FOUND: + return HA_ERR_NO_SUCH_TABLE; + case QMY_ERR_NON_UNIQUE_KEY: + return ER_DUP_ENTRY; + } + return rc; + } + +private: + + static db2i_ileBridge* createNewBridge(CONNECTION_HANDLE connID); + static void destroyBridge(db2i_ileBridge* bridge); + static int registerParmSpace(char* in, char* out); + static int32 doIt(); + int32 doItWithLog(); + + static _ILEpointer *functionSymbols; ///< Array of ILE function pointers + CONNECTION_HANDLE cachedConnectionID; ///< The associated connection + bool stmtTxActive; ///< Inside statement transaction + char *connErrText; ///< Storage for error message + int32 tacitErrors[TACIT_ERRORS_SIZE]; ///< List of errors to be suppressed + + static IleParms* initParmsForThread(); + + /** + Get space for passing parameters to the QMY_* APIs + + @details A fixed-length parameter passing space is associated with each + pthread. This space is allocated and registered by initParmsForThread() + the first time a pthread works with a bridge. The space is cached away + and remains available until the pthread ends. It became necessary to + disassociate the parameter space from the bridge in order to support + future enhancements to MySQL that sever the one-to-one relationship between + pthreads and user connections. The QMY_* APIs scope a registered parameter + space to the thread that executes the register operation. + */ + static IleParms* parms() + { + IleParms* p = my_pthread_getspecific_ptr(IleParms*, THR_ILEPARMS); + if (likely(p)) + return p; + + return initParmsForThread(); + } + + class PreservedHandleList + { + friend db2i_ileBridge* db2i_ileBridge::createNewBridge(CONNECTION_HANDLE); + public: + void add(const char* newname, FILE_HANDLE newhandle); + FILE_HANDLE findAndRemove(const char* fileName); + + private: + struct NameHandlePair + { + char name[FN_REFLEN]; + FILE_HANDLE handle; + NameHandlePair* next; + }* head; + } pendingLockedHandles; + + +#ifndef DBUG_OFF + bool cachedStateIsCoherent() + { + return (current_thd->thread_id == cachedConnectionID); + } + + friend void db2i_ileBridge::unregisterPtr(ILEMemHandle); + friend void db2i_ileBridge::registerPtr(const void*, ILEMemHandle*); + static uint32 registeredPtrs; +#endif +}; + + + +#endif diff --git a/storage/ibmdb2i/db2i_ioBuffers.cc b/storage/ibmdb2i/db2i_ioBuffers.cc new file mode 100644 index 00000000000..e503bd0e9f1 --- /dev/null +++ b/storage/ibmdb2i/db2i_ioBuffers.cc @@ -0,0 +1,332 @@ +/* +Licensed Materials - Property of IBM +DB2 Storage Engine Enablement +Copyright IBM Corporation 2007,2008 +All rights reserved + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + (a) Redistributions of source code must retain this list of conditions, the + copyright notice in section {d} below, and the disclaimer following this + list of conditions. + (b) Redistributions in binary form must reproduce this list of conditions, the + copyright notice in section (d) below, and the disclaimer following this + list of conditions, in the documentation and/or other materials provided + with the distribution. + (c) The name of IBM may not be used to endorse or promote products derived from + this software without specific prior written permission. + (d) The text of the required copyright notice is: + Licensed Materials - Property of IBM + DB2 Storage Engine Enablement + Copyright IBM Corporation 2007,2008 + All rights reserved + +THIS SOFTWARE IS PROVIDED BY IBM CORPORATION "AS IS" AND ANY EXPRESS OR IMPLIED +WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT +SHALL IBM CORPORATION BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT +OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT INCLUDING NEGLIGENCE OR OTHERWISE) ARISING +IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + + +#include "db2i_ioBuffers.h" + +/** + Request another block of rows + + Request the next set of rows from DB2. This must only be called after + newReadRequest(). + + @param orientation The direction to use when reading through the table. +*/ +void IOAsyncReadBuffer::loadNewRows(char orientation) +{ + rewind(); + maxRows() = rowsToBlock; + + DBUG_PRINT("db2i_ioBuffers::loadNewRows", ("Requesting %d rows, async = %d", rowsToBlock, readIsAsync)); + + rc = getBridge()->expectErrors(QMY_ERR_END_OF_BLOCK, QMY_ERR_LOB_SPACE_TOO_SMALL) + ->read(file, + ptr(), + accessIntent, + commitLevel, + orientation, + readIsAsync, + rrnList, + 0, + 0, + 0); + + DBUG_PRINT("db2i_ioBuffers::loadNewRows", ("recordsRead: %d, rc: %d", (uint32)rowCount(), rc)); + + + *releaseRowNeeded = true; + + if (rc == QMY_ERR_END_OF_BLOCK) + { + // This is really just an informational error, so we ignore it. + rc = 0; + DBUG_PRINT("db2i_ioBuffers::loadNewRows", ("End of block signalled")); + } + else if (rc == QMY_ERR_END_OF_FILE) + { + // If we reach EOF or end-of-key, DB2 guarantees that no rows will be locked. + rc = HA_ERR_END_OF_FILE; + *releaseRowNeeded = false; + } + else if (rc == QMY_ERR_KEY_NOT_FOUND) + { + rc = HA_ERR_KEY_NOT_FOUND; + *releaseRowNeeded = false; + } + + if (rc) closePipe(); +} + + +/** + Empty the message pipe to prepare for another read. +*/ +void IOAsyncReadBuffer::drainPipe() +{ + DBUG_ASSERT(pipeState == PendingFullBufferMsg); + PipeRpy_t msg[32]; + int bytes; + PipeRpy_t* lastMsg; + while ((bytes = read(msgPipe, msg, sizeof(msg))) > 0) + { + DBUG_PRINT("db2i_ioBuffers::drainPipe",("Pipe returned %d bytes", bytes)); + lastMsg = &msg[bytes / (sizeof(msg[0]))-1]; + if (lastMsg->CumRowCnt == maxRows() || + lastMsg->RtnCod != 0) + { + pipeState = ConsumedFullBufferMsg; + break; + } + + } + DBUG_PRINT("db2i_ioBuffers::drainPipe",("rc = %d, rows = %d, max = %d", lastMsg->RtnCod, lastMsg->CumRowCnt, (uint32)maxRows())); +} + + +/** + Poll the message pipe for async read messages + + Only valid in async + + @param orientation The direction to use when reading through the table. +*/ +void IOAsyncReadBuffer::pollNextRow(char orientation) +{ + DBUG_ASSERT(readIsAsync); + + // Handle the case in which the buffer is full. + if (rowCount() == maxRows()) + { + // If we haven't read to the end, exit here. + if (readCursor < rowCount()) + return; + + if (pipeState == PendingFullBufferMsg) + drainPipe(); + if (pipeState == ConsumedFullBufferMsg) + loadNewRows(orientation); + } + + if (!rc) + { + PipeRpy_t* lastMsg = NULL; + while (true) + { + PipeRpy_t msg[32]; + int bytes = read(msgPipe, msg, sizeof(msg)); + DBUG_PRINT("db2i_ioBuffers::pollNextRow",("Pipe returned %d bytes", bytes)); + + if (unlikely(bytes < 0)) + { + DBUG_PRINT("db2i_ioBuffers::pollNextRow", ("Error")); + rc = errno; + break; + } + else if (bytes == 0) + break; + + DBUG_ASSERT(bytes % sizeof(msg[0]) == 0); + lastMsg = &msg[bytes / (sizeof(msg[0]))-1]; + + if (lastMsg->RtnCod || (lastMsg->CumRowCnt == usedRows())) + { + rc = lastMsg->RtnCod; + break; + } + } + + *releaseRowNeeded = true; + + if (rc == QMY_ERR_END_OF_BLOCK) + rc = 0; + else if (rc == QMY_ERR_END_OF_FILE) + { + // If we reach EOF or end-of-key, DB2 guarantees that no rows will be locked. + rc = HA_ERR_END_OF_FILE; + *releaseRowNeeded = false; + } + else if (rc == QMY_ERR_KEY_NOT_FOUND) + { + rc = HA_ERR_KEY_NOT_FOUND; + *releaseRowNeeded = false; + } + + if (lastMsg) + DBUG_PRINT("db2i_ioBuffers::pollNextRow", ("Good data: rc=%d; rows=%d; usedRows=%d", lastMsg->RtnCod, lastMsg->CumRowCnt, (uint32)usedRows())); + if (lastMsg && likely(!rc)) + { + if (lastMsg->CumRowCnt < maxRows()) + pipeState = PendingFullBufferMsg; + else + pipeState = ConsumedFullBufferMsg; + + DBUG_ASSERT(lastMsg->CumRowCnt <= usedRows()); + + } + DBUG_ASSERT(rowCount() <= getRowCapacity()); + } + DBUG_PRINT("db2i_ioBuffers::pollNextRow", ("filledRows: %d, rc: %d", rowCount(), rc)); + if (rc) closePipe(); +} + + +/** + Prepare for the destruction of the row buffer storage. +*/ +void IOAsyncReadBuffer::prepForFree() +{ + interruptRead(); + rewind(); + IORowBuffer::prepForFree(); +} + + +/** + Initialize the newly allocated storage. + + @param sizeChanged Indicates whether the storage capacity is being changed. +*/ +void IOAsyncReadBuffer::initAfterAllocate(bool sizeChanged) +{ + rewind(); + + if (sizeChanged || ((void*)rrnList == NULL)) + rrnList.realloc(getRowCapacity() * sizeof(uint32)); +} + + +/** + Send an initial read request + + @param infile The file (table/index) being read from + @param orientation The orientation to use for this read request + @param rowsToBuffer The number of rows to request each time + @param useAsync Whether reads should be performed asynchronously. + @param key The key to use (if any) + @param keyLength The length of key (if any) + @param keyParts The number of columns in the key (if any) + +*/ +void IOAsyncReadBuffer::newReadRequest(FILE_HANDLE infile, + char orientation, + uint32 rowsToBuffer, + bool useAsync, + ILEMemHandle key, + int keyLength, + int keyParts) +{ + DBUG_ENTER("db2i_ioBuffers::newReadRequest"); + DBUG_ASSERT(rowsToBuffer <= getRowCapacity()); +#ifndef DBUG_OFF + if (readCursor < rowCount()) + DBUG_PRINT("PERF:",("Wasting %d buffered rows!\n", rowCount() - readCursor)); +#endif + + int fildes[2]; + int ileDescriptor = QMY_REUSE; + + closePipe(); + + if (likely(useAsync)) + { + if (rowsToBuffer == 1) + { + // Async provides little or no benefit for single row reads, so we turn it off + DBUG_PRINT("db2i_ioBuffers::newReadRequest", ("Disabling async")); + useAsync = false; + } + else + { + rc = pipe(fildes); + if (rc) DBUG_VOID_RETURN; + + // Translate the pipe write descriptor into the equivalent ILE descriptor + rc = fstatx(fildes[1], (struct stat*)&ileDescriptor, sizeof(ileDescriptor), STX_XPFFD_PASE); + if (rc) + { + close(fildes[0]); + close(fildes[1]); + DBUG_VOID_RETURN; + } + pipeState = Untouched; + msgPipe = fildes[0]; + + DBUG_PRINT("db2i_ioBuffers::newReadRequest", ("Opened pipe %d", fildes[0])); + } + } + + file = infile; + readIsAsync = useAsync; + rowsToBlock = rowsToBuffer; + + rewind(); + maxRows() = 1; + rc = getBridge()->expectErrors(QMY_ERR_END_OF_BLOCK, QMY_ERR_LOB_SPACE_TOO_SMALL) + ->read(file, + ptr(), + accessIntent, + commitLevel, + orientation, + useAsync, + rrnList, + key, + keyLength, + keyParts, + ileDescriptor); + + // Having shared the pipe with ILE, we relinquish our claim on the write end + // of the pipe. + if (useAsync) + close(fildes[1]); + + // If we reach EOF or end-of-key, DB2 guarantees that no rows will be locked. + if (rc == QMY_ERR_END_OF_FILE) + { + rc = HA_ERR_END_OF_FILE; + *releaseRowNeeded = false; + } + else if (rc == QMY_ERR_KEY_NOT_FOUND) + { + if (rowCount()) + rc = HA_ERR_END_OF_FILE; + else + rc = HA_ERR_KEY_NOT_FOUND; + *releaseRowNeeded = false; + } + else + *releaseRowNeeded = true; + + DBUG_VOID_RETURN; +} diff --git a/storage/ibmdb2i/db2i_ioBuffers.h b/storage/ibmdb2i/db2i_ioBuffers.h new file mode 100644 index 00000000000..40c88725ef9 --- /dev/null +++ b/storage/ibmdb2i/db2i_ioBuffers.h @@ -0,0 +1,411 @@ +/* +Licensed Materials - Property of IBM +DB2 Storage Engine Enablement +Copyright IBM Corporation 2007,2008 +All rights reserved + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + (a) Redistributions of source code must retain this list of conditions, the + copyright notice in section {d} below, and the disclaimer following this + list of conditions. + (b) Redistributions in binary form must reproduce this list of conditions, the + copyright notice in section (d) below, and the disclaimer following this + list of conditions, in the documentation and/or other materials provided + with the distribution. + (c) The name of IBM may not be used to endorse or promote products derived from + this software without specific prior written permission. + (d) The text of the required copyright notice is: + Licensed Materials - Property of IBM + DB2 Storage Engine Enablement + Copyright IBM Corporation 2007,2008 + All rights reserved + +THIS SOFTWARE IS PROVIDED BY IBM CORPORATION "AS IS" AND ANY EXPRESS OR IMPLIED +WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT +SHALL IBM CORPORATION BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT +OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT INCLUDING NEGLIGENCE OR OTHERWISE) ARISING +IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + + +/** + @file db2i_ioBuffers.h + + @brief Buffer classes used for interacting with QMYSE read/write buffers. + +*/ + + +#include "db2i_validatedPointer.h" +#include "mysql_priv.h" +#include +#include +#include + +// Needed for compilers which do not include fstatx in standard headers. +extern "C" int fstatx(int, struct stat *, int, int); + +/** + Basic row buffer + + Provides the basic structure and methods needed for communicating + with QMYSE I/O APIs. + + @details All QMYSE I/O apis use a buffer that is structured as two integer + row counts (max and used) and storage for some number of rows. The row counts + are both input and output for the API, and their usage depends on the + particular API invoked. This class encapsulates that buffer definition. +*/ +class IORowBuffer +{ + public: + IORowBuffer() : allocSize(0), rowLength(0) {;} + ~IORowBuffer() { freeBuf(); } + ValidatedPointer& ptr() { return data; } + + /** + Sets up the buffer to hold the size indicated. + + @param rowLen length of the rows that will be stored in this buffer + @param size buffer size requested + */ + void allocBuf(uint32 rowLen, uint32 size) + { + uint32 newSize = size + sizeof(BufferHdr_t); + // If the internal structure of the row is changing, we need to + // remember this and notify the subclasses via initAfterAllocate(); + bool formatChanged = ((size/rowLen) != rowCapacity); + + if (newSize > allocSize) + { + this->freeBuf(); + data.alloc(newSize); + if (likely((void*)data)) + allocSize = newSize; + } + + if (likely((void*)data)) + { + DBUG_ASSERT((uint64)(void*)data % 16 == 0); + rowLength = rowLen; + rowCapacity = size / rowLength; + initAfterAllocate(formatChanged); + } + else + { + allocSize = 0; + rowCapacity = 0; + } + + DBUG_PRINT("db2i_ioBuffers::allocBuf",("rowCapacity = %d", rowCapacity)); + } + + void zeroBuf() + { + memset(data, 0, allocSize); + } + + void freeBuf() + { + if (likely(allocSize)) + { + prepForFree(); + DBUG_PRINT("IORowBuffer::freeBuf",("Freeing 0x%p", (char*)data)); + data.dealloc(); + } + } + + char* getRowN(uint32 n) + { + if (unlikely(n >= getRowCapacity())) + return NULL; + return (char*)data + sizeof(BufferHdr_t) + (rowLength * n); + }; + + uint32 getRowCapacity() const {return rowCapacity;} + + protected: + /** + Called prior to freeing buffer storage so that subclasses can do + any required cleanup + */ + virtual void prepForFree() + { + allocSize = 0; + rowCapacity = 0; + } + + /** + Called after buffer storage so that subclasses can do any required setup. + */ + virtual void initAfterAllocate(bool sizeChanged) { return;} + + ValidatedPointer data; + uint32 allocSize; + uint32 rowCapacity; + uint32 rowLength; + uint32& usedRows() const { return ((BufferHdr_t*)(char*)data)->UsedRowCnt; } + uint32& maxRows() const {return ((BufferHdr_t*)(char*)data)->MaxRowCnt; } +}; + + +/** + Write buffer + + Implements methods for inserting data into a row buffer for use with the + QMY_WRITE and QMY_UPDATE APIs. + + @details The max row count defines how many rows are in the buffer. The used + row count is updated by QMYSE to indicate how many rows have been + successfully written. +*/ +class IOWriteBuffer : public IORowBuffer +{ + public: + bool endOfBuffer() const {return (maxRows() == getRowCapacity());} + + char* addRow() + { + return getRowN(maxRows()++); + } + + void resetAfterWrite() + { + maxRows() = 0; + } + + void deleteRow() + { + --maxRows(); + } + + uint32 rowCount() const {return maxRows();} + + uint32 rowsWritten() const {return usedRows()-1;} + + private: + void initAfterAllocate(bool sizeChanged) {maxRows() = 0; usedRows() = 0;} +}; + + +/** + Read buffer + + Implements methods for reading data from and managing a row buffer for use + with the QMY_READ APIs. This is primarily for use with metainformation queries. +*/ +class IOReadBuffer : public IORowBuffer +{ + public: + + IOReadBuffer() {;} + IOReadBuffer(uint32 rows, uint32 rowLength) + { + allocBuf(rows, rows * rowLength); + maxRows() = rows; + } + + uint32 rowCount() {return usedRows();} + void setRowsToProcess(uint32 rows) { maxRows() = rows; } +}; + + +/** + Read buffer + + Implements methods for reading data from and managing a row buffer for use + with the QMY_READ APIs. + + @details This class supports both sync and async read modes. The max row + count defines the number of rows that are requested to be read. The used row + count defines how many rows have been read. Sync mode is reasonably + straightforward, but async mode has a complex system of communicating with + QMYSE that is optimized for low latency. In async mode, the used row count is + updated continuously by QMYSE as rows are read. At the same time, messages are + sent to the associated pipe indicating that a row has been read. As long as + the internal read cursor lags behind the used row count, the pipe is never + consulted. But if the internal read cursor "catches up to" the used row count, + then we block on the pipe until we find a message indicating that a new row + has been read or that an error has occurred. +*/ +class IOAsyncReadBuffer : public IOReadBuffer +{ + public: + IOAsyncReadBuffer() : + file(0), readIsAsync(false), msgPipe(QMY_REUSE), bridge(NULL) + { + } + + ~IOAsyncReadBuffer() + { + interruptRead(); + rrnList.dealloc(); + } + + + /** + Signal read operation complete + + Indicates that the storage engine requires no more data from the table. + Must be called between calls to newReadRequest(). + */ + void endRead() + { +#ifndef DBUG_OFF + if (readCursor < rowCount()) + DBUG_PRINT("PERF:",("Wasting %d buffered rows!\n", rowCount() - readCursor)); +#endif + interruptRead(); + + file = 0; + bridge = NULL; + } + + /** + Update data that may change on each read operation + */ + void update(char newAccessIntent, + bool* newReleaseRowNeeded, + char commitLvl) + { + accessIntent = newAccessIntent; + releaseRowNeeded = newReleaseRowNeeded; + commitLevel = commitLvl; + } + + /** + Read the next row in the table. + + Return a pointer to the next row in the table, where "next" is defined + by the orientation. + + @param orientaton + @param[out] rrn The relative record number of the row returned. Not reliable + if NULL is returned by this function. + + @return Pointer to the row. Null if no more rows are available or an error + occurred. + */ + char* readNextRow(char orientation, uint32& rrn) + { + DBUG_PRINT("db2i_ioBuffers::readNextRow", ("readCursor: %d, filledRows: %d, rc: %d", readCursor, rowCount(), rc)); + + while (readCursor >= rowCount() && !rc) + { + if (!readIsAsync) + loadNewRows(orientation); + else + pollNextRow(orientation); + } + + if (readCursor >= rowCount()) + return NULL; + + rrn = rrnList[readCursor]; + return getRowN(readCursor++); + } + + /** + Retrieve the return code generated by the last operation. + + @return The return code, translated to the appropriate HA_ERR_* + value if possible. + */ + int32 lastrc() + { + return db2i_ileBridge::translateErrorCode(rc); + } + + void rewind() + { + readCursor = 0; + rc = 0; + usedRows() = 0; + } + + bool reachedEOD() { return EOD; } + + void newReadRequest(FILE_HANDLE infile, + char orientation, + uint32 rowsToBuffer, + bool useAsync, + ILEMemHandle key, + int keyLength, + int keyParts); + + private: + + /** + End any running async read operation. + */ + void interruptRead() + { + closePipe(); + if (file && readIsAsync && (rc == 0) && (rowCount() < getRowCapacity())) + { + DBUG_PRINT("IOReadBuffer::interruptRead", ("PERF: Interrupting %d", (uint32)file)); + getBridge()->readInterrupt(file); + } + } + + void closePipe() + { + if (msgPipe != QMY_REUSE) + { + DBUG_PRINT("db2i_ioBuffers::closePipe", ("Closing pipe %d", msgPipe)); + close(msgPipe); + msgPipe = QMY_REUSE; + } + } + + /** + Get a pointer to the active ILE bridge. + + Getting the bridge pointer is (relatively) expensive, so we cache + it off for each operation. + */ + db2i_ileBridge* getBridge() + { + if (unlikely(bridge == NULL)) + { + bridge = db2i_ileBridge::getBridgeForThread(); + } + return bridge; + } + + void drainPipe(); + void pollNextRow(char orientation); + void prepForFree(); + void initAfterAllocate(bool sizeChanged); + void loadNewRows(char orientation); + + + uint32 readCursor; // Read position within buffer + int32 rc; // Last return code received + ValidatedPointer rrnList; // Receiver for list of rrns + char accessIntent; // The access intent for this read + char commitLevel; // What isolation level should be used + char EOD; // Whether end-of-data was hit + char readIsAsync; // Are reads to be done asynchronously? + bool* releaseRowNeeded; + /* Does the caller need to release the current row when finished reading */ + FILE_HANDLE file; // The file to be read + int msgPipe; + /* The read descriptor of the pipe used to pass messages during async reads */ + db2i_ileBridge* bridge; // Cached pointer to bridge + uint32 rowsToBlock; // Number of rows to request + enum + { + ConsumedFullBufferMsg, + PendingFullBufferMsg, + Untouched + } pipeState; + /* The state of the async read message pipe */ +}; + diff --git a/storage/ibmdb2i/db2i_misc.h b/storage/ibmdb2i/db2i_misc.h new file mode 100644 index 00000000000..1b6f0bc3968 --- /dev/null +++ b/storage/ibmdb2i/db2i_misc.h @@ -0,0 +1,95 @@ +/* +Licensed Materials - Property of IBM +DB2 Storage Engine Enablement +Copyright IBM Corporation 2007,2008 +All rights reserved + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + (a) Redistributions of source code must retain this list of conditions, the + copyright notice in section {d} below, and the disclaimer following this + list of conditions. + (b) Redistributions in binary form must reproduce this list of conditions, the + copyright notice in section (d) below, and the disclaimer following this + list of conditions, in the documentation and/or other materials provided + with the distribution. + (c) The name of IBM may not be used to endorse or promote products derived from + this software without specific prior written permission. + (d) The text of the required copyright notice is: + Licensed Materials - Property of IBM + DB2 Storage Engine Enablement + Copyright IBM Corporation 2007,2008 + All rights reserved + +THIS SOFTWARE IS PROVIDED BY IBM CORPORATION "AS IS" AND ANY EXPRESS OR IMPLIED +WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT +SHALL IBM CORPORATION BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT +OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT INCLUDING NEGLIGENCE OR OTHERWISE) ARISING +IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef DB2I_MISC_H +#define DB2I_MISC_H + +/** + Undelimit quote-delimited DB2 names in-place +*/ +void stripExtraQuotes(char* name, uint maxLen) +{ + char* oldName = (char*)sql_strdup(name); + uint i = 0; + uint j = 0; + do + { + name[j] = oldName[i]; + if (oldName[i] == '"' && oldName[i+1] == '"') + ++i; + } while (++j < maxLen && oldName[++i]); + + if (j == maxLen) + --j; + name[j] = 0; +} + +/** + Convert a MySQL identifier name into a DB2 compatible format + + @parm input The MySQL name + @parm output The DB2 name + @parm outlen The amount of space allocated for output + @parm delimit Should delimiting quotes be placed around the converted name? + @parm delimitQuotes Should quotes in the MySQL be delimited with additional quotes? + + @return FALSE if output was too small and name was truncated; TRUE otherwise +*/ +bool convertMySQLNameToDB2Name(const char* input, + char* output, + size_t outlen, + bool delimit = true, + bool delimitQuotes = true) +{ + uint o = 0; + if (delimit) + output[o++] = '"'; + + uint i = 0; + do + { + output[o] = input[i]; + if (delimitQuotes && input[i] == '"') + output[++o] = '"'; + } while (++o < outlen-2 && input[++i]); + + if (delimit) + output[o++] = '"'; + output[min(o, outlen-1)] = 0; // This isn't the most user-friendly way to handle overflows, + // but at least its safe. + return (o <= outlen-1); +} + +#endif diff --git a/storage/ibmdb2i/db2i_myconv.cc b/storage/ibmdb2i/db2i_myconv.cc new file mode 100644 index 00000000000..7be6e1236cd --- /dev/null +++ b/storage/ibmdb2i/db2i_myconv.cc @@ -0,0 +1,1498 @@ +/* +Licensed Materials - Property of IBM +DB2 Storage Engine Enablement +Copyright IBM Corporation 2007,2008 +All rights reserved + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + (a) Redistributions of source code must retain this list of conditions, the + copyright notice in section {d} below, and the disclaimer following this + list of conditions. + (b) Redistributions in binary form must reproduce this list of conditions, the + copyright notice in section (d) below, and the disclaimer following this + list of conditions, in the documentation and/or other materials provided + with the distribution. + (c) The name of IBM may not be used to endorse or promote products derived from + this software without specific prior written permission. + (d) The text of the required copyright notice is: + Licensed Materials - Property of IBM + DB2 Storage Engine Enablement + Copyright IBM Corporation 2007,2008 + All rights reserved + +THIS SOFTWARE IS PROVIDED BY IBM CORPORATION "AS IS" AND ANY EXPRESS OR IMPLIED +WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT +SHALL IBM CORPORATION BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT +OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT INCLUDING NEGLIGENCE OR OTHERWISE) ARISING +IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +/** + @file + + @brief A direct map optimization of iconv and related functions + This was show to significantly reduce character conversion cost + for short strings when compared to calling iconv system code. +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "db2i_myconv.h" +#include "db2i_global.h" + +int32_t myconvDebug=0; + +static char szGetTimeString[20]; +static char * GetTimeString(time_t now) +{ + struct tm * tm; + + now = time(&now); + tm = (struct tm *) localtime(&now); + sprintf(szGetTimeString, "%04d/%02d/%02d %02d:%02d:%02d", + tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, + tm->tm_hour, tm->tm_min, tm->tm_sec); + + return szGetTimeString; +} + +static MEM_ROOT dmapMemRoot; + +void initMyconv() +{ + init_alloc_root(&dmapMemRoot, 0x200, 0); +} + +void cleanupMyconv() +{ + free_root(&dmapMemRoot,0); +} + + +#ifdef DEBUG +/* type: */ +#define STDOUT_WITH_TIME -1 /* to stdout with time */ +#define STDERR_WITH_TIME -2 /* to stderr with time */ +#define STDOUT_WO_TIME 1 /* : to stdout */ +#define STDERR_WO_TIME 2 /* : to stderr */ + + +static void MyPrintf(long type, + char * fmt, ...) +{ + char StdoutFN[256]; + va_list ap; + char * p; + time_t now; + FILE * fd=stderr; + + if (type < 0) + { + now = time(&now); + fprintf(fd, "%s ", GetTimeString(now)); + } + va_start(ap, fmt); + vfprintf(fd, fmt, ap); + va_end(ap); +} +#endif + + + + +#define MAX_CONVERTER 128 + +mycstoccsid(const char* pname) +{ + if (strcmp(pname, "UTF-16")==0) + return 1200; + else if (strcmp(pname, "big5")==0) + return 950; + else + return cstoccsid(pname); +} +#define cstoccsid mycstoccsid + +static struct __myconv_rec myconv_rec [MAX_CONVERTER]; +static struct __dmap_rec dmap_rec [MAX_CONVERTER]; + +static int dmap_open(const char * to, + const char * from, + const int32_t idx) +{ + if (myconvIsSBCS(from) && myconvIsSBCS(to)) { + dmap_rec[idx].codingSchema = DMAP_S2S; + if ((dmap_rec[idx].dmapS2S = (uchar *) alloc_root(&dmapMemRoot, 0x100)) == NULL) { +#ifdef DEBUG + MyPrintf(STDERR_WITH_TIME, + "dmap_open(%s,%s,%d), CS=%d failed with malloc(), errno = %d in %s at %d\n", + to, from, idx, DMAP_S2S, errno, __FILE__,__LINE__); +#endif + return -1; + } + memset(dmap_rec[idx].dmapS2S, 0x00, 0x100); + myconv_rec[idx].allocatedSize=0x100; + + { + char dmapSrc[0x100]; + iconv_t cd; + int32_t i; + size_t inBytesLeft=0x100; + size_t outBytesLeft=0x100; + size_t len; + char * inBuf=dmapSrc; + char * outBuf=(char *) dmap_rec[idx].dmapS2S; + + if ((cd = iconv_open(to, from)) == (iconv_t) -1) { +#ifdef DEBUG + MyPrintf(STDERR_WITH_TIME, + "dmap_open(%s,%s,%d) failed with iconv_open(), errno = %d in %s at %d\n", + to, from, idx, errno, __FILE__,__LINE__); +#endif + return -1; + } + + inBytesLeft = 0x100; + for (i = 0; i < inBytesLeft; ++i) + dmapSrc[i]=i; + + do { + if ((len = iconv(cd, &inBuf, &inBytesLeft, &outBuf, &outBytesLeft)) != (size_t) 0) { +#ifdef DEBUG + if (myconvDebug) { + MyPrintf(STDERR_WITH_TIME, + "dmap_open(%s,%s,%d), CS=%d: iconv() returns %d, errno = %d in %s at %d\n", + to, from, idx, DMAP_S2S, len, errno, __FILE__,__LINE__); + MyPrintf(STDERR_WITH_TIME, + "inBytesLeft = %d, inBuf - dmapSrc = %d\n", inBytesLeft, inBuf-dmapSrc); + MyPrintf(STDERR_WITH_TIME, + "outBytesLeft = %d, outBuf - dmapS2S = %d\n", outBytesLeft, outBuf-(char *) dmap_rec[idx].dmapS2S); + } + if ((inBytesLeft == 86 || inBytesLeft == 64 || inBytesLeft == 1) && + memcmp(from, "IBM-1256", 9) == 0 && + memcmp(to, "IBM-420", 8) == 0) { + /* Known problem for IBM-1256_IBM-420 */ + --inBytesLeft; + ++inBuf; + *outBuf=0x00; + ++outBuf; + --outBytesLeft; + continue; + } else if ((inBytesLeft == 173 || inBytesLeft == 172 || + inBytesLeft == 74 || inBytesLeft == 73 || + inBytesLeft == 52 || inBytesLeft == 50 || + inBytesLeft == 31 || inBytesLeft == 20 || + inBytesLeft == 6) && + memcmp(to, "IBM-1256", 9) == 0 && + memcmp(from, "IBM-420", 8) == 0) { + /* Known problem for IBM-420_IBM-1256 */ + --inBytesLeft; + ++inBuf; + *outBuf=0x00; + ++outBuf; + --outBytesLeft; + continue; + } else if ((128 >= inBytesLeft) && + memcmp(to, "IBM-037", 8) == 0 && + memcmp(from, "IBM-367", 8) == 0) { + /* Known problem for IBM-367_IBM-037 */ + --inBytesLeft; + ++inBuf; + *outBuf=0x00; + ++outBuf; + --outBytesLeft; + continue; + } else if (((1 <= inBytesLeft && inBytesLeft <= 4) || (97 <= inBytesLeft && inBytesLeft <= 128)) && + memcmp(to, "IBM-838", 8) == 0 && + memcmp(from, "TIS-620", 8) == 0) { + /* Known problem for TIS-620_IBM-838 */ + --inBytesLeft; + ++inBuf; + *outBuf=0x00; + ++outBuf; + --outBytesLeft; + continue; + } + iconv_close(cd); + return -1; +#else + /* Tolerant to undefined conversions for any converter */ + --inBytesLeft; + ++inBuf; + *outBuf=0x00; + ++outBuf; + --outBytesLeft; + continue; +#endif + } + } while (inBytesLeft > 0); + + if (myconvIsISO(to)) + myconv_rec[idx].subS=0x1A; + else if (myconvIsASCII(to)) + myconv_rec[idx].subS=0x7F; + else if (myconvIsEBCDIC(to)) + myconv_rec[idx].subS=0x3F; + + if (myconvIsISO(from)) + myconv_rec[idx].srcSubS=0x1A; + else if (myconvIsASCII(from)) + myconv_rec[idx].srcSubS=0x7F; + else if (myconvIsEBCDIC(from)) + myconv_rec[idx].srcSubS=0x3F; + + iconv_close(cd); + } + } else if (((myconvIsSBCS(from) && myconvIsUnicode2(to)) && (dmap_rec[idx].codingSchema = DMAP_S2U)) || + ((myconvIsSBCS(from) && myconvIsUTF8(to)) && (dmap_rec[idx].codingSchema = DMAP_S28))) { + int i; + + /* single byte mapping */ + if ((dmap_rec[idx].dmapD12U = (UniChar *) alloc_root(&dmapMemRoot, 0x100 * 2)) == NULL) { +#ifdef DEBUG + MyPrintf(STDERR_WITH_TIME, + "dmap_open(%s,%s,%d), CS=%d failed with malloc(), errno = %d in %s at %d\n", + to, from, idx, DMAP_S2U, errno, __FILE__,__LINE__); +#endif + return -1; + } + memset(dmap_rec[idx].dmapD12U, 0x00, 0x100 * 2); + myconv_rec[idx].allocatedSize=0x100 * 2; + + + { + char dmapSrc[2]; + iconv_t cd; + int32_t i; + size_t inBytesLeft; + size_t outBytesLeft; + size_t len; + char * inBuf; + char * outBuf; + char SS=0x1A; +#ifdef support_surrogate + if ((cd = iconv_open("UTF-16", from)) == (iconv_t) -1) { +#else + if ((cd = iconv_open("UCS-2", from)) == (iconv_t) -1) { +#endif +#ifdef DEBUG + MyPrintf(STDERR_WITH_TIME, + "dmap_open(%s,%s,%d) failed with iconv_open(), errno = %d in %s at %d\n", + to, from, idx, errno, __FILE__,__LINE__); +#endif + return -1; + } + + for (i = 0; i < 0x100; ++i) { + dmapSrc[0]=i; + inBuf=dmapSrc; + inBytesLeft=1; + outBuf=(char *) &(dmap_rec[idx].dmapD12U[i]); + outBytesLeft=2; + if ((len = iconv(cd, &inBuf, &inBytesLeft, &outBuf, &outBytesLeft)) != (size_t) 0) { + if ((errno == EILSEQ || errno == EINVAL) && + inBytesLeft == 1 && + outBytesLeft == 2) { + continue; + } else { +#ifdef DEBUG + if (myconvDebug) { + MyPrintf(STDERR_WITH_TIME, + "dmap_open(%s,%s,%d) failed to initialize with iconv(cd,%02x,%d,%02x%02x,%d), errno = %d in %s at %d\n", + to, from, idx, dmapSrc[0], 1, + (&dmap_rec[idx].dmapD12U[i])[0],(&dmap_rec[idx].dmapD12U[i])[1], 2, + errno, __FILE__,__LINE__); + MyPrintf(STDERR_WITH_TIME, + "inBytesLeft=%d, outBytesLeft=%d, %02x%02x\n", + inBytesLeft, outBytesLeft, + (&dmap_rec[idx].dmapD12U[i])[0],(&dmap_rec[idx].dmapD12U[i])[1]); + } +#endif + iconv_close(cd); + return -1; + } + dmap_rec[idx].dmapD12U[i]=0x0000; + } + if (dmap_rec[idx].dmapE02U[i] == 0x001A && /* pick the first one */ + myconv_rec[idx].srcSubS == 0x00) { + myconv_rec[idx].srcSubS=i; + } + } + iconv_close(cd); + } + myconv_rec[idx].subS=0x1A; + myconv_rec[idx].subD=0xFFFD; + + + } else if (((myconvIsUCS2(from) && myconvIsSBCS(to)) && (dmap_rec[idx].codingSchema = DMAP_U2S)) || + ((myconvIsUTF16(from) && myconvIsSBCS(to)) && (dmap_rec[idx].codingSchema = DMAP_T2S)) || + ((myconvIsUTF8(from) && myconvIsSBCS(to)) && (dmap_rec[idx].codingSchema = DMAP_82S))) { + /* UTF-16 -> SBCS, the direct map a bit of waste of space, + * binary search may be reasonable alternative + */ + if ((dmap_rec[idx].dmapU2S = (uchar *) alloc_root(&dmapMemRoot, 0x10000 * 2)) == NULL) { +#ifdef DEBUG + MyPrintf(STDERR_WITH_TIME, + "dmap_open(%s,%s,%d), CS=%d failed with malloc(), errno = %d in %s at %d\n", + to, from, idx, DMAP_U2S, errno, __FILE__,__LINE__); +#endif + return -1; + } + memset(dmap_rec[idx].dmapU2S, 0x00, 0x10000); + myconv_rec[idx].allocatedSize=(0x10000 * 2); + + { + iconv_t cd; + int32_t i; + +#ifdef support_surrogate + if ((cd = iconv_open(to, "UTF-16")) == (iconv_t) -1) { +#else + if ((cd = iconv_open(to, "UCS-2")) == (iconv_t) -1) { +#endif +#ifdef DEBUG + MyPrintf(STDERR_WITH_TIME, + "dmap_open(%s,%s,%d) failed with iconv_open(), errno = %d in %s at %d\n", + to, from, idx, errno, __FILE__,__LINE__); +#endif + return -1; + } + + for (i = 0; i < 0x100; ++i) { + UniChar dmapSrc[0x100]; + int32_t j; + for (j = 0; j < 0x100; ++j) { + dmapSrc[j]=i * 0x100 + j; + } + char * inBuf=(char *) dmapSrc; + char * outBuf=(char *) &(dmap_rec[idx].dmapU2S[i*0x100]); + size_t inBytesLeft=sizeof(dmapSrc); + size_t outBytesLeft=0x100; + size_t len; + + if ((len = iconv(cd, &inBuf, &inBytesLeft, &outBuf, &outBytesLeft)) != (size_t) 0) { + if (inBytesLeft == 0 && outBytesLeft == 0) { /* a number of substitution returns */ + continue; + } +#ifdef DEBUG + if (myconvDebug) { + MyPrintf(STDERR_WITH_TIME, + "dmap_open(%s,%s,%d) failed to initialize with iconv(), errno = %d in %s at %d\n", + from, to, idx, errno, __FILE__,__LINE__); + MyPrintf(STDERR_WITH_TIME, + "iconv() retuns %d, errno=%d, InBytesLeft=%d, OutBytesLeft=%d\n", + len, errno, inBytesLeft, outBytesLeft, __FILE__,__LINE__); + } +#endif + iconv_close(cd); + return -1; + } + } + iconv_close(cd); + + myconv_rec[idx].subS = dmap_rec[idx].dmapU2S[0x1A]; + myconv_rec[idx].subD = dmap_rec[idx].dmapU2S[0xFFFD]; + myconv_rec[idx].srcSubS = 0x1A; + myconv_rec[idx].srcSubD = 0xFFFD; + } + + + + } else if (((myconvIsDBCS(from) && myconvIsUnicode2(to)) && (dmap_rec[idx].codingSchema = DMAP_D2U)) || + ((myconvIsDBCS(from) && myconvIsUTF8(to)) && (dmap_rec[idx].codingSchema = DMAP_D28))) { + int i; + /* single byte mapping */ + if ((dmap_rec[idx].dmapD12U = (UniChar *) alloc_root(&dmapMemRoot, 0x100 * 2)) == NULL) { +#ifdef DEBUG + MyPrintf(STDERR_WITH_TIME, + "dmap_open(%s,%s,%d), CS=%d failed with malloc(), errno = %d in %s at %d\n", + to, from, idx, DMAP_D2U, errno, __FILE__,__LINE__); +#endif + return -1; + } + memset(dmap_rec[idx].dmapD12U, 0x00, 0x100 * 2); + + /* double byte mapping, assume 7 bit ASCII is not use as the first byte of DBCS. */ + if ((dmap_rec[idx].dmapD22U = (UniChar *) alloc_root(&dmapMemRoot, 0x8000 * 2)) == NULL) { +#ifdef DEBUG + MyPrintf(STDERR_WITH_TIME, + "dmap_open(%s,%s,%d), CS=%d failed with malloc(), errno = %d in %s at %d\n", + to, from, idx, DMAP_D2U, errno, __FILE__,__LINE__); +#endif + return -1; + } + memset(dmap_rec[idx].dmapD22U, 0x00, 0x8000 * 2); + + myconv_rec[idx].allocatedSize=(0x100 + 0x8000) * 2; + + + { + char dmapSrc[2]; + iconv_t cd; + int32_t i; + size_t inBytesLeft; + size_t outBytesLeft; + size_t len; + char * inBuf; + char * outBuf; + char SS=0x1A; + +#ifdef support_surrogate + if ((cd = iconv_open("UTF-16", from)) == (iconv_t) -1) { +#else + if ((cd = iconv_open("UCS-2", from)) == (iconv_t) -1) { +#endif +#ifdef DEBUG + MyPrintf(STDERR_WITH_TIME, + "dmap_open(%s,%s,%d) failed with iconv_open(), errno = %d in %s at %d\n", + to, from, idx, errno, __FILE__,__LINE__); +#endif + return -1; + } + + for (i = 0; i < 0x100; ++i) { + dmapSrc[0]=i; + inBuf=dmapSrc; + inBytesLeft=1; + outBuf=(char *) (&dmap_rec[idx].dmapD12U[i]); + outBytesLeft=2; + if ((len = iconv(cd, &inBuf, &inBytesLeft, &outBuf, &outBytesLeft)) != (size_t) 0) { + if ((errno == EILSEQ || errno == EINVAL) && + inBytesLeft == 1 && + outBytesLeft == 2) { + continue; + } else { +#ifdef DEBUG + if (myconvDebug) { + MyPrintf(STDERR_WITH_TIME, + "dmap_open(%s,%s,%d) failed to initialize with iconv(cd,%02x,%d,%02x%02x,%d), errno = %d in %s at %d\n", + to, from, idx, dmapSrc[0], 1, + (&dmap_rec[idx].dmapD12U[i])[0],(&dmap_rec[idx].dmapD12U[i])[1], 2, + errno, __FILE__,__LINE__); + MyPrintf(STDERR_WITH_TIME, + "inBytesLeft=%d, outBytesLeft=%d, %02x%02x\n", + inBytesLeft, outBytesLeft, + (&dmap_rec[idx].dmapD12U[i])[0],(&dmap_rec[idx].dmapD12U[i])[1]); + } +#endif + iconv_close(cd); + return -1; + } + dmap_rec[idx].dmapD12U[i]=0x0000; + } + if (dmap_rec[idx].dmapD12U[i] == 0x001A && /* pick the first one */ + myconv_rec[idx].srcSubS == 0x00) { + myconv_rec[idx].srcSubS=i; + } + } + + + for (i = 0x80; i < 0x100; ++i) { + int j; + if (dmap_rec[idx].dmapD12U[i] != 0x0000) + continue; + for (j = 0x01; j < 0x100; ++j) { + dmapSrc[0]=i; + dmapSrc[1]=j; + int offset = i-0x80; + offset<<=8; + offset+=j; + + inBuf=dmapSrc; + inBytesLeft=2; + outBuf=(char *) &(dmap_rec[idx].dmapD22U[offset]); + outBytesLeft=2; + if ((len = iconv(cd, &inBuf, &inBytesLeft, &outBuf, &outBytesLeft)) != (size_t) 0) { + if (inBytesLeft == 2 && outBytesLeft == 2 && (errno == EILSEQ || errno == EINVAL)) { + ; /* invalid DBCS character, dmapDD2U[offset] remains 0x0000 */ + } else { +#ifdef DEBUG + if (myconvDebug) { + MyPrintf(STDERR_WITH_TIME, + "dmap_open(%s,%s,%d) failed to initialize with iconv(cd,%p,2,%p,2), errno = %d in %s at %d\n", + to, from, idx, + dmapSrc, &(dmap_rec[idx].dmapD22U[offset]), + errno, __FILE__,__LINE__); + MyPrintf(STDERR_WO_TIME, + "iconv(cd,0x%02x%02x,2,0x%04x,2) returns %d, inBytesLeft=%d, outBytesLeft=%d\n", + dmapSrc[0], dmapSrc[1], + dmap_rec[idx].dmapD22U[offset], + len, inBytesLeft, outBytesLeft); + } +#endif + iconv_close(cd); + return -1; + } + } else { +#ifdef TRACE_DMAP + if (myconvDebug) { + MyPrintf(STDERR_WITH_TIME, + "dmap_open(%s,%s,%d) failed to initialize with iconv(), rc=%d, errno=%d in %s at %d\n", + to, from, idx, len, errno, __FILE__,__LINE__); + MyPrintf(STDERR_WITH_TIME, + "%04X: src=%04X%04X, inBuf=0x%02X%02X, inBytesLeft=%d, outBuf=%02X%02X%02X, outBytesLeft=%d\n", + i, dmapSrc[0], dmapSrc[1], inBuf[0], inBuf[1], + inBytesLeft, outBuf[-2], outBuf[-1], outBuf[0], outBytesLeft); + MyPrintf(STDERR_WITH_TIME, + "&dmapSrc=%p, inBuf=%p, %p, outBuf=%p\n", + dmapSrc, inBuf, dmap_rec[idx].dmapU2M3 + (i - 0x80) * 2, outBuf); + } +#endif + } + } + if (dmap_rec[idx].dmapD12U[i] == 0xFFFD) { /* pick the last one */ + myconv_rec[idx].srcSubD=i* 0x100 + j; + } + } + iconv_close(cd); + } + + myconv_rec[idx].subS=0x1A; + myconv_rec[idx].subD=0xFFFD; + myconv_rec[idx].srcSubD=0xFCFC; + + + } else if (((myconvIsUCS2(from) && myconvIsDBCS(to)) && (dmap_rec[idx].codingSchema = DMAP_U2D)) || + ((myconvIsUTF16(from) && myconvIsDBCS(to)) && (dmap_rec[idx].codingSchema = DMAP_T2D)) || + ((myconvIsUTF8(from) && myconvIsDBCS(to)) && (dmap_rec[idx].codingSchema = DMAP_82D))) { + /* UTF-16 -> DBCS single/double byte */ + /* A single table will cover all characters, assuming no second byte is 0x00. */ + if ((dmap_rec[idx].dmapU2D = (uchar *) alloc_root(&dmapMemRoot, 0x10000 * 2)) == NULL) { +#ifdef DEBUG + MyPrintf(STDERR_WITH_TIME, + "dmap_open(%s,%s,%d), CS=%d failed with malloc(), errno = %d in %s at %d\n", + to, from, idx, DMAP_U2D, errno, __FILE__,__LINE__); +#endif + return -1; + } + + memset(dmap_rec[idx].dmapU2D, 0x00, 0x10000 * 2); + myconv_rec[idx].allocatedSize=(0x10000 * 2); + + { + UniChar dmapSrc[1]; + iconv_t cd; + int32_t i; + size_t inBytesLeft; + size_t outBytesLeft; + size_t len; + char * inBuf; + char * outBuf; + +#ifdef support_surrogate + if ((cd = iconv_open(to, "UTF-16")) == (iconv_t) -1) { +#else + if ((cd = iconv_open(to, "UCS-2")) == (iconv_t) -1) { +#endif +#ifdef DEBUG + MyPrintf(STDERR_WITH_TIME, + "dmap_open(%s,%s,%d) failed with iconv_open(), errno = %d in %s at %d\n", + to, from, idx, errno, __FILE__,__LINE__); +#endif + return -1; + } + + /* easy implementation, convert 1 Unicode character at one time. */ + /* If the open performance is an issue, convert a chunk such as 128 chracters. */ + /* if the converted length is not the same as the original, convert one by one. */ + (dmap_rec[idx].dmapU2D)[0x0000]=0x00; + for (i = 1; i < 0x10000; ++i) { + dmapSrc[0]=i; + inBuf=(char *) dmapSrc; + inBytesLeft=2; + outBuf=(char *) &((dmap_rec[idx].dmapU2D)[2*i]); + outBytesLeft=2; + do { + if ((len = iconv(cd, &inBuf, &inBytesLeft, &outBuf, &outBytesLeft)) != (size_t) 0) { + if (len == 1 && inBytesLeft == 0 && outBytesLeft == 1 && (dmap_rec[idx].dmapU2D)[2*i] == 0x1A) { + /* UCS-2_TIS-620:0x0080 => 0x1A, converted to SBCS replacement character */ + (dmap_rec[idx].dmapU2D)[2*i+1]=0x00; + break; + } else if (len == 1 && inBytesLeft == 0 && outBytesLeft == 0) { + break; + } + if (errno == EILSEQ || errno == EINVAL) { +#ifdef DEBUG + if (myconvDebug) { + MyPrintf(STDERR_WITH_TIME, + "dmap_open(%s,%s,%d) failed to initialize with iconv(), errno = %d in %s at %d\n", + to, from, idx, errno, __FILE__,__LINE__); + MyPrintf(STDERR_WO_TIME, + "iconv(cd,%04x,2,%02x%02x,2) returns inBytesLeft=%d, outBytesLeft=%d\n", + dmapSrc[0], + (dmap_rec[idx].dmapU2D)[2*i], (dmap_rec[idx].dmapU2D)[2*i+1], + inBytesLeft, outBytesLeft); + if (outBuf - (char *) dmap_rec[idx].dmapU2M2 > 1) + MyPrintf(STDERR_WO_TIME, "outBuf[-2..2]=%02X%02X%02X%02X%02X\n", outBuf[-2],outBuf[-1],outBuf[0],outBuf[1],outBuf[2]); + else + MyPrintf(STDERR_WO_TIME, "outBuf[0..2]=%02X%02X%02X\n", outBuf[0],outBuf[1],outBuf[2]); + } +#endif + inBuf+=2; + inBytesLeft-=2; + memcpy(outBuf, (char *) &(myconv_rec[idx].subD), 2); + outBuf+=2; + outBytesLeft-=2; + } else { +#ifdef DEBUG + MyPrintf(STDERR_WITH_TIME, + "[%d] dmap_open(%s,%s,%d) failed to initialize with iconv(), errno = %d in %s at %d\n", + i, to, from, idx, errno, __FILE__,__LINE__); + MyPrintf(STDERR_WO_TIME, + "iconv(cd,%04x,2,%02x%02x,2) returns %d inBytesLeft=%d, outBytesLeft=%d\n", + dmapSrc[0], + (dmap_rec[idx].dmapU2D)[2*i], + (dmap_rec[idx].dmapU2D)[2*i+1], + len, inBytesLeft,outBytesLeft); + if (i == 1) { + MyPrintf(STDERR_WO_TIME, + " inBuf [-1..2]=%02x%02x%02x%02x\n", + inBuf[-1],inBuf[0],inBuf[1],inBuf[2]); + MyPrintf(STDERR_WO_TIME, + " outBuf [-1..2]=%02x%02x%02x%02x\n", + outBuf[-1],outBuf[0],outBuf[1],outBuf[2]); + } else { + MyPrintf(STDERR_WO_TIME, + " inBuf [-2..2]=%02x%02x%02x%02x%02x\n", + inBuf[-2],inBuf[-1],inBuf[0],inBuf[1],inBuf[2]); + MyPrintf(STDERR_WO_TIME, + " outBuf [-2..2]=%02x%02x%02x%02x%02x\n", + outBuf[-2],outBuf[-1],outBuf[0],outBuf[1],outBuf[2]); + } +#endif + iconv_close(cd); + return -1; + } + if (len == 0 && inBytesLeft == 0 && outBytesLeft == 1) { /* converted to SBCS */ + (dmap_rec[idx].dmapU2D)[2*i+1]=0x00; + break; + } + } + } while (inBytesLeft > 0); + } + iconv_close(cd); + myconv_rec[idx].subS = dmap_rec[idx].dmapU2D[2*0x1A]; + myconv_rec[idx].subD = dmap_rec[idx].dmapU2D[2*0xFFFD] * 0x100 + + dmap_rec[idx].dmapU2D[2*0xFFFD+1]; + myconv_rec[idx].srcSubS = 0x1A; + myconv_rec[idx].srcSubD = 0xFFFD; + } + + + } else if (((myconvIsEUC(from) && myconvIsUnicode2(to)) && (dmap_rec[idx].codingSchema = DMAP_E2U)) || + ((myconvIsEUC(from) && myconvIsUTF8(to)) && (dmap_rec[idx].codingSchema = DMAP_E28))) { + int i; + /* S0: 0x00 - 0x7F */ + if ((dmap_rec[idx].dmapE02U = (UniChar *) alloc_root(&dmapMemRoot, 0x100 * 2)) == NULL) { +#ifdef DEBUG + MyPrintf(STDERR_WITH_TIME, + "dmap_open(%s,%s,%d), CS=%d failed with malloc(), errno = %d in %s at %d\n", + to, from, idx, DMAP_E2U, errno, __FILE__,__LINE__); +#endif + return -1; + } + memset(dmap_rec[idx].dmapE02U, 0x00, 0x100 * 2); + + /* S1: 0xA0 - 0xFF, 0xA0 - 0xFF */ + if ((dmap_rec[idx].dmapE12U = (UniChar *) alloc_root(&dmapMemRoot, 0x60 * 0x60 * 2)) == NULL) { +#ifdef DEBUG + MyPrintf(STDERR_WITH_TIME, + "dmap_open(%s,%s,%d), CS=%d failed with malloc(), errno = %d in %s at %d\n", + to, from, idx, DMAP_E2U, errno, __FILE__,__LINE__); +#endif + return -1; + } + memset(dmap_rec[idx].dmapE12U, 0x00, 0x60 * 0x60 * 2); + + /* SS2: 0x8E + 0xA0 - 0xFF, 0xA0 - 0xFF */ + if ((dmap_rec[idx].dmapE22U = (UniChar *) alloc_root(&dmapMemRoot, 0x60 * 0x61 * 2)) == NULL) { +#ifdef DEBUG + MyPrintf(STDERR_WITH_TIME, + "dmap_open(%s,%s,%d), CS=%d failed with malloc(), errno = %d in %s at %d\n", + to, from, idx, DMAP_E2U, errno, __FILE__,__LINE__); +#endif + return -1; + } + memset(dmap_rec[idx].dmapE22U, 0x00, 0x60 * 0x61 * 2); + + /* SS3: 0x8F + 0xA0 - 0xFF, 0xA0 - 0xFF */ + if ((dmap_rec[idx].dmapE32U = (UniChar *) alloc_root(&dmapMemRoot, 0x60 * 0x61 * 2)) == NULL) { +#ifdef DEBUG + MyPrintf(STDERR_WITH_TIME, + "dmap_open(%s,%s,%d), CS=%d failed with malloc(), errno = %d in %s at %d\n", + to, from, idx, DMAP_E2U, errno, __FILE__,__LINE__); +#endif + return -1; + } + memset(dmap_rec[idx].dmapE32U, 0x00, 0x60 * 0x61 * 2); + + myconv_rec[idx].allocatedSize=(0x100 + 0x60 * 0x60 + 0x60 * 0x61* 2) * 2; + + + { + char dmapSrc[0x60 * 0x60 * 3]; + iconv_t cd; + int32_t i; + size_t inBytesLeft; + size_t outBytesLeft; + size_t len; + char * inBuf; + char * outBuf; + char SS=0x8E; + +#ifdef support_surrogate + if ((cd = iconv_open("UTF-16", from)) == (iconv_t) -1) { +#else + if ((cd = iconv_open("UCS-2", from)) == (iconv_t) -1) { +#endif +#ifdef DEBUG + MyPrintf(STDERR_WITH_TIME, + "dmap_open(%s,%s,%d) failed with iconv_open(), errno = %d in %s at %d\n", + to, from, idx, errno, __FILE__,__LINE__); +#endif + return -1; + } + + for (i = 0; i < 0x100; ++i) { + dmapSrc[0]=i; + inBuf=dmapSrc; + inBytesLeft=1; + outBuf=(char *) (&dmap_rec[idx].dmapE02U[i]); + outBytesLeft=2; + if ((len = iconv(cd, &inBuf, &inBytesLeft, &outBuf, &outBytesLeft)) != (size_t) 0) { +#ifdef DEBUG + if (myconvDebug) { + MyPrintf(STDERR_WITH_TIME, + "dmap_open(%s,%s,%d) failed to initialize with iconv(), errno = %d in %s at %d\n", + to, from, idx, errno, __FILE__,__LINE__); + } +#endif + dmap_rec[idx].dmapE02U[i]=0x0000; + } + if (dmap_rec[idx].dmapE02U[i] == 0x001A && /* pick the first one */ + myconv_rec[idx].srcSubS == 0x00) { + myconv_rec[idx].srcSubS=i; + } + } + + + inBuf=dmapSrc; + for (i = 0; i < 0x60; ++i) { + int j; + for (j = 0; j < 0x60; ++j) { + *inBuf=i+0xA0; + ++inBuf; + *inBuf=j+0xA0; + ++inBuf; + } + } + inBuf=dmapSrc; + inBytesLeft=0x60 * 0x60 * 2; + outBuf=(char *) dmap_rec[idx].dmapE12U; + outBytesLeft=0x60 * 0x60 * 2; + do { + if ((len = iconv(cd, &inBuf, &inBytesLeft, &outBuf, &outBytesLeft)) != (size_t) 0) { + if (errno == EILSEQ) { +#ifdef DEBUG + if (myconvDebug) { + MyPrintf(STDERR_WITH_TIME, + "dmap_open(%s,%s,%d) failed to initialize with iconv(), errno = %d in %s at %d\n", + to, from, idx, errno, __FILE__,__LINE__); + MyPrintf(STDERR_WO_TIME, "inBytesLeft=%d, outBytesLeft=%d\n", inBytesLeft, outBytesLeft); + if (inBuf - dmapSrc > 1 && inBuf - dmapSrc <= sizeof(dmapSrc) - 2) + MyPrintf(STDERR_WO_TIME, "inBuf[-2..2]=%02X%02X%02X%02X%02X\n", inBuf[-2],inBuf[-1],inBuf[0],inBuf[1],inBuf[2]); + else + MyPrintf(STDERR_WO_TIME, "inBuf[0..2]=%02X%02X%02X\n", inBuf[0],inBuf[1],inBuf[2]); + if (outBuf - (char *) dmap_rec[idx].dmapE12U > 1) + MyPrintf(STDERR_WO_TIME, "outBuf[-2..2]=%02X%02X%02X%02X%02X\n", outBuf[-2],outBuf[-1],outBuf[0],outBuf[1],outBuf[2]); + else + MyPrintf(STDERR_WO_TIME, "outBuf[0..2]=%02X%02X%02X\n", outBuf[0],outBuf[1],outBuf[2]); + } +#endif + inBuf+=2; + inBytesLeft-=2; + outBuf[0]=0x00; + outBuf[1]=0x00; + outBuf+=2; + outBytesLeft-=2; + } else { +#ifdef DEBUG + MyPrintf(STDERR_WITH_TIME, + "dmap_open(%s,%s,%d) failed to initialize with iconv(), errno = %d in %s at %d\n", + to, from, idx, errno, __FILE__,__LINE__); +#endif + iconv_close(cd); + return -1; + } + } + } while (inBytesLeft > 0); + + /* SS2: 0x8E + 1 or 2 bytes */ + /* SS3: 0x8E + 1 or 2 bytes */ + while (SS != 0x00) { + int32_t numSuccess=0; + for (i = 0; i < 0x60; ++i) { + inBuf=dmapSrc; + inBuf[0]=SS; + inBuf[1]=i+0xA0; + inBytesLeft=2; + if (SS == 0x8E) + outBuf=(char *) &(dmap_rec[idx].dmapE22U[i]); + else + outBuf=(char *) &(dmap_rec[idx].dmapE32U[i]); + outBytesLeft=2; + if ((len = iconv(cd, &inBuf, &inBytesLeft, &outBuf, &outBytesLeft)) != (size_t) 0) { + if (SS == 0x8E) + dmap_rec[idx].dmapE22U[i]=0x0000; + else + dmap_rec[idx].dmapE32U[i]=0x0000; + } else { + ++numSuccess; + } + } + if (numSuccess == 0) { /* SS2 is 2 bytes */ + inBuf=dmapSrc; + for (i = 0; i < 0x60; ++i) { + int j; + for (j = 0; j < 0x60; ++j) { + *inBuf=SS; + ++inBuf; + *inBuf=i+0xA0; + ++inBuf; + *inBuf=j+0xA0; + ++inBuf; + } + } + inBuf=dmapSrc; + inBytesLeft=0x60 * 0x60 * 3; + if (SS == 0x8E) + outBuf=(char *) &(dmap_rec[idx].dmapE22U[0x60]); + else + outBuf=(char *) &(dmap_rec[idx].dmapE32U[0x60]); + outBytesLeft=0x60 * 0x60 * 2; + do { + if ((len = iconv(cd, &inBuf, &inBytesLeft, &outBuf, &outBytesLeft)) != (size_t) 0) { +#ifdef DEBUG + if (myconvDebug) { + MyPrintf(STDERR_WITH_TIME, + "%02X:dmap_open(%s,%s,%d) failed to initialize with iconv(), errno = %d in %s at %d\n", + SS, to, from, idx, errno, __FILE__,__LINE__); + MyPrintf(STDERR_WO_TIME, "inBytesLeft=%d, outBytesLeft=%d\n", inBytesLeft, outBytesLeft); + if (inBuf - dmapSrc > 1 && inBuf - dmapSrc <= sizeof(dmapSrc) - 2) + MyPrintf(STDERR_WO_TIME, "inBuf[-2..2]=%02X%02X%02X%02X%02X\n", inBuf[-2],inBuf[-1],inBuf[0],inBuf[1],inBuf[2]); + else + MyPrintf(STDERR_WO_TIME, "inBuf[0..2]=%02X%02X%02X\n", inBuf[0],inBuf[1],inBuf[2]); + } +#endif + if (errno == EILSEQ || errno == EINVAL) { + inBuf+=3; + inBytesLeft-=3; + outBuf[0]=0x00; + outBuf[1]=0x00; + outBuf+=2; + outBytesLeft-=2; + } else { +#ifdef DEBUG + MyPrintf(STDERR_WITH_TIME, + "%02X:dmap_open(%s,%s,%d) failed to initialize with iconv(), errno = %d in %s at %d\n", + SS, to, from, idx, errno, __FILE__,__LINE__); +#endif + iconv_close(cd); + return -1; + } + } + } while (inBytesLeft > 0); + } + if (SS == 0x8E) + SS=0x8F; + else + SS = 0x00; + } + iconv_close(cd); + + myconv_rec[idx].subS=0x1A; + myconv_rec[idx].subD=0xFFFD; + for (i = 0; i < 0x80; ++i) { + if (dmap_rec[idx].dmapE02U[i] == 0x001A) { + myconv_rec[idx].srcSubS=i; /* pick the first one */ + break; + } + } + + for (i = 0; i < 0x60 * 0x60; ++i) { + if (dmap_rec[idx].dmapE12U[i] == 0xFFFD) { + uchar byte1=i / 0x60; + uchar byte2=i % 0x60; + myconv_rec[idx].srcSubD=(byte1 + 0xA0) * 0x100 + (byte2 + 0xA0); /* pick the last one */ + } + } + + } + + } else if (((myconvIsUCS2(from) && myconvIsEUC(to)) && (dmap_rec[idx].codingSchema = DMAP_U2E)) || + ((myconvIsUTF16(from) && myconvIsEUC(to)) && (dmap_rec[idx].codingSchema = DMAP_T2E)) || + ((myconvIsUTF8(from) && myconvIsEUC(to)) && (dmap_rec[idx].codingSchema = DMAP_82E))) { + /* S0: 0x00 - 0xFF */ + if ((dmap_rec[idx].dmapU2S = (uchar *) alloc_root(&dmapMemRoot, 0x100)) == NULL) { +#ifdef DEBUG + MyPrintf(STDERR_WITH_TIME, + "dmap_open(%s,%s,%d), CS=%d failed with malloc(), errno = %d in %s at %d\n", + to, from, idx, DMAP_U2E, errno, __FILE__,__LINE__); +#endif + return -1; + } + memset(dmap_rec[idx].dmapU2S, 0x00, 0x100); + + /* U0080 - UFFFF -> S1: 0xA0 - 0xFF, 0xA0 - 0xFF */ + if ((dmap_rec[idx].dmapU2M2 = (uchar *) alloc_root(&dmapMemRoot, 0xFF80 * 2)) == NULL) { +#ifdef DEBUG + MyPrintf(STDERR_WITH_TIME, + "dmap_open(%s,%s,%d), CS=%d failed with malloc(), errno = %d in %s at %d\n", + to, from, idx, DMAP_U2E, errno, __FILE__,__LINE__); +#endif + return -1; + } + memset(dmap_rec[idx].dmapU2M2, 0x00, 0xFF80 * 2); + + /* U0080 - UFFFF -> SS2: 0x8E + 0xA0 - 0xFF, 0xA0 - 0xFF + * SS3: 0x8F + 0xA0 - 0xFF, 0xA0 - 0xFF */ + if ((dmap_rec[idx].dmapU2M3 = (uchar *) alloc_root(&dmapMemRoot, 0xFF80 * 3)) == NULL) { +#ifdef DEBUG + MyPrintf(STDERR_WITH_TIME, + "dmap_open(%s,%s,%d), CS=%d failed with malloc(), errno = %d in %s at %d\n", + to, from, idx, DMAP_U2E, errno, __FILE__,__LINE__); +#endif + return -1; + } + memset(dmap_rec[idx].dmapU2M3, 0x00, 0xFF80 * 3); + myconv_rec[idx].allocatedSize=(0x100 + 0xFF80 * 2 + 0xFF80 * 3); + + { + UniChar dmapSrc[0x80]; + iconv_t cd; + int32_t i; + size_t inBytesLeft; + size_t outBytesLeft; + size_t len; + char * inBuf; + char * outBuf; + +#ifdef support_surrogate + if ((cd = iconv_open(to, "UTF-16")) == (iconv_t) -1) { +#else + if ((cd = iconv_open(to, "UCS-2")) == (iconv_t) -1) { +#endif +#ifdef DEBUG + MyPrintf(STDERR_WITH_TIME, + "dmap_open(%s,%s,%d) failed with iconv_open(), errno = %d in %s at %d\n", + to, from, idx, errno, __FILE__,__LINE__); +#endif + return -1; + } + + for (i = 0; i < 0x80; ++i) + dmapSrc[i]=i; + inBuf=(char *) dmapSrc; + inBytesLeft=0x80 * 2; + outBuf=(char *) dmap_rec[idx].dmapU2S; + outBytesLeft=0x80; + do { + if ((len = iconv(cd, &inBuf, &inBytesLeft, &outBuf, &outBytesLeft)) != (size_t) 0) { +#ifdef DEBUG + MyPrintf(STDERR_WITH_TIME, + "dmap_open(%s,%s,%d) failed to initialize with iconv(), errno = %d in %s at %d\n", + to, from, idx, errno, __FILE__,__LINE__); +#endif + iconv_close(cd); + return -1; + } + } while (inBytesLeft > 0); + + myconv_rec[idx].srcSubS = 0x1A; + myconv_rec[idx].srcSubD = 0xFFFD; + myconv_rec[idx].subS = dmap_rec[idx].dmapU2S[0x1A]; + + outBuf=(char *) &(myconv_rec[idx].subD); + dmapSrc[0]=0xFFFD; + inBuf=(char *) dmapSrc; + inBytesLeft=2; + outBytesLeft=2; + if ((len = iconv(cd, &inBuf, &inBytesLeft, &outBuf, &outBytesLeft)) != (size_t) 0) { +#ifdef DEBUG + if (myconvDebug) { + MyPrintf(STDERR_WITH_TIME, + "dmap_open(%s,%s,%d) failed to initialize with iconv(), rc=%d, errno=%d in %s at %d\n", + to, from, idx, len, errno, __FILE__,__LINE__); + MyPrintf(STDERR_WO_TIME, "iconv(0x1A,1,%p,1) returns outBuf=%p, outBytesLeft=%d\n", + dmapSrc, outBuf, outBytesLeft); + } +#endif + if (outBytesLeft == 0) { + /* UCS-2_IBM-eucKR returns error. + myconv(iconv) rc=1, error=0, InBytesLeft=0, OutBytesLeft=18 + myconv(iconvRev) rc=-1, error=116, InBytesLeft=2, OutBytesLeft=20 + iconv: 0xFFFD => 0xAFFE => 0x rc=1,-1 sub=0,0 + */ + ; + } else { + iconv_close(cd); + return -1; + } + } + + for (i = 0x80; i < 0xFFFF; ++i) { + uchar eucBuf[3]; + dmapSrc[0]=i; + inBuf=(char *) dmapSrc; + inBytesLeft=2; + outBuf=(char *) eucBuf; + outBytesLeft=sizeof(eucBuf); + errno=0; + if ((len = iconv(cd, &inBuf, &inBytesLeft, &outBuf, &outBytesLeft)) != (size_t) 0) { + if (len == 1 && errno == 0 && inBytesLeft == 0 && outBytesLeft == 1) { /* substitution occurred. */ continue; + } + + if (errno == EILSEQ) { +#ifdef DEBUG + if (myconvDebug) { + MyPrintf(STDERR_WITH_TIME, + "dmap_open(%s,%s,%d) failed to initialize with iconv(), errno = %d in %s at %d\n", + to, from, idx, errno, __FILE__,__LINE__); + MyPrintf(STDERR_WO_TIME, "inBytesLeft=%d, outBytesLeft=%d\n", inBytesLeft, outBytesLeft); + if (inBuf - (char *) dmapSrc > 1 && inBuf - (char *) dmapSrc <= sizeof(dmapSrc) - 2) + MyPrintf(STDERR_WO_TIME, "inBuf[-2..2]=%02X%02X%02X%02X%02X\n", inBuf[-2],inBuf[-1],inBuf[0],inBuf[1],inBuf[2]); + else + MyPrintf(STDERR_WO_TIME, "inBuf[0..2]=%02X%02X%02X\n", inBuf[0],inBuf[1],inBuf[2]); + if (outBuf - (char *) dmap_rec[idx].dmapU2M2 > 1) + MyPrintf(STDERR_WO_TIME, "outBuf[-2..2]=%02X%02X%02X%02X%02X\n", outBuf[-2],outBuf[-1],outBuf[0],outBuf[1],outBuf[2]); + else + MyPrintf(STDERR_WO_TIME, "outBuf[0..2]=%02X%02X%02X\n", outBuf[0],outBuf[1],outBuf[2]); + } +#endif + inBuf+=2; + inBytesLeft-=2; + memcpy(outBuf, (char *) &(myconv_rec[idx].subD), 2); + outBuf+=2; + outBytesLeft-=2; + } else { +#ifdef DEBUG + if (myconvDebug) { + MyPrintf(STDERR_WITH_TIME, + "dmap_open(%s,%s,%d) failed to initialize with iconv(), rc = %d, errno = %d in %s at %d\n", + to, from, idx, len, errno, __FILE__,__LINE__); + MyPrintf(STDERR_WITH_TIME, + "%04X: src=%04X%04X, inBuf=0x%02X%02X, inBytesLeft=%d, outBuf[-2..0]=%02X%02X%02X, outBytesLeft=%d\n", + i, dmapSrc[0], dmapSrc[1], inBuf[0], inBuf[1], + inBytesLeft, outBuf[-2], outBuf[-1], outBuf[0], outBytesLeft); + MyPrintf(STDERR_WITH_TIME, + "&dmapSrc=%p, inBuf=%p, dmapU2M2 + %d = %p, outBuf=%p\n", + dmapSrc, inBuf, (i - 0x80) * 2, dmap_rec[idx].dmapU2M2 + (i - 0x80) * 2, outBuf); + } +#endif + iconv_close(cd); + return -1; + } + } + if (sizeof(eucBuf) - outBytesLeft == 1) { + if (i < 0x100) { + (dmap_rec[idx].dmapU2S)[i]=eucBuf[0]; + } else { + dmap_rec[idx].dmapU2M2[(i - 0x80) * 2] = eucBuf[0]; + dmap_rec[idx].dmapU2M2[(i - 0x80) * 2 + 1] = 0x00; + } + } else if (sizeof(eucBuf) - outBytesLeft == 2) { /* 2 bytes */ + dmap_rec[idx].dmapU2M2[(i - 0x80) * 2] = eucBuf[0]; + dmap_rec[idx].dmapU2M2[(i - 0x80) * 2 + 1] = eucBuf[1]; + } else if (sizeof(eucBuf) - outBytesLeft == 3) { /* 3 byte SS2/SS3 */ + dmap_rec[idx].dmapU2M3[(i - 0x80) * 3] = eucBuf[0]; + dmap_rec[idx].dmapU2M3[(i - 0x80) * 3 + 1] = eucBuf[1]; + dmap_rec[idx].dmapU2M3[(i - 0x80) * 3 + 2] = eucBuf[2]; + } else { +#ifdef DEBUG + if (myconvDebug) { + MyPrintf(STDERR_WITH_TIME, + "dmap_open(%s,%s,%d) failed to initialize with iconv(), rc=%d, errno=%d in %s at %d\n", + to, from, idx, len, errno, __FILE__,__LINE__); + MyPrintf(STDERR_WITH_TIME, + "%04X: src=%04X%04X, inBuf=0x%02X%02X, inBytesLeft=%d, outBuf=%02X%02X%02X, outBytesLeft=%d\n", + i, dmapSrc[0], dmapSrc[1], inBuf[0], inBuf[1], + inBytesLeft, outBuf[-2], outBuf[-1], outBuf[0], outBytesLeft); + MyPrintf(STDERR_WITH_TIME, + "&dmapSrc=%p, inBuf=%p, %p, outBuf=%p\n", + dmapSrc, inBuf, dmap_rec[idx].dmapU2M3 + (i - 0x80) * 2, outBuf); + } +#endif + return -1; + } + + } + iconv_close(cd); + } + + } else if (myconvIsUTF16(from) && myconvIsUTF8(to)) { + dmap_rec[idx].codingSchema = DMAP_T28; + + } else if (myconvIsUCS2(from) && myconvIsUTF8(to)) { + dmap_rec[idx].codingSchema = DMAP_U28; + + } else if (myconvIsUTF8(from) && myconvIsUnicode2(to)) { + dmap_rec[idx].codingSchema = DMAP_82U; + + } else if (myconvIsUnicode2(from) && myconvIsUnicode2(to)) { + dmap_rec[idx].codingSchema = DMAP_U2U; + + } else { + + return -1; + } + myconv_rec[idx].cnv_dmap=&(dmap_rec[idx]); + return 0; +} + + + +static int bins_open(const char * to, + const char * from, + const int32_t idx) +{ + return -1; +} + + + +static int32_t dmap_close(const int32_t idx) +{ + if (dmap_rec[idx].codingSchema == DMAP_S2S) { + if (dmap_rec[idx].dmapS2S != NULL) { + dmap_rec[idx].dmapS2S=NULL; + } + } else if (dmap_rec[idx].codingSchema = DMAP_E2U) { + if (dmap_rec[idx].dmapE02U != NULL) { + dmap_rec[idx].dmapE02U=NULL; + } + if (dmap_rec[idx].dmapE12U != NULL) { + dmap_rec[idx].dmapE12U=NULL; + } + if (dmap_rec[idx].dmapE22U != NULL) { + dmap_rec[idx].dmapE22U=NULL; + } + if (dmap_rec[idx].dmapE32U != NULL) { + dmap_rec[idx].dmapE32U=NULL; + } + } + + return 0; +} + + +static int32_t bins_close(const int32_t idx) +{ + return 0; +} + + +myconv_t myconv_open(const char * toCode, + const char * fromCode, + int32_t converter) +{ + int32 i; + for (i = 0; i < MAX_CONVERTER; ++i) { + if (myconv_rec[i].converterType == 0) + break; + } + if (i >= MAX_CONVERTER) + return ((myconv_t) -1); + + myconv_rec[i].converterType = converter; + myconv_rec[i].index=i; + myconv_rec[i].fromCcsid=cstoccsid(fromCode); + if (myconv_rec[i].fromCcsid == 0 && memcmp(fromCode, "big5",5) == 0) + myconv_rec[i].fromCcsid=950; + myconv_rec[i].toCcsid=cstoccsid(toCode); + if (myconv_rec[i].toCcsid == 0 && memcmp(toCode, "big5",5) == 0) + myconv_rec[i].toCcsid=950; + strncpy(myconv_rec[i].from, fromCode, sizeof(myconv_rec[i].from)-1); + strncpy(myconv_rec[i].to, toCode, sizeof(myconv_rec[i].to)-1); + + if (converter == CONVERTER_ICONV) { + if ((myconv_rec[i].cnv_iconv=iconv_open(toCode, fromCode)) == (iconv_t) -1) { + return ((myconv_t) -1); + } + myconv_rec[i].allocatedSize = -1; + myconv_rec[i].srcSubS=myconvGetSubS(fromCode); + myconv_rec[i].srcSubD=myconvGetSubD(fromCode); + myconv_rec[i].subS=myconvGetSubS(toCode); + myconv_rec[i].subD=myconvGetSubD(toCode); + return &(myconv_rec[i]); + } else if (converter == CONVERTER_DMAP && + dmap_open(toCode, fromCode, i) != -1) { + return &(myconv_rec[i]); + } + return ((myconv_t) -1); +} + + + +int32_t myconv_close(myconv_t cd) +{ + int32_t ret=0; + + if (cd->converterType == CONVERTER_ICONV) { + ret=iconv_close(cd->cnv_iconv); + } else if (cd->converterType == CONVERTER_DMAP) { + ret=dmap_close(cd->index); + } + memset(&(myconv_rec[cd->index]), 0x00, sizeof(myconv_rec[cd->index])); + return ret; +} + + + + +/* reference: http://www-306.ibm.com/software/globalization/other/es.jsp */ +/* systemCL would be expensive, and myconvIsXXXXX is called frequently. + need to cache entries */ +#define MAX_CCSID 256 +static int ccsidList [MAX_CCSID]; +static int esList [MAX_CCSID]; +int32 getEncodingScheme(const uint16 inCcsid, int32& outEncodingScheme); +EXTERN int myconvGetES(CCSID ccsid) +{ + /* call QtqValidateCCSID in ILE to get encoding schema */ + /* return QtqValidateCCSID(ccsid); */ + int i; + for (i = 0; i < MAX_CCSID; ++i) { + if (ccsidList[i] == ccsid) + return esList[i]; + if (ccsidList[i] == 0x00) + break; + } + + if (i >= MAX_CCSID) { + i=MAX_CCSID-1; + } + + { + ccsidList[i]=ccsid; + getEncodingScheme(ccsid, esList[i]); +#ifdef DEBUG_PASE + if (myconvDebug) { + fprintf(stderr, "CCSID=%d, ES=0x%04X\n", ccsid, esList[i]); + } +#endif + return esList[i]; + } + return 0; +} + + +EXTERN int myconvIsEBCDIC(const char * pName) +{ + int es = myconvGetES(cstoccsid(pName)); + if (es == 0x1100 || + es == 0x1200 || + es == 0x6100 || + es == 0x6200 || + es == 0x1301 ) { + return TRUE; + } + return FALSE; +} + + +EXTERN int myconvIsISO(const char * pName) +{ + int es = myconvGetES(cstoccsid(pName)); + if (es == 0x4100 || + es == 0x4105 || + es == 0x4155 || + es == 0x5100 || + es == 0x5150 || + es == 0x5200 || + es == 0x5404 || + es == 0x5409 || + es == 0x540A || + es == 0x5700) { + return TRUE; + } + return FALSE; +} + + +EXTERN int myconvIsASCII(const char * pName) +{ + int es = myconvGetES(cstoccsid(pName)); + if (es == 0x2100 || + es == 0x3100 || + es == 0x8100 || + es == 0x2200 || + es == 0x3200 || + es == 0x9200 || + es == 0x2300 || + es == 0x2305 || + es == 0x3300 || + es == 0x2900 || + es == 0x2A00) { + return TRUE; + } else if (memcmp(pName, "big5", 5) == 0) { + return TRUE; + } + return FALSE; +} + + + +EXTERN int myconvIsUCS2(const char * pName) +{ + if (cstoccsid(pName) == 13488) { + return TRUE; + } + return FALSE; +} + + +EXTERN int myconvIsUTF16(const char * pName) +{ + if (cstoccsid(pName) == 1200) { + return TRUE; + } + return FALSE; +} + + +EXTERN int myconvIsUnicode2(const char * pName) +{ + int es = myconvGetES(cstoccsid(pName)); + if (es == 0x7200 || + es == 0x720B || + es == 0x720F) { + return TRUE; + } + return FALSE; +} + + +EXTERN int myconvIsUTF8(const char * pName) +{ + int es = myconvGetES(cstoccsid(pName)); + if (es == 0x7807) { + return TRUE; + } + return FALSE; +} + + +EXTERN int myconvIsUnicode(const char * pName) +{ + int es = myconvGetES(cstoccsid(pName)); + if (es == 0x7200 || + es == 0x720B || + es == 0x720F || + es == 0x7807) { + return TRUE; + } + return FALSE; +} + + +EXTERN int myconvIsEUC(const char * pName) +{ + int es = myconvGetES(cstoccsid(pName)); + if (es == 0x4403) { + return TRUE; + } + return FALSE; +} + + +EXTERN int myconvIsDBCS(const char * pName) +{ + int es = myconvGetES(cstoccsid(pName)); + if (es == 0x1200 || + es == 0x2200 || + es == 0x2300 || + es == 0x2305 || + es == 0x2A00 || + es == 0x3200 || + es == 0x3300 || + es == 0x5200 || + es == 0x6200 || + es == 0x9200) { + return TRUE; + } else if (memcmp(pName, "big5", 5) == 0) { + return TRUE; + } + return FALSE; +} + + +EXTERN int myconvIsSBCS(const char * pName) +{ + int es = myconvGetES(cstoccsid(pName)); + if (es == 0x1100 || + es == 0x2100 || + es == 0x3100 || + es == 0x4100 || + es == 0x4105 || + es == 0x5100 || + es == 0x5150 || + es == 0x6100 || + es == 0x8100) { + return TRUE; + } + return FALSE; +} + + + +EXTERN char myconvGetSubS(const char * code) +{ + if (myconvIsEBCDIC(code)) { + return 0x3F; + } else if (myconvIsASCII(code)) { + return 0x1A; + } else if (myconvIsISO(code)) { + return 0x1A; + } else if (myconvIsEUC(code)) { + return 0x1A; + } else if (myconvIsUCS2(code)) { + return 0x00; + } else if (myconvIsUTF8(code)) { + return 0x1A; + } + return 0x00; +} + + +EXTERN UniChar myconvGetSubD(const char * code) +{ + if (myconvIsEBCDIC(code)) { + return 0xFDFD; + } else if (myconvIsASCII(code)) { + return 0xFCFC; + } else if (myconvIsISO(code)) { + return 0x00; + } else if (myconvIsEUC(code)) { + return 0x00; + } else if (myconvIsUCS2(code)) { + return 0xFFFD; + } else if (myconvIsUTF8(code)) { + return 0x00; + } + return 0x00; +} + diff --git a/storage/ibmdb2i/db2i_myconv.h b/storage/ibmdb2i/db2i_myconv.h new file mode 100644 index 00000000000..a9e87474505 --- /dev/null +++ b/storage/ibmdb2i/db2i_myconv.h @@ -0,0 +1,3200 @@ +/* +Licensed Materials - Property of IBM +DB2 Storage Engine Enablement +Copyright IBM Corporation 2007,2008 +All rights reserved + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + (a) Redistributions of source code must retain this list of conditions, the + copyright notice in section {d} below, and the disclaimer following this + list of conditions. + (b) Redistributions in binary form must reproduce this list of conditions, the + copyright notice in section (d) below, and the disclaimer following this + list of conditions, in the documentation and/or other materials provided + with the distribution. + (c) The name of IBM may not be used to endorse or promote products derived from + this software without specific prior written permission. + (d) The text of the required copyright notice is: + Licensed Materials - Property of IBM + DB2 Storage Engine Enablement + Copyright IBM Corporation 2007,2008 + All rights reserved + +THIS SOFTWARE IS PROVIDED BY IBM CORPORATION "AS IS" AND ANY EXPRESS OR IMPLIED +WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT +SHALL IBM CORPORATION BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT +OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT INCLUDING NEGLIGENCE OR OTHERWISE) ARISING +IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +/** + @file + + @brief A direct map optimization of iconv and related functions + This was show to significantly reduce character conversion cost + for short strings when compared to calling iconv system code. +*/ + +#ifndef DB2I_MYCONV_H +#define DB2I_MYCONV_H + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifndef TRUE +#define TRUE 1 +#endif + +#ifndef FALSE +#define FALSE 0 +#endif + +#ifdef __cplusplus +#define INTERN inline +#define EXTERN extern "C" +#else +#define INTERN static +#define EXTERN extern +#endif + + +/* ANSI integer data types */ +#if defined(__OS400_TGTVRM__) +/* for DTAMDL(*P128), datamodel(P128): int/long/pointer=4/4/16 */ +/* LLP64:4/4/8 is used for teraspace ?? */ +typedef short int16_t; +typedef unsigned short uint16_t; +typedef int int32_t; +typedef unsigned int uint32_t; +typedef long long int64_t; +typedef unsigned long long uint64_t; +#elif defined(PASE) +/* PASE uses IPL32: int/long/pointer=4/4/4 + long long */ +#elif defined(__64BIT__) +/* AIX 64 bit uses LP64: int/long/pointer=4/8/8 */ +#endif + +#define CONVERTER_ICONV 1 +#define CONVERTER_DMAP 2 + +#define DMAP_S2S 10 +#define DMAP_S2U 20 +#define DMAP_D2U 30 +#define DMAP_E2U 40 +#define DMAP_U2S 120 +#define DMAP_T2S 125 +#define DMAP_U2D 130 +#define DMAP_T2D 135 +#define DMAP_U2E 140 +#define DMAP_T2E 145 +#define DMAP_S28 220 +#define DMAP_D28 230 +#define DMAP_E28 240 +#define DMAP_82S 310 +#define DMAP_82D 320 +#define DMAP_82E 330 +#define DMAP_U28 410 +#define DMAP_82U 420 +#define DMAP_T28 425 +#define DMAP_U2U 510 + + +typedef struct __dmap_rec *dmap_t; + +struct __dmap_rec +{ + uint32_t codingSchema; + unsigned char * dmapS2S; /* SBCS -> SBCS */ + /* The following conversion needs be followed by conversion from UCS-2/UTF-16 to UTF-8 */ + UniChar * dmapD12U; /* DBCS(non-EUC) -> UCS-2/UTF-16 */ + UniChar * dmapD22U; /* DBCS(non-EUC) -> UCS-2/UTF-16 */ + UniChar * dmapE02U; /* EUC/SS0 -> UCS-2/UTF-16 */ + UniChar * dmapE12U; /* EUC/SS1 -> UCS-2/UTF-16 */ + UniChar * dmapE22U; /* EUC/0x8E + SS2 -> UCS-2/UTF-16 */ + UniChar * dmapE32U; /* EUC/0x8F + SS3 -> UCS-2/UTF-16 */ + uchar * dmapU2D; /* UCS-2 -> DBCS */ + uchar * dmapU2S; /* UCS-2 -> EUC SS0 */ + uchar * dmapU2M2; /* UCS-2 -> EUC SS1 */ + uchar * dmapU2M3; /* UCS-2 -> EUC SS2/SS3 */ + /* All of these pointers/tables are not used at the same time. + * You may be able save some space if you consolidate them. + */ + uchar * dmapS28; /* SBCS -> UTF-8 */ + uchar * dmapD28; /* DBCS -> UTF-8 */ +}; + +typedef struct __myconv_rec *myconv_t; +struct __myconv_rec +{ + uint32_t converterType; + uint32_t index; /* for close */ + union { + iconv_t cnv_iconv; + dmap_t cnv_dmap; + }; + int32_t allocatedSize; + int32_t fromCcsid; + int32_t toCcsid; + UniChar subD; /* DBCS substitution char */ + char subS; /* SBCS substitution char */ + UniChar srcSubD; /* DBCS substitution char of src codepage */ + char srcSubS; /* SBCS substitution char of src codepage */ + char from [41+1]; /* codepage name is up to 41 bytes */ + char to [41+1]; /* codepage name is up to 41 bytes */ +#ifdef __64BIT__ + char reserved[10]; /* align 128 */ +#else + char reserved[14]; /* align 128 */ +#endif +}; + + +EXTERN int32_t myconvDebug; + + + +EXTERN int myconvGetES(CCSID); +EXTERN int myconvIsEBCDIC(const char *); +EXTERN int myconvIsASCII(const char *); +EXTERN int myconvIsUnicode(const char *); /* UTF-8, UTF-16, or UCS-2 */ +EXTERN int myconvIsUnicode2(const char *); /* 2 byte Unicode */ +EXTERN int myconvIsUCS2(const char *); +EXTERN int myconvIsUTF16(const char *); +EXTERN int myconvIsUTF8(const char *); +EXTERN int myconvIsEUC(const char *); +EXTERN int myconvIsISO(const char *); +EXTERN int myconvIsSBCS(const char *); +EXTERN int myconvIsDBCS(const char *); +EXTERN char myconvGetSubS(const char *); +EXTERN UniChar myconvGetSubD(const char *); + + +EXTERN myconv_t myconv_open(const char*, const char*, int32_t); +EXTERN int myconv_close(myconv_t); + +INTERN size_t myconv_iconv(myconv_t cd , + char** inBuf, + size_t* inBytesLeft, + char** outBuf, + size_t* outBytesLeft, + size_t* numSub) +{ + return iconv(cd->cnv_iconv, inBuf, inBytesLeft, outBuf, outBytesLeft); +} + +INTERN size_t myconv_dmap(myconv_t cd, + char** inBuf, + size_t* inBytesLeft, + char** outBuf, + size_t* outBytesLeft, + size_t* numSub) +{ + if (cd->cnv_dmap->codingSchema == DMAP_S2S) { + register unsigned char * dmapS2S=cd->cnv_dmap->dmapS2S; + register int inLen=*inBytesLeft; + register char * pOut=*outBuf; + register char * pIn=*inBuf; + register char * pLastOutBuf = *outBuf + *outBytesLeft - 1; + register char subS=cd->subS; + register size_t numS=0; + while (0 < inLen) { + if (pLastOutBuf < pOut) + break; + if (*pIn == 0x00) { + *pOut=0x00; + } else { + *pOut=dmapS2S[*pIn]; + if (*pOut == 0x00) { + *outBytesLeft-=(*inBytesLeft-inLen); + *inBytesLeft=inLen; + *outBuf=pOut; + *inBuf=pIn; + *numSub+=numS; + return -1; + } + if (*pOut == subS) { + if ((*pOut=dmapS2S[*pIn]) == subS) { + if (*pIn != cd->srcSubS) + ++numS; + } + } + } + ++pIn; + --inLen; + ++pOut; + } + *outBytesLeft-=(*inBytesLeft-inLen); + *inBytesLeft=inLen; + *outBuf=pOut; + *inBuf=pIn; + *numSub+=numS; + return 0; + + } else if (cd->cnv_dmap->codingSchema == DMAP_E2U) { + /* use uchar * instead of UniChar to avoid memcpy */ + register uchar * dmapE02U=(uchar *) (cd->cnv_dmap->dmapE02U); + register uchar * dmapE12U=(uchar *) (cd->cnv_dmap->dmapE12U); + register uchar * dmapE22U=(uchar *) (cd->cnv_dmap->dmapE22U); + register uchar * dmapE32U=(uchar *) (cd->cnv_dmap->dmapE32U); + register int inLen=*inBytesLeft; + register char * pOut=*outBuf; + register char * pIn=*inBuf; + register int offset; + register char * pLastOutBuf = *outBuf + *outBytesLeft - 1; + register size_t numS=0; + while (0 < inLen) { + if (pLastOutBuf < pOut) + break; + if (*pIn == 0x00) { + *pOut=0x00; + ++pOut; + *pOut=0x00; + ++pOut; + ++pIn; + --inLen; + } else { + if (*pIn == 0x8E) { /* SS2 */ + if (inLen < 2) { + if (cd->fromCcsid == 33722 || /* IBM-eucJP */ + cd->fromCcsid == 964) /* IBM-eucTW */ + errno=EINVAL; /* 22 */ + else + errno=EILSEQ; /* 116 */ + *outBytesLeft-=(pOut-*outBuf); + *inBytesLeft=inLen; + *outBuf=pOut; + *inBuf=pIn; + return -1; + } + ++pIn; + if (*pIn < 0xA0) { + if (cd->fromCcsid == 964) /* IBM-eucTW */ + errno=EINVAL; /* 22 */ + else + errno=EILSEQ; /* 116 */ + *outBytesLeft-=(pOut-*outBuf); + *inBytesLeft=inLen; + *outBuf=pOut; + *inBuf=pIn-1; + return -1; + } + offset=(*pIn - 0xA0); + offset<<=1; + if (dmapE22U[offset] == 0x00 && + dmapE22U[offset+1] == 0x00) { /* 2 bytes */ + if (inLen < 3) { + if (cd->fromCcsid == 964) /* IBM-eucTW */ + errno=EINVAL; /* 22 */ + else + errno=EILSEQ; /* 116 */ + *outBytesLeft-=(pOut-*outBuf); + *inBytesLeft=inLen; + *outBuf=pOut; + *inBuf=pIn-1; + return -1; + } + offset=(*pIn - 0xA0) * 0x60 + 0x60; + ++pIn; + if (*pIn < 0xA0) { + if (cd->fromCcsid == 964) /* IBM-eucTW */ + errno=EINVAL; /* 22 */ + else + errno=EILSEQ; /* 116 */ + *outBytesLeft-=(pOut-*outBuf); + *inBytesLeft=inLen; + *outBuf=pOut; + *inBuf=pIn-2; + return -1; + } + offset+=(*pIn - 0xA0); + offset<<=1; + if (dmapE22U[offset] == 0x00 && + dmapE22U[offset+1] == 0x00) { + if (cd->fromCcsid == 964) /* IBM-eucTW */ + errno=EINVAL; /* 22 */ + else + errno=EILSEQ; /* 116 */ + *outBytesLeft-=(pOut-*outBuf); + *inBytesLeft=inLen; + *outBuf=pOut; + *inBuf=pIn-2; + return -1; + } + *pOut=dmapE22U[offset]; + ++pOut; + *pOut=dmapE22U[offset+1]; + ++pOut; + if (dmapE22U[offset] == 0xFF && + dmapE22U[offset+1] == 0xFD) { + if (pIn[-2] * 0x100 + pIn[-1] != cd->srcSubD) + ++numS; + } + ++pIn; + inLen-=3; + } else { /* 1 bytes */ + *pOut=dmapE22U[offset]; + ++pOut; + *pOut=dmapE22U[offset+1]; + ++pOut; + ++pIn; + inLen-=2; + } + } else if (*pIn == 0x8F) { /* SS3 */ + if (inLen < 2) { + if (cd->fromCcsid == 33722) /* IBM-eucJP */ + errno=EINVAL; /* 22 */ + else + errno=EILSEQ; /* 116 */ + *outBytesLeft-=(pOut-*outBuf); + *inBytesLeft=inLen; + *outBuf=pOut; + *inBuf=pIn; + return -1; + } + ++pIn; + if (*pIn < 0xA0) { + if (cd->fromCcsid == 970 || /* IBM-eucKR */ + cd->fromCcsid == 964 || /* IBM-eucTW */ + cd->fromCcsid == 1383 || /* IBM-eucCN */ + (cd->fromCcsid == 33722 && 3 <= inLen)) /* IBM-eucJP */ + errno=EILSEQ; /* 116 */ + else + errno=EINVAL; /* 22 */ + *outBytesLeft-=(pOut-*outBuf); + *inBytesLeft=inLen; + *outBuf=pOut; + *inBuf=pIn-1; + return -1; + } + offset=(*pIn - 0xA0); + offset<<=1; + if (dmapE32U[offset] == 0x00 && + dmapE32U[offset+1] == 0x00) { /* 0x8F + 2 bytes */ + if (inLen < 3) { + if (cd->fromCcsid == 33722) + errno=EINVAL; /* 22 */ + else + errno=EILSEQ; /* 116 */ + *outBytesLeft-=(pOut-*outBuf); + *inBytesLeft=inLen; + *outBuf=pOut; + *inBuf=pIn-1; + return -1; + } + offset=(*pIn - 0xA0) * 0x60 + 0x60; + ++pIn; + if (*pIn < 0xA0) { + errno=EILSEQ; /* 116 */ + *outBytesLeft-=(pOut-*outBuf); + *inBytesLeft=inLen; + *outBuf=pOut; + *inBuf=pIn-2; + return -1; + } + offset+=(*pIn - 0xA0); + offset<<=1; + if (dmapE32U[offset] == 0x00 && + dmapE32U[offset+1] == 0x00) { + errno=EILSEQ; /* 116 */ + *outBytesLeft-=(pOut-*outBuf); + *inBytesLeft=inLen; + *outBuf=pOut; + *inBuf=pIn-2; + return -1; + } + *pOut=dmapE32U[offset]; + ++pOut; + *pOut=dmapE32U[offset+1]; + ++pOut; + if (dmapE32U[offset] == 0xFF && + dmapE32U[offset+1] == 0xFD) { + if (pIn[-2] * 0x100 + pIn[-1] != cd->srcSubD) + ++numS; + } + ++pIn; + inLen-=3; + } else { /* 0x8F + 1 bytes */ + *pOut=dmapE32U[offset]; + ++pOut; + *pOut=dmapE32U[offset+1]; + ++pOut; + ++pIn; + inLen-=2; + } + + } else { + offset=*pIn; + offset<<=1; + if (dmapE02U[offset] == 0x00 && + dmapE02U[offset+1] == 0x00) { /* SS1 */ + if (inLen < 2) { + if ((cd->fromCcsid == 33722 && (*pIn == 0xA0 || (0xA9 <= *pIn && *pIn <= 0xAF) || *pIn == 0xFF)) || + (cd->fromCcsid == 970 && (*pIn == 0xA0 || *pIn == 0xAD || *pIn == 0xAE || *pIn == 0xAF || *pIn == 0xFF)) || + (cd->fromCcsid == 964 && (*pIn == 0xA0 || (0xAA <= *pIn && *pIn <= 0xC1) || *pIn == 0xC3 || *pIn == 0xFE || *pIn == 0xFF)) || + (cd->fromCcsid == 1383 && (*pIn == 0xA0 || *pIn == 0xFF))) + errno=EILSEQ; /* 116 */ + else + errno=EINVAL; /* 22 */ + *outBytesLeft-=(pOut-*outBuf); + *inBytesLeft=inLen; + *outBuf=pOut; + *inBuf=pIn; + return -1; + } + if (*pIn < 0xA0) { + errno=EILSEQ; /* 116 */ + *outBytesLeft-=(pOut-*outBuf); + *inBytesLeft=inLen; + *outBuf=pOut; + *inBuf=pIn; + return -1; + } + offset=(*pIn - 0xA0) * 0x60; + ++pIn; + if (*pIn < 0xA0) { + errno=EILSEQ; /* 116 */ + *outBytesLeft-=(pOut-*outBuf); + *inBytesLeft=inLen; + *outBuf=pOut; + *inBuf=pIn-1; + return -1; + } + offset+=(*pIn - 0xA0); + offset<<=1; + if (dmapE12U[offset] == 0x00 && + dmapE12U[offset+1] == 0x00) { /* undefined mapping */ + errno=EILSEQ; /* 116 */ + *outBytesLeft-=(pOut-*outBuf); + *inBytesLeft=inLen; + *outBuf=pOut; + *inBuf=pIn-1; + return -1; + } + *pOut=dmapE12U[offset]; + ++pOut; + *pOut=dmapE12U[offset+1]; + ++pOut; + if (dmapE12U[offset] == 0xFF && + dmapE12U[offset+1] == 0xFD) { + if (pIn[-1] * 0x100 + pIn[0] != cd->srcSubD) + ++numS; + } + ++pIn; + inLen-=2; + } else { + *pOut=dmapE02U[offset]; + ++pOut; + *pOut=dmapE02U[offset+1]; + ++pOut; + if (dmapE02U[offset] == 0x00 && + dmapE02U[offset+1] == 0x1A) { + if (*pIn != cd->srcSubS) + ++numS; + } + ++pIn; + --inLen; + } + } + } + } + *outBytesLeft-=(pOut-*outBuf); + *inBytesLeft=inLen; + *outBuf=pOut; + *inBuf=pIn; + *numSub+=numS; + return 0; + + + } else if (cd->cnv_dmap->codingSchema == DMAP_E28) { + /* use uchar * instead of UniChar to avoid memcpy */ + register uchar * dmapE02U=(uchar *) (cd->cnv_dmap->dmapE02U); + register uchar * dmapE12U=(uchar *) (cd->cnv_dmap->dmapE12U); + register uchar * dmapE22U=(uchar *) (cd->cnv_dmap->dmapE22U); + register uchar * dmapE32U=(uchar *) (cd->cnv_dmap->dmapE32U); + register int inLen=*inBytesLeft; + register char * pOut=*outBuf; + register char * pIn=*inBuf; + register int offset; + register char * pLastOutBuf = *outBuf + *outBytesLeft - 1; + register size_t numS=0; + register UniChar in; /* copy part of U28 */ + register UniChar ucs2; + while (0 < inLen) { + if (pLastOutBuf < pOut) + break; + if (*pIn == 0x00) { + *pOut=0x00; + ++pOut; + ++pIn; + --inLen; + } else { + if (*pIn == 0x8E) { /* SS2 */ + if (inLen < 2) { + if (cd->fromCcsid == 33722 || /* IBM-eucJP */ + cd->fromCcsid == 964) /* IBM-eucTW */ + errno=EINVAL; /* 22 */ + else + errno=EILSEQ; /* 116 */ + *outBytesLeft-=(pOut-*outBuf); + *inBytesLeft=inLen; + *outBuf=pOut; + *inBuf=pIn; + return -1; + } + ++pIn; + if (*pIn < 0xA0) { + if (cd->fromCcsid == 964) /* IBM-eucTW */ + errno=EINVAL; /* 22 */ + else + errno=EILSEQ; /* 116 */ + *outBytesLeft-=(pOut-*outBuf); + *inBytesLeft=inLen; + *outBuf=pOut; + *inBuf=pIn-1; + return -1; + } + offset=(*pIn - 0xA0); + offset<<=1; + if (dmapE22U[offset] == 0x00 && + dmapE22U[offset+1] == 0x00) { /* 2 bytes */ + if (inLen < 3) { + if (cd->fromCcsid == 964) /* IBM-eucTW */ + errno=EINVAL; /* 22 */ + else + errno=EILSEQ; /* 116 */ + *outBytesLeft-=(pOut-*outBuf); + *inBytesLeft=inLen; + *outBuf=pOut; + *inBuf=pIn-1; + return -1; + } + offset=(*pIn - 0xA0) * 0x60 + 0x60; + ++pIn; + if (*pIn < 0xA0) { + if (cd->fromCcsid == 964) /* IBM-eucTW */ + errno=EINVAL; /* 22 */ + else + errno=EILSEQ; /* 116 */ + *outBytesLeft-=(pOut-*outBuf); + *inBytesLeft=inLen; + *outBuf=pOut; + *inBuf=pIn-2; + return -1; + } + offset+=(*pIn - 0xA0); + offset<<=1; + if (dmapE22U[offset] == 0x00 && + dmapE22U[offset+1] == 0x00) { + if (cd->fromCcsid == 964) /* IBM-eucTW */ + errno=EINVAL; /* 22 */ + else + errno=EILSEQ; /* 116 */ + *outBytesLeft-=(pOut-*outBuf); + *inBytesLeft=inLen; + *outBuf=pOut; + *inBuf=pIn-2; + return -1; + } + in=dmapE22U[offset]; + in<<=8; + in+=dmapE22U[offset+1]; + if (dmapE22U[offset] == 0xFF && + dmapE22U[offset+1] == 0xFD) { + if (pIn[-2] * 0x100 + pIn[-1] != cd->srcSubD) + ++numS; + } + ++pIn; + inLen-=3; + } else { /* 1 bytes */ + in=dmapE22U[offset]; + in<<=8; + in+=dmapE22U[offset+1]; + ++pIn; + inLen-=2; + } + } else if (*pIn == 0x8F) { /* SS3 */ + if (inLen < 2) { + if (cd->fromCcsid == 33722) /* IBM-eucJP */ + errno=EINVAL; /* 22 */ + else + errno=EILSEQ; /* 116 */ + *outBytesLeft-=(pOut-*outBuf); + *inBytesLeft=inLen; + *outBuf=pOut; + *inBuf=pIn; + return -1; + } + ++pIn; + if (*pIn < 0xA0) { + if (cd->fromCcsid == 970 || /* IBM-eucKR */ + cd->fromCcsid == 964 || /* IBM-eucTW */ + cd->fromCcsid == 1383 || /* IBM-eucCN */ + (cd->fromCcsid == 33722 && 3 <= inLen)) /* IBM-eucJP */ + errno=EILSEQ; /* 116 */ + else + errno=EINVAL; /* 22 */ + *outBytesLeft-=(pOut-*outBuf); + *inBytesLeft=inLen; + *outBuf=pOut; + *inBuf=pIn-1; + return -1; + } + offset=(*pIn - 0xA0); + offset<<=1; + if (dmapE32U[offset] == 0x00 && + dmapE32U[offset+1] == 0x00) { /* 0x8F + 2 bytes */ + if (inLen < 3) { + if (cd->fromCcsid == 33722) + errno=EINVAL; /* 22 */ + else + errno=EILSEQ; /* 116 */ + *outBytesLeft-=(pOut-*outBuf); + *inBytesLeft=inLen; + *outBuf=pOut; + *inBuf=pIn-1; + return -1; + } + offset=(*pIn - 0xA0) * 0x60 + 0x60; + ++pIn; + if (*pIn < 0xA0) { + errno=EILSEQ; /* 116 */ + *outBytesLeft-=(pOut-*outBuf); + *inBytesLeft=inLen; + *outBuf=pOut; + *inBuf=pIn-2; + return -1; + } + offset+=(*pIn - 0xA0); + offset<<=1; + if (dmapE32U[offset] == 0x00 && + dmapE32U[offset+1] == 0x00) { + errno=EILSEQ; /* 116 */ + *outBytesLeft-=(pOut-*outBuf); + *inBytesLeft=inLen; + *outBuf=pOut; + *inBuf=pIn-2; + return -1; + } + in=dmapE32U[offset]; + in<<=8; + in+=dmapE32U[offset+1]; + if (dmapE32U[offset] == 0xFF && + dmapE32U[offset+1] == 0xFD) { + if (pIn[-2] * 0x100 + pIn[-1] != cd->srcSubD) + ++numS; + } + ++pIn; + inLen-=3; + } else { /* 0x8F + 1 bytes */ + in=dmapE32U[offset]; + in<<=8; + in+=dmapE32U[offset+1]; + ++pIn; + inLen-=2; + } + + } else { + offset=*pIn; + offset<<=1; + if (dmapE02U[offset] == 0x00 && + dmapE02U[offset+1] == 0x00) { /* SS1 */ + if (inLen < 2) { + if ((cd->fromCcsid == 33722 && (*pIn == 0xA0 || (0xA9 <= *pIn && *pIn <= 0xAF) || *pIn == 0xFF)) || + (cd->fromCcsid == 970 && (*pIn == 0xA0 || *pIn == 0xAD || *pIn == 0xAE || *pIn == 0xAF || *pIn == 0xFF)) || + (cd->fromCcsid == 964 && (*pIn == 0xA0 || (0xAA <= *pIn && *pIn <= 0xC1) || *pIn == 0xC3 || *pIn == 0xFE || *pIn == 0xFF)) || + (cd->fromCcsid == 1383 && (*pIn == 0xA0 || *pIn == 0xFF))) + errno=EILSEQ; /* 116 */ + else + errno=EINVAL; /* 22 */ + *outBytesLeft-=(pOut-*outBuf); + *inBytesLeft=inLen; + *outBuf=pOut; + *inBuf=pIn; + return -1; + } + if (*pIn < 0xA0) { + errno=EILSEQ; /* 116 */ + *outBytesLeft-=(pOut-*outBuf); + *inBytesLeft=inLen; + *outBuf=pOut; + *inBuf=pIn; + return -1; + } + offset=(*pIn - 0xA0) * 0x60; + ++pIn; + if (*pIn < 0xA0) { + errno=EILSEQ; /* 116 */ + *outBytesLeft-=(pOut-*outBuf); + *inBytesLeft=inLen; + *outBuf=pOut; + *inBuf=pIn-1; + return -1; + } + offset+=(*pIn - 0xA0); + offset<<=1; + if (dmapE12U[offset] == 0x00 && + dmapE12U[offset+1] == 0x00) { /* undefined mapping */ + errno=EILSEQ; /* 116 */ + *outBytesLeft-=(pOut-*outBuf); + *inBytesLeft=inLen; + *outBuf=pOut; + *inBuf=pIn-1; + return -1; + } + in=dmapE12U[offset]; + in<<=8; + in+=dmapE12U[offset+1]; + if (dmapE12U[offset] == 0xFF && + dmapE12U[offset+1] == 0xFD) { + if (pIn[-1] * 0x100 + pIn[0] != cd->srcSubD) + ++numS; + } + ++pIn; + inLen-=2; + } else { + in=dmapE02U[offset]; + in<<=8; + in+=dmapE02U[offset+1]; + if (dmapE02U[offset] == 0x00 && + dmapE02U[offset+1] == 0x1A) { + if (*pIn != cd->srcSubS) + ++numS; + } + ++pIn; + --inLen; + } + } + ucs2=in; + if ((in & 0xFF80) == 0x0000) { /* U28: in & 0b1111111110000000 == 0x0000 */ + *pOut=in; + ++pOut; + } else if ((in & 0xF800) == 0x0000) { /* in & 0b1111100000000000 == 0x0000 */ + register uchar byte; + in>>=6; + in&=0x001F; /* 0b0000000000011111 */ + in|=0x00C0; /* 0b0000000011000000 */ + *pOut=in; + ++pOut; + byte=ucs2; /* dmapD12U[offset+1]; */ + byte&=0x3F; /* 0b00111111; */ + byte|=0x80; /* 0b10000000; */ + *pOut=byte; + ++pOut; + } else if ((in & 0xFC00) == 0xD800) { + *pOut=0xEF; + ++pOut; + *pOut=0xBF; + ++pOut; + *pOut=0xBD; + ++pOut; + } else { + register uchar byte; + register uchar work; + byte=(ucs2>>8); /* dmapD12U[offset]; */ + byte>>=4; + byte|=0xE0; /* 0b11100000; */ + *pOut=byte; + ++pOut; + + byte=(ucs2>>8); /* dmapD12U[offset]; */ + byte<<=2; + work=ucs2; /* dmapD12U[offset+1]; */ + work>>=6; + byte|=work; + byte&=0x3F; /* 0b00111111; */ + byte|=0x80; /* 0b10000000; */ + *pOut=byte; + ++pOut; + + byte=ucs2; /* dmapD12U[offset+1]; */ + byte&=0x3F; /* 0b00111111; */ + byte|=0x80; /* 0b10000000; */ + *pOut=byte; + ++pOut; + } + /* end of U28 */ + } + } + *outBytesLeft-=(pOut-*outBuf); + *inBytesLeft=inLen; + *outBuf=pOut; + *inBuf=pIn; + *numSub+=numS; + return 0; + + } else if (cd->cnv_dmap->codingSchema == DMAP_U2E) { + register uchar * dmapU2S=cd->cnv_dmap->dmapU2S; + register uchar * dmapU2M2=cd->cnv_dmap->dmapU2M2 - 0x80 * 2; + register uchar * dmapU2M3=cd->cnv_dmap->dmapU2M3 - 0x80 * 3; + register int inLen=*inBytesLeft; + register char * pOut=*outBuf; + register char * pIn=*inBuf; + register char * pLastOutBuf = *outBuf + *outBytesLeft - 1; + register char subS=cd->subS; + register char * pSubD=(char *) &(cd->subD); + register size_t numS=0; + register size_t rc=0; + while (0 < inLen) { + register uint32_t in; + if (inLen == 1) { + errno=EINVAL; /* 22 */ + *outBytesLeft-=(pOut-*outBuf); + *inBytesLeft=inLen; + *outBuf=pOut; + *inBuf=pIn; + return -1; + } + if (pLastOutBuf < pOut) + break; + in=pIn[0]; + in<<=8; + in+=pIn[1]; + if (in == 0x0000) { + *pOut=0x00; + ++pOut; + } else if (in < 0x100 && dmapU2S[in] != 0x0000) { + if ((*pOut=dmapU2S[in]) == subS) { + if (in != cd->srcSubS) + ++numS; + } + ++pOut; + } else { + in<<=1; + if (dmapU2M2[in] == 0x00) { /* not found in dmapU2M2 */ + in*=1.5; + if (dmapU2M3[in] == 0x00) { /* not found in dmapU2M3*/ + *pOut=pSubD[0]; + ++pOut; + *pOut=pSubD[1]; + ++pOut; + ++numS; + ++rc; + } else { + *pOut=dmapU2M3[in]; + ++pOut; + *pOut=dmapU2M3[1+in]; + ++pOut; + *pOut=dmapU2M3[2+in]; + ++pOut; + } + } else { + *pOut=dmapU2M2[in]; + ++pOut; + if (dmapU2M2[1+in] == 0x00) { + if (*pOut == subS) { + in>>=1; + if (in != cd->srcSubS) + ++numS; + } + } else { + *pOut=dmapU2M2[1+in]; + ++pOut; + if (memcmp(pOut-2, pSubD, 2) == 0) { + in>>=1; + if (in != cd->srcSubD) { + ++numS; + ++rc; + } + } + } + } + } + pIn+=2; + inLen-=2; + } + *outBytesLeft-=(pOut-*outBuf); + *inBytesLeft=inLen; + *outBuf=pOut; + *inBuf=pIn; + *numSub+=numS; + return rc; /* compatibility to iconv() */ + + } else if (cd->cnv_dmap->codingSchema == DMAP_T2E) { + register uchar * dmapU2S=cd->cnv_dmap->dmapU2S; + register uchar * dmapU2M2=cd->cnv_dmap->dmapU2M2 - 0x80 * 2; + register uchar * dmapU2M3=cd->cnv_dmap->dmapU2M3 - 0x80 * 3; + register int inLen=*inBytesLeft; + register char * pOut=*outBuf; + register char * pIn=*inBuf; + register char * pLastOutBuf = *outBuf + *outBytesLeft - 1; + register char subS=cd->subS; + register char * pSubD=(char *) &(cd->subD); + register size_t numS=0; + register size_t rc=0; + while (0 < inLen) { + register uint32_t in; + if (inLen == 1) { + errno=EINVAL; /* 22 */ + *outBytesLeft-=(pOut-*outBuf); + *inBytesLeft=inLen-1; + *outBuf=pOut; + *inBuf=pIn; + ++numS; + *numSub+=numS; + return 0; + } + if (pLastOutBuf < pOut) + break; + in=pIn[0]; + in<<=8; + in+=pIn[1]; + if (in == 0x0000) { + *pOut=0x00; + ++pOut; + } else if (0xD800 <= in && in <= 0xDBFF) { /* first byte of surrogate */ + errno=EINVAL; /* 22 */ + *inBytesLeft=inLen-2; + *outBytesLeft-=(pOut-*outBuf); + *outBuf=pOut; + *inBuf=pIn+2; + ++numS; + *numSub+=numS; + return -1; + + } else if (0xDC00 <= in && in <= 0xDFFF) { /* second byte of surrogate */ + errno=EINVAL; /* 22 */ + *inBytesLeft=inLen-1; + *outBytesLeft-=(pOut-*outBuf); + *outBuf=pOut; + *inBuf=pIn; + ++numS; + *numSub+=numS; + return -1; + + } else if (in < 0x100 && dmapU2S[in] != 0x0000) { + if ((*pOut=dmapU2S[in]) == subS) { + if (in != cd->srcSubS) + ++numS; + } + ++pOut; + } else { + in<<=1; + if (dmapU2M2[in] == 0x00) { /* not found in dmapU2M2 */ + in*=1.5; + if (dmapU2M3[in] == 0x00) { /* not found in dmapU2M3*/ + *pOut=pSubD[0]; + ++pOut; + *pOut=pSubD[1]; + ++pOut; + ++numS; + ++rc; + } else { + *pOut=dmapU2M3[in]; + ++pOut; + *pOut=dmapU2M3[1+in]; + ++pOut; + *pOut=dmapU2M3[2+in]; + ++pOut; + } + } else { + *pOut=dmapU2M2[in]; + ++pOut; + if (dmapU2M2[1+in] == 0x00) { + if (*pOut == subS) { + in>>=1; + if (in != cd->srcSubS) + ++numS; + } + } else { + *pOut=dmapU2M2[1+in]; + ++pOut; + if (memcmp(pOut-2, pSubD, 2) == 0) { + in>>=1; + if (in != cd->srcSubD) { + ++numS; + ++rc; + } + } + } + } + } + pIn+=2; + inLen-=2; + } + *outBytesLeft-=(pOut-*outBuf); + *inBytesLeft=inLen; + *outBuf=pOut; + *inBuf=pIn; + *numSub+=numS; + return 0; + + } else if (cd->cnv_dmap->codingSchema == DMAP_82E) { + register uchar * dmapU2S=cd->cnv_dmap->dmapU2S; + register uchar * dmapU2M2=cd->cnv_dmap->dmapU2M2 - 0x80 * 2; + register uchar * dmapU2M3=cd->cnv_dmap->dmapU2M3 - 0x80 * 3; + register int inLen=*inBytesLeft; + register char * pOut=*outBuf; + register char * pIn=*inBuf; + register char * pLastOutBuf = *outBuf + *outBytesLeft - 1; + register char subS=cd->subS; + register char * pSubD=(char *) &(cd->subD); + register size_t numS=0; + register size_t rc=0; + while (0 < inLen) { + register uint32_t in; + uint32_t in2; + if (pLastOutBuf < pOut) + break; + /* convert from UTF-8 to UCS-2 */ + if (*pIn == 0x00) { + in=0x0000; + ++pIn; + --inLen; + } else { /* 82U: */ + register uchar byte1=*pIn; + if ((byte1 & 0x80) == 0x00) { /* if (byte1 & 0b10000000 == 0b00000000) { */ + /* 1 bytes sequence: 0xxxxxxx => 00000000 0xxxxxxx*/ + in=byte1; + ++pIn; + --inLen; + } else if ((byte1 & 0xE0) == 0xC0) { /* (byte1 & 0b11100000 == 0b11000000) { */ + if (inLen < 2) { + errno=EINVAL; /* 22 */ + *outBytesLeft-=(pOut-*outBuf); + *inBytesLeft=inLen; + *outBuf=pOut; + *inBuf=pIn; + *numSub+=numS; + return -1; + } + if (byte1 == 0xC0 || byte1 == 0xC1) { /* invalid sequence */ + errno=EILSEQ; /* 116 */ + *outBytesLeft-=(pOut-*outBuf); + *inBytesLeft=inLen; + *outBuf=pOut; + *inBuf=pIn; + *numSub+=numS; + return -1; + } + /* 2 bytes sequence: + 110yyyyy 10xxxxxx => 00000yyy yyxxxxxx */ + register uchar byte2; + ++pIn; + byte2=*pIn; + if ((byte2 & 0xC0) == 0x80) { /* byte2 & 0b11000000 == 0b10000000) { */ + register uchar work=byte1; + work<<=6; + byte2&=0x3F; /* 0b00111111; */ + byte2|=work; + + byte1&=0x1F; /* 0b00011111; */ + byte1>>=2; + in=byte1; + in<<=8; + in+=byte2; + inLen-=2; + ++pIn; + } else { /* invalid sequence */ + errno=EILSEQ; /* 116 */ + *outBytesLeft-=(pOut-*outBuf); + *inBytesLeft=inLen; + *outBuf=pOut; + *inBuf=pIn-1; + *numSub+=numS; + return -1; + } + } else if ((byte1 & 0xF0) == 0xE0) { /* byte1 & 0b11110000 == 0b11100000 */ + /* 3 bytes sequence: + 1110zzzz 10yyyyyy 10xxxxxx => zzzzyyyy yyxxxxxx */ + register uchar byte2; + register uchar byte3; + if (inLen < 3) { + if (inLen == 2 && (pIn[1] & 0xC0) != 0x80) + errno=EILSEQ; /* 116 */ + else + errno=EINVAL; /* 22 */ + *outBytesLeft-=(pOut-*outBuf); + *inBytesLeft=inLen; + *outBuf=pOut; + *inBuf=pIn; + *numSub+=numS; + return -1; + } + ++pIn; + byte2=*pIn; + ++pIn; + byte3=*pIn; + if ((byte2 & 0xC0) != 0x80 || + (byte3 & 0xC0) != 0x80 || + (byte1 == 0xE0 && byte2 < 0xA0)) { /* invalid sequence, only 0xA0-0xBF allowed after 0xE0 */ + errno=EILSEQ; /* 116 */ + *outBytesLeft-=(pOut-*outBuf); + *inBytesLeft=inLen; + *outBuf=pOut; + *inBuf=pIn-2; + *numSub+=numS; + return -1; + } + { + register uchar work=byte2; + work<<=6; + byte3&=0x3F; /* 0b00111111; */ + byte3|=work; + + byte2&=0x3F; /* 0b00111111; */ + byte2>>=2; + + byte1<<=4; + in=byte1 | byte2;; + in<<=8; + in+=byte3; + inLen-=3; + ++pIn; + } + } else if ((0xF0 <= byte1 && byte1 <= 0xF4)) { /* (bytes1 & 11111000) == 0x1110000 */ + /* 4 bytes sequence + 11110uuu 10uuzzzz 10yyyyyy 10xxxxxx => 110110ww wwzzzzyy 110111yy yyxxxxxx + where uuuuu = wwww + 1 */ + register uchar byte2; + register uchar byte3; + register uchar byte4; + if (inLen < 4) { + if ((inLen >= 2 && (pIn[1] & 0xC0) != 0x80) || + (inLen >= 3 && (pIn[2] & 0xC0) != 0x80) || + (cd->toCcsid == 13488) ) + errno=EILSEQ; /* 116 */ + else + errno=EINVAL; /* 22 */ + *outBytesLeft-=(pOut-*outBuf); + *inBytesLeft=inLen; + *outBuf=pOut; + *inBuf=pIn; + *numSub+=numS; + return -1; + } + ++pIn; + byte2=*pIn; + ++pIn; + byte3=*pIn; + ++pIn; + byte4=*pIn; + if ((byte2 & 0xC0) == 0x80 && /* byte2 & 0b11000000 == 0b10000000 */ + (byte3 & 0xC0) == 0x80 && /* byte3 & 0b11000000 == 0b10000000 */ + (byte4 & 0xC0) == 0x80) { /* byte4 & 0b11000000 == 0b10000000 */ + register uchar work=byte2; + if (byte1 == 0xF0 && byte2 < 0x90) { + errno=EILSEQ; /* 116 */ + *outBytesLeft-=(pOut-*outBuf); + *inBytesLeft=inLen; + *outBuf=pOut; + *inBuf=pIn-3; + *numSub+=numS; + return -1; + /* iconv() returns 0 for 0xF4908080 and convert to 0x00 + } else if (byte1 == 0xF4 && byte2 > 0x8F) { + errno=EINVAL; + *outBytesLeft-=(pOut-*outBuf); + *inBytesLeft=inLen; + *outBuf=pOut; + *inBuf=pIn-3; + *numSub+=numS; + return -1; + */ + } + + work&=0x30; /* 0b00110000; */ + work>>=4; + byte1&=0x07; /* 0b00000111; */ + byte1<<=2; + byte1+=work; /* uuuuu */ + --byte1; /* wwww */ + + work=byte1 & 0x0F; + work>>=2; + work+=0xD8; /* 0b11011011; */ + in=work; + in<<=8; + + byte1<<=6; + byte2<<=2; + byte2&=0x3C; /* 0b00111100; */ + work=byte3; + work>>=4; + work&=0x03; /* 0b00000011; */ + work|=byte1; + work|=byte2; + in+=work; + + work=byte3; + work>>=2; + work&=0x03; /* 0b00000011; */ + work|=0xDC; /* 0b110111xx; */ + in2=work; + in2<<=8; + + byte3<<=6; + byte4&=0x3F; /* 0b00111111; */ + byte4|=byte3; + in2+=byte4; + inLen-=4; + ++pIn; +#ifdef match_with_GBK + if ((0xD800 == in && in2 < 0xDC80) || + (0xD840 == in && in2 < 0xDC80) || + (0xD880 == in && in2 < 0xDC80) || + (0xD8C0 == in && in2 < 0xDC80) || + (0xD900 == in && in2 < 0xDC80) || + (0xD940 == in && in2 < 0xDC80) || + (0xD980 == in && in2 < 0xDC80) || + (0xD9C0 == in && in2 < 0xDC80) || + (0xDA00 == in && in2 < 0xDC80) || + (0xDA40 == in && in2 < 0xDC80) || + (0xDA80 == in && in2 < 0xDC80) || + (0xDAC0 == in && in2 < 0xDC80) || + (0xDB00 == in && in2 < 0xDC80) || + (0xDB40 == in && in2 < 0xDC80) || + (0xDB80 == in && in2 < 0xDC80) || + (0xDBC0 == in && in2 < 0xDC80)) { +#else + if ((0xD800 <= in && in <= 0xDBFF) && + (0xDC00 <= in2 && in2 <= 0xDFFF)) { +#endif + *pOut=subS; + ++pOut; + ++numS; + continue; + } + } else { /* invalid sequence */ + errno=EILSEQ; /* 116 */ + *outBytesLeft-=(pOut-*outBuf); + *inBytesLeft=inLen; + *outBuf=pOut; + *inBuf=pIn-3; + *numSub+=numS; + return -1; + } + } else if (0xF5 <= byte1 && byte1 <= 0xFF) { /* minic iconv() behavior */ + if (inLen < 4 || + (inLen >= 4 && byte1 == 0xF8 && pIn[1] < 0x90) || + pIn[1] < 0x80 || 0xBF < pIn[1] || + pIn[2] < 0x80 || 0xBF < pIn[2] || + pIn[3] < 0x80 || 0xBF < pIn[3] ) { + if (inLen == 1) + errno=EINVAL; /* 22 */ + else if (inLen == 2 && (pIn[1] & 0xC0) != 0x80) + errno=EILSEQ; /* 116 */ + else if (inLen == 3 && ((pIn[1] & 0xC0) != 0x80 || (pIn[2] & 0xC0) != 0x80)) + errno=EILSEQ; /* 116 */ + else if (inLen >= 4 && (byte1 == 0xF8 || (pIn[1] & 0xC0) != 0x80 || (pIn[2] & 0xC0) != 0x80 || (pIn[3] & 0xC0) != 0x80)) + errno=EILSEQ; /* 116 */ + else + errno=EINVAL; /* 22 */ + + *outBytesLeft-=(pOut-*outBuf); + *inBytesLeft=inLen; + *outBuf=pOut; + *inBuf=pIn; + *numSub+=numS; + return -1; + } else if ((pIn[1] == 0x80 || pIn[1] == 0x90 || pIn[1] == 0xA0 || pIn[1] == 0xB0) && + pIn[2] < 0x82) { + *pOut=subS; /* Though returns replacement character, which iconv() does not return. */ + ++pOut; + ++numS; + pIn+=4; + inLen-=4; + continue; + } else { + *pOut=pSubD[0]; /* Though returns replacement character, which iconv() does not return. */ + ++pOut; + *pOut=pSubD[1]; + ++pOut; + ++numS; + pIn+=4; + inLen-=4; + continue; + /* iconv() returns 0 with strange 1 byte converted values */ + } + + } else { /* invalid sequence */ + errno=EILSEQ; /* 116 */ + *outBytesLeft-=(pOut-*outBuf); + *inBytesLeft=inLen; + *outBuf=pOut; + *inBuf=pIn; + *numSub+=numS; + return -1; + } + } + /* end of UTF-8 to UCS-2 */ + if (in == 0x0000) { + *pOut=0x00; + ++pOut; + } else if (in < 0x100 && dmapU2S[in] != 0x0000) { + if ((*pOut=dmapU2S[in]) == subS) { + if (in != cd->srcSubS) + ++numS; + } + ++pOut; + } else { + in<<=1; + if (dmapU2M2[in] == 0x00) { /* not found in dmapU2M2 */ + in*=1.5; + if (dmapU2M3[in] == 0x00) { /* not found in dmapU2M3*/ + *pOut=pSubD[0]; + ++pOut; + *pOut=pSubD[1]; + ++pOut; + ++numS; + ++rc; + } else { + *pOut=dmapU2M3[in]; + ++pOut; + *pOut=dmapU2M3[1+in]; + ++pOut; + *pOut=dmapU2M3[2+in]; + ++pOut; + } + } else { + *pOut=dmapU2M2[in]; + ++pOut; + if (dmapU2M2[1+in] == 0x00) { + if (*pOut == subS) { + in>>=1; + if (in != cd->srcSubS) + ++numS; + } + } else { + *pOut=dmapU2M2[1+in]; + ++pOut; + if (memcmp(pOut-2, pSubD, 2) == 0) { + in>>=1; + if (in != cd->srcSubD) { + ++numS; + ++rc; + } + } + } + } + } + } + *outBytesLeft-=(pOut-*outBuf); + *inBytesLeft=inLen; + *outBuf=pOut; + *inBuf=pIn; + *numSub+=numS; + return 0; + + } else if (cd->cnv_dmap->codingSchema == DMAP_S2U) { + /* use uchar * instead of UniChar to avoid memcpy */ + register uchar * dmapD12U=(uchar *) (cd->cnv_dmap->dmapD12U); + register int inLen=*inBytesLeft; + register char * pOut=*outBuf; + register char * pIn=*inBuf; + register int offset; + register char * pLastOutBuf = *outBuf + *outBytesLeft - 1; + register size_t numS=0; + while (0 < inLen) { + if (pLastOutBuf < pOut) + break; + if (*pIn == 0x00) { + *pOut=0x00; + ++pOut; + *pOut=0x00; + ++pOut; + ++pIn; + --inLen; + } else { + offset=*pIn; + offset<<=1; + *pOut=dmapD12U[offset]; + ++pOut; + *pOut=dmapD12U[offset+1]; + ++pOut; + if (dmapD12U[offset] == 0x00) { + if (dmapD12U[offset+1] == 0x1A) { + if (*pIn != cd->srcSubS) + ++numS; + } else if (dmapD12U[offset+1] == 0x00) { + pOut-=2; + *outBytesLeft-=(pOut-*outBuf); + *inBytesLeft=inLen; + *outBuf=pOut; + *inBuf=pIn; + *numSub+=numS; + return -1; + } + } + ++pIn; + --inLen; + } + } + *outBytesLeft-=(pOut-*outBuf); + *inBytesLeft=inLen; + *outBuf=pOut; + *inBuf=pIn; + *numSub+=numS; + return 0; + + } else if (cd->cnv_dmap->codingSchema == DMAP_S28) { + /* use uchar * instead of UniChar to avoid memcpy */ + register uchar * dmapD12U=(uchar *) (cd->cnv_dmap->dmapD12U); + register int inLen=*inBytesLeft; + register char * pOut=*outBuf; + register char * pIn=*inBuf; + register int offset; + register char * pLastOutBuf = *outBuf + *outBytesLeft - 1; + register size_t numS=0; + register UniChar in; /* copy part of U28 */ + while (0 < inLen) { + if (pLastOutBuf < pOut) + break; + if (*pIn == 0x00) { + *pOut=0x00; + ++pOut; + ++pIn; + --inLen; + } else { + offset=*pIn; + offset<<=1; + in=dmapD12U[offset]; + in<<=8; + in+=dmapD12U[offset+1]; + if ((in & 0xFF80) == 0x0000) { /* U28: in & 0b1111111110000000 == 0x0000 */ + if (in == 0x000) { + errno=EILSEQ; /* 116 */ + *outBytesLeft-=(pOut-*outBuf); + *inBytesLeft=inLen; + *outBuf=pOut; + *inBuf=pIn; + *numSub+=numS; + return -1; + } + *pOut=in; + ++pOut; + } else if ((in & 0xF800) == 0x0000) { /* in & 0b1111100000000000 == 0x0000 */ + register uchar byte; + in>>=6; + in&=0x001F; /* 0b0000000000011111 */ + in|=0x00C0; /* 0b0000000011000000 */ + *pOut=in; + ++pOut; + byte=dmapD12U[offset+1]; + byte&=0x3F; /* 0b00111111; */ + byte|=0x80; /* 0b10000000; */ + *pOut=byte; + ++pOut; + } else if ((in & 0xFC00) == 0xD800) { /* There should not be no surrogate character in SBCS. */ + *pOut=0xEF; + ++pOut; + *pOut=0xBF; + ++pOut; + *pOut=0xBD; + ++pOut; + } else { + register uchar byte; + register uchar work; + byte=dmapD12U[offset]; + byte>>=4; + byte|=0xE0; /* 0b11100000; */ + *pOut=byte; + ++pOut; + + byte=dmapD12U[offset]; + byte<<=2; + work=dmapD12U[offset+1]; + work>>=6; + byte|=work; + byte&=0x3F; /* 0b00111111; */ + byte|=0x80; /* 0b10000000; */ + *pOut=byte; + ++pOut; + + byte=dmapD12U[offset+1]; + byte&=0x3F; /* 0b00111111; */ + byte|=0x80; /* 0b10000000; */ + *pOut=byte; + ++pOut; + } + /* end of U28 */ + if (dmapD12U[offset] == 0x00) { + if (dmapD12U[offset+1] == 0x1A) { + if (*pIn != cd->srcSubS) + ++numS; + } + } + ++pIn; + --inLen; + } + } + *outBytesLeft-=(pOut-*outBuf); + *inBytesLeft=inLen; + *outBuf=pOut; + *inBuf=pIn; + *numSub+=numS; + return 0; + + } else if (cd->cnv_dmap->codingSchema == DMAP_U2S) { + register uchar * dmapU2S=cd->cnv_dmap->dmapU2S; + register int inLen=*inBytesLeft; + register char * pOut=*outBuf; + register char * pIn=*inBuf; + register char * pLastOutBuf = *outBuf + *outBytesLeft - 1; + register char subS=cd->subS; + register size_t numS=0; + while (0 < inLen) { + register uint32_t in; + if (inLen == 1) { + errno=EINVAL; /* 22 */ + + *inBytesLeft=inLen; + *outBytesLeft-=(pOut-*outBuf); + *outBuf=pOut; + *inBuf=pIn; + return -1; + } + if (pLastOutBuf < pOut) + break; + in=pIn[0]; + in<<=8; + in+=pIn[1]; + if (in == 0x0000) { + *pOut=0x00; + } else { + if ((*pOut=dmapU2S[in]) == 0x00) { + *pOut=subS; + ++numS; + errno=EINVAL; /* 22 */ + } else if (*pOut == subS) { + if (in != cd->srcSubS) + ++numS; + } + } + ++pOut; + pIn+=2; + inLen-=2; + } + *outBytesLeft-=(pOut-*outBuf); + *inBytesLeft=inLen; + *outBuf=pOut; + *inBuf=pIn; + *numSub+=numS; + return numS; + + } else if (cd->cnv_dmap->codingSchema == DMAP_T2S) { + register uchar * dmapU2S=cd->cnv_dmap->dmapU2S; + register int inLen=*inBytesLeft; + register char * pOut=*outBuf; + register char * pIn=*inBuf; + register char * pLastOutBuf = *outBuf + *outBytesLeft - 1; + register char subS=cd->subS; + register size_t numS=0; + while (0 < inLen) { + register uint32_t in; + if (inLen == 1) { + errno=EINVAL; /* 22 */ + + *inBytesLeft=inLen-1; + *outBytesLeft-=(pOut-*outBuf); + *outBuf=pOut; + *inBuf=pIn; + ++numS; + *numSub+=numS; + return 0; + } + if (pLastOutBuf < pOut) + break; + in=pIn[0]; + in<<=8; + in+=pIn[1]; + if (in == 0x0000) { + *pOut=0x00; + + } else if (0xD800 <= in && in <= 0xDFFF) { /* 0xD800-0xDFFF, surrogate first and second values */ + if (0xDC00 <= in ) { + errno=EINVAL; /* 22 */ + *inBytesLeft=inLen-1; + *outBytesLeft-=(pOut-*outBuf); + *outBuf=pOut; + *inBuf=pIn; + return -1; + + } else if (inLen < 4) { + errno=EINVAL; /* 22 */ + *inBytesLeft=inLen-2; + *outBytesLeft-=(pOut-*outBuf); + *outBuf=pOut; + *inBuf=pIn+2; + return -1; + + } else { + register uint32_t in2; + in2=pIn[2]; + in2<<=8; + in2+=pIn[3]; + if (0xDC00 <= in2 && in2 <= 0xDFFF) { /* second surrogate character =0xDC00 - 0xDFFF*/ + *pOut=subS; + ++numS; + pIn+=4; + } else { + errno=EINVAL; /* 22 */ + *inBytesLeft=inLen-1; + *outBytesLeft-=(pOut-*outBuf); + *outBuf=pOut; + *inBuf=pIn; + return -1; + } + } + } else { + if ((*pOut=dmapU2S[in]) == 0x00) { + *pOut=subS; + ++numS; + errno=EINVAL; /* 22 */ + } else if (*pOut == subS) { + if (in != cd->srcSubS) + ++numS; + } + } + ++pOut; + pIn+=2; + inLen-=2; + } + *outBytesLeft-=(pOut-*outBuf); + *inBytesLeft=inLen; + *outBuf=pOut; + *inBuf=pIn; + *numSub+=numS; + return 0; + + } else if (cd->cnv_dmap->codingSchema == DMAP_82S) { + register uchar * dmapU2S=cd->cnv_dmap->dmapU2S; + register int inLen=*inBytesLeft; + register char * pOut=*outBuf; + register char * pIn=*inBuf; + register char * pLastOutBuf = *outBuf + *outBytesLeft - 1; + register char subS=cd->subS; + register size_t numS=0; + while (0 < inLen) { + register uint32_t in; + uint32_t in2; /* The second surrogate value */ + if (pLastOutBuf < pOut) + break; + /* convert from UTF-8 to UCS-2 */ + if (*pIn == 0x00) { + in=0x0000; + ++pIn; + --inLen; + } else { /* 82U: */ + register uchar byte1=*pIn; + if ((byte1 & 0x80) == 0x00) { /* if (byte1 & 0b10000000 == 0b00000000) { */ + /* 1 bytes sequence: 0xxxxxxx => 00000000 0xxxxxxx*/ + in=byte1; + ++pIn; + --inLen; + } else if ((byte1 & 0xE0) == 0xC0) { /* (byte1 & 0b11100000 == 0b11000000) { */ + if (inLen < 2) { + errno=EINVAL; /* 22 */ + *outBytesLeft-=(pOut-*outBuf); + *inBytesLeft=inLen; + *outBuf=pOut; + *inBuf=pIn; + *numSub+=numS; + return -1; + } + if (byte1 == 0xC0 || byte1 == 0xC1) { /* invalid sequence */ + errno=EILSEQ; /* 116 */ + *outBytesLeft-=(pOut-*outBuf); + *inBytesLeft=inLen; + *outBuf=pOut; + *inBuf=pIn; + *numSub+=numS; + return -1; + } + /* 2 bytes sequence: + 110yyyyy 10xxxxxx => 00000yyy yyxxxxxx */ + register uchar byte2; + ++pIn; + byte2=*pIn; + if ((byte2 & 0xC0) == 0x80) { /* byte2 & 0b11000000 == 0b10000000) { */ + register uchar work=byte1; + work<<=6; + byte2&=0x3F; /* 0b00111111; */ + byte2|=work; + + byte1&=0x1F; /* 0b00011111; */ + byte1>>=2; + in=byte1; + in<<=8; + in+=byte2; + inLen-=2; + ++pIn; + } else { /* invalid sequence */ + errno=EILSEQ; /* 116 */ + *outBytesLeft-=(pOut-*outBuf); + *inBytesLeft=inLen; + *outBuf=pOut; + *inBuf=pIn-1; + *numSub+=numS; + return -1; + } + } else if ((byte1 & 0xF0) == 0xE0) { /* byte1 & 0b11110000 == 0b11100000 */ + /* 3 bytes sequence: + 1110zzzz 10yyyyyy 10xxxxxx => zzzzyyyy yyxxxxxx */ + register uchar byte2; + register uchar byte3; + if (inLen < 3) { + if (inLen == 2 && (pIn[1] & 0xC0) != 0x80) + errno=EILSEQ; /* 116 */ + else + errno=EINVAL; /* 22 */ + *outBytesLeft-=(pOut-*outBuf); + *inBytesLeft=inLen; + *outBuf=pOut; + *inBuf=pIn; + *numSub+=numS; + return -1; + } + ++pIn; + byte2=*pIn; + ++pIn; + byte3=*pIn; + if ((byte2 & 0xC0) != 0x80 || + (byte3 & 0xC0) != 0x80 || + (byte1 == 0xE0 && byte2 < 0xA0)) { /* invalid sequence, only 0xA0-0xBF allowed after 0xE0 */ + errno=EILSEQ; /* 116 */ + *outBytesLeft-=(pOut-*outBuf); + *inBytesLeft=inLen; + *outBuf=pOut; + *inBuf=pIn-2; + *numSub+=numS; + return -1; + } + { + register uchar work=byte2; + work<<=6; + byte3&=0x3F; /* 0b00111111; */ + byte3|=work; + + byte2&=0x3F; /* 0b00111111; */ + byte2>>=2; + + byte1<<=4; + in=byte1 | byte2;; + in<<=8; + in+=byte3; + inLen-=3; + ++pIn; + } + } else if ((0xF0 <= byte1 && byte1 <= 0xF4) || /* (bytes1 & 11111000) == 0x1110000 */ + ((byte1&=0xF7) && 0xF0 <= byte1 && byte1 <= 0xF4)) { /* minic iconv() behavior */ + /* 4 bytes sequence + 11110uuu 10uuzzzz 10yyyyyy 10xxxxxx => 110110ww wwzzzzyy 110111yy yyxxxxxx + where uuuuu = wwww + 1 */ + register uchar byte2; + register uchar byte3; + register uchar byte4; + if (inLen < 4) { + if ((inLen >= 2 && (pIn[1] & 0xC0) != 0x80) || + (inLen >= 3 && (pIn[2] & 0xC0) != 0x80) || + (cd->toCcsid == 13488) ) + errno=EILSEQ; /* 116 */ + else + errno=EINVAL; /* 22 */ + *outBytesLeft-=(pOut-*outBuf); + *inBytesLeft=inLen; + *outBuf=pOut; + *inBuf=pIn; + *numSub+=numS; + return -1; + } + ++pIn; + byte2=*pIn; + ++pIn; + byte3=*pIn; + ++pIn; + byte4=*pIn; + if ((byte2 & 0xC0) == 0x80 && /* byte2 & 0b11000000 == 0b10000000 */ + (byte3 & 0xC0) == 0x80 && /* byte3 & 0b11000000 == 0b10000000 */ + (byte4 & 0xC0) == 0x80) { /* byte4 & 0b11000000 == 0b10000000 */ + register uchar work=byte2; + if (byte1 == 0xF0 && byte2 < 0x90) { + errno=EILSEQ; /* 116 */ + *outBytesLeft-=(pOut-*outBuf); + *inBytesLeft=inLen; + *outBuf=pOut; + *inBuf=pIn-3; + *numSub+=numS; + return -1; + /* iconv() returns 0 for 0xF4908080 and convert to 0x00 + } else if (byte1 == 0xF4 && byte2 > 0x8F) { + errno=EINVAL; + *outBytesLeft-=(pOut-*outBuf); + *inBytesLeft=inLen; + *outBuf=pOut; + *inBuf=pIn-3; + *numSub+=numS; + return -1; + */ + } + + work&=0x30; /* 0b00110000; */ + work>>=4; + byte1&=0x07; /* 0b00000111; */ + byte1<<=2; + byte1+=work; /* uuuuu */ + --byte1; /* wwww */ + + work=byte1 & 0x0F; + work>>=2; + work+=0xD8; /* 0b11011011; */ + in=work; + in<<=8; + + byte1<<=6; + byte2<<=2; + byte2&=0x3C; /* 0b00111100; */ + work=byte3; + work>>=4; + work&=0x03; /* 0b00000011; */ + work|=byte1; + work|=byte2; + in+=work; + + work=byte3; + work>>=2; + work&=0x03; /* 0b00000011; */ + work|=0xDC; /* 0b110111xx; */ + in2=work; + in2<<=8; + + byte3<<=6; + byte4&=0x3F; /* 0b00111111; */ + byte4|=byte3; + in2+=byte4; + inLen-=4; + ++pIn; + } else { /* invalid sequence */ + errno=EILSEQ; /* 116 */ + *outBytesLeft-=(pOut-*outBuf); + *inBytesLeft=inLen; + *outBuf=pOut; + *inBuf=pIn-3; + *numSub+=numS; + return -1; + } + } else if ((byte1 & 0xF0) == 0xF0) { /* minic iconv() behavior */ + if (inLen < 4 || + pIn[1] < 0x80 || 0xBF < pIn[1] || + pIn[2] < 0x80 || 0xBF < pIn[2] || + pIn[3] < 0x80 || 0xBF < pIn[3] ) { + if (inLen == 1) + errno=EINVAL; /* 22 */ + else if (inLen == 2 && (pIn[1] & 0xC0) != 0x80) + errno=EILSEQ; /* 116 */ + else if (inLen == 3 && ((pIn[1] & 0xC0) != 0x80 || (pIn[2] & 0xC0) != 0x80)) + errno=EILSEQ; /* 116 */ + else if (inLen >= 4 && ((pIn[1] & 0xC0) != 0x80 || (pIn[2] & 0xC0) != 0x80 || (pIn[3] & 0xC0) != 0x80)) + errno=EILSEQ; /* 116 */ + else + errno=EINVAL; /* 22 */ + + *outBytesLeft-=(pOut-*outBuf); + *inBytesLeft=inLen; + *outBuf=pOut; + *inBuf=pIn; + *numSub+=numS; + return -1; + } else { + *pOut=subS; /* Though returns replacement character, which iconv() does not return. */ + ++pOut; + ++numS; + pIn+=4; + inLen-=4; + /* UTF-8_IBM-850 0xF0908080 : converted value does not match, iconv=0x00, dmap=0x7F + UTF-8_IBM-850 0xF0908081 : converted value does not match, iconv=0x01, dmap=0x7F + UTF-8_IBM-850 0xF0908082 : converted value does not match, iconv=0x02, dmap=0x7F + UTF-8_IBM-850 0xF0908083 : converted value does not match, iconv=0x03, dmap=0x7F + .... + UTF-8_IBM-850 0xF09081BE : converted value does not match, iconv=0x7E, dmap=0x7F + UTF-8_IBM-850 0xF09081BF : converted value does not match, iconv=0x1C, dmap=0x7F + UTF-8_IBM-850 0xF09082A0 : converted value does not match, iconv=0xFF, dmap=0x7F + UTF-8_IBM-850 0xF09082A1 : converted value does not match, iconv=0xAD, dmap=0x7F + .... + */ + continue; + /* iconv() returns 0 with strange 1 byte converted values */ + } + + } else { /* invalid sequence */ + errno=EILSEQ; /* 116 */ + *outBytesLeft-=(pOut-*outBuf); + *inBytesLeft=inLen; + *outBuf=pOut; + *inBuf=pIn; + *numSub+=numS; + return -1; + } + } + /* end of UTF-8 to UCS-2 */ + if (in == 0x0000) { + *pOut=0x00; + } else { + if ((*pOut=dmapU2S[in]) == 0x00) { + *pOut=subS; + ++numS; + errno=EINVAL; /* 22 */ + } else if (*pOut == subS) { + if (in != cd->srcSubS) { + ++numS; + } + } + } + ++pOut; + } + *outBytesLeft-=(pOut-*outBuf); + *inBytesLeft=inLen; + *outBuf=pOut; + *inBuf=pIn; + *numSub+=numS; + return 0; + + } else if (cd->cnv_dmap->codingSchema == DMAP_D2U) { + /* use uchar * instead of UniChar to avoid memcpy */ + register uchar * dmapD12U=(uchar *) (cd->cnv_dmap->dmapD12U); + register uchar * dmapD22U=(uchar *) (cd->cnv_dmap->dmapD22U); + register int inLen=*inBytesLeft; + register char * pOut=*outBuf; + register char * pIn=*inBuf; + register int offset; + register char * pLastOutBuf = *outBuf + *outBytesLeft - 1; + register size_t numS=0; + while (0 < inLen) { + if (pLastOutBuf < pOut) + break; + if (*pIn == 0x00) { + *pOut=0x00; + ++pOut; + *pOut=0x00; + ++pOut; + ++pIn; + --inLen; + } else { + offset=*pIn; + offset<<=1; + if (dmapD12U[offset] == 0x00 && + dmapD12U[offset+1] == 0x00) { /* DBCS */ + if (inLen < 2) { + if (*pIn == 0x80 || *pIn == 0xFF || + (cd->fromCcsid == 943 && (*pIn == 0x85 || *pIn == 0x86 || *pIn == 0xA0 || *pIn == 0xEB || *pIn == 0xEC || *pIn == 0xEF || *pIn == 0xFD || *pIn == 0xFE)) || + (cd->fromCcsid == 932 && (*pIn == 0x85 || *pIn == 0x86 || *pIn == 0x87 || *pIn == 0xEB || *pIn == 0xEC || *pIn == 0xED || *pIn == 0xEE || *pIn == 0xEF)) || + (cd->fromCcsid == 1381 && ((0x85 <= *pIn && *pIn <= 0x8B) || (0xAA <= *pIn && *pIn <= 0xAF) || (0xF8 <= *pIn && *pIn <= 0xFE)))) + errno=EILSEQ; /* 116 */ + else + errno=EINVAL; /* 22 */ + *outBytesLeft-=(pOut-*outBuf); + *inBytesLeft=inLen; + *outBuf=pOut; + *inBuf=pIn; + return -1; + } + offset-=0x100; + ++pIn; + offset<<=8; + offset+=(*pIn * 2); + if (dmapD22U[offset] == 0x00 && + dmapD22U[offset+1] == 0x00) { + errno=EILSEQ; /* 116 */ + *outBytesLeft-=(pOut-*outBuf); + *inBytesLeft=inLen; + *outBuf=pOut; + *inBuf=pIn-1; + return -1; + } + *pOut=dmapD22U[offset]; + ++pOut; + *pOut=dmapD22U[offset+1]; + ++pOut; + if (dmapD22U[offset] == 0xFF && + dmapD22U[offset+1] == 0xFD) { + if (pIn[-1] * 0x100 + pIn[0] != cd->srcSubD) + ++numS; + } + ++pIn; + inLen-=2; + } else { /* SBCS */ + *pOut=dmapD12U[offset]; + ++pOut; + *pOut=dmapD12U[offset+1]; + ++pOut; + if (dmapD12U[offset] == 0x00 && + dmapD12U[offset+1] == 0x1A) { + if (*pIn != cd->srcSubS) + ++numS; + } + ++pIn; + --inLen; + } + } + } + *outBytesLeft-=(pOut-*outBuf); + *inBytesLeft=inLen; + *outBuf=pOut; + *inBuf=pIn; + *numSub+=numS; + return 0; + + } else if (cd->cnv_dmap->codingSchema == DMAP_D28) { + /* use uchar * instead of UniChar to avoid memcpy */ + register uchar * dmapD12U=(uchar *) (cd->cnv_dmap->dmapD12U); + register uchar * dmapD22U=(uchar *) (cd->cnv_dmap->dmapD22U); + register int inLen=*inBytesLeft; + register char * pOut=*outBuf; + register char * pIn=*inBuf; + register int offset; + register char * pLastOutBuf = *outBuf + *outBytesLeft - 1; + register size_t numS=0; + register UniChar in; /* copy part of U28 */ + register UniChar ucs2; + while (0 < inLen) { + if (pLastOutBuf < pOut) + break; + if (*pIn == 0x00) { + *pOut=0x00; + ++pOut; + ++pIn; + --inLen; + } else { + offset=*pIn; + offset<<=1; + if (dmapD12U[offset] == 0x00 && + dmapD12U[offset+1] == 0x00) { /* DBCS */ + if (inLen < 2) { + if (*pIn == 0x80 || *pIn == 0xFF || + (cd->fromCcsid == 943 && (*pIn == 0x85 || *pIn == 0x86 || *pIn == 0xA0 || *pIn == 0xEB || *pIn == 0xEC || *pIn == 0xEF || *pIn == 0xFD || *pIn == 0xFE)) || + (cd->fromCcsid == 932 && (*pIn == 0x85 || *pIn == 0x86 || *pIn == 0x87 || *pIn == 0xEB || *pIn == 0xEC || *pIn == 0xED || *pIn == 0xEE || *pIn == 0xEF)) || + (cd->fromCcsid == 1381 && ((0x85 <= *pIn && *pIn <= 0x8B) || (0xAA <= *pIn && *pIn <= 0xAF) || (0xF8 <= *pIn && *pIn <= 0xFE)))) + errno=EILSEQ; /* 116 */ + else + errno=EINVAL; /* 22 */ + *outBytesLeft-=(pOut-*outBuf); + *inBytesLeft=inLen; + *outBuf=pOut; + *inBuf=pIn; + return -1; + } + offset-=0x100; + ++pIn; + offset<<=8; + offset+=(*pIn * 2); + if (dmapD22U[offset] == 0x00 && + dmapD22U[offset+1] == 0x00) { + errno=EILSEQ; /* 116 */ + *outBytesLeft-=(pOut-*outBuf); + *inBytesLeft=inLen; + *outBuf=pOut; + *inBuf=pIn-1; + return -1; + } + in=dmapD22U[offset]; + in<<=8; + in+=dmapD22U[offset+1]; + ucs2=in; + if (dmapD22U[offset] == 0xFF && + dmapD22U[offset+1] == 0xFD) { + if (in != cd->srcSubD) + ++numS; + } + ++pIn; + inLen-=2; + } else { /* SBCS */ + in=dmapD12U[offset]; + in<<=8; + in+=dmapD12U[offset+1]; + ucs2=in; + if (dmapD12U[offset] == 0x00 && + dmapD12U[offset+1] == 0x1A) { + if (in != cd->srcSubS) + ++numS; + } + ++pIn; + --inLen; + } + if ((in & 0xFF80) == 0x0000) { /* U28: in & 0b1111111110000000 == 0x0000 */ + *pOut=in; + ++pOut; + } else if ((in & 0xF800) == 0x0000) { /* in & 0b1111100000000000 == 0x0000 */ + register uchar byte; + in>>=6; + in&=0x001F; /* 0b0000000000011111 */ + in|=0x00C0; /* 0b0000000011000000 */ + *pOut=in; + ++pOut; + byte=ucs2; /* dmapD12U[offset+1]; */ + byte&=0x3F; /* 0b00111111; */ + byte|=0x80; /* 0b10000000; */ + *pOut=byte; + ++pOut; + } else if ((in & 0xFC00) == 0xD800) { /* There should not be no surrogate character in SBCS. */ + *pOut=0xEF; + ++pOut; + *pOut=0xBF; + ++pOut; + *pOut=0xBD; + ++pOut; + } else { + register uchar byte; + register uchar work; + byte=(ucs2>>8); /* dmapD12U[offset]; */ + byte>>=4; + byte|=0xE0; /* 0b11100000; */ + *pOut=byte; + ++pOut; + + byte=(ucs2>>8); /* dmapD12U[offset]; */ + byte<<=2; + work=ucs2; /* dmapD12U[offset+1]; */ + work>>=6; + byte|=work; + byte&=0x3F; /* 0b00111111; */ + byte|=0x80; /* 0b10000000; */ + *pOut=byte; + ++pOut; + + byte=ucs2; /* dmapD12U[offset+1]; */ + byte&=0x3F; /* 0b00111111; */ + byte|=0x80; /* 0b10000000; */ + *pOut=byte; + ++pOut; + } + /* end of U28 */ + } + } + *outBytesLeft-=(pOut-*outBuf); + *inBytesLeft=inLen; + *outBuf=pOut; + *inBuf=pIn; + *numSub+=numS; + return 0; + + } else if (cd->cnv_dmap->codingSchema == DMAP_U2D) { + register uchar * dmapU2D=cd->cnv_dmap->dmapU2D; + register int inLen=*inBytesLeft; + register char * pOut=*outBuf; + register char * pIn=*inBuf; + register char * pLastOutBuf = *outBuf + *outBytesLeft - 1; + register char subS=cd->subS; + register char * pSubD=(char *) &(cd->subD); + register size_t numS=0; + while (0 < inLen) { + register uint32_t in; + if (inLen == 1) { + errno=EINVAL; /* 22 */ + + *inBytesLeft=inLen; + *outBytesLeft-=(pOut-*outBuf); + *outBuf=pOut; + *inBuf=pIn; + return -1; + } + if (pLastOutBuf < pOut) + break; + in=pIn[0]; + in<<=8; + in+=pIn[1]; + if (in == 0x0000) { + *pOut=0x00; + ++pOut; + } else { + in<<=1; + *pOut=dmapU2D[in]; + ++pOut; + if (dmapU2D[in+1] == 0x00) { /* SBCS */ + if (*pOut == subS) { + if (in != cd->srcSubS) + ++numS; + } + } else { + *pOut=dmapU2D[in+1]; + ++pOut; + if (dmapU2D[in] == pSubD[0] && + dmapU2D[in+1] == pSubD[1]) { + in>>=1; + if (in != cd->srcSubD) + ++numS; + } + } + } + pIn+=2; + inLen-=2; + } + *outBytesLeft-=(pOut-*outBuf); + *inBytesLeft=inLen; + *outBuf=pOut; + *inBuf=pIn; + *numSub+=numS; + return numS; /* to minic iconv() behavior */ + + } else if (cd->cnv_dmap->codingSchema == DMAP_T2D) { + register uchar * dmapU2D=cd->cnv_dmap->dmapU2D; + register int inLen=*inBytesLeft; + register char * pOut=*outBuf; + register char * pIn=*inBuf; + register char * pLastOutBuf = *outBuf + *outBytesLeft - 1; + register char subS=cd->subS; + register char * pSubD=(char *) &(cd->subD); + register size_t numS=0; + while (0 < inLen) { + register uint32_t in; + if (inLen == 1) { + errno=EINVAL; /* 22 */ + *inBytesLeft=inLen-1; + *outBytesLeft-=(pOut-*outBuf); + *outBuf=pOut; + *inBuf=pIn; + ++numS; + *numSub+=numS; + return 0; + } + if (pLastOutBuf < pOut) + break; + in=pIn[0]; + in<<=8; + in+=pIn[1]; + if (in == 0x0000) { + *pOut=0x00; + ++pOut; + } else if (0xD800 <= in && in <= 0xDBFF) { /* first byte of surrogate */ + errno=EINVAL; /* 22 */ + *inBytesLeft=inLen-2; + *outBytesLeft-=(pOut-*outBuf); + *outBuf=pOut; + *inBuf=pIn+2; + ++numS; + *numSub+=numS; + return -1; + + } else if (0xDC00 <= in && in <= 0xDFFF) { /* second byte of surrogate */ + errno=EINVAL; /* 22 */ + *inBytesLeft=inLen-1; + *outBytesLeft-=(pOut-*outBuf); + *outBuf=pOut; + *inBuf=pIn; + ++numS; + *numSub+=numS; + return -1; + + } else { + in<<=1; + *pOut=dmapU2D[in]; + ++pOut; + if (dmapU2D[in+1] == 0x00) { /* SBCS */ + if (*pOut == subS) { + if (in != cd->srcSubS) + ++numS; + } + } else { + *pOut=dmapU2D[in+1]; + ++pOut; + if (dmapU2D[in] == pSubD[0] && + dmapU2D[in+1] == pSubD[1]) { + in>>=1; + if (in != cd->srcSubD) + ++numS; + } + } + } + pIn+=2; + inLen-=2; + } + *outBytesLeft-=(pOut-*outBuf); + *inBytesLeft=inLen; + *outBuf=pOut; + *inBuf=pIn; + *numSub+=numS; + return 0; /* to minic iconv() behavior */ + + } else if (cd->cnv_dmap->codingSchema == DMAP_82D) { + register uchar * dmapU2D=cd->cnv_dmap->dmapU2D; + register int inLen=*inBytesLeft; + register char * pOut=*outBuf; + register char * pIn=*inBuf; + register char * pLastOutBuf = *outBuf + *outBytesLeft - 1; + register char subS=cd->subS; + register char * pSubD=(char *) &(cd->subD); + register size_t numS=0; + while (0 < inLen) { + register uint32_t in; + uint32_t in2; + if (pLastOutBuf < pOut) + break; + /* convert from UTF-8 to UCS-2 */ + if (*pIn == 0x00) { + in=0x0000; + ++pIn; + --inLen; + } else { /* 82U: */ + register uchar byte1=*pIn; + if ((byte1 & 0x80) == 0x00) { /* if (byte1 & 0b10000000 == 0b00000000) { */ + /* 1 bytes sequence: 0xxxxxxx => 00000000 0xxxxxxx*/ + in=byte1; + ++pIn; + --inLen; + } else if ((byte1 & 0xE0) == 0xC0) { /* (byte1 & 0b11100000 == 0b11000000) { */ + if (inLen < 2) { + errno=EINVAL; /* 22 */ + *outBytesLeft-=(pOut-*outBuf); + *inBytesLeft=inLen; + *outBuf=pOut; + *inBuf=pIn; + *numSub+=numS; + return -1; + } + if (byte1 == 0xC0 || byte1 == 0xC1) { /* invalid sequence */ + errno=EILSEQ; /* 116 */ + *outBytesLeft-=(pOut-*outBuf); + *inBytesLeft=inLen; + *outBuf=pOut; + *inBuf=pIn; + *numSub+=numS; + return -1; + } + /* 2 bytes sequence: + 110yyyyy 10xxxxxx => 00000yyy yyxxxxxx */ + register uchar byte2; + ++pIn; + byte2=*pIn; + if ((byte2 & 0xC0) == 0x80) { /* byte2 & 0b11000000 == 0b10000000) { */ + register uchar work=byte1; + work<<=6; + byte2&=0x3F; /* 0b00111111; */ + byte2|=work; + + byte1&=0x1F; /* 0b00011111; */ + byte1>>=2; + in=byte1; + in<<=8; + in+=byte2; + inLen-=2; + ++pIn; + } else { /* invalid sequence */ + errno=EILSEQ; /* 116 */ + *outBytesLeft-=(pOut-*outBuf); + *inBytesLeft=inLen; + *outBuf=pOut; + *inBuf=pIn-1; + *numSub+=numS; + return -1; + } + } else if ((byte1 & 0xF0) == 0xE0) { /* byte1 & 0b11110000 == 0b11100000 */ + /* 3 bytes sequence: + 1110zzzz 10yyyyyy 10xxxxxx => zzzzyyyy yyxxxxxx */ + register uchar byte2; + register uchar byte3; + if (inLen < 3) { + if (inLen == 2 && (pIn[1] & 0xC0) != 0x80) + errno=EILSEQ; /* 116 */ + else + errno=EINVAL; /* 22 */ + *outBytesLeft-=(pOut-*outBuf); + *inBytesLeft=inLen; + *outBuf=pOut; + *inBuf=pIn; + *numSub+=numS; + return -1; + } + ++pIn; + byte2=*pIn; + ++pIn; + byte3=*pIn; + if ((byte2 & 0xC0) != 0x80 || + (byte3 & 0xC0) != 0x80 || + (byte1 == 0xE0 && byte2 < 0xA0)) { /* invalid sequence, only 0xA0-0xBF allowed after 0xE0 */ + errno=EILSEQ; /* 116 */ + *outBytesLeft-=(pOut-*outBuf); + *inBytesLeft=inLen; + *outBuf=pOut; + *inBuf=pIn-2; + *numSub+=numS; + return -1; + } + { + register uchar work=byte2; + work<<=6; + byte3&=0x3F; /* 0b00111111; */ + byte3|=work; + + byte2&=0x3F; /* 0b00111111; */ + byte2>>=2; + + byte1<<=4; + in=byte1 | byte2;; + in<<=8; + in+=byte3; + inLen-=3; + ++pIn; + } + } else if ((0xF0 <= byte1 && byte1 <= 0xF4)) { /* (bytes1 & 11111000) == 0x1110000 */ + /* 4 bytes sequence + 11110uuu 10uuzzzz 10yyyyyy 10xxxxxx => 110110ww wwzzzzyy 110111yy yyxxxxxx + where uuuuu = wwww + 1 */ + register uchar byte2; + register uchar byte3; + register uchar byte4; + if (inLen < 4) { + if ((inLen >= 2 && (pIn[1] & 0xC0) != 0x80) || + (inLen >= 3 && (pIn[2] & 0xC0) != 0x80) || + (cd->toCcsid == 13488) ) + errno=EILSEQ; /* 116 */ + else + errno=EINVAL; /* 22 */ + *outBytesLeft-=(pOut-*outBuf); + *inBytesLeft=inLen; + *outBuf=pOut; + *inBuf=pIn; + *numSub+=numS; + return -1; + } + ++pIn; + byte2=*pIn; + ++pIn; + byte3=*pIn; + ++pIn; + byte4=*pIn; + if ((byte2 & 0xC0) == 0x80 && /* byte2 & 0b11000000 == 0b10000000 */ + (byte3 & 0xC0) == 0x80 && /* byte3 & 0b11000000 == 0b10000000 */ + (byte4 & 0xC0) == 0x80) { /* byte4 & 0b11000000 == 0b10000000 */ + register uchar work=byte2; + if (byte1 == 0xF0 && byte2 < 0x90) { + errno=EILSEQ; /* 116 */ + *outBytesLeft-=(pOut-*outBuf); + *inBytesLeft=inLen; + *outBuf=pOut; + *inBuf=pIn-3; + *numSub+=numS; + return -1; + /* iconv() returns 0 for 0xF4908080 and convert to 0x00 + } else if (byte1 == 0xF4 && byte2 > 0x8F) { + errno=EINVAL; + *outBytesLeft-=(pOut-*outBuf); + *inBytesLeft=inLen; + *outBuf=pOut; + *inBuf=pIn-3; + *numSub+=numS; + return -1; + */ + } + + work&=0x30; /* 0b00110000; */ + work>>=4; + byte1&=0x07; /* 0b00000111; */ + byte1<<=2; + byte1+=work; /* uuuuu */ + --byte1; /* wwww */ + + work=byte1 & 0x0F; + work>>=2; + work+=0xD8; /* 0b11011011; */ + in=work; + in<<=8; + + byte1<<=6; + byte2<<=2; + byte2&=0x3C; /* 0b00111100; */ + work=byte3; + work>>=4; + work&=0x03; /* 0b00000011; */ + work|=byte1; + work|=byte2; + in+=work; + + work=byte3; + work>>=2; + work&=0x03; /* 0b00000011; */ + work|=0xDC; /* 0b110111xx; */ + in2=work; + in2<<=8; + + byte3<<=6; + byte4&=0x3F; /* 0b00111111; */ + byte4|=byte3; + in2+=byte4; + inLen-=4; + ++pIn; +#ifdef match_with_GBK + if ((0xD800 == in && in2 < 0xDC80) || + (0xD840 == in && in2 < 0xDC80) || + (0xD880 == in && in2 < 0xDC80) || + (0xD8C0 == in && in2 < 0xDC80) || + (0xD900 == in && in2 < 0xDC80) || + (0xD940 == in && in2 < 0xDC80) || + (0xD980 == in && in2 < 0xDC80) || + (0xD9C0 == in && in2 < 0xDC80) || + (0xDA00 == in && in2 < 0xDC80) || + (0xDA40 == in && in2 < 0xDC80) || + (0xDA80 == in && in2 < 0xDC80) || + (0xDAC0 == in && in2 < 0xDC80) || + (0xDB00 == in && in2 < 0xDC80) || + (0xDB40 == in && in2 < 0xDC80) || + (0xDB80 == in && in2 < 0xDC80) || + (0xDBC0 == in && in2 < 0xDC80)) { +#else + if ((0xD800 <= in && in <= 0xDBFF) && + (0xDC00 <= in2 && in2 <= 0xDFFF)) { +#endif + *pOut=subS; + ++pOut; + ++numS; + continue; + } + } else { /* invalid sequence */ + errno=EILSEQ; /* 116 */ + *outBytesLeft-=(pOut-*outBuf); + *inBytesLeft=inLen; + *outBuf=pOut; + *inBuf=pIn-3; + *numSub+=numS; + return -1; + } + } else if (0xF5 <= byte1 && byte1 <= 0xFF) { /* minic iconv() behavior */ + if (inLen < 4 || + (inLen >= 4 && byte1 == 0xF8 && pIn[1] < 0x90) || + pIn[1] < 0x80 || 0xBF < pIn[1] || + pIn[2] < 0x80 || 0xBF < pIn[2] || + pIn[3] < 0x80 || 0xBF < pIn[3] ) { + if (inLen == 1) + errno=EINVAL; /* 22 */ + else if (inLen == 2 && (pIn[1] & 0xC0) != 0x80) + errno=EILSEQ; /* 116 */ + else if (inLen == 3 && ((pIn[1] & 0xC0) != 0x80 || (pIn[2] & 0xC0) != 0x80)) + errno=EILSEQ; /* 116 */ + else if (inLen >= 4 && (byte1 == 0xF8 || (pIn[1] & 0xC0) != 0x80 || (pIn[2] & 0xC0) != 0x80 || (pIn[3] & 0xC0) != 0x80)) + errno=EILSEQ; /* 116 */ + else + errno=EINVAL; /* 22 */ + + *outBytesLeft-=(pOut-*outBuf); + *inBytesLeft=inLen; + *outBuf=pOut; + *inBuf=pIn; + *numSub+=numS; + return -1; + } else if ((pIn[1] == 0x80 || pIn[1] == 0x90 || pIn[1] == 0xA0 || pIn[1] == 0xB0) && + pIn[2] < 0x82) { + *pOut=subS; /* Though returns replacement character, which iconv() does not return. */ + ++pOut; + ++numS; + pIn+=4; + inLen-=4; + continue; + } else { + *pOut=pSubD[0]; /* Though returns replacement character, which iconv() does not return. */ + ++pOut; + *pOut=pSubD[1]; + ++pOut; + ++numS; + pIn+=4; + inLen-=4; + continue; + /* iconv() returns 0 with strange 1 byte converted values */ + } + + } else { /* invalid sequence */ + errno=EILSEQ; /* 116 */ + *outBytesLeft-=(pOut-*outBuf); + *inBytesLeft=inLen; + *outBuf=pOut; + *inBuf=pIn; + *numSub+=numS; + return -1; + } + } + /* end of UTF-8 to UCS-2 */ + if (in == 0x0000) { + *pOut=0x00; + ++pOut; + } else { + in<<=1; + *pOut=dmapU2D[in]; + ++pOut; + if (dmapU2D[in+1] == 0x00) { /* SBCS */ + if (dmapU2D[in] == subS) { + in>>=1; + if (in != cd->srcSubS) + ++numS; + } + } else { + *pOut=dmapU2D[in+1]; + ++pOut; + if (dmapU2D[in] == pSubD[0] && + dmapU2D[in+1] == pSubD[1]) { + in>>=1; + if (in != cd->srcSubD) + ++numS; + } + } + } + } + *outBytesLeft-=(pOut-*outBuf); + *inBytesLeft=inLen; + *outBuf=pOut; + *inBuf=pIn; + *numSub+=numS; + return 0; + + } else if (cd->cnv_dmap->codingSchema == DMAP_82U) { + /* See http://unicode.org/versions/corrigendum1.html */ + /* convert from UTF-8 to UTF-16 can cover all conversion from UTF-8 to UCS-2 */ + register int inLen=*inBytesLeft; + register char * pOut=*outBuf; + register char * pIn=*inBuf; + register char * pLastOutBuf = *outBuf + *outBytesLeft - 1; + register size_t numS=0; + while (0 < inLen) { + if (pLastOutBuf < pOut) + break; + if (*pIn == 0x00) { + *pOut=0x00; + ++pOut; + *pOut=0x00; + ++pOut; + ++pIn; + --inLen; + } else { /* 82U: */ + register uchar byte1=*pIn; + if ((byte1 & 0x80) == 0x00) { /* if (byte1 & 0b10000000 == 0b00000000) { */ + /* 1 bytes sequence: 0xxxxxxx => 00000000 0xxxxxxx*/ + *pOut=0x00; + ++pOut; + *pOut=byte1; + ++pOut; + ++pIn; + --inLen; + } else if ((byte1 & 0xE0) == 0xC0) { /* (byte1 & 0b11100000 == 0b11000000) { */ + if (inLen < 2) { + errno=EINVAL; /* 22 */ + *outBytesLeft-=(pOut-*outBuf); + *inBytesLeft=inLen; + *outBuf=pOut; + *inBuf=pIn; + *numSub+=numS; + return -1; + } + if (byte1 == 0xC0 || byte1 == 0xC1) { /* invalid sequence */ + errno=EILSEQ; /* 116 */ + *outBytesLeft-=(pOut-*outBuf); + *inBytesLeft=inLen; + *outBuf=pOut; + *inBuf=pIn; + *numSub+=numS; + return -1; + } + /* 2 bytes sequence: + 110yyyyy 10xxxxxx => 00000yyy yyxxxxxx */ + register uchar byte2; + ++pIn; + byte2=*pIn; + if ((byte2 & 0xC0) == 0x80) { /* byte2 & 0b11000000 == 0b10000000) { */ + register uchar work=byte1; + work<<=6; + byte2&=0x3F; /* 0b00111111; */ + byte2|=work; + + byte1&=0x1F; /* 0b00011111; */ + byte1>>=2; + *pOut=byte1; + ++pOut; + *pOut=byte2; + ++pOut; + inLen-=2; + ++pIn; + } else { /* invalid sequence */ + errno=EILSEQ; /* 116 */ + *outBytesLeft-=(pOut-*outBuf); + *inBytesLeft=inLen; + *outBuf=pOut; + *inBuf=pIn-1; + *numSub+=numS; + return -1; + } + } else if ((byte1 & 0xF0) == 0xE0) { /* byte1 & 0b11110000 == 0b11100000 */ + /* 3 bytes sequence: + 1110zzzz 10yyyyyy 10xxxxxx => zzzzyyyy yyxxxxxx */ + register uchar byte2; + register uchar byte3; + if (inLen < 3) { + if (inLen == 2 && (pIn[1] & 0xC0) != 0x80) + errno=EILSEQ; /* 116 */ + else + errno=EINVAL; /* 22 */ + *outBytesLeft-=(pOut-*outBuf); + *inBytesLeft=inLen; + *outBuf=pOut; + *inBuf=pIn; + *numSub+=numS; + return -1; + } + ++pIn; + byte2=*pIn; + ++pIn; + byte3=*pIn; + if ((byte2 & 0xC0) != 0x80 || + (byte3 & 0xC0) != 0x80 || + (byte1 == 0xE0 && byte2 < 0xA0)) { /* invalid sequence, only 0xA0-0xBF allowed after 0xE0 */ + errno=EILSEQ; /* 116 */ + *outBytesLeft-=(pOut-*outBuf); + *inBytesLeft=inLen; + *outBuf=pOut; + *inBuf=pIn-2; + *numSub+=numS; + return -1; + } + { + register uchar work=byte2; + work<<=6; + byte3&=0x3F; /* 0b00111111; */ + byte3|=work; + + byte2&=0x3F; /* 0b00111111; */ + byte2>>=2; + + byte1<<=4; + *pOut=byte1 | byte2;; + ++pOut; + *pOut=byte3; + ++pOut; + inLen-=3; + ++pIn; + } + } else if ((0xF0 <= byte1 && byte1 <= 0xF4) || /* (bytes1 & 11111000) == 0x1110000 */ + ((byte1&=0xF7) && 0xF0 <= byte1 && byte1 <= 0xF4)) { /* minic iconv() behavior */ + /* 4 bytes sequence + 11110uuu 10uuzzzz 10yyyyyy 10xxxxxx => 110110ww wwzzzzyy 110111yy yyxxxxxx + where uuuuu = wwww + 1 */ + register uchar byte2; + register uchar byte3; + register uchar byte4; + if (inLen < 4 || cd->toCcsid == 13488) { + if ((inLen >= 2 && (pIn[1] & 0xC0) != 0x80) || + (inLen >= 3 && (pIn[2] & 0xC0) != 0x80) || + (cd->toCcsid == 13488) ) + errno=EILSEQ; /* 116 */ + else + errno=EINVAL; /* 22 */ + *outBytesLeft-=(pOut-*outBuf); + *inBytesLeft=inLen; + *outBuf=pOut; + *inBuf=pIn; + *numSub+=numS; + return -1; + } + ++pIn; + byte2=*pIn; + ++pIn; + byte3=*pIn; + ++pIn; + byte4=*pIn; + if ((byte2 & 0xC0) == 0x80 && /* byte2 & 0b11000000 == 0b10000000 */ + (byte3 & 0xC0) == 0x80 && /* byte3 & 0b11000000 == 0b10000000 */ + (byte4 & 0xC0) == 0x80) { /* byte4 & 0b11000000 == 0b10000000 */ + register uchar work=byte2; + if (byte1 == 0xF0 && byte2 < 0x90) { + errno=EILSEQ; /* 116 */ + *outBytesLeft-=(pOut-*outBuf); + *inBytesLeft=inLen; + *outBuf=pOut; + *inBuf=pIn-3; + *numSub+=numS; + return -1; + } else if (byte1 == 0xF4 && byte2 > 0x8F) { + errno=EINVAL; /* 22 */ + *outBytesLeft-=(pOut-*outBuf); + *inBytesLeft=inLen; + *outBuf=pOut; + *inBuf=pIn-3; + *numSub+=numS; + return -1; + } + + work&=0x30; /* 0b00110000; */ + work>>=4; + byte1&=0x07; /* 0b00000111; */ + byte1<<=2; + byte1+=work; /* uuuuu */ + --byte1; /* wwww */ + + work=byte1 & 0x0F; + work>>=2; + work+=0xD8; /* 0b11011011; */ + *pOut=work; + ++pOut; + + byte1<<=6; + byte2<<=2; + byte2&=0x3C; /* 0b00111100; */ + work=byte3; + work>>=4; + work&=0x03; /* 0b00000011; */ + work|=byte1; + work|=byte2; + *pOut=work; + ++pOut; + + work=byte3; + work>>=2; + work&=0x03; /* 0b00000011; */ + work|=0xDC; /* 0b110111xx; */ + *pOut=work; + ++pOut; + + byte3<<=6; + byte4&=0x3F; /* 0b00111111; */ + byte4|=byte3; + *pOut=byte4; + ++pOut; + inLen-=4; + ++pIn; + } else { /* invalid sequence */ + errno=EILSEQ; /* 116 */ + *outBytesLeft-=(pOut-*outBuf); + *inBytesLeft=inLen; + *outBuf=pOut; + *inBuf=pIn-3; + *numSub+=numS; + return -1; + } + } else if ((byte1 & 0xF0) == 0xF0) { + if (cd->toCcsid == 13488) { + errno=EILSEQ; /* 116 */ + } else { + if (inLen == 1) + errno=EINVAL; /* 22 */ + else if (inLen == 2 && (pIn[1] & 0xC0) != 0x80) + errno=EILSEQ; /* 116 */ + else if (inLen == 3 && ((pIn[1] & 0xC0) != 0x80 || (pIn[2] & 0xC0) != 0x80)) + errno=EILSEQ; /* 116 */ + else if (inLen >= 4 && ((pIn[1] & 0xC0) != 0x80 || (pIn[2] & 0xC0) != 0x80 || (pIn[3] & 0xC0) != 0x80)) + errno=EILSEQ; /* 116 */ + else + errno=EINVAL; /* 22 */ + } + *outBytesLeft-=(pOut-*outBuf); + *inBytesLeft=inLen; + *outBuf=pOut; + *inBuf=pIn; + *numSub+=numS; + return -1; + + } else { /* invalid sequence */ + errno=EILSEQ; /* 116 */ + *outBytesLeft-=(pOut-*outBuf); + *inBytesLeft=inLen; + *outBuf=pOut; + *inBuf=pIn; + *numSub+=numS; + return -1; + } + } + } + *outBytesLeft-=(pOut-*outBuf); + *inBytesLeft=inLen; + *outBuf=pOut; + *inBuf=pIn; + *numSub+=numS; + return 0; + } else if (cd->cnv_dmap->codingSchema == DMAP_U28) { + /* See http://unicode.org/versions/corrigendum1.html */ + register int inLen=*inBytesLeft; + register char * pOut=*outBuf; + register char * pIn=*inBuf; + register char * pLastOutBuf = *outBuf + *outBytesLeft - 1; + // register size_t numS=0; + while (0 < inLen) { + register uint32_t in; + if (inLen == 1) { + errno=EINVAL; /* 22 */ + *inBytesLeft=inLen; + *outBytesLeft-=(pOut-*outBuf); + *outBuf=pOut; + *inBuf=pIn; + return -1; + } + if (pLastOutBuf < pOut) + break; + in=pIn[0]; + in<<=8; + in+=pIn[1]; + if (in == 0x0000) { + *pOut=0x00; + ++pOut; + } else if ((in & 0xFF80) == 0x0000) { /* U28: in & 0b1111111110000000 == 0x0000 */ + *pOut=in; + ++pOut; + } else if ((in & 0xF800) == 0x0000) { /* in & 0b1111100000000000 == 0x0000 */ + register uchar byte; + in>>=6; + in&=0x001F; /* 0b0000000000011111 */ + in|=0x00C0; /* 0b0000000011000000 */ + *pOut=in; + ++pOut; + byte=pIn[1]; + byte&=0x3F; /* 0b00111111; */ + byte|=0x80; /* 0b10000000; */ + *pOut=byte; + ++pOut; + } else { + register uchar byte; + register uchar work; + byte=pIn[0]; + byte>>=4; + byte|=0xE0; /* 0b11100000; */ + *pOut=byte; + ++pOut; + + byte=pIn[0]; + byte<<=2; + work=pIn[1]; + work>>=6; + byte|=work; + byte&=0x3F; /* 0b00111111; */ + byte|=0x80; /* 0b10000000; */ + *pOut=byte; + ++pOut; + + byte=pIn[1]; + byte&=0x3F; /* 0b00111111; */ + byte|=0x80; /* 0b10000000; */ + *pOut=byte; + ++pOut; + } + pIn+=2; + inLen-=2; + } + *outBytesLeft-=(pOut-*outBuf); + *inBytesLeft=inLen; + *outBuf=pOut; + *inBuf=pIn; + // *numSub+=numS; + return 0; + + } else if (cd->cnv_dmap->codingSchema == DMAP_T28) { /* UTF-16_UTF-8 */ + /* See http://unicode.org/versions/corrigendum1.html */ + register int inLen=*inBytesLeft; + register char * pOut=*outBuf; + register char * pIn=*inBuf; + register char * pLastOutBuf = *outBuf + *outBytesLeft - 1; + // register size_t numS=0; + while (0 < inLen) { + register uint32_t in; + if (inLen == 1) { + errno=EINVAL; /* 22 */ + *inBytesLeft=0; + *outBytesLeft-=(pOut-*outBuf); + *outBuf=pOut; + *inBuf=pIn; + return 0; + } + if (pLastOutBuf < pOut) + break; + in=pIn[0]; + in<<=8; + in+=pIn[1]; + if (in == 0x0000) { + *pOut=0x00; + ++pOut; + } else if ((in & 0xFF80) == 0x0000) { /* U28: in & 0b1111111110000000 == 0x0000 */ + *pOut=in; + ++pOut; + } else if ((in & 0xF800) == 0x0000) { /* in & 0b1111100000000000 == 0x0000 */ + register uchar byte; + in>>=6; + in&=0x001F; /* 0b0000000000011111 */ + in|=0x00C0; /* 0b0000000011000000 */ + *pOut=in; + ++pOut; + byte=pIn[1]; + byte&=0x3F; /* 0b00111111; */ + byte|=0x80; /* 0b10000000; */ + *pOut=byte; + ++pOut; + } else if ((in & 0xFC00) == 0xD800) { /* in & 0b1111110000000000 == 0b1101100000000000, first surrogate character */ + if (0xDC00 <= in ) { + errno=EINVAL; /* 22 */ + *inBytesLeft=inLen-1; + *outBytesLeft-=(pOut-*outBuf); + *outBuf=pOut; + *inBuf=pIn; + return -1; + + } else if (inLen < 4) { + errno=EINVAL; /* 22 */ + *inBytesLeft=inLen-2; + *outBytesLeft-=(pOut-*outBuf); + *outBuf=pOut; + *inBuf=pIn+2; + return -1; + + } else if ((pIn[2] & 0xFC) != 0xDC) { /* pIn[2] & 0b11111100 == 0b11011100, second surrogate character */ + errno=EINVAL; /* 22 */ + *inBytesLeft=inLen-2; + *outBytesLeft-=(pOut-*outBuf); + *outBuf=pOut; + *inBuf=pIn+2; + return -1; + + } else { + register uchar byte; + register uchar work; + in>>=6; + in&=0x000F; /* 0b0000000000001111 */ + byte=in; /* wwww */ + ++byte; /* uuuuu */ + work=byte; /* save uuuuu */ + byte>>=2; + byte|=0xF0; /* 0b11110000; */ + *pOut=byte; + ++pOut; + + byte=work; + byte&=0x03; /* 0b00000011; */ + byte<<=4; + byte|=0x80; /* 0b10000000; */ + work=pIn[1]; + work&=0x3C; /* 0b00111100; */ + work>>=2; + byte|=work; + *pOut=byte; + ++pOut; + + byte=pIn[1]; + byte&=0x03; /* 0b00000011; */ + byte<<=4; + byte|=0x80; /* 0b10000000; */ + work=pIn[2]; + work&=0x03; /* 0b00000011; */ + work<<=2; + byte|=work; + work=pIn[3]; + work>>=6; + byte|=work; + *pOut=byte; + ++pOut; + + byte=pIn[3]; + byte&=0x3F; /* 0b00111111; */ + byte|=0x80; /* 0b10000000; */ + *pOut=byte; + ++pOut; + pIn+=2; + inLen-=2; + } + } else if ((in & 0xFC00) == 0xDC00) { /* in & 0b11111100 == 0b11011100, second surrogate character */ + errno=EINVAL; /* 22 */ + *inBytesLeft=inLen-1; + *outBytesLeft-=(pOut-*outBuf); + *outBuf=pOut; + *inBuf=pIn; + return -1; + + } else { + register uchar byte; + register uchar work; + byte=pIn[0]; + byte>>=4; + byte|=0xE0; /* 0b11100000; */ + *pOut=byte; + ++pOut; + + byte=pIn[0]; + byte<<=2; + work=pIn[1]; + work>>=6; + byte|=work; + byte&=0x3F; /* 0b00111111; */ + byte|=0x80; /* 0b10000000; */ + *pOut=byte; + ++pOut; + + byte=pIn[1]; + byte&=0x3F; /* 0b00111111; */ + byte|=0x80; /* 0b10000000; */ + *pOut=byte; + ++pOut; + } + pIn+=2; + inLen-=2; + } + *outBytesLeft-=(pOut-*outBuf); + *inBytesLeft=inLen; + *outBuf=pOut; + *inBuf=pIn; + // *numSub+=numS; + return 0; + + } else if (cd->cnv_dmap->codingSchema == DMAP_U2U) { /* UTF-16_UCS-2 */ + register int inLen=*inBytesLeft; + register int outLen=*outBytesLeft; + if (inLen <= outLen) { + memcpy(*outBuf, *inBuf, inLen); + (*outBytesLeft)-=inLen; + (*inBuf)+=inLen; + (*outBuf)+=inLen; + *inBytesLeft=0; + return 0; + } + memcpy(*outBuf, *inBuf, outLen); + (*outBytesLeft)=0; + (*inBuf)+=outLen; + (*outBuf)+=outLen; + *inBytesLeft-=outLen; + return (*inBytesLeft); + + } else { + return -1; + } + return 0; +} + + +#ifdef DEBUG +inline size_t myconv(myconv_t cd , + char** inBuf, + size_t* inBytesLeft, + char** outBuf, + size_t* outBytesLeft, + size_t* numSub) +{ + if (cd->converterType == CONVERTER_ICONV) { + return myconv_iconv(cd,inBuf,inBytesLeft,outBuf,outBytesLeft,numSub); + } else if (cd->converterType == CONVERTER_DMAP) { + return myconv_dmap(cd,inBuf,inBytesLeft,outBuf,outBytesLeft,numSub); + } + return -1; +} + +inline char * converterName(int32_t type) +{ + if (type == CONVERTER_ICONV) + return "iconv"; + else if (type == CONVERTER_DMAP) + return "dmap"; + + return "?????"; +} +#else +#define myconv(a,b,c,d,e,f) \ +(((a)->converterType == CONVERTER_ICONV)? myconv_iconv((a),(b),(c),(d),(e),(f)): (((a)->converterType == CONVERTER_DMAP)? myconv_dmap((a),(b),(c),(d),(e),(f)): -1)) + + +#define converterName(a) \ +(((a) == CONVERTER_ICONV)? "iconv": ((a) == CONVERTER_DMAP)? "dmap": "?????") +#endif + +void initMyconv(); +void cleanupMyconv(); + +#endif diff --git a/storage/ibmdb2i/db2i_rir.cc b/storage/ibmdb2i/db2i_rir.cc new file mode 100644 index 00000000000..acae6da3085 --- /dev/null +++ b/storage/ibmdb2i/db2i_rir.cc @@ -0,0 +1,441 @@ +/* +Licensed Materials - Property of IBM +DB2 Storage Engine Enablement +Copyright IBM Corporation 2007,2008 +All rights reserved + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + (a) Redistributions of source code must retain this list of conditions, the + copyright notice in section {d} below, and the disclaimer following this + list of conditions. + (b) Redistributions in binary form must reproduce this list of conditions, the + copyright notice in section (d) below, and the disclaimer following this + list of conditions, in the documentation and/or other materials provided + with the distribution. + (c) The name of IBM may not be used to endorse or promote products derived from + this software without specific prior written permission. + (d) The text of the required copyright notice is: + Licensed Materials - Property of IBM + DB2 Storage Engine Enablement + Copyright IBM Corporation 2007,2008 + All rights reserved + +THIS SOFTWARE IS PROVIDED BY IBM CORPORATION "AS IS" AND ANY EXPRESS OR IMPLIED +WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT +SHALL IBM CORPORATION BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT +OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT INCLUDING NEGLIGENCE OR OTHERWISE) ARISING +IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + + +#include "ha_ibmdb2i.h" + +/* Helper function for records_in_range. + Input: Bitmap of used key parts. + Output: Number of used key parts. */ + +static inline int getKeyCntFromMap(key_part_map keypart_map) +{ + int cnt = 0; + while (keypart_map) + { + keypart_map = keypart_map >> 1; + cnt++; + } + return (cnt); +} + + +/** + @brief + Given a starting key and an ending key, estimate the number of rows that + will exist between the two keys. + + INPUT + inx Index to use + min_key Min key. Is NULL if no min range + max_key Max key. Is NULL if no max range + + NOTES + min_key.flag can have one of the following values: + HA_READ_KEY_EXACT Include the key in the range + HA_READ_AFTER_KEY Don't include key in range + + max_key.flag can have one of the following values: + HA_READ_BEFORE_KEY Don't include key in range + HA_READ_AFTER_KEY Include all 'end_key' values in the range + + RETURN + HA_POS_ERROR Error or the storage engine cannot estimate the number of rows + 1 There are no matching keys in the given range + n > 0 There are approximately n rows in the range +*/ +ha_rows ha_ibmdb2i::records_in_range(uint inx, + key_range *min_key, + key_range *max_key) +{ + DBUG_ENTER("ha_ibmdb2i::records_in_range"); + int rc = 0; // Return code + ha_rows rows = 0; // Row count returned to caller of this method + uint32 spcLen; // Length of space passed to DB2 + uint32 keyCnt; // Number of fields in the key composite + uint32 literalCnt = 0; // Number of literals + uint32 boundsOff; // Offset from beginning of space to range bounds + uint32 litDefOff; // Offset from beginning of space to literal definitions + uint32 literalsOff; // Offset from beginning of space to literal values + uint32 cutoff = 0; // Early exit cutoff (currently not used) + uint64 recCnt; // Row count from DB2 + uint16 rtnCode; // Return code from DB2 + Bounds* boundsPtr; // Pointer to a pair of range bounds + Bound* boundPtr; // Pointer to a single (high or low) range bound + LitDef* litDefPtr; // Pointer to a literal definition + char* literalsPtr; // Pointer to the start of all literal values + char* literalPtr; // Pointer to the start of this literal value + char* tempPtr; // Temporary pointer + char* tempMinPtr; // Temporary pointer into min_key + int minKeyCnt = 0; // Number of fields in the min_key composite + int maxKeyCnt = 0; // Number of fields in the max_key composite + size_t tempLen = 0; // Temporary length + uint16 DB2FieldWidth = 0; // DB2 field width + uint32 workFieldLen = 0; // Length of workarea needed for CCSID conversions + bool overrideInclusion; // Indicator for inclusion/exclusion + char* endOfLiteralPtr; // Pointer to the end of this literal + char* endOfMinPtr; // Pointer to end of min_key + uint16 endByte = 0; // End byte of char or graphic literal (padding not included) + bool reuseLiteral; // Indicator that hi and lo bounds use same literal + char* minPtr = NULL; // Work pointer for traversing min_key + char* maxPtr = NULL; // Work pointer for traversing max_key + /* + Handle the special case of 'x < null' anywhere in the key range. There are + no values less than null, but return 1 so that MySQL does not assume + the empty set for the query. + */ + if (min_key != NULL && max_key != NULL && + min_key->flag == HA_READ_AFTER_KEY && max_key->flag == HA_READ_BEFORE_KEY && + min_key->length == max_key->length && + (memcmp((uchar*)min_key->key,(uchar*)max_key->key,min_key->length)==0)) + { + DBUG_PRINT("ha_ibmdb2i::records_in_range",("Estimate 1 row for key %d; special case: < null", inx)); + DBUG_RETURN((ha_rows) 1 ); + } + /* + Determine the number of fields in the key composite. + */ + + if (min_key) + { + minKeyCnt = getKeyCntFromMap(min_key->keypart_map); + minPtr = (char*)min_key->key; + } + if (max_key) + { + maxKeyCnt = getKeyCntFromMap(max_key->keypart_map); + maxPtr = (char*)max_key->key; + } + keyCnt = maxKeyCnt >= minKeyCnt ? maxKeyCnt : minKeyCnt; + + /* + Allocate the space needed to pass range information to DB2. The + space must be large enough to store the following: + - one pair of bounds (high and low) per field in the key composite + - one literal definition per literal value + - the literal values + - work area for literal CCSID conversions + Since we don't know yet how many of these structures are needed, + allocate enough space for the maximum that we will possibly need. + The workarea for the literal conversion must be big enough to hold the + largest of the DB2 key fields. + */ + KEY& curKey = table->key_info[inx]; + + for (int i = 0; i < keyCnt; i++) + { + DB2FieldWidth = + db2Table->db2Field(curKey.key_part[i].field->field_index).getByteLengthInRecord(); + if (DB2FieldWidth > workFieldLen) + workFieldLen = DB2FieldWidth; // Get length of largest DB2 field + tempLen = tempLen + DB2FieldWidth; // Tally the DB2 field lengths + } + spcLen = (sizeof(Bounds)*keyCnt) + (sizeof(LitDef)*keyCnt*2) + (tempLen*2) + workFieldLen; + + ValidatedPointer spcPtr(spcLen); // Pointer to space passed to DB2 + memset(spcPtr, 0, spcLen); // Clear the allocated space + /* + Set addressability to the various sections of the DB2 interface space. + */ + boundsOff = 0; // Range bounds are at the start of the space + litDefOff = sizeof(Bounds) * keyCnt; // Literal defs follow all the range bounds + literalsOff = litDefOff + (sizeof(LitDef) * keyCnt * 2); // Literal values are last + boundsPtr = (Bounds_t*)(void*)spcPtr; // Address first bounds structure + tempPtr = (char*)((char*)spcPtr + litDefOff); + litDefPtr = (LitDef_t*)tempPtr; // Address first literal definition + tempPtr = (char*)((char*)spcPtr + literalsOff); + literalsPtr = (char*)tempPtr; // Address start of literal values + literalPtr = literalsPtr; // Address first literal value + /* + For each key part, build the low (min) and high (max) DB2 range bounds. + If literals are specified in the MySQL range, build DB2 literal + definitions and store the literal values for access by DB2. + + If no value is specified for a key part, assume infinity. Negative + infinity will cause processing to start at the first index entry. + Positive infinity will cause processing to end at the last index entry. + When infinity is specified in a bound, inclusion/exclusion and position + are ignored, and there is no literal definition or literal value for + the bound. + + If the keypart value is null, the null indicator is set in the range + bound and the other fields in the bound are ignored. When the bound is + null, only index entries with the null value will be included in the + estimate. If one bound is null, both bounds must be null. When the bound + is not null, the data offset and length must be set, and the literal + value stored for access by DB2. + */ + + for (int partsInUse = 0; partsInUse < keyCnt; ++partsInUse) + { + Field *field= curKey.key_part[partsInUse].field; + overrideInclusion = false; + reuseLiteral = false; + endOfLiteralPtr = NULL; + /* + Build the low bound for the key range. + */ + if ((partsInUse + 1) > minKeyCnt) // if no min_key info for this part + boundsPtr->LoBound.Infinity[0] = QMY_NEG_INFINITY; // select...where 3 between x and y + else + { + if ((curKey.key_part[partsInUse].null_bit) && (char*)minPtr[0]) + { // min_key is null + if (max_key == NULL || + ((partsInUse + 1) > maxKeyCnt)) // select...where x='ab' and y=null and z != 'c' + boundsPtr->LoBound.Infinity[0] = QMY_NEG_INFINITY; // select...where x not null or + // select...where x > null + else // max_key is not null + { + if (min_key->flag == HA_READ_KEY_EXACT) + boundsPtr->LoBound.IsNull[0] = QMY_YES; // select...where x is null + else + { + if ((char*)maxPtr[0]) + boundsPtr->LoBound.IsNull[0] = QMY_YES; // select...where a = null and b < 5 (max-before) + // select...where a='a' and b is null and c !='a' (max-after) + else + boundsPtr->LoBound.Infinity[0] = QMY_NEG_INFINITY; // select...where x < y + } + } // end min_key is null + } + else // min_key is not null + { + if (literalCnt) litDefPtr = litDefPtr + 1; + literalCnt = literalCnt + 1; + boundsPtr->LoBound.Position = literalCnt; + /* + Determine inclusion or exclusion. + */ + if (min_key->flag == HA_READ_KEY_EXACT || //select...where a like 'this%' + + /* An example for the following conditions is 'select...where a = 5 and b > null'. */ + + (max_key && + (memcmp((uchar*)minPtr,(uchar*)maxPtr, + curKey.key_part[partsInUse].store_length)==0))) + + { + if ((min_key->flag != HA_READ_KEY_EXACT) || + (max_key && + (memcmp((uchar*)minPtr,(uchar*)maxPtr, + curKey.key_part[partsInUse].store_length)==0))) + overrideInclusion = true; // Need inclusion for both min and max + } + else + boundsPtr->LoBound.Embodiment[0] = QMY_EXCLUSION; + litDefPtr->FieldNbr = field->field_index + 1; + DB2Field& db2Field = db2Table->db2Field(field->field_index); + litDefPtr->DataType = db2Field.getType(); + /* + Convert the literal to DB2 format. + */ + rc = convertMySQLtoDB2(field, + db2Field, + literalPtr, + (uchar*)minPtr+((curKey.key_part[partsInUse].null_bit)? 1 : 0)); + if (rc != 0) break; + litDefPtr->Offset = (uint32_t)(literalPtr - literalsPtr); + litDefPtr->Length = db2Field.getByteLengthInRecord(); + tempLen = litDefPtr->Length; + /* + Do additional conversion of a character or graphic value. + */ + CHARSET_INFO* fieldCharSet = field->charset(); + if ((field->type() != MYSQL_TYPE_BIT) && // Don't do conversion on BIT data + (field->charset() != &my_charset_bin) && // Don't do conversion on BINARY data + (litDefPtr->DataType == QMY_CHAR || litDefPtr->DataType == QMY_VARCHAR || + litDefPtr->DataType == QMY_GRAPHIC || litDefPtr->DataType == QMY_VARGRAPHIC)) + { + if (litDefPtr->DataType == QMY_VARCHAR || + litDefPtr->DataType == QMY_VARGRAPHIC) + tempPtr = literalPtr + sizeof(uint16); + else + tempPtr = literalPtr; + /* The following code checks to determine if MySQL is passing a + partial key. DB2 will accept a partial field value, but only + in the last field position of the key composite (and only if + there is no ICU sort sequence on the index). */ + tempMinPtr = (char*)minPtr+((curKey.key_part[partsInUse].null_bit)? 1 : 0); + if (field->type() == MYSQL_TYPE_VARCHAR) + { + /* MySQL always stores key lengths as 2 bytes, little-endian. */ + tempLen = *(uint8*)tempMinPtr + ((*(uint8*)(tempMinPtr+1)) << 8); + tempMinPtr = (char*)((char*)tempMinPtr + 2); + } + else + tempLen = field->field_length; + + if (litDefPtr->DataType == QMY_CHAR || litDefPtr->DataType == QMY_VARCHAR || + (strncmp(fieldCharSet->csname, "utf8", sizeof("utf8")) == 0)) + { + endOfMinPtr = (char*)memchr(tempMinPtr,field->charset()->min_sort_char,tempLen); + if (endOfMinPtr) + endOfLiteralPtr = tempPtr + (((uint32_t)(endOfMinPtr - tempMinPtr)) * + (litDefPtr->DataType == QMY_CHAR || litDefPtr->DataType == QMY_VARCHAR ? 1 : 2)); + } + else + { + endOfMinPtr = (char*)wmemchr((wchar_t*)tempMinPtr,field->charset()->min_sort_char,tempLen/2); + if (endOfMinPtr) + endOfLiteralPtr = tempPtr + (endOfMinPtr - tempMinPtr); + } + /* Enforce here that a partial is only allowed on the last field position + of the key composite */ + if (endOfLiteralPtr) + { + if ((partsInUse + 1) < minKeyCnt) + { + rc = HA_POS_ERROR; + break; + } + endByte = endOfLiteralPtr - tempPtr; + /* We're making an assumption that if MySQL gives us a partial key, + the length of the partial is the same for both the min_key and max_key. */ + } + } + literalPtr = literalPtr + litDefPtr->Length; // Bump pointer for next literal + } + /* If there is a max_key value for this field, and if the max_key value is + the same as the min_key value, then the low bound literal can be reused + for the high bound literal. This eliminates the overhead of copying and + converting the same value twice. */ + if (max_key && ((partsInUse + 1) <= maxKeyCnt) && + (memcmp((uchar*)minPtr,(uchar*)maxPtr, + curKey.key_part[partsInUse].store_length)==0 || endOfLiteralPtr)) + reuseLiteral = true; + minPtr += curKey.key_part[partsInUse].store_length; + } + /* + Build the high bound for the key range. + */ + if (max_key == NULL || ((partsInUse + 1) > maxKeyCnt)) + boundsPtr->HiBound.Infinity[0] = QMY_POS_INFINITY; + else + { + if ((curKey.key_part[partsInUse].null_bit) && (char*)maxPtr[0]) + { + if (min_key == NULL) + boundsPtr->HiBound.Infinity[0] = QMY_POS_INFINITY; + else + boundsPtr->HiBound.IsNull[0] = QMY_YES; // select...where x is null + } + else // max_key field is not null + { + if (!reuseLiteral) + { + if (literalCnt) + litDefPtr = litDefPtr + 1; + literalCnt = literalCnt + 1; + litDefPtr->FieldNbr = field->field_index + 1; + DB2Field& db2Field = db2Table->db2Field(field->field_index); + litDefPtr->DataType = db2Field.getType(); + /* + Convert the literal to DB2 format + */ + rc = convertMySQLtoDB2(field, + db2Field, + literalPtr, + (uchar*)maxPtr+((curKey.key_part[partsInUse].null_bit)? 1 : 0)); + if (rc != 0) break; + litDefPtr->Offset = (uint32_t)(literalPtr - literalsPtr); + litDefPtr->Length = db2Field.getByteLengthInRecord(); + tempLen = litDefPtr->Length; + /* + Now convert a character or graphic value. + */ + if ((field->type() != MYSQL_TYPE_BIT) && + (litDefPtr->DataType == QMY_CHAR || litDefPtr->DataType == QMY_VARCHAR || + litDefPtr->DataType == QMY_GRAPHIC || litDefPtr->DataType == QMY_VARGRAPHIC)) + { + if (litDefPtr->DataType == QMY_VARCHAR || litDefPtr->DataType == QMY_VARGRAPHIC) + { + tempPtr = literalPtr + sizeof(uint16); + } + else + tempPtr = literalPtr; + } + literalPtr = literalPtr + litDefPtr->Length; // Bump pointer for next literal + } + boundsPtr->HiBound.Position = literalCnt; + if (max_key->flag == HA_READ_BEFORE_KEY && !overrideInclusion) + boundsPtr->HiBound.Embodiment[0] = QMY_EXCLUSION; + } + maxPtr += curKey.key_part[partsInUse].store_length; + } + /* + Bump to the next field in the key composite. + */ + + if ((partsInUse+1) < keyCnt) + boundsPtr = boundsPtr + 1; + } + + /* + Call DB2 to estimate the number of rows in the key range. + */ + if (rc == 0) + { + rc = db2i_ileBridge::getBridgeForThread()->recordsInRange((indexHandles[inx] ? indexHandles[inx] : db2Table->indexFile(inx)->getMasterDefnHandle()), + spcPtr, + keyCnt, + literalCnt, + boundsOff, + litDefOff, + literalsOff, + cutoff, + (uint32_t)(literalPtr - (char*)spcPtr), + endByte, + &recCnt, + &rtnCode); + } + /* + Set the row count and return. + Beware that if this method returns a zero row count, MySQL assumes the + result set for the query is zero; never return a zero row count. + */ + if ((rc == 0) && (rtnCode == QMY_SUCCESS || rtnCode == QMY_EARLY_EXIT)) + { + rows = recCnt ? (ha_rows)recCnt : 1; + } + + rows = (rows > 0 ? rows : HA_POS_ERROR); + + setIndexReadEstimate(inx, rows); + + DBUG_PRINT("ha_ibmdb2i::recordsInRange",("Estimate %d rows for key %d", uint32(rows), inx)); + + DBUG_RETURN(rows); +} diff --git a/storage/ibmdb2i/db2i_safeString.h b/storage/ibmdb2i/db2i_safeString.h new file mode 100644 index 00000000000..e353316c8fc --- /dev/null +++ b/storage/ibmdb2i/db2i_safeString.h @@ -0,0 +1,98 @@ +/* +Licensed Materials - Property of IBM +DB2 Storage Engine Enablement +Copyright IBM Corporation 2007,2008 +All rights reserved + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + (a) Redistributions of source code must retain this list of conditions, the + copyright notice in section {d} below, and the disclaimer following this + list of conditions. + (b) Redistributions in binary form must reproduce this list of conditions, the + copyright notice in section (d) below, and the disclaimer following this + list of conditions, in the documentation and/or other materials provided + with the distribution. + (c) The name of IBM may not be used to endorse or promote products derived from + this software without specific prior written permission. + (d) The text of the required copyright notice is: + Licensed Materials - Property of IBM + DB2 Storage Engine Enablement + Copyright IBM Corporation 2007,2008 + All rights reserved + +THIS SOFTWARE IS PROVIDED BY IBM CORPORATION "AS IS" AND ANY EXPRESS OR IMPLIED +WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT +SHALL IBM CORPORATION BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT +OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT INCLUDING NEGLIGENCE OR OTHERWISE) ARISING +IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + + + +#ifndef DB2I_SAFESTRING_H +#define DB2I_SAFESTRING_H + + +#include +#include + +/** + @class SafeString + + This class was designed to provide safe, but lightweight, concatenation + operations C strings inside pre-allocated buffers. +*/ +class SafeString +{ +public: + SafeString(char* buffer, size_t size) : + allocSize(size), curPos(0), buf(buffer) + { + DBUG_ASSERT(size > 0); + buf[allocSize - 1] = 0xFF; // Set an overflow indicator + } + + char* ptr() { return buf; } + operator char*() { return buf; } + + SafeString& strcat(const char* str) + { + return this->strncat(str, strlen(str)); + } + + SafeString& strcat(char one) + { + if (curPos < allocSize - 2) + { + buf[curPos++] = one; + } + buf[curPos] = 0; + + return *this; + } + + SafeString& strncat(const char* str, size_t len) + { + uint64 amountToCopy = min((allocSize-1) - curPos, len); + memcpy(buf + curPos, str, amountToCopy); + curPos += amountToCopy; + buf[curPos] = 0; + return *this; + } + + bool overflowed() const { return (buf[allocSize - 1] == 0);} + +private: + char* buf; + uint64 curPos; + size_t allocSize; +}; + + +#endif diff --git a/storage/ibmdb2i/db2i_sqlStatementStream.cc b/storage/ibmdb2i/db2i_sqlStatementStream.cc new file mode 100644 index 00000000000..92a8b03fd00 --- /dev/null +++ b/storage/ibmdb2i/db2i_sqlStatementStream.cc @@ -0,0 +1,86 @@ +/* +Licensed Materials - Property of IBM +DB2 Storage Engine Enablement +Copyright IBM Corporation 2007,2008 +All rights reserved + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + (a) Redistributions of source code must retain this list of conditions, the + copyright notice in section {d} below, and the disclaimer following this + list of conditions. + (b) Redistributions in binary form must reproduce this list of conditions, the + copyright notice in section (d) below, and the disclaimer following this + list of conditions, in the documentation and/or other materials provided + with the distribution. + (c) The name of IBM may not be used to endorse or promote products derived from + this software without specific prior written permission. + (d) The text of the required copyright notice is: + Licensed Materials - Property of IBM + DB2 Storage Engine Enablement + Copyright IBM Corporation 2007,2008 + All rights reserved + +THIS SOFTWARE IS PROVIDED BY IBM CORPORATION "AS IS" AND ANY EXPRESS OR IMPLIED +WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT +SHALL IBM CORPORATION BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT +OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT INCLUDING NEGLIGENCE OR OTHERWISE) ARISING +IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + + +#include "db2i_sqlStatementStream.h" +#include "as400_types.h" + +/** + Add a statement to the statement stream, allocating additional memory as needed. + + @parm stmt The statement text + @parm length The length of the statement text + @parm fileSortSequence The DB2 sort sequence identifier, in EBCDIC + @parm fileSortSequenceLibrary The DB2 sort sequence library, in EBCDIC + + @return Reference to this object +*/ +SqlStatementStream& SqlStatementStream::addStatementInternal(const char* stmt, + uint32 length, + const char* fileSortSequence, + const char* fileSortSequenceLibrary) +{ + uint32 storageNeeded = length + sizeof(StmtHdr_t); + storageNeeded = (storageNeeded + 3) & ~3; // We have to be 4-byte aligned. + if (storageNeeded > storageRemaining()) + { + // We overallocate new storage to reduce number of times reallocation is + // needed. + int newSize = curSize + 2 * storageNeeded; + DBUG_PRINT("SqlStatementStream::addStatementInternal", + ("PERF: Had to realloc! Old size=%d. New size=%d", curSize, newSize)); + char* old_space = block; + char* new_space = (char*)getNewSpace(newSize); + memcpy(new_space, old_space, curSize); + ptr = new_space + (ptr - old_space); + curSize = newSize; + } + + DBUG_ASSERT((address64_t)ptr % 4 == 0); + + memcpy(((StmtHdr_t*)ptr)->SrtSeqNam, + fileSortSequence, + sizeof(((StmtHdr_t*)ptr)->SrtSeqNam)); + memcpy(((StmtHdr_t*)ptr)->SrtSeqSch, + fileSortSequenceLibrary, + sizeof(((StmtHdr_t*)ptr)->SrtSeqSch)); + ((StmtHdr_t*)ptr)->Length = length; + memcpy(ptr + sizeof(StmtHdr_t), stmt, length); + + ptr += storageNeeded; + ++statements; + + return *this; +} diff --git a/storage/ibmdb2i/db2i_sqlStatementStream.h b/storage/ibmdb2i/db2i_sqlStatementStream.h new file mode 100644 index 00000000000..11db41a6c5d --- /dev/null +++ b/storage/ibmdb2i/db2i_sqlStatementStream.h @@ -0,0 +1,151 @@ +/* +Licensed Materials - Property of IBM +DB2 Storage Engine Enablement +Copyright IBM Corporation 2007,2008 +All rights reserved + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + (a) Redistributions of source code must retain this list of conditions, the + copyright notice in section {d} below, and the disclaimer following this + list of conditions. + (b) Redistributions in binary form must reproduce this list of conditions, the + copyright notice in section (d) below, and the disclaimer following this + list of conditions, in the documentation and/or other materials provided + with the distribution. + (c) The name of IBM may not be used to endorse or promote products derived from + this software without specific prior written permission. + (d) The text of the required copyright notice is: + Licensed Materials - Property of IBM + DB2 Storage Engine Enablement + Copyright IBM Corporation 2007,2008 + All rights reserved + +THIS SOFTWARE IS PROVIDED BY IBM CORPORATION "AS IS" AND ANY EXPRESS OR IMPLIED +WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT +SHALL IBM CORPORATION BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT +OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT INCLUDING NEGLIGENCE OR OTHERWISE) ARISING +IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + + +#ifndef DB2I_SQLSTATEMENTSTREAM_H +#define DB2I_SQLSTATEMENTSTREAM_H + +#include "db2i_charsetSupport.h" +#include "qmyse.h" + +/** + @class SqlStatementStream + + This class handles building the stream of SQL statements expected by the + QMY_EXECUTE_IMMEDIATE and QMY_PREPARE_OPEN_CURSOR APIs. + Memory allocation is handled internally. +*/ +class SqlStatementStream +{ + public: + /** + ctor to be used when multiple strings may be appended. + */ + SqlStatementStream(uint32 firstStringSize) : statements(0) + { + curSize = firstStringSize + sizeof(StmtHdr_t); + curSize = (curSize + 3) & ~3; + ptr = (char*) getNewSpace(curSize); + if (ptr == NULL) + curSize = 0; + } + + /** + ctor to be used when only a single statement will be executed. + */ + SqlStatementStream(const String& statement) : statements(0), block(NULL), curSize(0), ptr(0) + { + addStatement(statement); + } + + /** + ctor to be used when only a single statement will be executed. + */ + SqlStatementStream(const char* statement) : statements(0), block(NULL), curSize(0), ptr(0) + { + addStatement(statement); + } + + /** + Append an SQL statement, specifiying the DB2 sort sequence under which + the statement should be executed. This is important for CREATE TABLE + and CREATE INDEX statements. + */ + SqlStatementStream& addStatement(const String& append, const char* fileSortSequence, const char* fileSortSequenceLibrary) + { + char sortSeqEbcdic[10]; + char sortSeqLibEbcdic[10]; + + DBUG_ASSERT(strlen(fileSortSequence) <= 10 && + strlen(fileSortSequenceLibrary) <= 10); + memset(sortSeqEbcdic, 0x40, 10); + memset(sortSeqLibEbcdic, 0x40, 10); + convToEbcdic(fileSortSequence, sortSeqEbcdic, strlen(fileSortSequence)); + convToEbcdic(fileSortSequenceLibrary, sortSeqLibEbcdic, strlen(fileSortSequenceLibrary)); + + return addStatementInternal(append.ptr(), append.length(), sortSeqEbcdic, sortSeqLibEbcdic); + } + + /** + Append an SQL statement using default (*HEX) sort sequence. + */ + SqlStatementStream& addStatement(const String& append) + { + const char splatHEX[] = {0x5C, 0xC8, 0xC5, 0xE7, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40}; // *HEX + const char blanks[] = {0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40}; // + + return addStatementInternal(append.ptr(), append.length(), splatHEX, blanks); + } + + /** + Append an SQL statement using default (*HEX) sort sequence. + */ + SqlStatementStream& addStatement(const char* stmt) + { + const char splatHEX[] = {0x5C, 0xC8, 0xC5, 0xE7, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40}; // *HEX + const char blanks[] = {0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40}; // + + return addStatementInternal(stmt, strlen(stmt), splatHEX, blanks); + } + + char* getPtrToData() const { return block; } + uint32 getStatementCount() const { return statements; } + private: + SqlStatementStream& addStatementInternal(const char* stmt, + uint32 length, + const char* fileSortSequence, + const char* fileSortSequenceLibrary); + + uint32 storageRemaining() const + { + return (block == NULL ? 0 : curSize - (ptr - block)); + } + + char* getNewSpace(size_t size) + { + allocBase = (char*)sql_alloc(size + 15); + block = (char*)roundToQuadWordBdy(allocBase); + return block; + } + + uint32 curSize; // The size of the usable memory. + char* allocBase; // The allocated memory (with padding for aligment) + char* block; // The usable memory chunck (aligned for ILE) + char* ptr; // The current position within block. + uint32 statements; // The number of statements that have been appended. +}; + +#endif + diff --git a/storage/ibmdb2i/db2i_validatedPointer.h b/storage/ibmdb2i/db2i_validatedPointer.h new file mode 100644 index 00000000000..c4e31d1f11b --- /dev/null +++ b/storage/ibmdb2i/db2i_validatedPointer.h @@ -0,0 +1,162 @@ +/* +Licensed Materials - Property of IBM +DB2 Storage Engine Enablement +Copyright IBM Corporation 2007,2008 +All rights reserved + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + (a) Redistributions of source code must retain this list of conditions, the + copyright notice in section {d} below, and the disclaimer following this + list of conditions. + (b) Redistributions in binary form must reproduce this list of conditions, the + copyright notice in section (d) below, and the disclaimer following this + list of conditions, in the documentation and/or other materials provided + with the distribution. + (c) The name of IBM may not be used to endorse or promote products derived from + this software without specific prior written permission. + (d) The text of the required copyright notice is: + Licensed Materials - Property of IBM + DB2 Storage Engine Enablement + Copyright IBM Corporation 2007,2008 + All rights reserved + +THIS SOFTWARE IS PROVIDED BY IBM CORPORATION "AS IS" AND ANY EXPRESS OR IMPLIED +WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT +SHALL IBM CORPORATION BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT +OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT INCLUDING NEGLIGENCE OR OTHERWISE) ARISING +IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +#ifndef DB2I_VALIDATEDPOINTER_H +#define DB2I_VALIDATEDPOINTER_H + +#include "db2i_ileBridge.h" + +/** + @class ValidatedPointer + @brief Encapsulates a pointer registered for usage by the QMYSE APIs + + @details As a performance optimization, to prevent pointer validation each + time a particular pointer is thunked across to ILE, QMYSE allows us to + "register" a pointer such that it is validated once and then subsequently + referenced on QMYSE APIs by means of a handle value. This class should be + used to manage memory allocation/registration/unregistration of these + pointers. Using the alloc function guarantees that the resulting storage is + 16-byte aligned, a requirement for many pointers passed to QMYSE. +*/ +template +class ValidatedPointer +{ +public: + ValidatedPointer() : address(NULL), handle(NULL) {;} + + ValidatedPointer(size_t size) + { + alloc(size); + } + + ValidatedPointer(T* ptr) + { + assign(ptr); + } + + operator T*() + { + return address; + }; + + operator T*() const + { + return address; + }; + + operator void*() + { + return address; + }; + + operator ILEMemHandle() + { + return handle; + } + + void alloc(size_t size) + { + address = (T*)malloc_aligned(size); + if (address) + db2i_ileBridge::registerPtr(address, &handle); + mallocedHere = 1; + } + + void assign(T* ptr) + { + address = ptr; + db2i_ileBridge::registerPtr((void*)ptr, &handle); + mallocedHere = 0; + } + + void realloc(size_t size) + { + dealloc(); + alloc(size); + } + + void reassign(T* ptr) + { + dealloc(); + assign(ptr); + } + + void dealloc() + { + if (address) + { + db2i_ileBridge::unregisterPtr(handle); + + if (mallocedHere) + free_aligned((void*)address); + } + address = NULL; + handle = 0; + } + + ~ValidatedPointer() + { + dealloc(); + } + +private: + // Disable copy ctor and assignment operator, as these would break + // the registration guarantees provided by the class. + ValidatedPointer& operator= (const ValidatedPointer newVal); + ValidatedPointer(ValidatedPointer& newCopy); + + ILEMemHandle handle; + T* address; + char mallocedHere; +}; + + +/** + @class ValidatedObject + @brief This class allows users to instantiate and register a particular + object in a single step. +*/ +template +class ValidatedObject : public ValidatedPointer +{ + public: + ValidatedObject() : ValidatedPointer(&value) {;} + + T& operator= (const T newVal) { value = newVal; return value; } + + private: + T value; +}; +#endif diff --git a/storage/ibmdb2i/ha_ibmdb2i.cc b/storage/ibmdb2i/ha_ibmdb2i.cc new file mode 100644 index 00000000000..9a65e41021b --- /dev/null +++ b/storage/ibmdb2i/ha_ibmdb2i.cc @@ -0,0 +1,3171 @@ +/* +Licensed Materials - Property of IBM +DB2 Storage Engine Enablement +Copyright IBM Corporation 2007,2008 +All rights reserved + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + (a) Redistributions of source code must retain this list of conditions, the + copyright notice in section {d} below, and the disclaimer following this + list of conditions. + (b) Redistributions in binary form must reproduce this list of conditions, the + copyright notice in section (d) below, and the disclaimer following this + list of conditions, in the documentation and/or other materials provided + with the distribution. + (c) The name of IBM may not be used to endorse or promote products derived from + this software without specific prior written permission. + (d) The text of the required copyright notice is: + Licensed Materials - Property of IBM + DB2 Storage Engine Enablement + Copyright IBM Corporation 2007,2008 + All rights reserved + +THIS SOFTWARE IS PROVIDED BY IBM CORPORATION "AS IS" AND ANY EXPRESS OR IMPLIED +WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT +SHALL IBM CORPORATION BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT +OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT INCLUDING NEGLIGENCE OR OTHERWISE) ARISING +IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + + +/** + @file ha_ibmdb2i.cc + + @brief + The ha_ibmdb2i storage engine provides an interface from MySQL to IBM DB2 for i. + +*/ + +#ifdef USE_PRAGMA_IMPLEMENTATION +#pragma implementation // gcc: Class implementation +#endif + +#include "ha_ibmdb2i.h" +#include "mysql_priv.h" +#include +#include "db2i_ileBridge.h" +#include "db2i_charsetSupport.h" +#include +#include "db2i_safeString.h" + +static const char __NOT_NULL_VALUE_EBCDIC = 0xF0; // '0' +static const char __NULL_VALUE_EBCDIC = 0xF1; // '1' +static const char __DEFAULT_VALUE_EBCDIC = 0xC4; // 'D' +static const char BlankASPName[19] = " "; +static const int DEFAULT_MAX_ROWS_TO_BUFFER = 4096; + +static const char SAVEPOINT_PREFIX[] = {0xD4, 0xE8, 0xE2, 0xD7}; // MYSP (in EBCDIC) + +OSVersion osVersion; + + +// ================================================================ +// ================================================================ +// System variables +static char* ibmdb2i_rdb_name; +static MYSQL_SYSVAR_STR(rdb_name, ibmdb2i_rdb_name, + PLUGIN_VAR_MEMALLOC | PLUGIN_VAR_READONLY, + "The name of the RDB to use", + NULL, + NULL, + BlankASPName); + +static MYSQL_THDVAR_BOOL(transaction_unsafe, + 0, + "True auto-commit mode.", + NULL, + NULL, + FALSE); + +static MYSQL_THDVAR_UINT(lob_alloc_size, + 0, + "Baseline allocation for lob read buffer", + NULL, + NULL, + 2*1024*1024, + 64*1024, + 128*1024*1024, + 1); + +static MYSQL_THDVAR_UINT(max_read_buffer_size, + 0, + "Maximum size of buffers used for read-ahead.", + NULL, + NULL, + 1*1024*1024, + 32*1024, + 16*1024*1024, + 1); + +static MYSQL_THDVAR_UINT(max_write_buffer_size, + 0, + "Maximum size of buffers used for bulk writes.", + NULL, + NULL, + 8*1024*1024, + 32*1024, + 64*1024*1024, + 1); + +static MYSQL_THDVAR_BOOL(create_time_columns_as_TOD, + 0, + "Control how new TIME columns should be defined in DB2. 1=time-of-day (default), 0=duration.", + NULL, + NULL, + TRUE); + +static MYSQL_THDVAR_UINT(map_blob_to_varchar, + 0, + "Control how new TEXT columns should be defined in DB2. 0=CLOB (default), 1=VARCHAR", + NULL, + NULL, + 0, + 0, + 1, + 1); + +static my_bool ibmdb2i_assume_exclusive_use; +static MYSQL_SYSVAR_BOOL(assume_exclusive_use, ibmdb2i_assume_exclusive_use, + 0, + "Can MySQL assume that this process is the only one modifying the DB2 tables. ", + NULL, + NULL, + FALSE); + +static MYSQL_THDVAR_BOOL(async_enabled, + 0, + "Should reads be done asynchronously when possible", + NULL, + NULL, + TRUE); + +static MYSQL_THDVAR_UINT(create_index_option, + 0, + "Control whether additional indexes are created. 0=No (default), 1=Create additional *HEX-based index", + NULL, + NULL, + 0, + 0, + 1, + 1); + +static MYSQL_THDVAR_UINT(discovery_mode, + 0, + "Unsupported", + NULL, + NULL, + 0, + 0, + 1, + 1); + + +inline uint8 ha_ibmdb2i::getCommitLevel(THD* thd) +{ + if (!THDVAR(thd, transaction_unsafe)) + { + switch (thd_tx_isolation(thd)) + { + case ISO_READ_UNCOMMITTED: + return (accessIntent == QMY_READ_ONLY ? QMY_READ_UNCOMMITTED : QMY_REPEATABLE_READ); + case ISO_READ_COMMITTED: + return (accessIntent == QMY_READ_ONLY ? QMY_READ_COMMITTED : QMY_REPEATABLE_READ); + case ISO_REPEATABLE_READ: + return QMY_REPEATABLE_READ; + case ISO_SERIALIZABLE: + return QMY_SERIALIZABLE; + } + } + + return QMY_NONE; +} + +inline uint8 ha_ibmdb2i::getCommitLevel() +{ + return getCommitLevel(ha_thd()); +} + +//===================================================================== + +static handler *ibmdb2i_create_handler(handlerton *hton, + TABLE_SHARE *table, + MEM_ROOT *mem_root); +static void ibmdb2i_drop_database(handlerton *hton, char* path); +static int ibmdb2i_savepoint_set(handlerton *hton, THD* thd, void *sv); +static int ibmdb2i_savepoint_rollback(handlerton *hton, THD* thd, void *sv); +static int ibmdb2i_savepoint_release(handlerton *hton, THD* thd, void *sv); +static uint ibmdb2i_alter_table_flags(uint flags); + +handlerton *ibmdb2i_hton; +static bool was_ILE_inited; + +/* Tracks the number of open tables */ +static HASH ibmdb2i_open_tables; + +/* Mutex used to synchronize initialization of the hash */ +static pthread_mutex_t ibmdb2i_mutex; + + +/** + Create hash key for tracking open tables. +*/ + +static uchar* ibmdb2i_get_key(IBMDB2I_SHARE *share,size_t *length, + bool not_used __attribute__((unused))) +{ + *length=share->table_name_length; + return (uchar*) share->table_name; +} + + +int ibmdb2i_close_connection(handlerton* hton, THD *thd) +{ + DBUG_PRINT("ha_ibmdb2i::close_connection", ("Closing %d", thd->thread_id)); + db2i_ileBridge::getBridgeForThread(thd)->closeConnection(thd->thread_id); + db2i_ileBridge::destroyBridgeForThread(thd); + + return 0; +} + + +static int ibmdb2i_init_func(void *p) +{ + DBUG_ENTER("ibmdb2i_init_func"); + + utsname tempName; + uname(&tempName); + osVersion.v = atoi(tempName.version); + osVersion.r = atoi(tempName.release); + + was_ILE_inited = false; + ibmdb2i_hton= (handlerton *)p; + VOID(pthread_mutex_init(&ibmdb2i_mutex,MY_MUTEX_INIT_FAST)); + (void) hash_init(&ibmdb2i_open_tables,system_charset_info,32,0,0, + (hash_get_key) ibmdb2i_get_key,0,0); + + ibmdb2i_hton->state= SHOW_OPTION_YES; + ibmdb2i_hton->create= ibmdb2i_create_handler; + ibmdb2i_hton->drop_database= ibmdb2i_drop_database; + ibmdb2i_hton->commit= ha_ibmdb2i::doCommit; + ibmdb2i_hton->rollback= ha_ibmdb2i::doRollback; + ibmdb2i_hton->savepoint_offset= 0; + ibmdb2i_hton->savepoint_set= ibmdb2i_savepoint_set; + ibmdb2i_hton->savepoint_rollback= ibmdb2i_savepoint_rollback; + ibmdb2i_hton->savepoint_release= ibmdb2i_savepoint_release; + ibmdb2i_hton->alter_table_flags=ibmdb2i_alter_table_flags; + ibmdb2i_hton->close_connection=ibmdb2i_close_connection; + + int rc; + + rc = initCharsetSupport(); + + if (!rc) + rc = db2i_ileBridge::setup(); + + if (!rc) + { + int nameLen = strlen(ibmdb2i_rdb_name); + for (int i = 0; i < nameLen; ++i) + { + ibmdb2i_rdb_name[i] = my_toupper(system_charset_info, (uchar)ibmdb2i_rdb_name[i]); + } + + rc = db2i_ileBridge::initILE(ibmdb2i_rdb_name); + if (rc == 0) + { + was_ILE_inited = true; + } + } + + DBUG_RETURN(rc); +} + + +static int ibmdb2i_done_func(void *p) +{ + int error= 0; + DBUG_ENTER("ibmdb2i_done_func"); + + if (ibmdb2i_open_tables.records) + error= 1; + + if (was_ILE_inited) + db2i_ileBridge::exitILE(); + + db2i_ileBridge::takedown(); + + doneCharsetSupport(); + + hash_free(&ibmdb2i_open_tables); + pthread_mutex_destroy(&ibmdb2i_mutex); + + DBUG_RETURN(0); +} + + +IBMDB2I_SHARE *ha_ibmdb2i::get_share(const char *table_name, TABLE *table) +{ + IBMDB2I_SHARE *share; + uint length; + char *tmp_name; + + pthread_mutex_lock(&ibmdb2i_mutex); + length=(uint) strlen(table_name); + + if (!(share=(IBMDB2I_SHARE*) hash_search(&ibmdb2i_open_tables, + (uchar*)table_name, + length))) + { + if (!(share=(IBMDB2I_SHARE *) + my_multi_malloc(MYF(MY_WME | MY_ZEROFILL), + &share, sizeof(*share), + &tmp_name, length+1, + NullS))) + { + pthread_mutex_unlock(&ibmdb2i_mutex); + return NULL; + } + + share->use_count=0; + share->table_name_length=length; + share->table_name=tmp_name; + strmov(share->table_name,table_name); + if (my_hash_insert(&ibmdb2i_open_tables, (uchar*) share)) + goto error; + thr_lock_init(&share->lock); + pthread_mutexattr_t mutexattr = MY_MUTEX_INIT_FAST; + pthread_mutexattr_settype(&mutexattr, PTHREAD_MUTEX_RECURSIVE); + pthread_mutex_init(&share->mutex, &mutexattr); + + share->db2Table = new db2i_table(table->s, table_name); + int32 rc = share->db2Table->initDB2Objects(table_name); + + if (rc) + { + delete share->db2Table; + hash_delete(&ibmdb2i_open_tables, (uchar*) share); + thr_lock_delete(&share->lock); + my_errno = rc; + goto error; + } + + memset(&share->cachedStats, 0, sizeof(share->cachedStats)); + } + share->use_count++; + pthread_mutex_unlock(&ibmdb2i_mutex); + + db2Table = share->db2Table; + + return share; + +error: + pthread_mutex_destroy(&share->mutex); + my_free((uchar*) share, MYF(0)); + pthread_mutex_unlock(&ibmdb2i_mutex); + + return NULL; +} + + + +int ha_ibmdb2i::free_share(IBMDB2I_SHARE *share) +{ + pthread_mutex_lock(&ibmdb2i_mutex); + if (!--share->use_count) + { + delete share->db2Table; + db2Table = NULL; + + hash_delete(&ibmdb2i_open_tables, (uchar*) share); + thr_lock_delete(&share->lock); + pthread_mutex_destroy(&share->mutex); + my_free(share, MYF(0)); + } + pthread_mutex_unlock(&ibmdb2i_mutex); + + return 0; +} + +static handler* ibmdb2i_create_handler(handlerton *hton, + TABLE_SHARE *table, + MEM_ROOT *mem_root) +{ + return new (mem_root) ha_ibmdb2i(hton, table); +} + +static void ibmdb2i_drop_database(handlerton *hton, char* path) +{ + DBUG_ENTER("ha_ibmdb2i::ibmdb2i_drop_database"); + int rc = 0; + char queryBuffer[200]; + String query(queryBuffer, sizeof(queryBuffer), system_charset_info); + query.length(0); + query.append(STRING_WITH_LEN(" DROP SCHEMA \"")); + query.append(path+2, strchr(path+2, '/')-(path+2)); + query.append('"'); + + SqlStatementStream sqlStream(query); + + rc = db2i_ileBridge::getBridgeForThread()->execSQL(sqlStream.getPtrToData(), + sqlStream.getStatementCount(), + QMY_NONE, + FALSE, + TRUE); + DBUG_VOID_RETURN; +} + +inline static void genSavepointName(const void* sv, char* out) +{ + *(uint32*)out = *(uint32*)SAVEPOINT_PREFIX; + DBUG_ASSERT(sizeof(SAVEPOINT_PREFIX) == 4); + out += sizeof(SAVEPOINT_PREFIX); + + longlong2str((longlong)sv, out, 10); + while (*out) + { + out += 0xF0; + ++out; + } +} + + +/********************************************************************* +Sets a transaction savepoint. */ +static int ibmdb2i_savepoint_set(handlerton* hton, THD* thd, void* sv) +{ + DBUG_ENTER("ibmdb2i_savepoint_set"); + int rc = 0; + if (!THDVAR(thd ,transaction_unsafe)) + { + char name[64]; + genSavepointName(sv, name); + DBUG_PRINT("ibmdb2i_savepoint_set",("Setting %s", name)); + rc = ha_ibmdb2i::doSavepointSet(thd, name); + } + DBUG_RETURN(rc); +} + + +/********************************************************************* +Rollback a savepoint. */ +static int ibmdb2i_savepoint_rollback(handlerton* hton, THD* thd, void* sv) +{ + DBUG_ENTER("ibmdb2i_savepoint_rollback"); + int rc = 0; + if (!THDVAR(thd,transaction_unsafe)) + { + char name[64]; + genSavepointName(sv, name); + DBUG_PRINT("ibmdb2i_savepoint_rollback",("Rolling back %s", name)); + rc = ha_ibmdb2i::doSavepointRollback(thd, name); + } + DBUG_RETURN(rc); +} + + +/********************************************************************* +Release a savepoint. */ +static int ibmdb2i_savepoint_release(handlerton* hton, THD* thd, void* sv) +{ + DBUG_ENTER("ibmdb2i_savepoint_release"); + int rc = 0; + if (!THDVAR(thd,transaction_unsafe)) + { + char name[64]; + genSavepointName(sv, name); + DBUG_PRINT("ibmdb2i_savepoint_release",("Releasing %s", name)); + rc = ha_ibmdb2i::doSavepointRelease(thd, name); + } + DBUG_RETURN(rc); +} + +/* Thse flags allow for the online add and drop of an index via the CREATE INDEX, + DROP INDEX, and ALTER TABLE statements. These flags indicate that MySQL is not + required to lock the table before calling the storage engine to add or drop the + index(s). */ +static uint ibmdb2i_alter_table_flags(uint flags) +{ + return (HA_ONLINE_ADD_INDEX | HA_ONLINE_DROP_INDEX | + HA_ONLINE_ADD_UNIQUE_INDEX | HA_ONLINE_DROP_UNIQUE_INDEX | + HA_ONLINE_ADD_PK_INDEX | HA_ONLINE_DROP_PK_INDEX); +} + +ha_ibmdb2i::ha_ibmdb2i(handlerton *hton, TABLE_SHARE *table_arg) + :share(NULL), handler(hton, table_arg), + activeHandle(0), dataHandle(0), + activeReadBuf(NULL), activeWriteBuf(NULL), + blobReadBuffers(NULL), accessIntent(QMY_UPDATABLE), currentRRN(0), + releaseRowNeeded(FALSE), + indexReadSizeEstimates(NULL), + outstanding_start_bulk_insert(false), + last_rnd_init_rc(0), + last_index_init_rc(0), + last_start_bulk_insert_rc(0), + autoIncLockAcquired(false), + got_auto_inc_values(false), + next_identity_value(0), + indexHandles(0), + returnDupKeysImmediately(false), + onDupUpdate(false), + blobWriteBuffers(NULL), + forceSingleRowRead(false) + { + activeReferences = 0; + ref_length = sizeof(currentRRN); + if (table_share && table_share->keys > 0) + { + indexHandles = (FILE_HANDLE*)my_malloc(table_share->keys * sizeof(FILE_HANDLE), MYF(MY_WME | MY_ZEROFILL)); + } + clear_alloc_root(&conversionBufferMemroot); + } + + +ha_ibmdb2i::~ha_ibmdb2i() +{ + if (indexHandles) + my_free(indexHandles, MYF(0)); + if (indexReadSizeEstimates) + my_free(indexReadSizeEstimates, MYF(0)); + + cleanupBuffers(); +} + + +static const char *ha_ibmdb2i_exts[] = { + FID_EXT, + NullS +}; + +const char **ha_ibmdb2i::bas_ext() const +{ + return ha_ibmdb2i_exts; +} + + +int ha_ibmdb2i::open(const char *name, int mode, uint test_if_locked) +{ + DBUG_ENTER("ha_ibmdb2i::open"); + + initBridge(); + + if (!(share = get_share(name, table))) + DBUG_RETURN(my_errno); + thr_lock_data_init(&share->lock,&lock,NULL); + + info(HA_STATUS_NO_LOCK | HA_STATUS_CONST | HA_STATUS_VARIABLE); + + dataHandle = bridge()->findAndRemovePreservedHandle(name); + + DBUG_RETURN(0); +} + + + + +int ha_ibmdb2i::close(void) +{ + DBUG_ENTER("ha_ibmdb2i::close"); + int32 rc = 0; + + db2i_ileBridge* bridge = db2i_ileBridge::getBridgeForThread(); + + if (dataHandle) + { + if (bridge->expectErrors(QMY_ERR_PEND_LOCKS)->deallocateFile(dataHandle, FALSE) == QMY_ERR_PEND_LOCKS) + bridge->preserveHandle(share->table_name, dataHandle); + dataHandle = 0; + } + + for (int idx = 0; idx < table_share->keys; ++idx) + { + if (indexHandles[idx] != 0) + { + bridge->deallocateFile(indexHandles[idx], FALSE); + } + } + + cleanupBuffers(); + + free_share(share); + + DBUG_RETURN(rc); +} + + + +int ha_ibmdb2i::write_row(uchar * buf) +{ + + DBUG_ENTER("ha_ibmdb2i::write_row"); + + if (last_start_bulk_insert_rc) + DBUG_RETURN( last_start_bulk_insert_rc ); + + ha_statistic_increment(&SSV::ha_write_count); + int rc; + + bool fileHandleNeedsRelease = false; + + if (!activeHandle) + { + rc = useDataFile(QMY_UPDATABLE); + if (rc) DBUG_RETURN(rc); + fileHandleNeedsRelease = true; + } + + if (!outstanding_start_bulk_insert) + prepWriteBuffer(1); + + if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT) + table->timestamp_field->set_time(); + + char* writeBuffer = activeWriteBuf->addRow(); + rc = prepareRowForWrite(writeBuffer, + writeBuffer+activeFormat->writeRowNullOffset, + true); + if (rc == 0) + { + // If we are doing block inserts, if the MI is supposed to generate an auto_increment + // (i.e. identity column) value for this record, and if this is not the first record in + // the block, then store the value (that the MI will generate for the identity column) + // into the MySQL write buffer. We can predetermine the value because the file is locked. + + if ((autoIncLockAcquired) && (default_identity_value) && (got_auto_inc_values)) + { + if (unlikely((next_identity_value - 1) == + maxValueForField(table->next_number_field))) + { + rc = QMY_ERR_MAXVALUE; + } + else + { + rc = table->next_number_field->store((longlong) next_identity_value, TRUE); + next_identity_value = next_identity_value + incrementByValue; + } + } + // If the buffer is full, or if we locked the file and this is the first or last row + // of a blocked insert, then flush the buffer. + if (!rc && (activeWriteBuf->endOfBuffer()) || + ((autoIncLockAcquired) && + ((!got_auto_inc_values))) || + (returnDupKeysImmediately)) + rc = flushWrite(activeHandle, buf); + } + else + activeWriteBuf->deleteRow(); + + + if (fileHandleNeedsRelease) + releaseActiveHandle(); + + DBUG_RETURN(rc); +} + +/** + @brief + Helper function used by write_row and update_row to prepare the MySQL + row for insertion into DB2. +*/ +int ha_ibmdb2i::prepareRowForWrite(char* data, char* nulls, bool honorIdentCols) +{ + int rc = 0; + + // set null map all to non nulls + memset(nulls,__NOT_NULL_VALUE_EBCDIC, table->s->fields); + default_identity_value = FALSE; + + ulong sql_mode = ha_thd()->variables.sql_mode; + + my_bitmap_map *old_map= dbug_tmp_use_all_columns(table, table->read_set); + for (Field **field = table->field; *field && !rc; ++field) + { + int fieldIndex = (*field)->field_index; + if ((*field)->Field::is_null()) + { + nulls[fieldIndex] = __NULL_VALUE_EBCDIC; + } + if (honorIdentCols && ((*field)->flags & AUTO_INCREMENT_FLAG) && + *field == table->next_number_field) +// && ((!autoIncLockAcquired) || (!got_auto_inc_values))) + { + if (sql_mode & MODE_NO_AUTO_VALUE_ON_ZERO) + { + if (!table->auto_increment_field_not_null) + { + nulls[fieldIndex] = __DEFAULT_VALUE_EBCDIC; + default_identity_value = TRUE; + } + } + else if ((*field)->val_int() == 0) + { + nulls[fieldIndex] = __DEFAULT_VALUE_EBCDIC; + default_identity_value = TRUE; + } + } + + DB2Field& db2Field = db2Table->db2Field(fieldIndex); + if (nulls[fieldIndex] == __NOT_NULL_VALUE_EBCDIC || + db2Field.isBlob()) + { + rc = convertMySQLtoDB2(*field, db2Field, data + db2Field.getBufferOffset()); + } + } + + if (!rc && db2Table->hasBlobs()) + rc = db2i_ileBridge::getBridgeForThread()->objectOverride(activeHandle, + activeWriteBuf->ptr()); + + dbug_tmp_restore_column_map(table->read_set, old_map); + + return rc; +} + + + +int ha_ibmdb2i::update_row(const uchar * old_data, uchar * new_data) +{ + DBUG_ENTER("ha_ibmdb2i::update_row"); + ha_statistic_increment(&SSV::ha_update_count); + int rc; + + bool fileHandleNeedsRelease = false; + + if (!activeHandle) + { + rc = useFileByHandle(QMY_UPDATABLE, rrnAssocHandle); + if (rc) DBUG_RETURN(rc); + fileHandleNeedsRelease = true; + } + + if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_UPDATE) + table->timestamp_field->set_time(); + + char* writeBuf = activeWriteBuf->addRow(); + rc = prepareRowForWrite(writeBuf, + writeBuf+activeFormat->writeRowNullOffset, + onDupUpdate); + + char* lastDupKeyNamePtr = NULL; + uint32 lastDupKeyNameLen = 0; + + if (!rc) + { + rc = db2i_ileBridge::getBridgeForThread()->updateRow(activeHandle, + currentRRN, + activeWriteBuf->ptr(), + &lastDupKeyRRN, + &lastDupKeyNamePtr, + &lastDupKeyNameLen); + } + + if (lastDupKeyNameLen) + { + lastDupKeyID = getKeyFromName(lastDupKeyNamePtr, lastDupKeyNameLen); + rrnAssocHandle = activeHandle; + } + + if (fileHandleNeedsRelease) + releaseActiveHandle(); + + activeWriteBuf->resetAfterWrite(); + + DBUG_RETURN(rc); +} + + +int ha_ibmdb2i::delete_row(const uchar * buf) +{ + DBUG_ENTER("ha_ibmdb2i::delete_row"); + ha_statistic_increment(&SSV::ha_delete_count); + + bool needReleaseFile = false; + int rc = 0; + + if (!activeHandle) // In some circumstances, MySQL comes here after + { // closing the active handle. We need to re-open. + rc = useFileByHandle(QMY_UPDATABLE, rrnAssocHandle); + needReleaseFile = true; + } + + if (likely(!rc)) + { + rc = db2i_ileBridge::getBridgeForThread()->deleteRow(activeHandle, + currentRRN); + invalidateCachedStats(); + if (needReleaseFile) + releaseActiveHandle(); + } + + DBUG_RETURN(rc); +} + + + +int ha_ibmdb2i::index_init(uint idx, bool sorted) +{ + DBUG_ENTER("ha_ibmdb2i::index_init"); + + int& rc = last_index_init_rc; + rc = 0; + + invalidDataFound=false; + tweakReadSet(); + + active_index=idx; + + rc = useIndexFile(accessIntent, idx); + if (accessIntent != QMY_READ_ONLY) + prepWriteBuffer(1); + + DBUG_RETURN(rc); +} + + + +int ha_ibmdb2i::index_read(uchar * buf, const uchar * key, + uint key_len, + enum ha_rkey_function find_flag) +{ + DBUG_ENTER("ha_ibmdb2i::index_read"); + + if (unlikely(last_index_init_rc)) DBUG_RETURN(last_index_init_rc); + + int rc; + + ha_rows estimatedRows = getIndexReadEstimate(active_index); + rc = prepReadBuffer(estimatedRows); + if (unlikely(rc)) DBUG_RETURN(rc); + + DBUG_ASSERT(activeReadBuf); + + keyBuf.allocBuf(activeFormat->readRowLen, activeFormat->readRowLen); + keyBuf.zeroBuf(); + + char* db2KeyBufPtr = keyBuf.ptr(); + char* nullKeyMap = db2KeyBufPtr + activeFormat->readRowNullOffset; + + const uchar* keyBegin = key; + int partsInUse; + + KEY& curKey = table->key_info[active_index]; + + for (partsInUse = 0; partsInUse < curKey.key_parts, key - keyBegin < key_len; ++partsInUse) + { + Field* field = curKey.key_part[partsInUse].field; + if ((curKey.key_part[partsInUse].null_bit) && + (char*)key[0]) + { + if (field->flags & AUTO_INCREMENT_FLAG) + { + table->status = STATUS_NOT_FOUND; + DBUG_RETURN(HA_ERR_END_OF_FILE); + } + else + { + nullKeyMap[partsInUse] = __NULL_VALUE_EBCDIC; + } + } + else + { + nullKeyMap[partsInUse] = __NOT_NULL_VALUE_EBCDIC; + convertMySQLtoDB2(field, + db2Table->db2Field(field->field_index), + db2KeyBufPtr, + (uchar*)key+((curKey.key_part[partsInUse].null_bit)? 1 : 0) ); // + (curKey.key_parts+7) / 8); + } + + db2KeyBufPtr += db2Table->db2Field(field->field_index).getByteLengthInRecord(); + key += curKey.key_part[partsInUse].store_length; + } + + keyLen = db2KeyBufPtr - (char*)keyBuf.ptr(); + + DBUG_PRINT("ha_ibmdb2i::index_read", ("find_flag: %d", find_flag)); + + char readDirection = QMY_NEXT; + + switch (find_flag) + { + case HA_READ_AFTER_KEY: + doInitialRead(QMY_AFTER_EQUAL, estimatedRows, + keyBuf.ptr(), keyLen, partsInUse); + break; + case HA_READ_BEFORE_KEY: + doInitialRead(QMY_BEFORE_EQUAL, estimatedRows, + keyBuf.ptr(), keyLen, partsInUse); + break; + case HA_READ_KEY_OR_NEXT: + doInitialRead(QMY_AFTER_OR_EQUAL, estimatedRows, + keyBuf.ptr(), keyLen, partsInUse); + break; + case HA_READ_KEY_OR_PREV: + DBUG_ASSERT(0); // This function is unused + doInitialRead(QMY_BEFORE_OR_EQUAL, estimatedRows, + keyBuf.ptr(), keyLen, partsInUse); + break; + case HA_READ_PREFIX_LAST_OR_PREV: + doInitialRead(QMY_LAST_PREVIOUS, estimatedRows, + keyBuf.ptr(), keyLen, partsInUse); + readDirection = QMY_PREVIOUS; + break; + case HA_READ_PREFIX_LAST: + doInitialRead(QMY_PREFIX_LAST, estimatedRows, + keyBuf.ptr(), keyLen, partsInUse); + readDirection = QMY_PREVIOUS; + break; + case HA_READ_KEY_EXACT: + doInitialRead(QMY_EQUAL, estimatedRows, keyBuf.ptr(), keyLen, partsInUse); + break; + default: + DBUG_ASSERT(0); + return HA_ERR_GENERIC; + break; + } + + ha_statistic_increment(&SSV::ha_read_key_count); + rc = readFromBuffer(buf, readDirection); + + table->status= (rc ? STATUS_NOT_FOUND: 0); + DBUG_RETURN(rc); +} + + +int ha_ibmdb2i::index_next(uchar * buf) +{ + DBUG_ENTER("ha_ibmdb2i::index_next"); + ha_statistic_increment(&SSV::ha_read_next_count); + + int rc = readFromBuffer(buf, QMY_NEXT); + + table->status= (rc ? STATUS_NOT_FOUND: 0); + DBUG_RETURN(rc); +} + + +int ha_ibmdb2i::index_next_same(uchar *buf, const uchar *key, uint keylen) +{ + DBUG_ENTER("ha_ibmdb2i::index_next_same"); + ha_statistic_increment(&SSV::ha_read_next_count); + + int rc = readFromBuffer(buf, QMY_NEXT_EQUAL); + + if (rc == HA_ERR_KEY_NOT_FOUND) + { + rc = HA_ERR_END_OF_FILE; + } + + table->status= (rc ? STATUS_NOT_FOUND: 0); + DBUG_RETURN(rc); +} + +int ha_ibmdb2i::index_read_last(uchar * buf, const uchar * key, uint key_len) +{ + DBUG_ENTER("ha_ibmdb2i::index_read_last"); + DBUG_RETURN(index_read(buf, key, key_len, HA_READ_PREFIX_LAST)); +} + + + +int ha_ibmdb2i::index_prev(uchar * buf) +{ + DBUG_ENTER("ha_ibmdb2i::index_prev"); + ha_statistic_increment(&SSV::ha_read_prev_count); + + int rc = readFromBuffer(buf, QMY_PREVIOUS); + + table->status= (rc ? STATUS_NOT_FOUND: 0); + DBUG_RETURN(rc); +} + + +int ha_ibmdb2i::index_first(uchar * buf) +{ + DBUG_ENTER("ha_ibmdb2i::index_first"); + + if (unlikely(last_index_init_rc)) DBUG_RETURN(last_index_init_rc); + + int rc = prepReadBuffer(DEFAULT_MAX_ROWS_TO_BUFFER); + + if (rc == 0) + { + doInitialRead(QMY_FIRST, DEFAULT_MAX_ROWS_TO_BUFFER); + ha_statistic_increment(&SSV::ha_read_first_count); + rc = readFromBuffer(buf, QMY_NEXT); + } + + table->status= (rc ? STATUS_NOT_FOUND: 0); + DBUG_RETURN(rc); +} + + +int ha_ibmdb2i::index_last(uchar * buf) +{ + DBUG_ENTER("ha_ibmdb2i::index_last"); + + if (unlikely(last_index_init_rc)) DBUG_RETURN(last_index_init_rc); + + int rc = prepReadBuffer(DEFAULT_MAX_ROWS_TO_BUFFER); + + if (rc == 0) + { + doInitialRead(QMY_LAST, DEFAULT_MAX_ROWS_TO_BUFFER); + ha_statistic_increment(&SSV::ha_read_last_count); + rc = readFromBuffer(buf, QMY_PREVIOUS); + } + + table->status= (rc ? STATUS_NOT_FOUND: 0); + DBUG_RETURN(rc); +} + + +int ha_ibmdb2i::rnd_init(bool scan) +{ + DBUG_ENTER("ha_ibmdb2i::rnd_init"); + + int& rc = last_rnd_init_rc; + rc = 0; + + tweakReadSet(); + invalidDataFound=false; + + uint32 rowsToBlockOnRead; + + if (!scan) + { + rowsToBlockOnRead = 1; + } + else + { + rowsToBlockOnRead = DEFAULT_MAX_ROWS_TO_BUFFER; + } + + rc = useDataFile(accessIntent); + + if (rc == 0) + { + if (accessIntent != QMY_READ_ONLY) + prepWriteBuffer(1); + rc = prepReadBuffer(rowsToBlockOnRead); + + if (rc == 0 && scan) + { + doInitialRead(QMY_FIRST, rowsToBlockOnRead); + } + + if (rc) + releaseDataFile(); + } + + DBUG_RETURN(0); // MySQL sometimes does not check the return code, causing + // an assert in ha_rnd_end later on if we return a non-zero + // value here. +} + +int ha_ibmdb2i::rnd_end() +{ + DBUG_ENTER("ha_ibmdb2i::rnd_end"); + + warnIfInvalidData(); + if (likely(activeReadBuf)) + activeReadBuf->endRead(); + if (last_rnd_init_rc == 0) + releaseActiveHandle(); + last_rnd_init_rc = 0; + DBUG_RETURN(0); +} + + +int32 ha_ibmdb2i::mungeDB2row(uchar* record, const char* dataPtr, const char* nullMapPtr, bool skipLOBs) +{ + DBUG_ASSERT(dataPtr); + + my_bitmap_map *old_write_map= dbug_tmp_use_all_columns(table, table->write_set); + my_bitmap_map *old_read_map; + + if (unlikely(readAllColumns)) + old_read_map = tmp_use_all_columns(table, table->read_set); + + resetCharacterConversionBuffers(); + + my_ptrdiff_t old_ptr= (my_ptrdiff_t) (record - table->record[0]); + int fieldIndex = 0; + for (Field **field = table->field; *field; ++field, ++fieldIndex) + { + if (unlikely(old_ptr)) + (*field)->move_field_offset(old_ptr); + if (nullMapPtr[fieldIndex] == __NULL_VALUE_EBCDIC || + (!bitmap_is_set(table->read_set, fieldIndex)) || + (skipLOBs && db2Table->db2Field(fieldIndex).isBlob())) + { + (*field)->set_null(); + } + else + { + (*field)->set_notnull(); + convertDB2toMySQL(db2Table->db2Field(fieldIndex), *field, dataPtr); + } + if (unlikely(old_ptr)) + (*field)->move_field_offset(-old_ptr); + + } + + if (unlikely(readAllColumns)) + tmp_restore_column_map(table->read_set, old_read_map); + dbug_tmp_restore_column_map(table->write_set, old_write_map); + + return 0; +} + + +int ha_ibmdb2i::rnd_next(uchar *buf) +{ + DBUG_ENTER("ha_ibmdb2i::rnd_next"); + + if (unlikely(last_rnd_init_rc)) DBUG_RETURN(last_rnd_init_rc); + ha_statistic_increment(&SSV::ha_read_rnd_next_count); + + int rc; + + rc = readFromBuffer(buf, QMY_NEXT); + + table->status= (rc ? STATUS_NOT_FOUND: 0); + DBUG_RETURN(rc); +} + + +void ha_ibmdb2i::position(const uchar *record) +{ + DBUG_ENTER("ha_ibmdb2i::position"); + my_store_ptr(ref, ref_length, currentRRN); + DBUG_VOID_RETURN; +} + + +int ha_ibmdb2i::rnd_pos(uchar * buf, uchar *pos) +{ + DBUG_ENTER("ha_ibmdb2i::rnd_pos"); + if (unlikely(last_rnd_init_rc)) DBUG_RETURN( last_rnd_init_rc); + ha_statistic_increment(&SSV::ha_read_rnd_count); + + currentRRN = my_get_ptr(pos, ref_length); + + tweakReadSet(); + + int rc = 0; + + if (activeHandle != rrnAssocHandle) + { + if (activeHandle) releaseActiveHandle(); + rc = useFileByHandle(QMY_UPDATABLE, rrnAssocHandle); + } + + if (likely(rc == 0)) + { + rc = prepReadBuffer(1); + + if (likely(rc == 0)) + { + rc = db2i_ileBridge::getBridgeForThread()->readByRRN(activeHandle, + activeReadBuf->ptr(), + currentRRN, + accessIntent, + getCommitLevel()); + + if (likely(rc == 0)) + { + rrnAssocHandle = activeHandle; + const char* readBuf = activeReadBuf->getRowN(0); + rc = mungeDB2row(buf, readBuf, readBuf + activeFormat->readRowNullOffset, false); + releaseRowNeeded = TRUE; + } + } + } + + DBUG_RETURN(rc); +} + + +int ha_ibmdb2i::info(uint flag) +{ + DBUG_ENTER("ha_ibmdb2i::info"); + + uint16 infoRequested = 0; + ValidatedPointer rowKeySpcPtr; // Space pointer passed to DB2 + uint32 rowKeySpcLen; // Length of space passed to DB2 + THD* thd = ha_thd(); + int command = thd_sql_command(thd); + + if (flag & HA_STATUS_AUTO) + stats.auto_increment_value = (ulonglong) 0; + + if (flag & HA_STATUS_ERRKEY) + { + errkey = lastDupKeyID; + my_store_ptr(dup_ref, ref_length, lastDupKeyRRN); + } + + if (flag & HA_STATUS_TIME) + { + if ((flag & HA_STATUS_NO_LOCK) && + ibmdb2i_assume_exclusive_use && + share && + (share->cachedStats.isInited(lastModTime))) + stats.update_time = share->cachedStats.getUpdateTime(); + else + infoRequested |= lastModTime; + } + + if (flag & HA_STATUS_CONST) + { + stats.block_size=4096; + infoRequested |= createTime; + + if (table->s->keys) + { + infoRequested |= rowsPerKey; + rowKeySpcLen = (table->s->keys) * MAX_DB2_KEY_PARTS * sizeof(uint64); + rowKeySpcPtr.alloc(rowKeySpcLen); + memset(rowKeySpcPtr, 0, rowKeySpcLen); // Clear the allocated space + } + } + + if (flag & HA_STATUS_VARIABLE) + { + if ((flag & HA_STATUS_NO_LOCK) && + (command != SQLCOM_SHOW_TABLE_STATUS) && + ibmdb2i_assume_exclusive_use && + share && + (share->cachedStats.isInited(rowCount | deletedRowCount | meanRowLen | ioCount)) && + (share->cachedStats.getRowCount() >= 2)) + { + stats.records = share->cachedStats.getRowCount(); + stats.deleted = share->cachedStats.getDelRowCount(); + stats.mean_rec_length = share->cachedStats.getMeanLength(); + stats.data_file_length = share->cachedStats.getAugmentedDataLength(); + } + else + { + infoRequested |= rowCount | deletedRowCount | meanRowLen; + if (command == SQLCOM_SHOW_TABLE_STATUS) + infoRequested |= objLength; + else + infoRequested |= ioCount; + } + } + + int rc = 0; + + if (infoRequested) + { + DBUG_PRINT("ha_ibmdb2i::info",("Retrieving fresh stats %d", flag)); + + initBridge(thd); + rc = bridge()->retrieveTableInfo((dataHandle ? dataHandle : db2Table->dataFile()->getMasterDefnHandle()), + infoRequested, + stats, + rowKeySpcPtr); + + if (!rc) + { + if ((flag & HA_STATUS_VARIABLE) && + (command != SQLCOM_SHOW_TABLE_STATUS)) + stats.data_file_length = stats.data_file_length * IO_SIZE; + + if ((ibmdb2i_assume_exclusive_use) && + (share) && + (command != SQLCOM_SHOW_TABLE_STATUS)) + { + if (flag & HA_STATUS_VARIABLE) + { + share->cachedStats.cacheRowCount(stats.records); + share->cachedStats.cacheDelRowCount(stats.deleted); + share->cachedStats.cacheMeanLength(stats.mean_rec_length); + share->cachedStats.cacheAugmentedDataLength(stats.data_file_length); + } + + if (flag & HA_STATUS_TIME) + { + share->cachedStats.cacheUpdateTime(stats.update_time); + } + } + + if (flag & HA_STATUS_CONST) + { + ulong i; // Loop counter for indexes + ulong j; // Loop counter for key parts + RowKey* rowKeyPtr; // Pointer to 'number of unique rows' array for this index + + rowKeyPtr = (RowKey_t*)(void*)rowKeySpcPtr; // Address first array of DB2 row counts + for (i = 0; i < table->s->keys; i++) // Do for each index, including primary + { + for (j = 0; j < table->key_info[i].key_parts; j++) + { + table->key_info[i].rec_per_key[j]= rowKeyPtr->RowKeyArray[j]; + } + rowKeyPtr = rowKeyPtr + 1; // Address next array of DB2 row counts + } + } + } + else if (rc == HA_ERR_LOCK_WAIT_TIMEOUT && share) + { + // If we couldn't retrieve the info because the object was locked, + // we'll do our best by returning the most recently cached data. + if ((infoRequested & rowCount) && + share->cachedStats.isInited(rowCount)) + stats.records = share->cachedStats.getRowCount(); + if ((infoRequested & deletedRowCount) && + share->cachedStats.isInited(deletedRowCount)) + stats.deleted = share->cachedStats.getDelRowCount(); + if ((infoRequested & meanRowLen) && + share->cachedStats.isInited(meanRowLen)) + stats.mean_rec_length = share->cachedStats.getMeanLength(); + if ((infoRequested & lastModTime) && + share->cachedStats.isInited(lastModTime)) + stats.update_time = share->cachedStats.getUpdateTime(); + + rc = 0; + } + } + + DBUG_RETURN(rc); +} + + +ha_rows ha_ibmdb2i::records() +{ + DBUG_ENTER("ha_ibmdb2i::records"); + int rc; + rc = bridge()->retrieveTableInfo((dataHandle ? dataHandle : db2Table->dataFile()->getMasterDefnHandle()), + rowCount, + stats); + + if (unlikely(rc)) + { + if (rc == HA_ERR_LOCK_WAIT_TIMEOUT && + share && + (share->cachedStats.isInited(rowCount))) + DBUG_RETURN(share->cachedStats.getRowCount()); + else + DBUG_RETURN(HA_POS_ERROR); + } + else if (share) + { + share->cachedStats.cacheRowCount(stats.records); + } + + DBUG_RETURN(stats.records); +} + + +int ha_ibmdb2i::extra(enum ha_extra_function operation) +{ + DBUG_ENTER("ha_ibmdb2i::extra"); + + switch(operation) + { + // Can these first five flags be replaced by attending to HA_EXTRA_WRITE_CACHE? + case HA_EXTRA_NO_IGNORE_DUP_KEY: + case HA_EXTRA_WRITE_CANNOT_REPLACE: + { + returnDupKeysImmediately = false; + onDupUpdate = false; + } + break; + case HA_EXTRA_INSERT_WITH_UPDATE: + { + returnDupKeysImmediately = true; + onDupUpdate = true; + } + break; + case HA_EXTRA_IGNORE_DUP_KEY: + case HA_EXTRA_WRITE_CAN_REPLACE: + returnDupKeysImmediately = true; + break; + case HA_EXTRA_FLUSH_CACHE: + if (outstanding_start_bulk_insert) + finishBulkInsert(); + break; + } + + + DBUG_RETURN(0); +} + +/** + @brief + The DB2 storage engine will ignore a MySQL generated value and will generate + a new value in SLIC. We arbitrarily set first_value to 1, and set the + interval to infinity for better performance on multi-row inserts. +*/ +void ha_ibmdb2i::get_auto_increment(ulonglong offset, ulonglong increment, + ulonglong nb_desired_values, + ulonglong *first_value, + ulonglong *nb_reserved_values) +{ + DBUG_ENTER("ha_ibmdb2i::get_auto_increment"); + *first_value= 1; + *nb_reserved_values= ULONGLONG_MAX; +} + + + +void ha_ibmdb2i::update_create_info(HA_CREATE_INFO *create_info) +{ + DBUG_ENTER("ha_ibmdb2i::update_create_info"); + + if ((!(create_info->used_fields & HA_CREATE_USED_AUTO)) && + (table->found_next_number_field != NULL)) + { + initBridge(); + + create_info->auto_increment_value= 1; + + ha_rows rowCount = records(); + + if (rowCount == 0) + { + create_info->auto_increment_value = db2Table->getStartId(); + DBUG_VOID_RETURN; + } + else if (rowCount == HA_POS_ERROR) + { + DBUG_VOID_RETURN; + } + + getNextIdVal(&create_info->auto_increment_value); + } + DBUG_VOID_RETURN; +} + + +int ha_ibmdb2i::getNextIdVal(ulonglong *value) +{ + DBUG_ENTER("ha_ibmdb2i::getNextIdVal"); + + char queryBuffer[MAX_DB2_COLNAME_LENGTH + MAX_DB2_QUALIFIEDNAME_LENGTH + 64]; + strcpy(queryBuffer, " SELECT CAST(MAX( "); + convertMySQLNameToDB2Name(table->found_next_number_field->field_name, strend(queryBuffer), MAX_DB2_COLNAME_LENGTH+1); + strcat(queryBuffer, ") AS BIGINT) FROM "); + db2Table->getDB2QualifiedName(strend(queryBuffer)); + DBUG_ASSERT(strlen(queryBuffer) < sizeof(queryBuffer)); + + SqlStatementStream sqlStream(queryBuffer); + DBUG_PRINT("ha_ibmdb2i::getNextIdVal", ("Sent to DB2: %s",queryBuffer)); + + int rc = 0; + FILE_HANDLE fileHandle2; + uint32 db2RowDataLen2; + rc = bridge()->prepOpen(sqlStream.getPtrToData(), + &fileHandle2, + &db2RowDataLen2); + if (likely(rc == 0)) + { + IOReadBuffer rowBuffer(1, db2RowDataLen2); + rc = bridge()->read(fileHandle2, + rowBuffer.ptr(), + QMY_READ_ONLY, + QMY_NONE, + QMY_FIRST); + + if (likely(rc == 0)) + { + /* This check is here for the case where the table is not empty, + but the auto_increment starting value has been changed since + the last record was written. */ + + longlong maxIdVal = *(longlong*)(rowBuffer.getRowN(0)); + if ((maxIdVal + 1) > db2Table->getStartId()) + *value = maxIdVal + 1; + else + *value = db2Table->getStartId(); + } + + bridge()->deallocateFile(fileHandle2); + } + DBUG_RETURN(rc); +} + + +/* + Updates index cardinalities. +*/ +int ha_ibmdb2i::analyze(THD* thd, HA_CHECK_OPT *check_opt) +{ + DBUG_ENTER("ha_ibmdb2i::analyze"); + info(HA_STATUS_TIME | HA_STATUS_CONST | HA_STATUS_VARIABLE); + DBUG_RETURN(0); +} + +int ha_ibmdb2i::optimize(THD* thd, HA_CHECK_OPT *check_opt) +{ + DBUG_ENTER("ha_ibmdb2i::optimize"); + + initBridge(thd); + + if (unlikely(records() == 0)) + DBUG_RETURN(0); // DB2 doesn't like to reorganize a table with no data. + + quiesceAllFileHandles(); + + int32 rc = bridge()->optimizeTable(db2Table->dataFile()->getMasterDefnHandle()); + info(HA_STATUS_TIME | HA_STATUS_CONST | HA_STATUS_VARIABLE); + + DBUG_RETURN(rc); +} + + +/** + @brief + Determines if an ALTER TABLE is allowed to switch the storage engine + for this table. If the table has a foreign key or is referenced by a + foreign key, then it cannot be switched. +*/ +bool ha_ibmdb2i::can_switch_engines(void) +/*=================================*/ +{ + DBUG_ENTER("ha_ibmdb2i::can_switch_engines"); + + int rc = 0; + FILE_HANDLE queryFile = 0; + uint32 resultRowLen; + uint count = 0; + bool can_switch = FALSE; // 1 if changing storage engine is allowed + + const char* libName = db2Table->getDB2LibName(db2i_table::ASCII_SQL); + const char* fileName = db2Table->getDB2TableName(db2i_table::ASCII_SQL); + + String query(256); + query.append(STRING_WITH_LEN(" SELECT COUNT(*) FROM SYSIBM.SQLFOREIGNKEYS WHERE ((PKTABLE_SCHEM = '")); + query.append(libName+1, strlen(libName)-2); // Remove quotes from parent schema name + query.append(STRING_WITH_LEN("' AND PKTABLE_NAME = '")); + query.append(fileName+1,strlen(fileName)-2); // Remove quotes from file name + query.append(STRING_WITH_LEN("') OR (FKTABLE_SCHEM = '")); + query.append(libName+1,strlen(libName)-2); // Remove quotes from child schema + query.append(STRING_WITH_LEN("' AND FKTABLE_NAME = '")); + query.append(fileName+1,strlen(fileName)-2); // Remove quotes from child name + query.append(STRING_WITH_LEN("'))")); + + SqlStatementStream sqlStream(query); + + rc = bridge()->prepOpen(sqlStream.getPtrToData(), + &queryFile, + &resultRowLen); + if (rc == 0) + { + IOReadBuffer rowBuffer(1, resultRowLen); + + rc = bridge()->read(queryFile, + rowBuffer.ptr(), + QMY_READ_ONLY, + QMY_NONE, + QMY_FIRST); + if (!rc) + { + count = *(uint*)(rowBuffer.getRowN(0)); + if (count == 0) + can_switch = TRUE; + } + + bridge()->deallocateFile(queryFile); + } + DBUG_RETURN(can_switch); +} + + + +bool ha_ibmdb2i::check_if_incompatible_data(HA_CREATE_INFO *info, + uint table_changes) +{ + DBUG_ENTER("ha_ibmdb2i::check_if_incompatible_data"); + uint i; + /* Check that auto_increment value and field definitions were + not changed. */ + if ((info->used_fields & HA_CREATE_USED_AUTO && + info->auto_increment_value != 0) || + table_changes != IS_EQUAL_YES) + DBUG_RETURN(COMPATIBLE_DATA_NO); + /* Check if any fields were renamed. */ + for (i= 0; i < table->s->fields; i++) + { + Field *field= table->field[i]; + if (field->flags & FIELD_IS_RENAMED) + { + DBUG_PRINT("info", ("Field has been renamed, copy table")); + DBUG_RETURN(COMPATIBLE_DATA_NO); + } + } + DBUG_RETURN(COMPATIBLE_DATA_YES); +} + +int ha_ibmdb2i::reset_auto_increment(ulonglong value) + { + DBUG_ENTER("ha_ibmdb2i::reset_auto_increment"); + + int rc = 0; + + quiesceAllFileHandles(); + + const char* libName = db2Table->getDB2LibName(db2i_table::ASCII_SQL); + const char* fileName = db2Table->getDB2TableName(db2i_table::ASCII_SQL); + + String query(512); + query.append(STRING_WITH_LEN(" ALTER TABLE ")); + query.append(libName); + query.append('.'); + query.append(fileName); + query.append(STRING_WITH_LEN(" ALTER COLUMN ")); + char colName[MAX_DB2_COLNAME_LENGTH+1]; + convertMySQLNameToDB2Name(table->found_next_number_field->field_name, colName, sizeof(colName)); + query.append(colName); + + char restart_value[22]; + CHARSET_INFO *cs= &my_charset_bin; + uint len = (uint)(cs->cset->longlong10_to_str)(cs,restart_value,sizeof(restart_value), 10, value); + restart_value[len] = 0; + + query.append(STRING_WITH_LEN(" RESTART WITH ")); + query.append(restart_value); + + SqlStatementStream sqlStream(query); + DBUG_PRINT("ha_ibmdb2i::reset_auto_increment", ("Sent to DB2: %s",query.c_ptr())); + + rc = db2i_ileBridge::getBridgeForThread()->execSQL(sqlStream.getPtrToData(), + sqlStream.getStatementCount(), + getCommitLevel(), + FALSE, + FALSE, + FALSE, + dataHandle); + if (rc == 0) + db2Table->updateStartId(value); + + DBUG_RETURN(rc); +} + + +/** + @brief + This function receives an error code that was previously set by the handler. + It returns to MySQL the error string associated with that error. +*/ +bool ha_ibmdb2i::get_error_message(int error, String *buf) +{ + DBUG_ENTER("ha_ibmdb2i::get_error_message"); + if (error >= DB2I_FIRST_ERR && error <= DB2I_LAST_ERR) + { + db2i_ileBridge* bridge = db2i_ileBridge::getBridgeForThread(ha_thd()); + char* errMsg = bridge->getErrorStorage(); + buf->copy(errMsg, strlen(errMsg),system_charset_info); + bridge->freeErrorStorage(); + } + DBUG_RETURN(FALSE); +} + + +int ha_ibmdb2i::delete_all_rows() +{ + DBUG_ENTER("ha_ibmdb2i::delete_all_rows"); + int rc = 0; + char queryBuffer[MAX_DB2_QUALIFIEDNAME_LENGTH + 64]; + strcpy(queryBuffer, " DELETE FROM "); + db2Table->getDB2QualifiedName(strend(queryBuffer)); + DBUG_ASSERT(strlen(queryBuffer) < sizeof(queryBuffer)); + + SqlStatementStream sqlStream(queryBuffer); + DBUG_PRINT("ha_ibmdb2i::delete_all_rows", ("Sent to DB2: %s",queryBuffer)); + rc = bridge()->execSQL(sqlStream.getPtrToData(), + sqlStream.getStatementCount(), + getCommitLevel(), + false, + false, + true, + dataHandle); + + /* If this method was called on behalf of a TRUNCATE TABLE statement, and if */ + /* the table has an auto_increment field, then reset the starting value for */ + /* the auto_increment field to 1. + */ + if (rc == 0 && thd_sql_command(ha_thd()) == SQLCOM_TRUNCATE && + table->found_next_number_field ) + rc = reset_auto_increment(1); + + invalidateCachedStats(); + + DBUG_RETURN(rc); +} + + +int ha_ibmdb2i::external_lock(THD *thd, int lock_type) +{ + int rc = 0; + + DBUG_ENTER("ha_ibmdb2i::external_lock"); + DBUG_PRINT("ha_ibmdb2i::external_lock",("Lock type: %d", lock_type)); + + if (lock_type == F_RDLCK) + accessIntent = QMY_READ_ONLY; + else if (lock_type == F_WRLCK) + accessIntent = QMY_UPDATABLE; + + initBridge(thd); + int command = thd_sql_command(thd); + + if (!THDVAR(thd,transaction_unsafe)) + { + if (lock_type != F_UNLCK) + { + if (autoCommitIsOn(thd) == QMY_YES) + { + trans_register_ha(thd, FALSE, ibmdb2i_hton); + } + else + { + trans_register_ha(thd, TRUE, ibmdb2i_hton); + if (likely(command != SQLCOM_CREATE_TABLE)) + { + trans_register_ha(thd, FALSE, ibmdb2i_hton); + bridge()->beginStmtTx(); + } + } + } + } + + if (command == SQLCOM_LOCK_TABLES || + command == SQLCOM_ALTER_TABLE || + command == SQLCOM_UNLOCK_TABLES || + (accessIntent == QMY_UPDATABLE && + (command == SQLCOM_UPDATE || + command == SQLCOM_UPDATE_MULTI || + command == SQLCOM_DELETE || + command == SQLCOM_DELETE_MULTI || + command == SQLCOM_REPLACE || + command == SQLCOM_REPLACE_SELECT) && + getCommitLevel(thd) == QMY_NONE)) + { + char action; + char type; + if (lock_type == F_UNLCK) + { + action = QMY_UNLOCK; + type = accessIntent == QMY_READ_ONLY ? QMY_LSRD : QMY_LENR; + } + else + { + action = QMY_LOCK; + type = lock_type == F_RDLCK ? QMY_LSRD : QMY_LENR; + } + + DBUG_PRINT("ha_ibmdb2i::external_lock",("%socking table", action==QMY_LOCK ? "L" : "Unl")); + + if (!dataHandle) + rc = db2Table->dataFile()->allocateNewInstance(&dataHandle, curConnection); + + rc = bridge()->lockObj(dataHandle, + 0, + action, + type, + (command == SQLCOM_LOCK_TABLES ? QMY_NO : QMY_YES)); + + } + + + DBUG_RETURN(rc); +} + + +THR_LOCK_DATA **ha_ibmdb2i::store_lock(THD *thd, + THR_LOCK_DATA **to, + enum thr_lock_type lock_type) +{ + if (lock_type != TL_IGNORE && lock.type == TL_UNLOCK) + { + if ((lock_type >= TL_WRITE_CONCURRENT_INSERT && + lock_type <= TL_WRITE) && !(thd->in_lock_tables && thd_sql_command(thd) == SQLCOM_LOCK_TABLES)) + lock_type= TL_WRITE_ALLOW_WRITE; + lock.type=lock_type; + } + *to++= &lock; + return to; +} + + +int ha_ibmdb2i::delete_table(const char *name) +{ + DBUG_ENTER("ha_ibmdb2i::delete_table"); + THD* thd = ha_thd(); + db2i_ileBridge* bridge = db2i_ileBridge::getBridgeForThread(thd); + + char db2Name[MAX_DB2_QUALIFIEDNAME_LENGTH]; + db2i_table::getDB2QualifiedNameFromPath(name, db2Name); + + String query(128); + query.append(STRING_WITH_LEN(" DROP TABLE ")); + query.append(db2Name); + + if (thd_sql_command(thd) == SQLCOM_DROP_TABLE && + thd->lex->drop_mode == DROP_RESTRICT) + query.append(STRING_WITH_LEN(" RESTRICT ")); + DBUG_PRINT("ha_ibmdb2i::delete_table", ("Sent to DB2: %s",query.c_ptr())); + + SqlStatementStream sqlStream(query); + + db2i_table::getDB2LibNameFromPath(name, db2Name); + bool isTemporary = (strcmp(db2Name, DB2I_TEMP_TABLE_SCHEMA) == 0 ? TRUE : FALSE); + + int rc = bridge->execSQL(sqlStream.getPtrToData(), + sqlStream.getStatementCount(), + (isTemporary ? QMY_NONE : getCommitLevel(thd)), + FALSE, + FALSE, + isTemporary); + + if (rc == HA_ERR_NO_SUCH_TABLE) + { + warning(thd, DB2I_ERR_TABLE_NOT_FOUND, name); + rc = 0; + } + + if (rc == 0) + { + db2i_table::deleteAssocFiles(name); + FILE_HANDLE savedHandle = bridge->findAndRemovePreservedHandle(name); + if (savedHandle) + bridge->deallocateFile(savedHandle, TRUE); + } + + my_errno = rc; + DBUG_RETURN(rc); +} + + +int ha_ibmdb2i::rename_table(const char * from, const char * to) +{ + DBUG_ENTER("ha_ibmdb2i::rename_table "); + + char db2FromFileName[MAX_DB2_FILENAME_LENGTH + 1]; + char db2ToFileName[MAX_DB2_FILENAME_LENGTH+1]; + char db2FromLibName[MAX_DB2_SCHEMANAME_LENGTH+1]; + char db2ToLibName[MAX_DB2_SCHEMANAME_LENGTH+1]; + + db2i_table::getDB2LibNameFromPath(from, db2FromLibName); + db2i_table::getDB2LibNameFromPath(to, db2ToLibName); + + if (strcmp(db2FromLibName, db2ToLibName) != 0 ) + { + getErrTxt(DB2I_ERR_RENAME_MOVE,from,to); + DBUG_RETURN(DB2I_ERR_RENAME_MOVE); + } + + db2i_table::getDB2FileNameFromPath(from, db2FromFileName, db2i_table::ASCII_NATIVE); + db2i_table::getDB2FileNameFromPath(to, db2ToFileName); + + char escapedFromFileName[2 * MAX_DB2_FILENAME_LENGTH + 1]; + + uint o = 0; + uint i = 1; + do + { + escapedFromFileName[o++] = db2FromFileName[i]; + if (db2FromFileName[i] == '+') + escapedFromFileName[o++] = '+'; + } while (db2FromFileName[++i]); + escapedFromFileName[o-1] = 0; + + + int rc = 0; + + char queryBuffer[sizeof(db2FromLibName) + 2 * sizeof(db2FromFileName) + 256]; + SafeString selectQuery(queryBuffer, sizeof(queryBuffer)); + selectQuery.strncat(STRING_WITH_LEN("SELECT CAST(INDEX_NAME AS VARCHAR(128) CCSID 1208) FROM QSYS2.SYSINDEXES WHERE INDEX_NAME LIKE '%+_+_+_%")); + selectQuery.strcat(escapedFromFileName); + selectQuery.strncat(STRING_WITH_LEN("' ESCAPE '+' AND TABLE_NAME='")); + selectQuery.strncat(db2FromFileName+1, strlen(db2FromFileName)-2); + selectQuery.strncat(STRING_WITH_LEN("' AND TABLE_SCHEMA='")); + selectQuery.strncat(db2FromLibName+1, strlen(db2FromLibName)-2); + selectQuery.strcat('\''); + DBUG_ASSERT(!selectQuery.overflowed()); + + SqlStatementStream indexQuery(selectQuery.ptr()); + + FILE_HANDLE queryFile = 0; + uint32 resultRowLen; + + initBridge(); + rc = bridge()->prepOpen(indexQuery.getPtrToData(), + &queryFile, + &resultRowLen); + + if (unlikely(rc)) + DBUG_RETURN(rc); + + IOReadBuffer rowBuffer(1, resultRowLen); + + int tableNameLen = strlen(db2FromFileName) - 2; + + SqlStatementStream renameQuery(64); + String query; + while (rc == 0) + { + query.length(0); + + rc = bridge()->read(queryFile, + rowBuffer.ptr(), + QMY_READ_ONLY, + QMY_NONE, + QMY_NEXT); + + if (!rc) + { + const char* rowData = rowBuffer.getRowN(0); + char indexFileName[MAX_DB2_FILENAME_LENGTH]; + memset(indexFileName, 0, sizeof(indexFileName)); + + uint16 fileNameLen = *(uint16*)(rowData); + strncpy(indexFileName, rowData + sizeof(uint16), fileNameLen); + + int bytesToRetain = fileNameLen - tableNameLen; + if (bytesToRetain <= 0) + /* We can't handle index names in which the MySQL index name and + the table name together are longer than the max index name. */ + { + getErrTxt(DB2I_ERR_INVALID_NAME,"index","*generated*"); + DBUG_RETURN(DB2I_ERR_INVALID_NAME); + } + char indexName[MAX_DB2_FILENAME_LENGTH]; + memset(indexName, 0, sizeof(indexName)); + + strncpy(indexName, + indexFileName, + bytesToRetain); + + char db2IndexName[MAX_DB2_FILENAME_LENGTH+1]; + + convertMySQLNameToDB2Name(indexFileName, db2IndexName, sizeof(db2IndexName)); + + query.append(STRING_WITH_LEN("RENAME INDEX ")); + query.append(db2FromLibName); + query.append('.'); + query.append(db2IndexName); + query.append(STRING_WITH_LEN(" TO ")); + if (db2i_table::appendQualifiedIndexFileName(indexName, db2ToFileName, query, db2i_table::ASCII_SQL, typeNone) == -1) + { + getErrTxt(DB2I_ERR_INVALID_NAME,"index","*generated*"); + DBUG_RETURN(DB2I_ERR_INVALID_NAME ); + } + renameQuery.addStatement(query); + DBUG_PRINT("ha_ibmdb2i::rename_table", ("Sent to DB2: %s",query.c_ptr_safe())); + } + } + + + if (queryFile) + bridge()->deallocateFile(queryFile); + + if (rc != HA_ERR_END_OF_FILE) + DBUG_RETURN(rc); + + char db2Name[MAX_DB2_QUALIFIEDNAME_LENGTH]; + + /* Rename the table */ + query.length(0); + query.append(STRING_WITH_LEN(" RENAME TABLE ")); + db2i_table::getDB2QualifiedNameFromPath(from, db2Name); + query.append(db2Name); + query.append(STRING_WITH_LEN(" TO ")); + query.append(db2ToFileName); + DBUG_PRINT("ha_ibmdb2i::rename_table", ("Sent to DB2: %s",query.c_ptr_safe())); + renameQuery.addStatement(query); + rc = bridge()->execSQL(renameQuery.getPtrToData(), + renameQuery.getStatementCount(), + getCommitLevel()); + + if (!rc) + db2i_table::renameAssocFiles(from, to); + + DBUG_RETURN(rc); +} + + +int ha_ibmdb2i::create(const char *name, TABLE *table_arg, + HA_CREATE_INFO *create_info) +{ + DBUG_ENTER("ha_ibmdb2i::create"); + + int rc; + char fileSortSequence[11] = "*HEX"; + char fileSortSequenceLibrary[11] = ""; + char fileSortSequenceType = ' '; + char libName[MAX_DB2_SCHEMANAME_LENGTH+1]; + char fileName[MAX_DB2_FILENAME_LENGTH+1]; + char colName[MAX_DB2_COLNAME_LENGTH+1]; + bool isTemporary; + ulong auto_inc_value; + + db2i_table::getDB2LibNameFromPath(name, libName); + db2i_table::getDB2FileNameFromPath(name, fileName); + + if (osVersion.v < 6) + { + if (strlen(libName) > MAX_DB2_V5R4_LIBNAME_LENGTH) + { + getErrTxt(DB2I_ERR_TOO_LONG_SCHEMA,libName, MAX_DB2_V5R4_LIBNAME_LENGTH); + DBUG_RETURN(DB2I_ERR_TOO_LONG_SCHEMA); + } + } + else if (strlen(libName) > MAX_DB2_V6R1_LIBNAME_LENGTH) + { + getErrTxt(DB2I_ERR_TOO_LONG_SCHEMA,libName, MAX_DB2_V6R1_LIBNAME_LENGTH); + DBUG_RETURN(DB2I_ERR_TOO_LONG_SCHEMA); + } + + String query(256); + + if (strcmp(libName, DB2I_TEMP_TABLE_SCHEMA)) + { + query.append(STRING_WITH_LEN("CREATE TABLE ")); + query.append(libName); + query.append('.'); + query.append(fileName); + isTemporary = FALSE; + } + else + { + query.append(STRING_WITH_LEN("DECLARE GLOBAL TEMPORARY TABLE ")); + query.append(fileName); + isTemporary = TRUE; + } + query.append(STRING_WITH_LEN(" (")); + + THD* thd = ha_thd(); + enum_TimeFormat timeFormat = (THDVAR(thd, create_time_columns_as_TOD) ? TIME_OF_DAY : DURATION); + enum_BlobMapping blobMapping = (enum_BlobMapping)(THDVAR(thd, map_blob_to_varchar)); + + Field **field; + for (field= table_arg->field; *field; field++) + { + if ( field != table_arg->field ) // Not the first one + query.append(STRING_WITH_LEN(" , ")); + + if (!convertMySQLNameToDB2Name((*field)->field_name, colName, sizeof(colName))) + { + getErrTxt(DB2I_ERR_INVALID_NAME,"field",(*field)->field_name); + DBUG_RETURN(DB2I_ERR_INVALID_NAME ); + } + + query.append(colName); + query.append(' '); + + if (rc = getFieldTypeMapping(*field, query, timeFormat, blobMapping)) + DBUG_RETURN(rc); + + if ( (*field)->flags & NOT_NULL_FLAG ) + { + query.append(STRING_WITH_LEN(" NOT NULL ")); + } + if ( (*field)->flags & AUTO_INCREMENT_FLAG ) + { +#ifdef WITH_PARTITION_STORAGE_ENGINE + if (table_arg->part_info) + { + getErrTxt(DB2I_ERR_PART_AUTOINC); + DBUG_RETURN(DB2I_ERR_PART_AUTOINC); + } +#endif + query.append(STRING_WITH_LEN(" GENERATED BY DEFAULT AS IDENTITY ") ); + if (create_info->auto_increment_value != 0) + { + /* Query was ALTER TABLE...AUTO_INCREMENT = x; or + CREATE TABLE ...AUTO_INCREMENT = x; Set the starting + value for the auto_increment column. */ + char stringValue[22]; + CHARSET_INFO *cs= &my_charset_bin; + uint len = (uint)(cs->cset->longlong10_to_str)(cs,stringValue,sizeof(stringValue), 10, create_info->auto_increment_value); + stringValue[len] = 0; + query.append(STRING_WITH_LEN(" (START WITH ")); + query.append(stringValue); + + uint64 maxValue=maxValueForField(*field); + + if (maxValue) + { + len = (uint)(cs->cset->longlong10_to_str)(cs,stringValue,sizeof(stringValue), 10, maxValue); + stringValue[len] = 0; + query.append(STRING_WITH_LEN(" MAXVALUE ")); + query.append(stringValue); + } + + query.append(STRING_WITH_LEN(") ")); + } + + } + } + + String primaryKeyQuery; + primaryKeyQuery.length(0); + if (table_arg->s->primary_key != MAX_KEY && !isTemporary) + { + KEY& curKey = table_arg->key_info[table_arg->s->primary_key]; + primaryKeyQuery.append(STRING_WITH_LEN(" PRIMARY KEY( ")); + for (int j = 0; j < curKey.key_parts; ++j) + { + if (j != 0) + { + primaryKeyQuery.append( STRING_WITH_LEN(" , ") ); + } + Field* field = curKey.key_part[j].field; + convertMySQLNameToDB2Name(field->field_name, colName, sizeof(colName)); + primaryKeyQuery.append(colName); + rc = updateAssociatedSortSequence(field, + &fileSortSequenceType, + fileSortSequence, + fileSortSequenceLibrary); + if (rc) DBUG_RETURN (rc); + } + primaryKeyQuery.append(STRING_WITH_LEN(" ) ")); + } + + bool needAlterForPrimaryKey = FALSE; + if ((fileSortSequence[0] != '*') && (fileSortSequence[0] != 'Q')) // An ICU sort sequence + { + needAlterForPrimaryKey = TRUE; + } + else + { + if (primaryKeyQuery.length() > 0) + { + query.append(STRING_WITH_LEN(" , ")); + query.append(primaryKeyQuery); + } + } + + rc = buildDB2ConstraintString(thd->lex, + query, + name, + table_arg->field, + &fileSortSequenceType, + fileSortSequence, + fileSortSequenceLibrary); + if (rc) DBUG_RETURN (rc); + + query.append(STRING_WITH_LEN(" ) ")); + + if (isTemporary) + query.append(STRING_WITH_LEN(" ON COMMIT PRESERVE ROWS ")); + + DBUG_PRINT("ha_ibmdb2i::create", ("Sent to DB2: %s",query.c_ptr())); + SqlStatementStream sqlStream(query.length()); + sqlStream.addStatement(query,fileSortSequence,fileSortSequenceLibrary); + + + + if (needAlterForPrimaryKey == TRUE && !isTemporary) + { + rc = buildCreateIndexStatement(sqlStream, + table_arg->key_info[table_arg->s->primary_key], + true, + libName, + fileName); + if (rc) DBUG_RETURN (rc); + } + + uint i = 0; + + for (uint i = 0; i < table_arg->s->keys; ++i) + { + if (i != table_arg->s->primary_key || isTemporary) + { + rc = buildCreateIndexStatement(sqlStream, + table_arg->key_info[i], + false, + libName, + fileName); + if (rc) DBUG_RETURN (rc); + } + } + + bool noCommit = isTemporary || ((!autoCommitIsOn(thd)) && (thd_sql_command(thd) == SQLCOM_ALTER_TABLE)); + + initBridge(); + + if (THDVAR(thd, discovery_mode) == 1) + bridge()->expectErrors(QMY_ERR_TABLE_EXISTS); + + rc = bridge()->execSQL(sqlStream.getPtrToData(), + sqlStream.getStatementCount(), + (isTemporary ? QMY_NONE : getCommitLevel(thd)), + TRUE, + FALSE, + noCommit ); + + if (unlikely(rc == QMY_ERR_MSGID) && + memcmp(bridge()->getErrorMsgID(), DB2I_SQL0350, 7) == 0) + { + my_error(ER_BLOB_USED_AS_KEY, MYF(0), "*unknown*"); + rc = ER_BLOB_USED_AS_KEY; + } + else if (unlikely(rc == QMY_ERR_TABLE_EXISTS) && + THDVAR(thd, discovery_mode) == 1) + { + db2i_table* temp = new db2i_table(table_arg->s, name); + int32 rc = temp->fastInitForCreate(name); + delete temp; + + if (!rc) + warning(thd, DB2I_ERR_WARN_CREATE_DISCOVER); + + DBUG_RETURN(rc); + } + + if (!rc && !isTemporary) + { + db2i_table* temp = new db2i_table(table_arg->s, name); + int32 rc = temp->fastInitForCreate(name); + delete temp; + if (rc) + delete_table(name); + } + + DBUG_RETURN(rc); +} + + +/** + @brief + Add an index on-line to a table. This method is called on behalf of + a CREATE INDEX or ALTER TABLE statement. + It is implemented via a composed DDL statement passed to DB2. +*/ +int ha_ibmdb2i::add_index(TABLE *table_arg, + KEY *key_info, + uint num_of_keys) +{ + DBUG_ENTER("ha_ibmdb2i::add_index"); + + int rc; + SqlStatementStream sqlStream(256); + const char* libName = db2Table->getDB2LibName(db2i_table::ASCII_SQL); + const char* fileName = db2Table->getDB2TableName(db2i_table::ASCII_SQL); + + quiesceAllFileHandles(); + + uint primaryKey = MAX_KEY; + if (table_arg->s->primary_key >= MAX_KEY && !db2Table->isTemporary()) + { + for (int i = 0; i < num_of_keys; ++i) + { + if (strcmp(key_info[i].name, "PRIMARY") == 0) + { + primaryKey = i; + break; + } + else if (primaryKey == MAX_KEY && + key_info[i].flags & HA_NOSAME) + { + primaryKey = i; + for (int j=0 ; j < key_info[i].key_parts ;j++) + { + uint fieldnr= key_info[i].key_part[j].fieldnr; + if (table_arg->s->field[fieldnr]->null_ptr || + table_arg->s->field[fieldnr]->key_length() != + key_info[i].key_part[j].length) + { + primaryKey = MAX_KEY; + break; + } + } + } + } + } + + + for (int i = 0; i < num_of_keys; ++i) + { + KEY& curKey= key_info[i]; + rc = buildCreateIndexStatement(sqlStream, + curKey, + (i == primaryKey), + libName, + fileName); + if (rc) DBUG_RETURN (rc); + } + + rc = bridge()->execSQL(sqlStream.getPtrToData(), + sqlStream.getStatementCount(), + getCommitLevel(), + FALSE, + FALSE, + FALSE, + dataHandle); + + /* Handle the case where a unique index is being created but an error occurs + because the file contains duplicate key values. */ + if (rc == ER_DUP_ENTRY) + print_keydup_error(MAX_KEY,ER(ER_DUP_ENTRY_WITH_KEY_NAME)); + + DBUG_RETURN(rc); +} + +/** + @brief + Drop an index on-line from a table. This method is called on behalf of + a DROP INDEX or ALTER TABLE statement. + It is implemented via a composed DDL statement passed to DB2. +*/ +int ha_ibmdb2i::prepare_drop_index(TABLE *table_arg, + uint *key_num, uint num_of_keys) +{ + DBUG_ENTER("ha_ibmdb2i::prepare_drop_index"); + int rc; + int i = 0; + String query(64); + SqlStatementStream sqlStream(64 * num_of_keys); + SqlStatementStream shadowStream(64 * num_of_keys); + + quiesceAllFileHandles(); + + const char* libName = db2Table->getDB2LibName(db2i_table::ASCII_SQL); + const char* fileName = db2Table->getDB2TableName(db2i_table::ASCII_SQL); + + while (i < num_of_keys) + { + query.length(0); + DBUG_PRINT("info", ("ha_ibmdb2i::prepare_drop_index %u", key_num[i])); + KEY& curKey= table_arg->key_info[key_num[i]]; + if (key_num[i] == table->s->primary_key && !db2Table->isTemporary()) + { + query.append(STRING_WITH_LEN("ALTER TABLE ")); + query.append(libName); + query.append(STRING_WITH_LEN(".")); + query.append(fileName); + query.append(STRING_WITH_LEN(" DROP PRIMARY KEY")); + } + else + { + query.append(STRING_WITH_LEN("DROP INDEX ")); + query.append(libName); + query.append(STRING_WITH_LEN(".")); + db2i_table::appendQualifiedIndexFileName(curKey.name, fileName, query); + } + DBUG_PRINT("ha_ibmdb2i::prepare_drop_index", ("Sent to DB2: %s",query.c_ptr_safe())); + sqlStream.addStatement(query); + + query.length(0); + query.append(STRING_WITH_LEN("DROP INDEX ")); + query.append(libName); + query.append(STRING_WITH_LEN(".")); + db2i_table::appendQualifiedIndexFileName(curKey.name, fileName, query, db2i_table::ASCII_SQL, typeHex); + + DBUG_PRINT("ha_ibmdb2i::prepare_drop_index", ("Sent to DB2: %s",query.c_ptr_safe())); + shadowStream.addStatement(query); + + ++i; + } + + rc = bridge()->execSQL(sqlStream.getPtrToData(), + sqlStream.getStatementCount(), + getCommitLevel(), + FALSE, + FALSE, + FALSE, + dataHandle); + + if (rc == 0) + bridge()->execSQL(shadowStream.getPtrToData(), + shadowStream.getStatementCount(), + getCommitLevel()); + + DBUG_RETURN(rc); +} + + +void +ha_ibmdb2i::unlock_row() +{ + DBUG_ENTER("ha_ibmdb2i::unlock_row"); + DBUG_VOID_RETURN; +} + +int +ha_ibmdb2i::index_end() +{ + DBUG_ENTER("ha_ibmdb2i::index_end"); + warnIfInvalidData(); + last_index_init_rc = 0; + if (likely(activeReadBuf)) + activeReadBuf->endRead(); + if (likely(!last_index_init_rc)) + releaseIndexFile(active_index); + active_index= MAX_KEY; + DBUG_RETURN (0); +} + +int ha_ibmdb2i::doCommit(handlerton *hton, THD *thd, bool all) +{ + if (!THDVAR(thd, transaction_unsafe)) + { + if (all || autoCommitIsOn(thd)) + { + DBUG_PRINT("ha_ibmdb2i::doCommit",("Committing all")); + return (db2i_ileBridge::getBridgeForThread(thd)->commitmentControl(QMY_COMMIT)); + } + else + { + DBUG_PRINT("ha_ibmdb2i::doCommit",("Committing stmt")); + return (db2i_ileBridge::getBridgeForThread(thd)->commitStmtTx()); + } + } + + return (0); +} + + +int ha_ibmdb2i::doRollback(handlerton *hton, THD *thd, bool all) +{ + if (!THDVAR(thd,transaction_unsafe)) + { + if (all || autoCommitIsOn(thd)) + { + DBUG_PRINT("ha_ibmdb2i::doRollback",("Rolling back all")); + return ( db2i_ileBridge::getBridgeForThread(thd)->commitmentControl(QMY_ROLLBACK)); + } + else + { + DBUG_PRINT("ha_ibmdb2i::doRollback",("Rolling back stmt")); + return (db2i_ileBridge::getBridgeForThread(thd)->rollbackStmtTx()); + } + } + return (0); +} + + +void ha_ibmdb2i::start_bulk_insert(ha_rows rows) +{ + DBUG_ENTER("ha_ibmdb2i::start_bulk_insert"); + DBUG_PRINT("ha_ibmdb2i::start_bulk_insert",("Rows hinted %d", rows)); + int rc; + THD* thd = ha_thd(); + int command = thd_sql_command(thd); + + if (db2Table->hasBlobs() || + (command == SQLCOM_REPLACE || command == SQLCOM_REPLACE_SELECT)) + rows = 1; + else if (rows == 0) + rows = DEFAULT_MAX_ROWS_TO_BUFFER; // Shoot the moon + + // If we're doing a multi-row insert, binlogging is active, and the table has an + // auto_increment column, then we'll attempt to lock the file while we perform a 'fast path' blocked + // insert. If we can't get the lock, then we'll do a row-by-row 'slow path' insert instead. The reason is + // because the MI generates the auto_increment (identity value), and if we can't lock the file, + // then we can't predetermine what that value will be for insertion into the MySQL write buffer. + + if ((rows > 1) && // Multi-row insert + (thd->options & OPTION_BIN_LOG) && // Binlogging is on + (table->found_next_number_field)) // Table has an auto_increment column + { + if (!dataHandle) + rc = db2Table->dataFile()->allocateNewInstance(&dataHandle, curConnection); + + rc = bridge()->lockObj(dataHandle, 1, QMY_LOCK, QMY_LEAR, QMY_YES); + if (rc==0) // Got the lock + { + autoIncLockAcquired = TRUE; + got_auto_inc_values = FALSE; + } + else // Didn't get the lock + rows = 1; // No problem, but don't block inserts + } + + if (activeHandle == 0) + { + last_start_bulk_insert_rc = useDataFile(QMY_UPDATABLE); + if (last_start_bulk_insert_rc == 0) + prepWriteBuffer(rows); + } + + if (last_start_bulk_insert_rc == 0) + outstanding_start_bulk_insert = true; + else + { + if (autoIncLockAcquired == TRUE) + { + bridge()->lockObj(dataHandle, 0, QMY_UNLOCK, QMY_LEAR, QMY_YES); + autoIncLockAcquired = FALSE; + } + } + + DBUG_VOID_RETURN; +} + + +int ha_ibmdb2i::end_bulk_insert() +{ + DBUG_ENTER("ha_ibmdb2i::end_bulk_insert"); + int rc = 0; + + if (outstanding_start_bulk_insert) + { + rc = finishBulkInsert(); + } + + my_errno = rc; + + DBUG_RETURN(rc); +} + + +int ha_ibmdb2i::prepReadBuffer(ha_rows rowsToRead) +{ + DBUG_ENTER("ha_ibmdb2i::prepReadBuffer"); + DBUG_ASSERT((accessIntent == QMY_READ_ONLY || accessIntent == QMY_UPDATABLE) && rowsToRead > 0); + + int rc = 0; + + if (lobFieldsRequested()) + { + forceSingleRowRead = true; + rowsToRead = 1; + } + + rowsToRead = min(stats.records+1,min(rowsToRead, DEFAULT_MAX_ROWS_TO_BUFFER)); + + THD* thd = ha_thd(); + + uint bufSize = min((activeFormat->readRowLen * rowsToRead), THDVAR(thd, max_read_buffer_size)); + multiRowReadBuf.allocBuf(activeFormat->readRowLen, bufSize); + activeReadBuf = &multiRowReadBuf; + + if (db2Table->hasBlobs()) + { + if (!blobReadBuffers) + blobReadBuffers = new BlobCollection(db2Table, THDVAR(thd, lob_alloc_size)); + rc = prepareReadBufferForLobs(); + if (rc) DBUG_RETURN(rc); + } + activeReadBuf->update(accessIntent, &releaseRowNeeded, getCommitLevel(thd)); + + DBUG_RETURN(rc); +} + + +void ha_ibmdb2i::prepWriteBuffer(ha_rows rowsToWrite) +{ + DBUG_ENTER("ha_ibmdb2i::prepWriteBuffer"); + DBUG_ASSERT(accessIntent == QMY_UPDATABLE && rowsToWrite > 0); + + rowsToWrite = min(rowsToWrite, DEFAULT_MAX_ROWS_TO_BUFFER); + + uint bufSize = min((activeFormat->writeRowLen * rowsToWrite), THDVAR(ha_thd(), max_write_buffer_size)); + multiRowWriteBuf.allocBuf(activeFormat->writeRowLen, bufSize); + activeWriteBuf = &multiRowWriteBuf; + + if (!blobWriteBuffers && db2Table->hasBlobs()) + { + blobWriteBuffers = new ValidatedPointer[db2Table->getBlobCount()]; + } + DBUG_VOID_RETURN; +} + + +int ha_ibmdb2i::flushWrite(FILE_HANDLE fileHandle, uchar* buf ) +{ + DBUG_ENTER("ha_ibmdb2i::flushWrite"); + int rc; + int64 generatedIdValue = 0; + bool IdValueWasGenerated = FALSE; + char* lastDupKeyNamePtr = NULL; + uint32 lastDupKeyNameLen = 0; + int loopCnt = 0; + bool retry_dup = FALSE; + + while (loopCnt == 0 || retry_dup == TRUE) + { + rc = bridge()->writeRows(fileHandle, + activeWriteBuf->ptr(), + getCommitLevel(), + &generatedIdValue, + &IdValueWasGenerated, + &lastDupKeyRRN, + &lastDupKeyNamePtr, + &lastDupKeyNameLen, + &incrementByValue); + loopCnt++; + retry_dup = FALSE; + invalidateCachedStats(); + if (lastDupKeyNameLen) + { + rrnAssocHandle = fileHandle; + + int command = thd_sql_command(ha_thd()); + + if (command == SQLCOM_REPLACE || + command == SQLCOM_REPLACE_SELECT) + lastDupKeyID = 0; + else + { + lastDupKeyID = getKeyFromName(lastDupKeyNamePtr, lastDupKeyNameLen); + + if (likely(lastDupKeyID != MAX_KEY)) + { + uint16 failedRow = activeWriteBuf->rowsWritten()+1; + + if (buf && (failedRow != activeWriteBuf->rowCount())) + { + const char* badRow = activeWriteBuf->getRowN(failedRow-1); + bool savedReadAllColumns = readAllColumns; + readAllColumns = true; + mungeDB2row(buf, + badRow, + badRow + activeFormat->writeRowNullOffset, + true); + readAllColumns = savedReadAllColumns; + + if (table->found_next_number_field) + { + table->next_number_field->store(next_identity_value - (incrementByValue * (activeWriteBuf->rowCount() - (failedRow - 1)))); + } + } + + if (default_identity_value && // Table has ID colm and generating a value + (!autoIncLockAcquired || !got_auto_inc_values) && + // Writing first or only row in block + loopCnt == 1 && // Didn't already retry + lastDupKeyID == table->s->next_number_index) // Autoinc column is in failed index + { + if (alterStartWith() == 0) // Reset next Identity value to max+1 + retry_dup = TRUE; // Rtry the write operation + } + } + else + { + char unknownIndex[MAX_DB2_FILENAME_LENGTH+1]; + convFromEbcdic(lastDupKeyNamePtr, unknownIndex, min(lastDupKeyNameLen, MAX_DB2_FILENAME_LENGTH)); + unknownIndex[min(lastDupKeyNameLen, MAX_DB2_FILENAME_LENGTH)] = 0; + getErrTxt(DB2I_ERR_UNKNOWN_IDX, unknownIndex); + } + } + } + } + + if ((rc == 0 || rc == HA_ERR_FOUND_DUPP_KEY) + && default_identity_value && IdValueWasGenerated && + (!autoIncLockAcquired || !got_auto_inc_values)) + { + /* Save the generated identity value for the MySQL last_insert_id() function. */ + insert_id_for_cur_row = generatedIdValue; + + /* Store the value into MySQL's buf for row-based replication + or for an 'on duplicate key update' clause. */ + table->next_number_field->store((longlong) generatedIdValue, TRUE); + if (autoIncLockAcquired) + { + got_auto_inc_values = TRUE; + next_identity_value = generatedIdValue + incrementByValue; + } + } + else + { + if (!autoIncLockAcquired) // Don't overlay value for first row of a block + insert_id_for_cur_row = 0; + } + + + activeWriteBuf->resetAfterWrite(); + DBUG_RETURN(rc); +} + +int ha_ibmdb2i::alterStartWith() +{ + DBUG_ENTER("ha_ibmdb2i::alterStartWith"); + int rc = 0; + ulonglong nextIdVal; + if (!dataHandle) + rc = db2Table->dataFile()->allocateNewInstance(&dataHandle, curConnection); + if (!rc) {rc = bridge()->lockObj(dataHandle, 1, QMY_LOCK, QMY_LENR, QMY_YES);} + if (!rc) + { + rc = getNextIdVal(&nextIdVal); + if (!rc) {rc = reset_auto_increment(nextIdVal);} + bridge()->lockObj(dataHandle, 0, QMY_UNLOCK, QMY_LENR, QMY_YES); + } + DBUG_RETURN(rc); +} + +bool ha_ibmdb2i::lobFieldsRequested() +{ + if (!db2Table->hasBlobs()) + { + DBUG_PRINT("ha_ibmdb2i::lobFieldsRequested",("No LOBs")); + return (false); + } + + if (readAllColumns) + { + DBUG_PRINT("ha_ibmdb2i::lobFieldsRequested",("All cols requested")); + return (true); + } + + for (int i = 0; i < db2Table->getBlobCount(); ++i) + { + if (bitmap_is_set(table->read_set, db2Table->blobFields[i])) + { + DBUG_PRINT("ha_ibmdb2i::lobFieldsRequested",("LOB requested")); + return (true); + } + } + + DBUG_PRINT("ha_ibmdb2i::lobFieldsRequested",("No LOBs requested")); + return (false); +} + + +int ha_ibmdb2i::prepareReadBufferForLobs() +{ + DBUG_ENTER("ha_ibmdb2i::prepareReadBufferForLobs"); + DBUG_ASSERT(db2Table->hasBlobs()); + + uint32 activeLobFields = 0; + DB2LobField* lobField; + uint16 blobCount = db2Table->getBlobCount(); + + char* readBuf = activeReadBuf->getRowN(0); + + for (int i = 0; i < blobCount; ++i) + { + int fieldID = db2Table->blobFields[i]; + DB2Field& db2Field = db2Table->db2Field(fieldID); + lobField = db2Field.asBlobField(readBuf); + if (readAllColumns || + bitmap_is_set(table->read_set, fieldID)) + { + lobField->dataHandle = (ILEMemHandle)blobReadBuffers->getBufferPtr(fieldID); + activeLobFields++; + } + else + { + lobField->dataHandle = NULL; + } + } + + if (activeLobFields == 0) + { + for (int i = 0; i < blobCount; ++i) + { + DB2Field& db2Field = db2Table->db2Field(db2Table->blobFields[i]); + uint16 offset = db2Field.getBufferOffset() + db2Field.calcBlobPad(); + + for (int r = 1; r < activeReadBuf->getRowCapacity(); ++r) + { + lobField = (DB2LobField*)(activeReadBuf->getRowN(r) + offset); + lobField->dataHandle = NULL; + } + } + } + + activeReadBuf->setRowsToProcess((activeLobFields ? 1 : activeReadBuf->getRowCapacity())); + int rc = bridge()->objectOverride(activeHandle, + activeReadBuf->ptr(), + activeFormat->readRowLen); + DBUG_RETURN(rc); +} + + +uint32 ha_ibmdb2i::adjustLobBuffersForRead() +{ + DBUG_ENTER("ha_ibmdb2i::adjustLobBuffersForRead"); + + char* readBuf = activeReadBuf->getRowN(0); + + for (int i = 0; i < db2Table->getBlobCount(); ++i) + { + DB2Field& db2Field = db2Table->db2Field(db2Table->blobFields[i]); + DB2LobField* lobField = db2Field.asBlobField(readBuf); + if (readAllColumns || + bitmap_is_set(table->read_set, db2Table->blobFields[i])) + { + lobField->dataHandle = (ILEMemHandle)blobReadBuffers->reallocBuffer(db2Table->blobFields[i], lobField->length); + + if (lobField->dataHandle == NULL) + DBUG_RETURN(HA_ERR_OUT_OF_MEM); + } + else + { + lobField->dataHandle = 0; + } + } + + int32 rc = bridge()->objectOverride(activeHandle, + activeReadBuf->ptr()); + DBUG_RETURN(rc); +} + + + +int ha_ibmdb2i::reset() +{ + DBUG_ENTER("ha_ibmdb2i::reset"); + + if (outstanding_start_bulk_insert) + { + finishBulkInsert(); + } + + if (activeHandle != 0) + { + releaseActiveHandle(); + } + + cleanupBuffers(); + + db2i_ileBridge::getBridgeForThread(ha_thd())->freeErrorStorage(); + + last_rnd_init_rc = last_index_init_rc = last_start_bulk_insert_rc = 0; + + returnDupKeysImmediately = false; + onDupUpdate = false; + forceSingleRowRead = false; + +#ifndef DBUG_OFF + cachedBridge=NULL; +#endif + + DBUG_RETURN(0); +} + + +int32 ha_ibmdb2i::buildCreateIndexStatement(SqlStatementStream& sqlStream, + KEY& key, + bool isPrimary, + const char* db2LibName, + const char* db2FileName) +{ + DBUG_ENTER("ha_ibmdb2i::buildCreateIndexStatement"); + + char fileSortSequence[11] = "*HEX"; + char fileSortSequenceLibrary[11] = ""; + char fileSortSequenceType = ' '; + String query(256); + query.length(0); + int rc = 0; + + if (isPrimary) + { + query.append(STRING_WITH_LEN("ALTER TABLE ")); + query.append(db2LibName); + query.append('.'); + query.append(db2FileName); + query.append(STRING_WITH_LEN(" ADD PRIMARY KEY ")); + } + else + { + query.append(STRING_WITH_LEN("CREATE")); + + if (key.flags & HA_NOSAME) + query.append(STRING_WITH_LEN(" UNIQUE WHERE NOT NULL")); + + query.append(STRING_WITH_LEN(" INDEX ")); + + query.append(db2LibName); + query.append('.'); + if (db2i_table::appendQualifiedIndexFileName(key.name, db2FileName, query)) + { + getErrTxt(DB2I_ERR_INVALID_NAME,"index","*generated*"); + DBUG_RETURN(DB2I_ERR_INVALID_NAME ); + } + + query.append(STRING_WITH_LEN(" ON ")); + + query.append(db2LibName); + query.append('.'); + query.append(db2FileName); + } + + String fieldDefinition(128); + fieldDefinition.length(0); + fieldDefinition.append(STRING_WITH_LEN(" ( ")); + for (int j = 0; j < key.key_parts; ++j) + { + char colName[MAX_DB2_COLNAME_LENGTH+1]; + if (j != 0) + { + fieldDefinition.append(STRING_WITH_LEN(" , ")); + } + Field* field = key.key_part[j].field; + convertMySQLNameToDB2Name(field->field_name, colName, sizeof(colName)); + fieldDefinition.append(colName); + rc = updateAssociatedSortSequence(field,&fileSortSequenceType,fileSortSequence,fileSortSequenceLibrary); + if (rc) DBUG_RETURN (rc); + } + fieldDefinition.append(STRING_WITH_LEN(" ) ")); + + query.append(fieldDefinition); + + if ((THDVAR(ha_thd(), create_index_option)==1) && + (fileSortSequenceType != 'B')) + { + String shadowQuery(256); + shadowQuery.length(0); + + shadowQuery.append(STRING_WITH_LEN("CREATE INDEX ")); + + shadowQuery.append(db2LibName); + shadowQuery.append('.'); + if (db2i_table::appendQualifiedIndexFileName(key.name, db2FileName, shadowQuery, db2i_table::ASCII_SQL, typeHex)) + { + getErrTxt(DB2I_ERR_INVALID_NAME,"index","*generated*"); + DBUG_RETURN(DB2I_ERR_INVALID_NAME ); + } + + shadowQuery.append(STRING_WITH_LEN(" ON ")); + + shadowQuery.append(db2LibName); + shadowQuery.append('.'); + shadowQuery.append(db2FileName); + shadowQuery.append(fieldDefinition); + DBUG_PRINT("ha_ibmdb2i::buildCreateIndexStatement", ("Sent to DB2: %s",shadowQuery.c_ptr_safe())); + sqlStream.addStatement(shadowQuery,"*HEX","QSYS"); + } + + DBUG_PRINT("ha_ibmdb2i::buildCreateIndexStatement", ("Sent to DB2: %s",query.c_ptr_safe())); + sqlStream.addStatement(query,fileSortSequence,fileSortSequenceLibrary); + + DBUG_RETURN(0); +} + + +void ha_ibmdb2i::doInitialRead(char orientation, + uint32 rowsToBuffer, + ILEMemHandle key, + int keyLength, + int keyParts) +{ + DBUG_ENTER("ha_ibmdb2i::doInitialRead"); + + if (forceSingleRowRead) + rowsToBuffer = 1; + else + rowsToBuffer = min(rowsToBuffer, activeReadBuf->getRowCapacity()); + + activeReadBuf->newReadRequest(activeHandle, + orientation, + rowsToBuffer, + THDVAR(ha_thd(), async_enabled), + key, + keyLength, + keyParts); + DBUG_VOID_RETURN; +} + + +int ha_ibmdb2i::start_stmt(THD *thd, thr_lock_type lock_type) +{ + DBUG_ENTER("ha_ibmdb2i::start_stmt"); + initBridge(thd); + if (!THDVAR(thd, transaction_unsafe)) + { + trans_register_ha(thd, FALSE, ibmdb2i_hton); + + if (!autoCommitIsOn(thd)) + { + bridge()->beginStmtTx(); + } + } + + DBUG_RETURN(0); +} + +int32 ha_ibmdb2i::handleLOBReadOverflow() +{ + DBUG_ENTER("ha_ibmdb2i::handleLOBReadOverflow"); + DBUG_ASSERT(db2Table->hasBlobs() && (activeReadBuf->getRowCapacity() == 1)); + + int32 rc = adjustLobBuffersForRead(); + + if (!rc) + { + activeReadBuf->rewind(); + rc = bridge()->expectErrors(QMY_ERR_END_OF_BLOCK) + ->read(activeHandle, + activeReadBuf->ptr(), + accessIntent, + getCommitLevel(), + QMY_SAME); + releaseRowNeeded = TRUE; + + } + DBUG_RETURN(rc); +} + + +int32 ha_ibmdb2i::finishBulkInsert() +{ + int32 rc = 0; + + if (activeWriteBuf->rowCount() && activeHandle) + rc = flushWrite(activeHandle, table->record[0]); + + if (activeHandle) + releaseActiveHandle(); + + if (autoIncLockAcquired == TRUE) + { + // We could check the return code on the unlock, but beware not + // to overlay the return code from the flushwrite or we will mask + // duplicate key errors.. + bridge()->lockObj(dataHandle, 0, QMY_UNLOCK, QMY_LEAR, QMY_YES); + autoIncLockAcquired = FALSE; + } + outstanding_start_bulk_insert = false; + multiRowWriteBuf.freeBuf(); + last_start_bulk_insert_rc = 0; + + resetCharacterConversionBuffers(); + + return rc; +} + +int ha_ibmdb2i::getKeyFromName(const char* name, size_t len) +{ + for (int i = 0; i < table_share->keys; ++i) + { + const char* indexName = db2Table->indexFile(i)->getDB2FileName(); + if ((strncmp(name, indexName, len) == 0) && + (strlen(indexName) == len)) + { + return i; + } + } + return MAX_KEY; +} + +/* +Determine the number of I/O's it takes to read through the table. + */ +double ha_ibmdb2i::scan_time() + { + DBUG_ENTER("ha_ibmdb2i::scan_time"); + DBUG_RETURN(ulonglong2double((stats.data_file_length)/IO_SIZE)); + } + + +/** + Estimate the number of I/O's it takes to read a set of ranges through + an index. + + @param index + @param ranges + @param rows + + @return The estimate number of I/Os +*/ + +double ha_ibmdb2i::read_time(uint index, uint ranges, ha_rows rows) +{ + DBUG_ENTER("ha_ibmdb2i::read_time"); + int rc; + uint64 idxPageCnt = 0; + double cost; + + if (unlikely(rows == HA_POS_ERROR)) + DBUG_RETURN(double(rows) + ranges); + + rc = bridge()->retrieveIndexInfo(db2Table->indexFile(index)->getMasterDefnHandle(), + &idxPageCnt); + if (!rc) + { + if ((idxPageCnt == 1) || // Retrieving rows in requested order or + (ranges == rows)) // 'Sweep' full records retrieval + cost = idxPageCnt/4; + else + { + uint64 totalRecords = stats.records + 1; + double dataPageCount = stats.data_file_length/IO_SIZE; + + cost = (rows * dataPageCount / totalRecords) + + min(idxPageCnt, (log_2(idxPageCnt) * ranges + + rows * (log_2(idxPageCnt) + log_2(rows) - log_2(totalRecords)))); + } + } + else + { + cost = rows2double(ranges+rows); // Use default costing + } + DBUG_RETURN(cost); +} + +int ha_ibmdb2i::useIndexFile(char intent, int idx) +{ + DBUG_ENTER("ha_ibmdb2i::useIndexFile"); + + if (activeHandle) + releaseActiveHandle(); + + int rc = 0; + + if (!indexHandles[idx]) + rc = db2Table->indexFile(idx)->allocateNewInstance(&indexHandles[idx], curConnection); + + if (rc == 0) + { + rc = db2Table->indexFile(idx)->useFile(indexHandles[idx], + intent, + getCommitLevel(), + &activeFormat); + + if (rc == 0) + { + activeHandle = indexHandles[idx]; + bumpInUseCounter(1); + } + } + + DBUG_RETURN(rc); +} + + +ulong ha_ibmdb2i::index_flags(uint inx, uint part, bool all_parts) const +{ + return HA_READ_NEXT | HA_READ_PREV | HA_KEYREAD_ONLY | HA_READ_ORDER | HA_READ_RANGE; +} + + +static struct st_mysql_sys_var* ibmdb2i_system_variables[] = { + MYSQL_SYSVAR(rdb_name), + MYSQL_SYSVAR(transaction_unsafe), + MYSQL_SYSVAR(lob_alloc_size), + MYSQL_SYSVAR(max_read_buffer_size), + MYSQL_SYSVAR(max_write_buffer_size), + MYSQL_SYSVAR(async_enabled), + MYSQL_SYSVAR(create_time_columns_as_TOD), + MYSQL_SYSVAR(assume_exclusive_use), + MYSQL_SYSVAR(map_blob_to_varchar), + MYSQL_SYSVAR(create_index_option), + MYSQL_SYSVAR(discovery_mode), + NULL +}; + + +struct st_mysql_storage_engine ibmdb2i_storage_engine= +{ MYSQL_HANDLERTON_INTERFACE_VERSION }; + +mysql_declare_plugin(ibmdb2i) +{ + MYSQL_STORAGE_ENGINE_PLUGIN, + &ibmdb2i_storage_engine, + "IBMDB2I", + "The IBM development team in Rochester, Minnesota", + "IBM DB2 for i Storage Engine", + PLUGIN_LICENSE_PROPRIETARY, + ibmdb2i_init_func, /* Plugin Init */ + ibmdb2i_done_func, /* Plugin Deinit */ + 0x0100 /* 1.0 */, + NULL, /* status variables */ + ibmdb2i_system_variables, /* system variables */ + NULL /* config options */ +} +mysql_declare_plugin_end; diff --git a/storage/ibmdb2i/ha_ibmdb2i.h b/storage/ibmdb2i/ha_ibmdb2i.h new file mode 100644 index 00000000000..321951bfe3c --- /dev/null +++ b/storage/ibmdb2i/ha_ibmdb2i.h @@ -0,0 +1,727 @@ +/* +Licensed Materials - Property of IBM +DB2 Storage Engine Enablement +Copyright IBM Corporation 2007,2008 +All rights reserved + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + (a) Redistributions of source code must retain this list of conditions, the + copyright notice in section {d} below, and the disclaimer following this + list of conditions. + (b) Redistributions in binary form must reproduce this list of conditions, the + copyright notice in section (d) below, and the disclaimer following this + list of conditions, in the documentation and/or other materials provided + with the distribution. + (c) The name of IBM may not be used to endorse or promote products derived from + this software without specific prior written permission. + (d) The text of the required copyright notice is: + Licensed Materials - Property of IBM + DB2 Storage Engine Enablement + Copyright IBM Corporation 2007,2008 + All rights reserved + +THIS SOFTWARE IS PROVIDED BY IBM CORPORATION "AS IS" AND ANY EXPRESS OR IMPLIED +WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT +SHALL IBM CORPORATION BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT +OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT INCLUDING NEGLIGENCE OR OTHERWISE) ARISING +IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. +*/ + +/** @file ha_ibmdb2i.h + + @brief + + @note + + @see +*/ + +#ifdef USE_PRAGMA_INTERFACE +#pragma interface /* gcc class implementation */ +#endif + +#include "as400_types.h" +#include "as400_protos.h" +#include "db2i_global.h" +#include "db2i_ileBridge.h" +#include "builtins.h" +#include "db2i_misc.h" +#include "db2i_file.h" +#include "db2i_blobCollection.h" +#include "db2i_collationSupport.h" +#include "db2i_validatedPointer.h" +#include "db2i_ioBuffers.h" +#include "db2i_errors.h" +#include "db2i_sqlStatementStream.h" + +/** @brief + IBMDB2I_SHARE is a structure that will be shared among all open handlers. + It is used to describe the underlying table definition, and it caches + table statistics. +*/ +typedef struct st_ibmdb2i_share { + char *table_name; + uint table_name_length,use_count; + pthread_mutex_t mutex; + THR_LOCK lock; + + db2i_table* db2Table; + + class CStats + { + public: + void cacheUpdateTime(time_t time) + {update_time = time; initFlag |= lastModTime;} + time_t getUpdateTime() const + {return update_time;} + void cacheRowCount(ha_rows rows) + {records = rows; initFlag |= rowCount;} + ha_rows getRowCount() const + {return records;} + void cacheDelRowCount(ha_rows rows) + {deleted = rows; initFlag |= deletedRowCount;} + ha_rows getDelRowCount() const + {return deleted;} + void cacheMeanLength(ulong len) + {mean_rec_length = len; initFlag |= meanRowLen;} + ulong getMeanLength() + {return mean_rec_length;} + void cacheAugmentedDataLength(ulong len) + {data_file_length = len; initFlag |= ioCount;} + ulong getAugmentedDataLength() + {return data_file_length;} + bool isInited(uint flags) + {return initFlag & flags;} + void invalidate(uint flags) + {initFlag &= ~flags;} + + private: + uint initFlag; + time_t update_time; + ha_rows records; + ha_rows deleted; + ulong mean_rec_length; + ulong data_file_length; + } cachedStats; + +} IBMDB2I_SHARE; + +class ha_ibmdb2i: public handler +{ + THR_LOCK_DATA lock; ///< MySQL lock + IBMDB2I_SHARE *share; ///< Shared lock info + + // The record we are positioned on, together with the handle used to get + // i. + uint32 currentRRN; + uint32 rrnAssocHandle; + + // Dup key values needed by info() + uint32 lastDupKeyRRN; + uint32 lastDupKeyID; + + bool returnDupKeysImmediately; + + // Dup key value need by update() + bool onDupUpdate; + + + db2i_table* db2Table; + + // The file handle of the PF or LF being accessed by the current operation. + FILE_HANDLE activeHandle; + + // The file handle of the underlying PF + FILE_HANDLE dataHandle; + + // Array of file handles belonging to the underlying LFs + FILE_HANDLE* indexHandles; + + // Pointer to a definition of the layout of the row buffer for the file + // described by activeHandle + const db2i_file::RowFormat* activeFormat; + + // Flag to indicate whether a call needs to be made to unlock a row when + // a read operation has ended. DB2 will handle row unlocking as we move + // through rows, but if an operation ends before we reach the end of a file, + // DB2 needs to know to unlock the last row read. + bool releaseRowNeeded; + + + IORowBuffer keyBuf; + uint32 keyLen; + + IOWriteBuffer multiRowWriteBuf; + IOAsyncReadBuffer multiRowReadBuf; + + IOAsyncReadBuffer* activeReadBuf; + IOWriteBuffer* activeWriteBuf; + + BlobCollection* blobReadBuffers; // Dynamically allocated per query and used + // to manage the buffers used for reading LOBs + ValidatedPointer* blobWriteBuffers; + + // Return codes are not used/honored by rnd_init and start_bulk_insert + // so we need a way to signal the failure "downstream" to subsequent + // functions. + int last_rnd_init_rc; + int last_index_init_rc; + int last_start_bulk_insert_rc; + + // end_bulk_insert may get called twice for a single start_bulk_insert + // This is our way to do cleanup only once. + bool outstanding_start_bulk_insert; + + // Auto_increment 'increment by' value needed by write_row() + uint32 incrementByValue; + bool default_identity_value; + + // Flags and values used during write operations for auto_increment processing + bool autoIncLockAcquired; + bool got_auto_inc_values; + uint64 next_identity_value; + + // The access intent indicated by the last external_locks() call. + // May be either QMY_READ or QMY_UPDATABLE + char accessIntent; + + ha_rows* indexReadSizeEstimates; + + MEM_ROOT conversionBufferMemroot; + + bool forceSingleRowRead; + + bool readAllColumns; + + bool invalidDataFound; + + db2i_ileBridge* cachedBridge; + + ValidatedObject curConnection; + uint16 activeReferences; + +public: + + ha_ibmdb2i(handlerton *hton, TABLE_SHARE *table_arg); + ~ha_ibmdb2i(); + + const char *table_type() const { return "IBMDB2I"; } + const char *index_type(uint inx) { return "RADIX"; } + const key_map *keys_to_use_for_scanning() { return &key_map_full; } + const char **bas_ext() const; + + ulonglong table_flags() const + { + return HA_NULL_IN_KEY | HA_REC_NOT_IN_SEQ | HA_AUTO_PART_KEY | + HA_PARTIAL_COLUMN_READ | + HA_DUPLICATE_POS | HA_NO_PREFIX_CHAR_KEYS | + HA_HAS_RECORDS | HA_BINLOG_ROW_CAPABLE | HA_REQUIRES_KEY_COLUMNS_FOR_DELETE | + HA_CAN_INDEX_BLOBS; + } + + ulong index_flags(uint inx, uint part, bool all_parts) const; + +// Note that we do not implement max_supported_record_length. +// We'll let create fail accordingly if the row is +// too long. This allows us to hide the fact that varchars > 32K are being +// implemented as DB2 LOBs. + + uint max_supported_keys() const { return 4000; } + uint max_supported_key_parts() const { return MAX_DB2_KEY_PARTS; } + uint max_supported_key_length() const { return 32767; } + uint max_supported_key_part_length() const { return 32767; } + double read_time(uint index, uint ranges, ha_rows rows); + double scan_time(); + int open(const char *name, int mode, uint test_if_locked); + int close(void); + int write_row(uchar * buf); + int update_row(const uchar * old_data, uchar * new_data); + int delete_row(const uchar * buf); + int index_init(uint idx, bool sorted); + int index_read(uchar * buf, const uchar * key, + uint key_len, enum ha_rkey_function find_flag); + int index_next(uchar * buf); + int index_read_last(uchar * buf, const uchar * key, uint key_len); + int index_next_same(uchar *buf, const uchar *key, uint keylen); + int index_prev(uchar * buf); + int index_first(uchar * buf); + int index_last(uchar * buf); + int rnd_init(bool scan); + int rnd_end(); + int rnd_next(uchar *buf); + int rnd_pos(uchar * buf, uchar *pos); + void position(const uchar *record); + int info(uint); + ha_rows records(); + int extra(enum ha_extra_function operation); + int external_lock(THD *thd, int lock_type); + int delete_all_rows(void); + ha_rows records_in_range(uint inx, key_range *min_key, + key_range *max_key); + int delete_table(const char *from); + int rename_table(const char * from, const char * to); + int create(const char *name, TABLE *form, + HA_CREATE_INFO *create_info); + int updateFrm(TABLE *table_def, File file); + int openTableDef(TABLE *table_def); + int add_index(TABLE *table_arg, KEY *key_info, uint num_of_keys); + int prepare_drop_index(TABLE *table_arg, uint *key_num, uint num_of_keys); + int final_drop_index(TABLE *table_arg) {return 0;} + void get_auto_increment(ulonglong offset, ulonglong increment, + ulonglong nb_desired_values, + ulonglong *first_value, + ulonglong *nb_reserved_values); + int reset_auto_increment(ulonglong value); + void restore_auto_increment(ulonglong prev_insert_id) {return;} + void update_create_info(HA_CREATE_INFO *create_info); + int getNextIdVal(ulonglong *value); + int analyze(THD* thd,HA_CHECK_OPT* check_opt); + int optimize(THD* thd, HA_CHECK_OPT* check_opt); + bool can_switch_engines(); + void free_foreign_key_create_info(char* str); + char* get_foreign_key_create_info(); + int get_foreign_key_list(THD *thd, List *f_key_list); + uint referenced_by_foreign_key(); + bool check_if_incompatible_data(HA_CREATE_INFO *info, uint table_changes); + virtual bool get_error_message(int error, String *buf); + + THR_LOCK_DATA **store_lock(THD *thd, THR_LOCK_DATA **to, + enum thr_lock_type lock_type); + + bool low_byte_first() const { return 0; } + void unlock_row(); + int index_end(); + int reset(); + static int doCommit(handlerton *hton, THD *thd, bool all); + static int doRollback(handlerton *hton, THD *thd, bool all); + void start_bulk_insert(ha_rows rows); + int end_bulk_insert(); + int start_stmt(THD *thd, thr_lock_type lock_type); + + void initBridge(THD* thd = NULL) + { + if (thd == NULL) thd = ha_thd(); + DBUG_PRINT("ha_ibmdb2i::initBridge",("Initing bridge. Conn ID=%d", thd->thread_id)); + cachedBridge = db2i_ileBridge::getBridgeForThread(thd); + } + + db2i_ileBridge* bridge() {DBUG_ASSERT(cachedBridge); return cachedBridge;} + + static uint8 autoCommitIsOn(THD* thd) + { return (thd_test_options(thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN) ? QMY_NO : QMY_YES); } + + uint8 getCommitLevel(); + uint8 getCommitLevel(THD* thd); + + static int doSavepointSet(THD* thd, char* name) + { + return db2i_ileBridge::getBridgeForThread(thd)->savepoint(QMY_SET_SAVEPOINT, + name); + } + + static int doSavepointRollback(THD* thd, char* name) + { + return db2i_ileBridge::getBridgeForThread(thd)->savepoint(QMY_ROLLBACK_SAVEPOINT, + name); + } + + static int doSavepointRelease(THD* thd, char* name) + { + return db2i_ileBridge::getBridgeForThread(thd)->savepoint(QMY_RELEASE_SAVEPOINT, + name); + } + + // We can't guarantee that the rows we know about when this is called + // will be the same number of rows that read returns (since DB2 activity + // may insert additional rows). Therefore, we do as the Federated SE and + // return the max possible. + ha_rows estimate_rows_upper_bound() + { + return HA_POS_ERROR; + } + + +private: + + enum enum_TimeFormat + { + TIME_OF_DAY, + DURATION + }; + + enum enum_BlobMapping + { + AS_BLOB, + AS_VARCHAR + }; + + IBMDB2I_SHARE *get_share(const char *table_name, TABLE *table); + int free_share(IBMDB2I_SHARE *share); + int32 mungeDB2row(uchar* record, const char* dataPtr, const char* nullMapPtr, bool skipLOBs); + int prepareRowForWrite(char* data, char* nulls, bool honorIdentCols); + int prepareReadBufferForLobs(); + int32 prepareWriteBufferForLobs(); + uint32 adjustLobBuffersForRead(); + bool lobFieldsRequested(); + int convertFieldChars(enum_conversionDirection direction, uint16 fieldID, const char* input, char* output, size_t ilen, size_t olen, size_t* outDataLen); + + /** + Fast integer log2 function + */ + uint64 log_2(uint64 val) + { + uint64 exp = 0; + while( (val >> exp) != 0) + { + exp++; + } + DBUG_ASSERT(exp-1 == (uint64)log2(val)); + return exp-1; + } + + void bumpInUseCounter(uint16 amount) + { + activeReferences += amount; + DBUG_PRINT("ha_ibmdb2i::bumpInUseCounter", ("activeReferences = %d", activeReferences)); + if (activeReferences) + curConnection = (uint32)(ha_thd()->thread_id); + else + curConnection = 0; + } + + + int useDataFile(char intent) + { + DBUG_ENTER("ha_ibmdb2i::useDataFile"); + DBUG_PRINT("ha_ibmdb2i::useDataFile", ("Intent: %d", intent)); + + int rc = 0; + if (!dataHandle) + rc = db2Table->dataFile()->allocateNewInstance(&dataHandle, curConnection); + else if (activeHandle == dataHandle) + DBUG_RETURN(0); + + DBUG_ASSERT(activeHandle == 0); + + + if (likely(rc == 0)) + { + rc = db2Table->dataFile()->useFile(dataHandle, + intent, + getCommitLevel(), + &activeFormat); + + if (likely(rc == 0)) + { + activeHandle = dataHandle; + bumpInUseCounter(1); + } + } + + DBUG_RETURN(rc); + } + + void releaseAnyLockedRows() + { + if (releaseRowNeeded) + { + DBUG_PRINT("ha_ibmdb2i::releaseAnyLockedRows", ("Releasing rows")); + db2i_ileBridge::getBridgeForThread()->rrlslck(activeHandle, accessIntent); + releaseRowNeeded = FALSE; + } + } + + + void releaseDataFile() + { + DBUG_ENTER("ha_ibmdb2i::releaseDataFile"); + releaseAnyLockedRows(); + bumpInUseCounter(-1); + DBUG_ASSERT((volatile int)activeReferences >= 0); + activeHandle = 0; + DBUG_VOID_RETURN; + } + + int useIndexFile(char intent, int idx); + + void releaseIndexFile(int idx) + { + DBUG_ENTER("ha_ibmdb2i::releaseIndexFile"); + releaseAnyLockedRows(); + bumpInUseCounter(-1); + DBUG_ASSERT((volatile int)activeReferences >= 0); + activeHandle = 0; + DBUG_VOID_RETURN; + } + + FILE_HANDLE allocateFileHandle(char* database, char* table, int* activityReference, bool hasBlobs); + + int updateBuffers(const db2i_file::RowFormat* format, uint rowsToRead, uint rowsToWrite); + + int flushWrite(FILE_HANDLE fileHandle, uchar* buf = NULL); + + int alterStartWith(); + + int buildDB2ConstraintString(LEX* lex, + String& appendHere, + const char* database, + Field** fields, + char* fileSortSequenceType, + char* fileSortSequence, + char* fileSortSequenceLibrary); + + void releaseWriteBuffer(); + + void setIndexReadEstimate(uint index, ha_rows rows) + { + if (!indexReadSizeEstimates) + { + indexReadSizeEstimates = (ha_rows*)my_malloc(sizeof(ha_rows) * table->s->keys, MYF(MY_WME | MY_ZEROFILL)); + } + indexReadSizeEstimates[index] = rows; + } + + ha_rows getIndexReadEstimate(uint index) + { + if (indexReadSizeEstimates) + return max(indexReadSizeEstimates[index], 1); + + return 10000; // Assume index scan if no estimate exists. + } + + + void quiesceAllFileHandles() + { + db2i_ileBridge* bridge = db2i_ileBridge::getBridgeForThread(); + if (dataHandle) + { + bridge->quiesceFileInstance(dataHandle); + } + + for (int idx = 0; idx < table_share->keys; ++idx) + { + if (indexHandles[idx] != 0) + { + bridge->quiesceFileInstance(indexHandles[idx]); + } + } + } + + int32 buildCreateIndexStatement(SqlStatementStream& sqlStream, + KEY& key, + bool isPrimary, + const char* db2LibName, + const char* db2FileName); + + // Specify NULL for data when using the data pointed to by field + int32 convertMySQLtoDB2(Field* field, const DB2Field& db2Field, char* db2Buf, const uchar* data = NULL); + + int32 convertDB2toMySQL(const DB2Field& db2Field, Field* field, const char* buf); + int getFieldTypeMapping(Field* field, + String& mapping, + enum_TimeFormat timeFormate, + enum_BlobMapping blobMapping); + + int getKeyFromName(const char* name, size_t len); + + void releaseActiveHandle() + { + if (activeHandle == dataHandle) + releaseDataFile(); + else + releaseIndexFile(active_index); + } + + + int32 finishBulkInsert(); + + void doInitialRead(char orientation, + uint32 rowsToBuffer, + ILEMemHandle key = 0, + int keyLength = 0, + int keyParts = 0); + + + int32 readFromBuffer(uchar* destination, char orientation) + { + char* row; + int32 rc = 0; + row = activeReadBuf->readNextRow(orientation, currentRRN); + + if (unlikely(!row)) + { + rc = activeReadBuf->lastrc(); + if (rc == QMY_ERR_LOB_SPACE_TOO_SMALL) + { + rc = handleLOBReadOverflow(); + if (rc == 0) + { + DBUG_ASSERT(activeReadBuf->rowCount() == 1); + row = activeReadBuf->readNextRow(orientation, currentRRN); + } + } + } + + if (likely(rc == 0)) + { + rrnAssocHandle = activeHandle; + rc = mungeDB2row(destination, row, row+activeFormat->readRowNullOffset, false); + } + return rc; + } + + int32 handleLOBReadOverflow(); + + char* getCharacterConversionBuffer(int fieldId, int length) + { + if (unlikely(!alloc_root_inited(&conversionBufferMemroot))) + init_alloc_root(&conversionBufferMemroot, 8192, 0); + + return (char*)alloc_root(&conversionBufferMemroot, length);; + } + + void resetCharacterConversionBuffers() + { + if (alloc_root_inited(&conversionBufferMemroot)) + { + free_root(&conversionBufferMemroot, MYF(MY_MARK_BLOCKS_FREE)); + } + } + + void tweakReadSet() + { + THD* thd = ha_thd(); + int command = thd_sql_command(thd); + if ((command == SQLCOM_UPDATE || + command == SQLCOM_UPDATE_MULTI) || + ((command == SQLCOM_DELETE || + command == SQLCOM_DELETE_MULTI) && + thd->options & OPTION_BIN_LOG)) + readAllColumns = TRUE; + else + readAllColumns = FALSE; + } + + /** + + */ + int useFileByHandle(char intent, + FILE_HANDLE handle) + { + DBUG_ENTER("ha_ibmdb2i::useFileByHandle"); + + const db2i_file* file; + if (handle == dataHandle) + file = db2Table->dataFile(); + else + { + for (uint i = 0; i < table_share->keys; ++i) + { + if (indexHandles[i] == handle) + { + file = db2Table->indexFile(i); + active_index = i; + } + } + } + + int rc = file->useFile(handle, intent, getCommitLevel(), &activeFormat); + if (likely(rc == 0)) + { + activeHandle = handle; + bumpInUseCounter(1); + } + + DBUG_RETURN(rc); + } + + int prepReadBuffer(ha_rows rowsToRead); + void prepWriteBuffer(ha_rows rowsToWrite); + + void invalidateCachedStats() + { + share->cachedStats.invalidate(rowCount | deletedRowCount | objLength | meanRowLen | ioCount); + } + + void warnIfInvalidData() + { + if (unlikely(invalidDataFound)) + { + warning(ha_thd(), DB2I_ERR_INVALID_DATA, table->alias); + } + } + + /** + Calculate the maximum value that a particular field can hold. + + This is used to anticipate overflows in the auto_increment processing. + + @param field The Field to be analyzed + + @return The maximum value + */ + static uint64 maxValueForField(const Field* field) + { + uint64 maxValue=0; + switch (field->type()) + { + case MYSQL_TYPE_TINY: + if (((const Field_num*)field)->unsigned_flag) + maxValue = (1 << 8) - 1; + else + maxValue = (1 << 7) - 1; + break; + case MYSQL_TYPE_SHORT: + if (((const Field_num*)field)->unsigned_flag) + maxValue = (1 << 16) - 1; + else + maxValue = (1 << 15) - 1; + break; + case MYSQL_TYPE_INT24: + if (((const Field_num*)field)->unsigned_flag) + maxValue = (1 << 24) - 1; + else + maxValue = (1 << 23) - 1; + break; + case MYSQL_TYPE_LONG: + if (((const Field_num*)field)->unsigned_flag) + maxValue = (1LL << 32) - 1; + else + maxValue = (1 << 31) - 1; + break; + case MYSQL_TYPE_LONGLONG: + if (((const Field_num*)field)->unsigned_flag) + maxValue = ~(0LL); + else + maxValue = 1 << 63 - 1; + break; + } + + return maxValue; + } + + void cleanupBuffers() + { + if (blobReadBuffers) + { + delete blobReadBuffers; + blobReadBuffers = NULL; + } + if (blobWriteBuffers) + { + delete[] blobWriteBuffers; + blobWriteBuffers = NULL; + } + if (alloc_root_inited(&conversionBufferMemroot)) + { + free_root(&conversionBufferMemroot, MYF(0)); + } + } + +}; diff --git a/storage/ibmdb2i/plug.in b/storage/ibmdb2i/plug.in new file mode 100644 index 00000000000..0913d72aabf --- /dev/null +++ b/storage/ibmdb2i/plug.in @@ -0,0 +1,12 @@ +MYSQL_STORAGE_ENGINE([ibmdb2i], [], [IBM DB2 for i Storage Engine], + [IBM DB2 for i Storage Engine], [max,max-no-ndb]) +MYSQL_PLUGIN_DYNAMIC([ibmdb2i], [ha_ibmdb2i.la]) + +AC_CHECK_HEADER([qlgusr.h], + # qlgusr.h is just one of the headers from the i5/OS PASE environment; the + # EBCDIC headers are in /QIBM/include, and have to be converted to ASCII + # before cpp gets to them + [:], + # Missing PASE environment, can't build this engine + [mysql_plugin_ibmdb2i=no + with_plugin_ibmdb2i=no]) From 65e2c68a4dc75c3d476433f959685776cc95ebc9 Mon Sep 17 00:00:00 2001 From: Alexey Kopytov Date: Sun, 15 Feb 2009 12:26:08 +0300 Subject: [PATCH 090/219] Fixed PB failures on IA64 hosts introduced by the patch for bug #21205. mysql-test/t/gis.test: IA64 gcc backend lacks -fno-fused-madd option, so we have to adjust results. --- mysql-test/t/gis.test | 3 +++ 1 file changed, 3 insertions(+) diff --git a/mysql-test/t/gis.test b/mysql-test/t/gis.test index cf2e4a21419..cc2ac5b7392 100644 --- a/mysql-test/t/gis.test +++ b/mysql-test/t/gis.test @@ -355,6 +355,9 @@ insert into t1 values ('85984',GeomFromText('MULTIPOLYGON(((-115.006363 select object_id, geometrytype(geo), ISSIMPLE(GEO), ASTEXT(centroid(geo)) from t1 where object_id=85998; +# Expected result is 36.3310176346905, but IA64 returns 36.3310176346904 +# due to fused multiply-add instructions. +--replace_result 36.3310176346904 36.3310176346905 select object_id, geometrytype(geo), ISSIMPLE(GEO), ASTEXT(centroid(geo)) from t1 where object_id=85984; From d945db1ddd31f015492427d4512b86546f13c5d1 Mon Sep 17 00:00:00 2001 From: Alexey Kopytov Date: Sun, 15 Feb 2009 14:11:50 +0300 Subject: [PATCH 091/219] Take additional precision into account --- mysql-test/suite/funcs_1/r/ndb_func_view.result | 4 ++-- mysql-test/suite/funcs_1/r/ndb_views.result | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/mysql-test/suite/funcs_1/r/ndb_func_view.result b/mysql-test/suite/funcs_1/r/ndb_func_view.result index 1547c5461be..4beb0c8aaf2 100644 --- a/mysql-test/suite/funcs_1/r/ndb_func_view.result +++ b/mysql-test/suite/funcs_1/r/ndb_func_view.result @@ -5245,7 +5245,7 @@ WHERE select_id = 1 OR select_id IS NULL order by id; sqrt(my_bigint) my_bigint id NULL NULL 1 NULL -9223372036854775808 2 -3037000499.976 9223372036854775807 3 +3037000499.97605 9223372036854775807 3 0 0 4 NULL -1 5 2 4 6 @@ -5259,7 +5259,7 @@ WHERE select_id = 1 OR select_id IS NULL) order by id; sqrt(my_bigint) my_bigint id NULL NULL 1 NULL -9223372036854775808 2 -3037000499.976 9223372036854775807 3 +3037000499.97605 9223372036854775807 3 0 0 4 NULL -1 5 2 4 6 diff --git a/mysql-test/suite/funcs_1/r/ndb_views.result b/mysql-test/suite/funcs_1/r/ndb_views.result index 671ef590f4d..430f1180fc9 100644 --- a/mysql-test/suite/funcs_1/r/ndb_views.result +++ b/mysql-test/suite/funcs_1/r/ndb_views.result @@ -22824,7 +22824,7 @@ f1 f2 ABC 3 SELECT * FROM v1 order by 2; f1 my_sqrt -ABC 1.7320508075689 +ABC 1.73205080756888 ALTER TABLE t1 CHANGE COLUMN f2 f2 VARCHAR(30); INSERT INTO t1 SET f1 = 'ABC', f2 = 'DEF'; DESCRIBE t1; @@ -22842,7 +22842,7 @@ ABC DEF SELECT * FROM v1 order by 2; f1 my_sqrt ABC 0 -ABC 1.7320508075689 +ABC 1.73205080756888 SELECT SQRT('DEF'); SQRT('DEF') 0 @@ -22862,7 +22862,7 @@ my_sqrt double YES NULL SELECT * FROM v2 order by 2; f1 my_sqrt ABC 0 -ABC 1.7320508075689 +ABC 1.73205080756888 CREATE TABLE t2 AS SELECT f1, SQRT(f2) my_sqrt FROM t1; SELECT * FROM t2 order by 2; f1 ABC From cd1960ff26a34ca64c45e1964c92865cbf4f6355 Mon Sep 17 00:00:00 2001 From: Andrei Elkin Date: Mon, 16 Feb 2009 10:49:51 +0200 Subject: [PATCH 092/219] rpl_cross_version.test is disable for win till a proper fixing bug#42451 --- mysql-test/suite/rpl/t/rpl_cross_version.test | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mysql-test/suite/rpl/t/rpl_cross_version.test b/mysql-test/suite/rpl/t/rpl_cross_version.test index bb2ca350152..adeba7f2b15 100644 --- a/mysql-test/suite/rpl/t/rpl_cross_version.test +++ b/mysql-test/suite/rpl/t/rpl_cross_version.test @@ -11,7 +11,7 @@ # --source include/have_log_bin.inc - +--source include/not_windows.inc # # Bug#31240 load data infile replication between (4.0 or 4.1) and 5.1 fails # From d3a10ec6efdf8a257935a8f6161ca83d5538ce6b Mon Sep 17 00:00:00 2001 From: Davi Arnaut Date: Mon, 16 Feb 2009 08:38:15 -0300 Subject: [PATCH 093/219] Bug#41077: Warning contains wrong future version Substitute all references of MySQL version "5.2" to "6.0" in deprecation warning messages.Deprecated constructs are being removed in the 6.0 tree. --- mysql-test/r/backup.result | 26 +++++++++---------- mysql-test/r/show_check.result | 2 +- mysql-test/r/sp-error.result | 2 +- mysql-test/r/sp.result | 4 +-- mysql-test/r/sp_trans.result | 2 +- mysql-test/r/type_blob.result | 4 +-- mysql-test/r/type_timestamp.result | 14 +++++----- mysql-test/r/warnings.result | 2 +- mysql-test/suite/rpl/r/rpl_sp.result | 6 ++--- ...og_bin_trust_routine_creators_basic.result | 26 +++++++++---------- sql/mysqld.cc | 2 +- sql/set_var.cc | 4 +-- sql/sql_parse.cc | 2 +- sql/sql_table.cc | 4 +-- sql/sql_yacc.yy | 14 +++++----- 15 files changed, 57 insertions(+), 57 deletions(-) diff --git a/mysql-test/r/backup.result b/mysql-test/r/backup.result index b657c620805..bab2c83448c 100644 --- a/mysql-test/r/backup.result +++ b/mysql-test/r/backup.result @@ -4,23 +4,23 @@ create table t4(n int); backup table t4 to '../../bogus'; Table Op Msg_type Msg_text test.t4 backup error Failed copying .frm file (errno: X) -test.t4 backup Warning The syntax 'BACKUP TABLE' is deprecated and will be removed in MySQL 5.2. Please use MySQL Administrator (mysqldump, mysql) instead +test.t4 backup Warning The syntax 'BACKUP TABLE' is deprecated and will be removed in MySQL 6.0. Please use MySQL Administrator (mysqldump, mysql) instead test.t4 backup Error Can't create/write to file 'MYSQLTEST_VARDIR/bogus/t4.frm' (Errcode: X) test.t4 backup status Operation failed backup table t4 to '../../tmp'; Table Op Msg_type Msg_text -test.t4 backup Warning The syntax 'BACKUP TABLE' is deprecated and will be removed in MySQL 5.2. Please use MySQL Administrator (mysqldump, mysql) instead +test.t4 backup Warning The syntax 'BACKUP TABLE' is deprecated and will be removed in MySQL 6.0. Please use MySQL Administrator (mysqldump, mysql) instead test.t4 backup status OK backup table t4 to '../../tmp'; Table Op Msg_type Msg_text test.t4 backup error Failed copying .frm file (errno: X) -test.t4 backup Warning The syntax 'BACKUP TABLE' is deprecated and will be removed in MySQL 5.2. Please use MySQL Administrator (mysqldump, mysql) instead +test.t4 backup Warning The syntax 'BACKUP TABLE' is deprecated and will be removed in MySQL 6.0. Please use MySQL Administrator (mysqldump, mysql) instead test.t4 backup Error Can't create/write to file 'MYSQLTEST_VARDIR/tmp/t4.frm' (Errcode: X) test.t4 backup status Operation failed drop table t4; restore table t4 from '../../tmp'; Table Op Msg_type Msg_text -test.t4 restore Warning The syntax 'RESTORE TABLE' is deprecated and will be removed in MySQL 5.2. Please use MySQL Administrator (mysqldump, mysql) instead +test.t4 restore Warning The syntax 'RESTORE TABLE' is deprecated and will be removed in MySQL 6.0. Please use MySQL Administrator (mysqldump, mysql) instead test.t4 restore status OK select count(*) from t4; count(*) @@ -29,18 +29,18 @@ create table t1(n int); insert into t1 values (23),(45),(67); backup table t1 to '../../tmp'; Table Op Msg_type Msg_text -test.t1 backup Warning The syntax 'BACKUP TABLE' is deprecated and will be removed in MySQL 5.2. Please use MySQL Administrator (mysqldump, mysql) instead +test.t1 backup Warning The syntax 'BACKUP TABLE' is deprecated and will be removed in MySQL 6.0. Please use MySQL Administrator (mysqldump, mysql) instead test.t1 backup status OK drop table t1; restore table t1 from '../../bogus'; Table Op Msg_type Msg_text t1 restore error Failed copying .frm file Warnings: -Warning 1287 The syntax 'RESTORE TABLE' is deprecated and will be removed in MySQL 5.2. Please use MySQL Administrator (mysqldump, mysql) instead +Warning 1287 The syntax 'RESTORE TABLE' is deprecated and will be removed in MySQL 6.0. Please use MySQL Administrator (mysqldump, mysql) instead Error 29 File 'MYSQLTEST_VARDIR/bogus/t1.frm' not found (Errcode: X) restore table t1 from '../../tmp'; Table Op Msg_type Msg_text -test.t1 restore Warning The syntax 'RESTORE TABLE' is deprecated and will be removed in MySQL 5.2. Please use MySQL Administrator (mysqldump, mysql) instead +test.t1 restore Warning The syntax 'RESTORE TABLE' is deprecated and will be removed in MySQL 6.0. Please use MySQL Administrator (mysqldump, mysql) instead test.t1 restore status OK select n from t1; n @@ -53,13 +53,13 @@ insert into t2 values (123),(145),(167); insert into t3 values (223),(245),(267); backup table t2,t3 to '../../tmp'; Table Op Msg_type Msg_text -test.t2 backup Warning The syntax 'BACKUP TABLE' is deprecated and will be removed in MySQL 5.2. Please use MySQL Administrator (mysqldump, mysql) instead +test.t2 backup Warning The syntax 'BACKUP TABLE' is deprecated and will be removed in MySQL 6.0. Please use MySQL Administrator (mysqldump, mysql) instead test.t2 backup status OK test.t3 backup status OK drop table t1,t2,t3; restore table t1,t2,t3 from '../../tmp'; Table Op Msg_type Msg_text -test.t1 restore Warning The syntax 'RESTORE TABLE' is deprecated and will be removed in MySQL 5.2. Please use MySQL Administrator (mysqldump, mysql) instead +test.t1 restore Warning The syntax 'RESTORE TABLE' is deprecated and will be removed in MySQL 6.0. Please use MySQL Administrator (mysqldump, mysql) instead test.t1 restore status OK test.t2 restore status OK test.t3 restore status OK @@ -81,14 +81,14 @@ k drop table t1,t2,t3,t4; restore table t1 from '../../tmp'; Table Op Msg_type Msg_text -test.t1 restore Warning The syntax 'RESTORE TABLE' is deprecated and will be removed in MySQL 5.2. Please use MySQL Administrator (mysqldump, mysql) instead +test.t1 restore Warning The syntax 'RESTORE TABLE' is deprecated and will be removed in MySQL 6.0. Please use MySQL Administrator (mysqldump, mysql) instead test.t1 restore status OK rename table t1 to t5; lock tables t5 write; backup table t5 to '../../tmp'; unlock tables; Table Op Msg_type Msg_text -test.t5 backup Warning The syntax 'BACKUP TABLE' is deprecated and will be removed in MySQL 5.2. Please use MySQL Administrator (mysqldump, mysql) instead +test.t5 backup Warning The syntax 'BACKUP TABLE' is deprecated and will be removed in MySQL 6.0. Please use MySQL Administrator (mysqldump, mysql) instead test.t5 backup status OK drop table t5; DROP TABLE IF EXISTS `t+1`; @@ -96,12 +96,12 @@ CREATE TABLE `t+1` (c1 INT); INSERT INTO `t+1` VALUES (1), (2), (3); BACKUP TABLE `t+1` TO '../../tmp'; Table Op Msg_type Msg_text -test.t+1 backup Warning The syntax 'BACKUP TABLE' is deprecated and will be removed in MySQL 5.2. Please use MySQL Administrator (mysqldump, mysql) instead +test.t+1 backup Warning The syntax 'BACKUP TABLE' is deprecated and will be removed in MySQL 6.0. Please use MySQL Administrator (mysqldump, mysql) instead test.t+1 backup status OK DROP TABLE `t+1`; RESTORE TABLE `t+1` FROM '../../tmp'; Table Op Msg_type Msg_text -test.t+1 restore Warning The syntax 'RESTORE TABLE' is deprecated and will be removed in MySQL 5.2. Please use MySQL Administrator (mysqldump, mysql) instead +test.t+1 restore Warning The syntax 'RESTORE TABLE' is deprecated and will be removed in MySQL 6.0. Please use MySQL Administrator (mysqldump, mysql) instead test.t+1 restore status OK SELECT * FROM `t+1`; c1 diff --git a/mysql-test/r/show_check.result b/mysql-test/r/show_check.result index 2051939e4b6..c8ea9d79a13 100644 --- a/mysql-test/r/show_check.result +++ b/mysql-test/r/show_check.result @@ -1295,7 +1295,7 @@ drop database mysqltest; show full plugin; show warnings; Level Code Message -Warning 1287 The syntax 'SHOW PLUGIN' is deprecated and will be removed in MySQL 5.2. Please use 'SHOW PLUGINS' instead +Warning 1287 The syntax 'SHOW PLUGIN' is deprecated and will be removed in MySQL 6.0. Please use 'SHOW PLUGINS' instead show plugin; show plugins; create database `mysqlttest\1`; diff --git a/mysql-test/r/sp-error.result b/mysql-test/r/sp-error.result index 3def6536897..35d61ce757d 100644 --- a/mysql-test/r/sp-error.result +++ b/mysql-test/r/sp-error.result @@ -1643,7 +1643,7 @@ create table t1 (a int) type=MyISAM; drop table t1; end| Warnings: -Warning 1287 The syntax 'TYPE=storage_engine' is deprecated and will be removed in MySQL 5.2. Please use 'ENGINE=storage_engine' instead +Warning 1287 The syntax 'TYPE=storage_engine' is deprecated and will be removed in MySQL 6.0. Please use 'ENGINE=storage_engine' instead call p1(); call p1(); drop procedure p1; diff --git a/mysql-test/r/sp.result b/mysql-test/r/sp.result index cf4eac563ad..0a416a20c95 100644 --- a/mysql-test/r/sp.result +++ b/mysql-test/r/sp.result @@ -4350,10 +4350,10 @@ call bug13012()| Table Op Msg_type Msg_text test.t1 repair status OK Table Op Msg_type Msg_text -test.t1 backup Warning The syntax 'BACKUP TABLE' is deprecated and will be removed in MySQL 5.2. Please use MySQL Administrator (mysqldump, mysql) instead +test.t1 backup Warning The syntax 'BACKUP TABLE' is deprecated and will be removed in MySQL 6.0. Please use MySQL Administrator (mysqldump, mysql) instead test.t1 backup status OK Table Op Msg_type Msg_text -test.t1 restore Warning The syntax 'RESTORE TABLE' is deprecated and will be removed in MySQL 5.2. Please use MySQL Administrator (mysqldump, mysql) instead +test.t1 restore Warning The syntax 'RESTORE TABLE' is deprecated and will be removed in MySQL 6.0. Please use MySQL Administrator (mysqldump, mysql) instead test.t1 restore status OK drop procedure bug13012| create view v1 as select * from t1| diff --git a/mysql-test/r/sp_trans.result b/mysql-test/r/sp_trans.result index abd454ac907..3cc251bc0a6 100644 --- a/mysql-test/r/sp_trans.result +++ b/mysql-test/r/sp_trans.result @@ -535,7 +535,7 @@ use db_bug7787| CREATE PROCEDURE p1() SHOW INNODB STATUS; | Warnings: -Warning 1287 The syntax 'SHOW INNODB STATUS' is deprecated and will be removed in MySQL 5.2. Please use 'SHOW ENGINE INNODB STATUS' instead +Warning 1287 The syntax 'SHOW INNODB STATUS' is deprecated and will be removed in MySQL 6.0. Please use 'SHOW ENGINE INNODB STATUS' instead GRANT EXECUTE ON PROCEDURE p1 TO user_bug7787@localhost| DROP DATABASE db_bug7787| drop user user_bug7787@localhost| diff --git a/mysql-test/r/type_blob.result b/mysql-test/r/type_blob.result index a80adab1f87..d11ab236c34 100644 --- a/mysql-test/r/type_blob.result +++ b/mysql-test/r/type_blob.result @@ -891,11 +891,11 @@ CREATE TABLE b15776 (a year(-2)); ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '-2))' at line 1 CREATE TABLE b15776 (a timestamp(4294967294)); Warnings: -Warning 1287 The syntax 'TIMESTAMP(4294967294)' is deprecated and will be removed in MySQL 5.2. Please use 'TIMESTAMP' instead +Warning 1287 The syntax 'TIMESTAMP(4294967294)' is deprecated and will be removed in MySQL 6.0. Please use 'TIMESTAMP' instead DROP TABLE b15776; CREATE TABLE b15776 (a timestamp(4294967295)); Warnings: -Warning 1287 The syntax 'TIMESTAMP(4294967295)' is deprecated and will be removed in MySQL 5.2. Please use 'TIMESTAMP' instead +Warning 1287 The syntax 'TIMESTAMP(4294967295)' is deprecated and will be removed in MySQL 6.0. Please use 'TIMESTAMP' instead DROP TABLE b15776; CREATE TABLE b15776 (a timestamp(4294967296)); ERROR 42000: Display width out of range for column 'a' (max = 4294967295) diff --git a/mysql-test/r/type_timestamp.result b/mysql-test/r/type_timestamp.result index 91938771ee3..24cb725de9f 100644 --- a/mysql-test/r/type_timestamp.result +++ b/mysql-test/r/type_timestamp.result @@ -101,13 +101,13 @@ create table t1 (t2 timestamp(2), t4 timestamp(4), t6 timestamp(6), t8 timestamp(8), t10 timestamp(10), t12 timestamp(12), t14 timestamp(14)); Warnings: -Warning 1287 The syntax 'TIMESTAMP(2)' is deprecated and will be removed in MySQL 5.2. Please use 'TIMESTAMP' instead -Warning 1287 The syntax 'TIMESTAMP(4)' is deprecated and will be removed in MySQL 5.2. Please use 'TIMESTAMP' instead -Warning 1287 The syntax 'TIMESTAMP(6)' is deprecated and will be removed in MySQL 5.2. Please use 'TIMESTAMP' instead -Warning 1287 The syntax 'TIMESTAMP(8)' is deprecated and will be removed in MySQL 5.2. Please use 'TIMESTAMP' instead -Warning 1287 The syntax 'TIMESTAMP(10)' is deprecated and will be removed in MySQL 5.2. Please use 'TIMESTAMP' instead -Warning 1287 The syntax 'TIMESTAMP(12)' is deprecated and will be removed in MySQL 5.2. Please use 'TIMESTAMP' instead -Warning 1287 The syntax 'TIMESTAMP(14)' is deprecated and will be removed in MySQL 5.2. Please use 'TIMESTAMP' instead +Warning 1287 The syntax 'TIMESTAMP(2)' is deprecated and will be removed in MySQL 6.0. Please use 'TIMESTAMP' instead +Warning 1287 The syntax 'TIMESTAMP(4)' is deprecated and will be removed in MySQL 6.0. Please use 'TIMESTAMP' instead +Warning 1287 The syntax 'TIMESTAMP(6)' is deprecated and will be removed in MySQL 6.0. Please use 'TIMESTAMP' instead +Warning 1287 The syntax 'TIMESTAMP(8)' is deprecated and will be removed in MySQL 6.0. Please use 'TIMESTAMP' instead +Warning 1287 The syntax 'TIMESTAMP(10)' is deprecated and will be removed in MySQL 6.0. Please use 'TIMESTAMP' instead +Warning 1287 The syntax 'TIMESTAMP(12)' is deprecated and will be removed in MySQL 6.0. Please use 'TIMESTAMP' instead +Warning 1287 The syntax 'TIMESTAMP(14)' is deprecated and will be removed in MySQL 6.0. Please use 'TIMESTAMP' instead insert t1 values (0,0,0,0,0,0,0), ("1997-12-31 23:47:59", "1997-12-31 23:47:59", "1997-12-31 23:47:59", "1997-12-31 23:47:59", "1997-12-31 23:47:59", "1997-12-31 23:47:59", diff --git a/mysql-test/r/warnings.result b/mysql-test/r/warnings.result index 19d95acd5c1..2e393aea9e4 100644 --- a/mysql-test/r/warnings.result +++ b/mysql-test/r/warnings.result @@ -168,7 +168,7 @@ max_error_count 10 drop table t1; set table_type=MYISAM; Warnings: -Warning 1287 The syntax '@@table_type' is deprecated and will be removed in MySQL 5.2. Please use '@@storage_engine' instead +Warning 1287 The syntax '@@table_type' is deprecated and will be removed in MySQL 6.0. Please use '@@storage_engine' instead create table t1 (a int); insert into t1 (a) values (1), (2), (3), (4), (5), (6), (7), (8), (9), (10); update t1 set a='abc'; diff --git a/mysql-test/suite/rpl/r/rpl_sp.result b/mysql-test/suite/rpl/r/rpl_sp.result index 86d126f6176..90a362c352b 100644 --- a/mysql-test/suite/rpl/r/rpl_sp.result +++ b/mysql-test/suite/rpl/r/rpl_sp.result @@ -195,7 +195,7 @@ set @old_log_bin_trust_routine_creators= @@global.log_bin_trust_routine_creators set @old_log_bin_trust_function_creators= @@global.log_bin_trust_function_creators; set global log_bin_trust_routine_creators=1; Warnings: -Warning 1287 The syntax '@@log_bin_trust_routine_creators' is deprecated and will be removed in MySQL 5.2. Please use '@@log_bin_trust_function_creators' instead +Warning 1287 The syntax '@@log_bin_trust_routine_creators' is deprecated and will be removed in MySQL 6.0. Please use '@@log_bin_trust_function_creators' instead set global log_bin_trust_function_creators=0; set global log_bin_trust_function_creators=1; set @old_log_bin_trust_routine_creators= @@global.log_bin_trust_routine_creators; @@ -559,11 +559,11 @@ end master-bin.000001 # Query 1 # use `mysqltest`; SELECT `mysqltest2`.`f1`() set @@global.log_bin_trust_routine_creators= @old_log_bin_trust_routine_creators; Warnings: -Warning 1287 The syntax '@@log_bin_trust_routine_creators' is deprecated and will be removed in MySQL 5.2. Please use '@@log_bin_trust_function_creators' instead +Warning 1287 The syntax '@@log_bin_trust_routine_creators' is deprecated and will be removed in MySQL 6.0. Please use '@@log_bin_trust_function_creators' instead set @@global.log_bin_trust_function_creators= @old_log_bin_trust_function_creators; set @@global.log_bin_trust_routine_creators= @old_log_bin_trust_routine_creators; Warnings: -Warning 1287 The syntax '@@log_bin_trust_routine_creators' is deprecated and will be removed in MySQL 5.2. Please use '@@log_bin_trust_function_creators' instead +Warning 1287 The syntax '@@log_bin_trust_routine_creators' is deprecated and will be removed in MySQL 6.0. Please use '@@log_bin_trust_function_creators' instead set @@global.log_bin_trust_function_creators= @old_log_bin_trust_function_creators; drop database mysqltest; drop database mysqltest2; diff --git a/mysql-test/suite/sys_vars/r/log_bin_trust_routine_creators_basic.result b/mysql-test/suite/sys_vars/r/log_bin_trust_routine_creators_basic.result index cfcbcddfca3..66e253645b1 100644 --- a/mysql-test/suite/sys_vars/r/log_bin_trust_routine_creators_basic.result +++ b/mysql-test/suite/sys_vars/r/log_bin_trust_routine_creators_basic.result @@ -5,17 +5,17 @@ SELECT @start_global_value; '#--------------------FN_DYNVARS_064_01-------------------------#' SET @@global.log_bin_trust_routine_creators = TRUE; Warnings: -Warning 1287 The syntax '@@log_bin_trust_routine_creators' is deprecated and will be removed in MySQL 5.2. Please use '@@log_bin_trust_function_creators' instead +Warning 1287 The syntax '@@log_bin_trust_routine_creators' is deprecated and will be removed in MySQL 6.0. Please use '@@log_bin_trust_function_creators' instead SET @@global.log_bin_trust_routine_creators = DEFAULT; Warnings: -Warning 1287 The syntax '@@log_bin_trust_routine_creators' is deprecated and will be removed in MySQL 5.2. Please use '@@log_bin_trust_function_creators' instead +Warning 1287 The syntax '@@log_bin_trust_routine_creators' is deprecated and will be removed in MySQL 6.0. Please use '@@log_bin_trust_function_creators' instead SELECT @@global.log_bin_trust_routine_creators; @@global.log_bin_trust_routine_creators 0 '#--------------------FN_DYNVARS_064_02-------------------------#' SET @@global.log_bin_trust_routine_creators = DEFAULT; Warnings: -Warning 1287 The syntax '@@log_bin_trust_routine_creators' is deprecated and will be removed in MySQL 5.2. Please use '@@log_bin_trust_function_creators' instead +Warning 1287 The syntax '@@log_bin_trust_routine_creators' is deprecated and will be removed in MySQL 6.0. Please use '@@log_bin_trust_function_creators' instead SELECT @@global.log_bin_trust_routine_creators = 'FALSE'; @@global.log_bin_trust_routine_creators = 'FALSE' 1 @@ -24,37 +24,37 @@ Warning 1292 Truncated incorrect DOUBLE value: 'FALSE' '#--------------------FN_DYNVARS_064_03-------------------------#' SET @@global.log_bin_trust_routine_creators = ON; Warnings: -Warning 1287 The syntax '@@log_bin_trust_routine_creators' is deprecated and will be removed in MySQL 5.2. Please use '@@log_bin_trust_function_creators' instead +Warning 1287 The syntax '@@log_bin_trust_routine_creators' is deprecated and will be removed in MySQL 6.0. Please use '@@log_bin_trust_function_creators' instead SELECT @@global.log_bin_trust_routine_creators; @@global.log_bin_trust_routine_creators 1 SET @@global.log_bin_trust_routine_creators = OFF; Warnings: -Warning 1287 The syntax '@@log_bin_trust_routine_creators' is deprecated and will be removed in MySQL 5.2. Please use '@@log_bin_trust_function_creators' instead +Warning 1287 The syntax '@@log_bin_trust_routine_creators' is deprecated and will be removed in MySQL 6.0. Please use '@@log_bin_trust_function_creators' instead SELECT @@global.log_bin_trust_routine_creators; @@global.log_bin_trust_routine_creators 0 SET @@global.log_bin_trust_routine_creators = 0; Warnings: -Warning 1287 The syntax '@@log_bin_trust_routine_creators' is deprecated and will be removed in MySQL 5.2. Please use '@@log_bin_trust_function_creators' instead +Warning 1287 The syntax '@@log_bin_trust_routine_creators' is deprecated and will be removed in MySQL 6.0. Please use '@@log_bin_trust_function_creators' instead SELECT @@global.log_bin_trust_routine_creators; @@global.log_bin_trust_routine_creators 0 SET @@global.log_bin_trust_routine_creators = 1; Warnings: -Warning 1287 The syntax '@@log_bin_trust_routine_creators' is deprecated and will be removed in MySQL 5.2. Please use '@@log_bin_trust_function_creators' instead +Warning 1287 The syntax '@@log_bin_trust_routine_creators' is deprecated and will be removed in MySQL 6.0. Please use '@@log_bin_trust_function_creators' instead SELECT @@global.log_bin_trust_routine_creators; @@global.log_bin_trust_routine_creators 1 SET @@global.log_bin_trust_routine_creators = TRUE; Warnings: -Warning 1287 The syntax '@@log_bin_trust_routine_creators' is deprecated and will be removed in MySQL 5.2. Please use '@@log_bin_trust_function_creators' instead +Warning 1287 The syntax '@@log_bin_trust_routine_creators' is deprecated and will be removed in MySQL 6.0. Please use '@@log_bin_trust_function_creators' instead SELECT @@global.log_bin_trust_routine_creators; @@global.log_bin_trust_routine_creators 1 SET @@global.log_bin_trust_routine_creators = FALSE; Warnings: -Warning 1287 The syntax '@@log_bin_trust_routine_creators' is deprecated and will be removed in MySQL 5.2. Please use '@@log_bin_trust_function_creators' instead +Warning 1287 The syntax '@@log_bin_trust_routine_creators' is deprecated and will be removed in MySQL 6.0. Please use '@@log_bin_trust_function_creators' instead SELECT @@global.log_bin_trust_routine_creators; @@global.log_bin_trust_routine_creators 0 @@ -70,7 +70,7 @@ SET @@global.log_bin_trust_routine_creators = "OFFF"; ERROR 42000: Variable 'log_bin_trust_routine_creators' can't be set to the value of 'OFFF' SET @@global.log_bin_trust_routine_creators = OF; Warnings: -Warning 1287 The syntax '@@log_bin_trust_routine_creators' is deprecated and will be removed in MySQL 5.2. Please use '@@log_bin_trust_function_creators' instead +Warning 1287 The syntax '@@log_bin_trust_routine_creators' is deprecated and will be removed in MySQL 6.0. Please use '@@log_bin_trust_function_creators' instead SELECT @@global.log_bin_trust_routine_creators; @@global.log_bin_trust_routine_creators 0 @@ -96,14 +96,14 @@ ERROR HY000: Variable 'log_bin_trust_routine_creators' is a GLOBAL variable '#---------------------FN_DYNVARS_064_07----------------------#' SET @@global.log_bin_trust_routine_creators = TRUE; Warnings: -Warning 1287 The syntax '@@log_bin_trust_routine_creators' is deprecated and will be removed in MySQL 5.2. Please use '@@log_bin_trust_function_creators' instead +Warning 1287 The syntax '@@log_bin_trust_routine_creators' is deprecated and will be removed in MySQL 6.0. Please use '@@log_bin_trust_function_creators' instead SELECT @@log_bin_trust_routine_creators = @@global.log_bin_trust_routine_creators; @@log_bin_trust_routine_creators = @@global.log_bin_trust_routine_creators 1 '#---------------------FN_DYNVARS_064_08----------------------#' SET @@global.log_bin_trust_routine_creators = TRUE; Warnings: -Warning 1287 The syntax '@@log_bin_trust_routine_creators' is deprecated and will be removed in MySQL 5.2. Please use '@@log_bin_trust_function_creators' instead +Warning 1287 The syntax '@@log_bin_trust_routine_creators' is deprecated and will be removed in MySQL 6.0. Please use '@@log_bin_trust_function_creators' instead SELECT @@log_bin_trust_routine_creators; @@log_bin_trust_routine_creators 1 @@ -115,7 +115,7 @@ SELECT log_bin_trust_routine_creators = @@session.log_bin_trust_routine_creators ERROR 42S22: Unknown column 'log_bin_trust_routine_creators' in 'field list' SET @@global.log_bin_trust_routine_creators = @start_global_value; Warnings: -Warning 1287 The syntax '@@log_bin_trust_routine_creators' is deprecated and will be removed in MySQL 5.2. Please use '@@log_bin_trust_function_creators' instead +Warning 1287 The syntax '@@log_bin_trust_routine_creators' is deprecated and will be removed in MySQL 6.0. Please use '@@log_bin_trust_function_creators' instead SELECT @@global.log_bin_trust_routine_creators; @@global.log_bin_trust_routine_creators 1 diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 88b923244e7..973073935a4 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -8053,7 +8053,7 @@ mysqld_get_one_option(int optid, if (!slave_warning_issued) //only show the warning once { slave_warning_issued = true; - WARN_DEPRECATED(NULL, "5.2", "for replication startup options", + WARN_DEPRECATED(NULL, "6.0", "for replication startup options", "'CHANGE MASTER'"); } break; diff --git a/sql/set_var.cc b/sql/set_var.cc index f14068fcfcb..7e2efd2d580 100644 --- a/sql/set_var.cc +++ b/sql/set_var.cc @@ -3682,7 +3682,7 @@ bool sys_var_thd_storage_engine::update(THD *thd, set_var *var) void sys_var_thd_table_type::warn_deprecated(THD *thd) { - WARN_DEPRECATED(thd, "5.2", "@@table_type", "'@@storage_engine'"); + WARN_DEPRECATED(thd, "6.0", "@@table_type", "'@@storage_engine'"); } void sys_var_thd_table_type::set_default(THD *thd, enum_var_type type) @@ -3944,7 +3944,7 @@ bool process_key_caches(process_key_cache_t func) void sys_var_trust_routine_creators::warn_deprecated(THD *thd) { - WARN_DEPRECATED(thd, "5.2", "@@log_bin_trust_routine_creators", + WARN_DEPRECATED(thd, "6.0", "@@log_bin_trust_routine_creators", "'@@log_bin_trust_function_creators'"); } diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 7c5f469da41..f7d6d5bac4d 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -5967,7 +5967,7 @@ bool add_field_to_list(THD *thd, LEX_STRING *field_name, enum_field_types type, */ char buf[32]; my_snprintf(buf, sizeof(buf), "TIMESTAMP(%s)", length); - WARN_DEPRECATED(thd, "5.2", buf, "'TIMESTAMP'"); + WARN_DEPRECATED(thd, "6.0", buf, "'TIMESTAMP'"); } if (!(new_field= new Create_field()) || diff --git a/sql/sql_table.cc b/sql/sql_table.cc index aa2a5739f17..f0059e7a95b 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -4639,7 +4639,7 @@ err: bool mysql_backup_table(THD* thd, TABLE_LIST* table_list) { DBUG_ENTER("mysql_backup_table"); - WARN_DEPRECATED(thd, "5.2", "BACKUP TABLE", + WARN_DEPRECATED(thd, "6.0", "BACKUP TABLE", "MySQL Administrator (mysqldump, mysql)"); DBUG_RETURN(mysql_admin_table(thd, table_list, 0, "backup", TL_READ, 0, 0, 0, 0, @@ -4650,7 +4650,7 @@ bool mysql_backup_table(THD* thd, TABLE_LIST* table_list) bool mysql_restore_table(THD* thd, TABLE_LIST* table_list) { DBUG_ENTER("mysql_restore_table"); - WARN_DEPRECATED(thd, "5.2", "RESTORE TABLE", + WARN_DEPRECATED(thd, "6.0", "RESTORE TABLE", "MySQL Administrator (mysqldump, mysql)"); DBUG_RETURN(mysql_admin_table(thd, table_list, 0, "restore", TL_WRITE, 1, 1, 0, diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 588c4334b84..371a146696d 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -4392,7 +4392,7 @@ create_table_option: | TYPE_SYM opt_equal storage_engines { Lex->create_info.db_type= $3; - WARN_DEPRECATED(yythd, "5.2", "TYPE=storage_engine", + WARN_DEPRECATED(yythd, "6.0", "TYPE=storage_engine", "'ENGINE=storage_engine'"); Lex->create_info.used_fields|= HA_CREATE_USED_ENGINE; } @@ -9874,7 +9874,7 @@ show_param: | opt_full PLUGIN_SYM { LEX *lex= Lex; - WARN_DEPRECATED(yythd, "5.2", "SHOW PLUGIN", "'SHOW PLUGINS'"); + WARN_DEPRECATED(yythd, "6.0", "SHOW PLUGIN", "'SHOW PLUGINS'"); lex->sql_command= SQLCOM_SHOW_PLUGINS; if (prepare_schema_table(YYTHD, lex, 0, SCH_PLUGINS)) MYSQL_YYABORT; @@ -9943,7 +9943,7 @@ show_param: { LEX *lex=Lex; lex->sql_command= SQLCOM_SHOW_STORAGE_ENGINES; - WARN_DEPRECATED(yythd, "5.2", "SHOW TABLE TYPES", "'SHOW [STORAGE] ENGINES'"); + WARN_DEPRECATED(yythd, "6.0", "SHOW TABLE TYPES", "'SHOW [STORAGE] ENGINES'"); if (prepare_schema_table(YYTHD, lex, 0, SCH_ENGINES)) MYSQL_YYABORT; } @@ -10004,7 +10004,7 @@ show_param: my_error(ER_UNKNOWN_STORAGE_ENGINE, MYF(0), "InnoDB"); MYSQL_YYABORT; } - WARN_DEPRECATED(yythd, "5.2", "SHOW INNODB STATUS", "'SHOW ENGINE INNODB STATUS'"); + WARN_DEPRECATED(yythd, "6.0", "SHOW INNODB STATUS", "'SHOW ENGINE INNODB STATUS'"); } | MUTEX_SYM STATUS_SYM { @@ -10016,7 +10016,7 @@ show_param: my_error(ER_UNKNOWN_STORAGE_ENGINE, MYF(0), "InnoDB"); MYSQL_YYABORT; } - WARN_DEPRECATED(yythd, "5.2", "SHOW MUTEX STATUS", "'SHOW ENGINE INNODB MUTEX'"); + WARN_DEPRECATED(yythd, "6.0", "SHOW MUTEX STATUS", "'SHOW ENGINE INNODB MUTEX'"); } | opt_full PROCESSLIST_SYM { Lex->sql_command= SQLCOM_SHOW_PROCESSLIST;} @@ -10411,7 +10411,7 @@ load: | LOAD TABLE_SYM table_ident FROM MASTER_SYM { LEX *lex=Lex; - WARN_DEPRECATED(yythd, "5.2", "LOAD TABLE FROM MASTER", + WARN_DEPRECATED(yythd, "6.0", "LOAD TABLE FROM MASTER", "MySQL Administrator (mysqldump, mysql)"); if (lex->sphead) { @@ -10458,7 +10458,7 @@ load_data: | FROM MASTER_SYM { Lex->sql_command = SQLCOM_LOAD_MASTER_DATA; - WARN_DEPRECATED(yythd, "5.2", "LOAD DATA FROM MASTER", + WARN_DEPRECATED(yythd, "6.0", "LOAD DATA FROM MASTER", "mysqldump or future " "BACKUP/RESTORE DATABASE facility"); } From 924950b6312e46c8d9e574ad44ce0d6f294f72fd Mon Sep 17 00:00:00 2001 From: Andrei Elkin Date: Mon, 16 Feb 2009 14:51:39 +0200 Subject: [PATCH 094/219] commenting windows disable for rpl_cross_version to relate to Bug #42879 --- mysql-test/suite/rpl/t/rpl_cross_version.test | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/mysql-test/suite/rpl/t/rpl_cross_version.test b/mysql-test/suite/rpl/t/rpl_cross_version.test index adeba7f2b15..8cd268a5fd9 100644 --- a/mysql-test/suite/rpl/t/rpl_cross_version.test +++ b/mysql-test/suite/rpl/t/rpl_cross_version.test @@ -11,7 +11,12 @@ # --source include/have_log_bin.inc + +# The test is disabled for windows due to +# Bug #42879 CHANGE MASTER RELAY_LOG_FILE=path fails on windows +# Todo: release it from not_windows --source include/not_windows.inc + # # Bug#31240 load data infile replication between (4.0 or 4.1) and 5.1 fails # From ec8de22f9f6671b512c1da365146a0fd04df7b57 Mon Sep 17 00:00:00 2001 From: "Tatiana A. Nurnberg" Date: Mon, 16 Feb 2009 15:38:18 +0100 Subject: [PATCH 095/219] Bug#42027: Incorrect parsing of debug and verbose options for mysqldumpslow Options got normalised to long rather than short options since we gave primary name and alias in wrong order. Consequently querying for the option using the short options (the correct primary name) didn't work, rendering the options in question inaccessible. We restore the right order of the universe, or at least the alii for --debug and --verbose. scripts/mysqldumpslow.sh: Normalise --verbose/-v and --debug/-d to short options, not long options. --- scripts/mysqldumpslow.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/mysqldumpslow.sh b/scripts/mysqldumpslow.sh index f05761bb837..009745fd896 100644 --- a/scripts/mysqldumpslow.sh +++ b/scripts/mysqldumpslow.sh @@ -17,9 +17,9 @@ my %opt = ( ); GetOptions(\%opt, - 'verbose|v+',# verbose + 'v|verbose+',# verbose 'help+', # write usage info - 'debug|d+', # debug + 'd|debug+', # debug 's=s', # what to sort by (t, at, l, al, r, ar etc) 'r!', # reverse the sort order (largest last instead of first) 't=i', # just show the top n queries From 544fa7593b92a3949b9676e9abd9ad5e7a1a5c30 Mon Sep 17 00:00:00 2001 From: Sergey Glukhov Date: Tue, 17 Feb 2009 18:22:48 +0400 Subject: [PATCH 096/219] Bug#25830 SHOW TABLE STATUS behaves differently depending on table name(for 5.0 only) replace wild_case_compare with my_wildcmp which is multibyte safe function mysql-test/r/lowercase_utf8.result: test result mysql-test/t/lowercase_utf8-master.opt: test case mysql-test/t/lowercase_utf8.test: test case sql/sql_show.cc: replace wild_case_compare with my_wildcmp which is multibyte safe function --- mysql-test/r/lowercase_utf8.result | 9 +++++++++ mysql-test/t/lowercase_utf8-master.opt | 4 ++++ mysql-test/t/lowercase_utf8.test | 9 +++++++++ sql/sql_show.cc | 18 ++++++++++++++---- 4 files changed, 36 insertions(+), 4 deletions(-) create mode 100644 mysql-test/r/lowercase_utf8.result create mode 100644 mysql-test/t/lowercase_utf8-master.opt create mode 100644 mysql-test/t/lowercase_utf8.test diff --git a/mysql-test/r/lowercase_utf8.result b/mysql-test/r/lowercase_utf8.result new file mode 100644 index 00000000000..945e0912e80 --- /dev/null +++ b/mysql-test/r/lowercase_utf8.result @@ -0,0 +1,9 @@ +set names utf8; +create table `Ð` (id int); +show tables from test like 'Ð'; +Tables_in_test (Ð) +а +show tables from test like 'а'; +Tables_in_test (а) +а +drop table `Ð`; diff --git a/mysql-test/t/lowercase_utf8-master.opt b/mysql-test/t/lowercase_utf8-master.opt new file mode 100644 index 00000000000..1b70aa33023 --- /dev/null +++ b/mysql-test/t/lowercase_utf8-master.opt @@ -0,0 +1,4 @@ +--lower-case-table-names=1 --character-set-server=utf8 + + + diff --git a/mysql-test/t/lowercase_utf8.test b/mysql-test/t/lowercase_utf8.test new file mode 100644 index 00000000000..a0d847d5b9f --- /dev/null +++ b/mysql-test/t/lowercase_utf8.test @@ -0,0 +1,9 @@ +# +# Bug#25830 SHOW TABLE STATUS behaves differently depending on table name +# +set names utf8; +create table `Ð` (id int); +show tables from test like 'Ð'; +show tables from test like 'а'; +drop table `Ð`; + diff --git a/sql/sql_show.cc b/sql/sql_show.cc index d6bb3427fe4..19155eec06b 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -287,11 +287,18 @@ find_files(THD *thd, List *files, const char *db, #ifndef NO_EMBEDDED_ACCESS_CHECKS uint col_access=thd->col_access; #endif + uint wild_length= 0; TABLE_LIST table_list; DBUG_ENTER("find_files"); - if (wild && !wild[0]) - wild=0; + if (wild) + { + if (!wild[0]) + wild= 0; + else + wild_length= strlen(wild); + } + bzero((char*) &table_list,sizeof(table_list)); @@ -340,8 +347,11 @@ find_files(THD *thd, List *files, const char *db, { if (lower_case_table_names) { - if (wild_case_compare(files_charset_info, file->name, wild)) - continue; + if (my_wildcmp(files_charset_info, + file->name, file->name + strlen(file->name), + wild, wild + wild_length, + wild_prefix, wild_one,wild_many)) + continue; } else if (wild_compare(file->name,wild,0)) continue; From 41728a3104dde42a5eb65c78a9978d7f4b4adff3 Mon Sep 17 00:00:00 2001 From: Georgi Kodinov Date: Wed, 18 Feb 2009 12:18:38 +0200 Subject: [PATCH 097/219] Bug #26724: mysql command line client, ignores input to internal cmd after space Removed the misleading "NOTE:" from the \h command. client/mysql.cc: Bug #26724: removed the misleading note from the \h command --- client/mysql.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/mysql.cc b/client/mysql.cc index 88ddd40fa68..2ecfd637453 100644 --- a/client/mysql.cc +++ b/client/mysql.cc @@ -243,7 +243,7 @@ static COMMANDS commands[] = { { "connect",'r', com_connect,1, "Reconnect to the server. Optional arguments are db and host." }, { "delimiter", 'd', com_delimiter, 1, - "Set statement delimiter. NOTE: Takes the rest of the line as new delimiter." }, + "Set statement delimiter." }, #ifdef USE_POPEN { "edit", 'e', com_edit, 0, "Edit command with $EDITOR."}, #endif From 85cc17d3cd2a7ae926ed58adbb0446b9a2b09ed2 Mon Sep 17 00:00:00 2001 From: Mattias Jonsson Date: Wed, 18 Feb 2009 21:10:19 +0100 Subject: [PATCH 098/219] Bug#36001: Partitions: spelling and using some error messages Backport from 6.0 Changed error message to show that it is partitioning that does not support foreign keys yet. Changed spelling from British english to American english. mysql-test/r/partition.result: Bug#36001: Partitions: spelling and using some error messages Backport from 6.0 Changed spelling from British english to American english. mysql-test/r/partition_mgm_err.result: Bug#36001: Partitions: spelling and using some error messages Backport from 6.0 Changed spelling from British english to American english. mysql-test/t/partition.test: Bug#36001: Partitions: spelling and using some error messages Backport from 6.0 Added test for verifying error message sql/share/errmsg.txt: Bug#36001: Partitions: spelling and using some error messages Backport from 6.0 Changed spelling from British english to American english. sql/sql_table.cc: Bug#36001: Partitions: spelling and using some error messages Backport from 6.0 Using a better error message. --- mysql-test/r/partition.result | 4 ++++ mysql-test/r/partition_mgm_err.result | 4 ++-- mysql-test/t/partition.test | 8 ++++++++ sql/share/errmsg.txt | 16 ++++++++-------- sql/sql_table.cc | 2 +- 5 files changed, 23 insertions(+), 11 deletions(-) diff --git a/mysql-test/r/partition.result b/mysql-test/r/partition.result index cec4e60d139..c5733e33569 100644 --- a/mysql-test/r/partition.result +++ b/mysql-test/r/partition.result @@ -1,5 +1,9 @@ SET @old_general_log= @@global.general_log; drop table if exists t1, t2; +CREATE TABLE t1 (a INT, FOREIGN KEY (a) REFERENCES t0 (a)) +ENGINE=MyISAM +PARTITION BY HASH (a); +ERROR HY000: Foreign key clause is not yet supported in conjunction with partitioning CREATE TABLE t1 ( pk INT NOT NULL AUTO_INCREMENT, PRIMARY KEY (pk) diff --git a/mysql-test/r/partition_mgm_err.result b/mysql-test/r/partition_mgm_err.result index db89c6ef6e7..f8403988f47 100644 --- a/mysql-test/r/partition_mgm_err.result +++ b/mysql-test/r/partition_mgm_err.result @@ -25,13 +25,13 @@ ALTER TABLE t1 DROP PARTITION x10, x1, x2, x3; ERROR HY000: Error in list of partitions to DROP ALTER TABLE t1 REORGANIZE PARTITION x0,x1,x2,x3,x4,x5,x6,x7,x8,x9,x10 INTO (PARTITION x11 VALUES LESS THAN (22)); -ERROR HY000: More partitions to reorganise than there are partitions +ERROR HY000: More partitions to reorganize than there are partitions ALTER TABLE t1 REORGANIZE PARTITION x0,x1,x2 INTO (PARTITION x3 VALUES LESS THAN (6)); ERROR HY000: Duplicate partition name x3 ALTER TABLE t1 REORGANIZE PARTITION x0, x2 INTO (PARTITION x11 VALUES LESS THAN (2)); -ERROR HY000: When reorganising a set of partitions they must be in consecutive order +ERROR HY000: When reorganizing a set of partitions they must be in consecutive order ALTER TABLE t1 REORGANIZE PARTITION x0, x1, x1 INTO (PARTITION x11 VALUES LESS THAN (4)); ERROR HY000: Error in list of partitions to REORGANIZE diff --git a/mysql-test/t/partition.test b/mysql-test/t/partition.test index 23a300de9e5..fc6a33819d6 100644 --- a/mysql-test/t/partition.test +++ b/mysql-test/t/partition.test @@ -16,6 +16,14 @@ SET @old_general_log= @@global.general_log; drop table if exists t1, t2; --enable_warnings +# +# Bug#36001: Partitions: spelling and using some error messages +# +--error ER_FOREIGN_KEY_ON_PARTITIONED +CREATE TABLE t1 (a INT, FOREIGN KEY (a) REFERENCES t0 (a)) +ENGINE=MyISAM +PARTITION BY HASH (a); + # # Bug#40954: Crash if range search and order by. # diff --git a/sql/share/errmsg.txt b/sql/share/errmsg.txt index befd064e3e3..5dc75c340ea 100644 --- a/sql/share/errmsg.txt +++ b/sql/share/errmsg.txt @@ -5775,9 +5775,9 @@ ER_PARTITION_MGMT_ON_NONPARTITIONED ger "Partitionsverwaltung einer nicht partitionierten Tabelle ist nicht möglich" swe "Partitioneringskommando på en opartitionerad tabell är inte möjligt" ER_FOREIGN_KEY_ON_PARTITIONED - eng "Foreign key condition is not yet supported in conjunction with partitioning" + eng "Foreign key clause is not yet supported in conjunction with partitioning" ger "Fremdschlüssel-Beschränkungen sind im Zusammenhang mit Partitionierung nicht zulässig" - swe "Foreign key villkor är inte ännu implementerad i kombination med partitionering" + swe "Foreign key klausul är inte ännu implementerad i kombination med partitionering" ER_DROP_PARTITION_NON_EXISTENT eng "Error in list of partitions to %-.64s" ger "Fehler in der Partitionsliste bei %-.64s" @@ -5791,13 +5791,13 @@ ER_COALESCE_ONLY_ON_HASH_PARTITION ger "COALESCE PARTITION kann nur auf HASH- oder KEY-Partitionen benutzt werden" swe "COALESCE PARTITION kan bara användas på HASH/KEY partitioner" ER_REORG_HASH_ONLY_ON_SAME_NO - eng "REORGANISE PARTITION can only be used to reorganise partitions not to change their numbers" + eng "REORGANIZE PARTITION can only be used to reorganize partitions not to change their numbers" ger "REORGANIZE PARTITION kann nur zur Reorganisation von Partitionen verwendet werden, nicht, um ihre Nummern zu ändern" - swe "REORGANISE PARTITION kan bara användas för att omorganisera partitioner, inte för att ändra deras antal" + swe "REORGANIZE PARTITION kan bara användas för att omorganisera partitioner, inte för att ändra deras antal" ER_REORG_NO_PARAM_ERROR - eng "REORGANISE PARTITION without parameters can only be used on auto-partitioned tables using HASH PARTITIONs" + eng "REORGANIZE PARTITION without parameters can only be used on auto-partitioned tables using HASH PARTITIONs" ger "REORGANIZE PARTITION ohne Parameter kann nur für auto-partitionierte Tabellen verwendet werden, die HASH-Partitionierung benutzen" - swe "REORGANISE PARTITION utan parametrar kan bara användas på auto-partitionerade tabeller som använder HASH partitionering" + swe "REORGANIZE PARTITION utan parametrar kan bara användas på auto-partitionerade tabeller som använder HASH partitionering" ER_ONLY_ON_RANGE_LIST_PARTITION eng "%-.64s PARTITION can only be used on RANGE/LIST partitions" ger "%-.64s PARTITION kann nur für RANGE- oder LIST-Partitionen verwendet werden" @@ -5815,7 +5815,7 @@ ER_COALESCE_PARTITION_NO_PARTITION ger "Zumindest eine Partition muss mit COALESCE PARTITION zusammengefügt werden" swe "Åtminstone en partition måste slås ihop vid COALESCE PARTITION" ER_REORG_PARTITION_NOT_EXIST - eng "More partitions to reorganise than there are partitions" + eng "More partitions to reorganize than there are partitions" ger "Es wurde versucht, mehr Partitionen als vorhanden zu reorganisieren" swe "Fler partitioner att reorganisera än det finns partitioner" ER_SAME_NAME_PARTITION @@ -5827,7 +5827,7 @@ ER_NO_BINLOG_ERROR ger "Es es nicht erlaubt, bei diesem Befehl binlog abzuschalten" swe "Det är inte tillåtet att stänga av binlog på detta kommando" ER_CONSECUTIVE_REORG_PARTITIONS - eng "When reorganising a set of partitions they must be in consecutive order" + eng "When reorganizing a set of partitions they must be in consecutive order" ger "Bei der Reorganisation eines Satzes von Partitionen müssen diese in geordneter Reihenfolge vorliegen" swe "När ett antal partitioner omorganiseras måste de vara i konsekutiv ordning" ER_REORG_OUTSIDE_RANGE diff --git a/sql/sql_table.cc b/sql/sql_table.cc index aa2a5739f17..e72aa3ca8f3 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -3321,7 +3321,7 @@ bool mysql_create_table_no_lock(THD *thd, if (key->type == Key::FOREIGN_KEY && !part_info->is_auto_partitioned) { - my_error(ER_CANNOT_ADD_FOREIGN, MYF(0)); + my_error(ER_FOREIGN_KEY_ON_PARTITIONED, MYF(0)); goto err; } } From bf442fcaae7772f00c04e180cee81304f288b31e Mon Sep 17 00:00:00 2001 From: Mattias Jonsson Date: Wed, 18 Feb 2009 21:22:56 +0100 Subject: [PATCH 099/219] Backport of bug#36001 from 6.0 to 5.1 --- .../suite/parts/r/partition_mgm_lc0_archive.result | 12 ++++++------ .../suite/parts/r/partition_mgm_lc0_innodb.result | 12 ++++++------ .../suite/parts/r/partition_mgm_lc0_memory.result | 12 ++++++------ .../suite/parts/r/partition_mgm_lc0_myisam.result | 12 ++++++------ .../suite/parts/r/partition_mgm_lc0_ndb.result | 4 ++-- .../suite/parts/r/partition_mgm_lc1_archive.result | 12 ++++++------ .../suite/parts/r/partition_mgm_lc1_innodb.result | 12 ++++++------ .../suite/parts/r/partition_mgm_lc1_memory.result | 12 ++++++------ .../suite/parts/r/partition_mgm_lc1_myisam.result | 12 ++++++------ .../suite/parts/r/partition_mgm_lc1_ndb.result | 4 ++-- .../suite/parts/r/partition_mgm_lc2_archive.result | 12 ++++++------ .../suite/parts/r/partition_mgm_lc2_innodb.result | 12 ++++++------ .../suite/parts/r/partition_mgm_lc2_memory.result | 12 ++++++------ .../suite/parts/r/partition_mgm_lc2_myisam.result | 12 ++++++------ .../suite/parts/r/partition_mgm_lc2_ndb.result | 4 ++-- 15 files changed, 78 insertions(+), 78 deletions(-) diff --git a/mysql-test/suite/parts/r/partition_mgm_lc0_archive.result b/mysql-test/suite/parts/r/partition_mgm_lc0_archive.result index 7672ac330fb..30ff27df298 100644 --- a/mysql-test/suite/parts/r/partition_mgm_lc0_archive.result +++ b/mysql-test/suite/parts/r/partition_mgm_lc0_archive.result @@ -93,11 +93,11 @@ TableA CREATE TABLE `TableA` ( ALTER TABLE TableA REORGANIZE PARTITION parta,partB,Partc INTO (PARTITION PARTA , PARTITION partc ); -ERROR HY000: REORGANISE PARTITION can only be used to reorganise partitions not to change their numbers +ERROR HY000: REORGANIZE PARTITION can only be used to reorganize partitions not to change their numbers ALTER TABLE TableA REORGANIZE PARTITION parta,Partc INTO (PARTITION partB , PARTITION parta ); -ERROR HY000: When reorganising a set of partitions they must be in consecutive order +ERROR HY000: When reorganizing a set of partitions they must be in consecutive order ALTER TABLE TableA REORGANIZE PARTITION parta,partB INTO (PARTITION partB COMMENT="Previusly named parta", PARTITION parta COMMENT="Previusly named partB"); @@ -329,11 +329,11 @@ TableA CREATE TABLE `TableA` ( ALTER TABLE TableA REORGANIZE PARTITION parta,partB,Partc INTO (PARTITION PARTA , PARTITION partc ); -ERROR HY000: REORGANISE PARTITION can only be used to reorganise partitions not to change their numbers +ERROR HY000: REORGANIZE PARTITION can only be used to reorganize partitions not to change their numbers ALTER TABLE TableA REORGANIZE PARTITION parta,Partc INTO (PARTITION partB , PARTITION parta ); -ERROR HY000: When reorganising a set of partitions they must be in consecutive order +ERROR HY000: When reorganizing a set of partitions they must be in consecutive order ALTER TABLE TableA REORGANIZE PARTITION parta,partB INTO (PARTITION partB COMMENT="Previusly named parta", PARTITION parta COMMENT="Previusly named partB"); @@ -559,7 +559,7 @@ TableA CREATE TABLE `TableA` ( ALTER TABLE TableA REORGANIZE PARTITION parta,Partc INTO (PARTITION partB VALUES LESS THAN (3) , PARTITION parta VALUES LESS THAN (11) ); -ERROR HY000: When reorganising a set of partitions they must be in consecutive order +ERROR HY000: When reorganizing a set of partitions they must be in consecutive order ALTER TABLE TableA REORGANIZE PARTITION partB,Partc,PartD,PartE INTO (PARTITION partD VALUES LESS THAN (8) COMMENT="Previously partB and partly Partc", @@ -793,7 +793,7 @@ PARTITION partF VALUES IN (3,9) COMMENT = "Mix 2 of old parta and Partc", PARTITION parta VALUES IN (4,8) COMMENT = "Mix 3 of old parta and Partc"); -ERROR HY000: When reorganising a set of partitions they must be in consecutive order +ERROR HY000: When reorganizing a set of partitions they must be in consecutive order ALTER TABLE TableA REORGANIZE PARTITION parta,partB,Partc INTO (PARTITION Partc VALUES IN (1,7) COMMENT = "Mix 1 of old parta and Partc", diff --git a/mysql-test/suite/parts/r/partition_mgm_lc0_innodb.result b/mysql-test/suite/parts/r/partition_mgm_lc0_innodb.result index e85cbeba594..cd55ffbad03 100644 --- a/mysql-test/suite/parts/r/partition_mgm_lc0_innodb.result +++ b/mysql-test/suite/parts/r/partition_mgm_lc0_innodb.result @@ -93,11 +93,11 @@ TableA CREATE TABLE `TableA` ( ALTER TABLE TableA REORGANIZE PARTITION parta,partB,Partc INTO (PARTITION PARTA , PARTITION partc ); -ERROR HY000: REORGANISE PARTITION can only be used to reorganise partitions not to change their numbers +ERROR HY000: REORGANIZE PARTITION can only be used to reorganize partitions not to change their numbers ALTER TABLE TableA REORGANIZE PARTITION parta,Partc INTO (PARTITION partB , PARTITION parta ); -ERROR HY000: When reorganising a set of partitions they must be in consecutive order +ERROR HY000: When reorganizing a set of partitions they must be in consecutive order ALTER TABLE TableA REORGANIZE PARTITION parta,partB INTO (PARTITION partB COMMENT="Previusly named parta", PARTITION parta COMMENT="Previusly named partB"); @@ -329,11 +329,11 @@ TableA CREATE TABLE `TableA` ( ALTER TABLE TableA REORGANIZE PARTITION parta,partB,Partc INTO (PARTITION PARTA , PARTITION partc ); -ERROR HY000: REORGANISE PARTITION can only be used to reorganise partitions not to change their numbers +ERROR HY000: REORGANIZE PARTITION can only be used to reorganize partitions not to change their numbers ALTER TABLE TableA REORGANIZE PARTITION parta,Partc INTO (PARTITION partB , PARTITION parta ); -ERROR HY000: When reorganising a set of partitions they must be in consecutive order +ERROR HY000: When reorganizing a set of partitions they must be in consecutive order ALTER TABLE TableA REORGANIZE PARTITION parta,partB INTO (PARTITION partB COMMENT="Previusly named parta", PARTITION parta COMMENT="Previusly named partB"); @@ -559,7 +559,7 @@ TableA CREATE TABLE `TableA` ( ALTER TABLE TableA REORGANIZE PARTITION parta,Partc INTO (PARTITION partB VALUES LESS THAN (3) , PARTITION parta VALUES LESS THAN (11) ); -ERROR HY000: When reorganising a set of partitions they must be in consecutive order +ERROR HY000: When reorganizing a set of partitions they must be in consecutive order ALTER TABLE TableA REORGANIZE PARTITION partB,Partc,PartD,PartE INTO (PARTITION partD VALUES LESS THAN (8) COMMENT="Previously partB and partly Partc", @@ -793,7 +793,7 @@ PARTITION partF VALUES IN (3,9) COMMENT = "Mix 2 of old parta and Partc", PARTITION parta VALUES IN (4,8) COMMENT = "Mix 3 of old parta and Partc"); -ERROR HY000: When reorganising a set of partitions they must be in consecutive order +ERROR HY000: When reorganizing a set of partitions they must be in consecutive order ALTER TABLE TableA REORGANIZE PARTITION parta,partB,Partc INTO (PARTITION Partc VALUES IN (1,7) COMMENT = "Mix 1 of old parta and Partc", diff --git a/mysql-test/suite/parts/r/partition_mgm_lc0_memory.result b/mysql-test/suite/parts/r/partition_mgm_lc0_memory.result index 1f7197abe6d..faf776e03a3 100644 --- a/mysql-test/suite/parts/r/partition_mgm_lc0_memory.result +++ b/mysql-test/suite/parts/r/partition_mgm_lc0_memory.result @@ -93,11 +93,11 @@ TableA CREATE TABLE `TableA` ( ALTER TABLE TableA REORGANIZE PARTITION parta,partB,Partc INTO (PARTITION PARTA , PARTITION partc ); -ERROR HY000: REORGANISE PARTITION can only be used to reorganise partitions not to change their numbers +ERROR HY000: REORGANIZE PARTITION can only be used to reorganize partitions not to change their numbers ALTER TABLE TableA REORGANIZE PARTITION parta,Partc INTO (PARTITION partB , PARTITION parta ); -ERROR HY000: When reorganising a set of partitions they must be in consecutive order +ERROR HY000: When reorganizing a set of partitions they must be in consecutive order ALTER TABLE TableA REORGANIZE PARTITION parta,partB INTO (PARTITION partB COMMENT="Previusly named parta", PARTITION parta COMMENT="Previusly named partB"); @@ -329,11 +329,11 @@ TableA CREATE TABLE `TableA` ( ALTER TABLE TableA REORGANIZE PARTITION parta,partB,Partc INTO (PARTITION PARTA , PARTITION partc ); -ERROR HY000: REORGANISE PARTITION can only be used to reorganise partitions not to change their numbers +ERROR HY000: REORGANIZE PARTITION can only be used to reorganize partitions not to change their numbers ALTER TABLE TableA REORGANIZE PARTITION parta,Partc INTO (PARTITION partB , PARTITION parta ); -ERROR HY000: When reorganising a set of partitions they must be in consecutive order +ERROR HY000: When reorganizing a set of partitions they must be in consecutive order ALTER TABLE TableA REORGANIZE PARTITION parta,partB INTO (PARTITION partB COMMENT="Previusly named parta", PARTITION parta COMMENT="Previusly named partB"); @@ -559,7 +559,7 @@ TableA CREATE TABLE `TableA` ( ALTER TABLE TableA REORGANIZE PARTITION parta,Partc INTO (PARTITION partB VALUES LESS THAN (3) , PARTITION parta VALUES LESS THAN (11) ); -ERROR HY000: When reorganising a set of partitions they must be in consecutive order +ERROR HY000: When reorganizing a set of partitions they must be in consecutive order ALTER TABLE TableA REORGANIZE PARTITION partB,Partc,PartD,PartE INTO (PARTITION partD VALUES LESS THAN (8) COMMENT="Previously partB and partly Partc", @@ -793,7 +793,7 @@ PARTITION partF VALUES IN (3,9) COMMENT = "Mix 2 of old parta and Partc", PARTITION parta VALUES IN (4,8) COMMENT = "Mix 3 of old parta and Partc"); -ERROR HY000: When reorganising a set of partitions they must be in consecutive order +ERROR HY000: When reorganizing a set of partitions they must be in consecutive order ALTER TABLE TableA REORGANIZE PARTITION parta,partB,Partc INTO (PARTITION Partc VALUES IN (1,7) COMMENT = "Mix 1 of old parta and Partc", diff --git a/mysql-test/suite/parts/r/partition_mgm_lc0_myisam.result b/mysql-test/suite/parts/r/partition_mgm_lc0_myisam.result index cb5228bd78e..827f7a15c24 100644 --- a/mysql-test/suite/parts/r/partition_mgm_lc0_myisam.result +++ b/mysql-test/suite/parts/r/partition_mgm_lc0_myisam.result @@ -93,11 +93,11 @@ TableA CREATE TABLE `TableA` ( ALTER TABLE TableA REORGANIZE PARTITION parta,partB,Partc INTO (PARTITION PARTA , PARTITION partc ); -ERROR HY000: REORGANISE PARTITION can only be used to reorganise partitions not to change their numbers +ERROR HY000: REORGANIZE PARTITION can only be used to reorganize partitions not to change their numbers ALTER TABLE TableA REORGANIZE PARTITION parta,Partc INTO (PARTITION partB , PARTITION parta ); -ERROR HY000: When reorganising a set of partitions they must be in consecutive order +ERROR HY000: When reorganizing a set of partitions they must be in consecutive order ALTER TABLE TableA REORGANIZE PARTITION parta,partB INTO (PARTITION partB COMMENT="Previusly named parta", PARTITION parta COMMENT="Previusly named partB"); @@ -329,11 +329,11 @@ TableA CREATE TABLE `TableA` ( ALTER TABLE TableA REORGANIZE PARTITION parta,partB,Partc INTO (PARTITION PARTA , PARTITION partc ); -ERROR HY000: REORGANISE PARTITION can only be used to reorganise partitions not to change their numbers +ERROR HY000: REORGANIZE PARTITION can only be used to reorganize partitions not to change their numbers ALTER TABLE TableA REORGANIZE PARTITION parta,Partc INTO (PARTITION partB , PARTITION parta ); -ERROR HY000: When reorganising a set of partitions they must be in consecutive order +ERROR HY000: When reorganizing a set of partitions they must be in consecutive order ALTER TABLE TableA REORGANIZE PARTITION parta,partB INTO (PARTITION partB COMMENT="Previusly named parta", PARTITION parta COMMENT="Previusly named partB"); @@ -559,7 +559,7 @@ TableA CREATE TABLE `TableA` ( ALTER TABLE TableA REORGANIZE PARTITION parta,Partc INTO (PARTITION partB VALUES LESS THAN (3) , PARTITION parta VALUES LESS THAN (11) ); -ERROR HY000: When reorganising a set of partitions they must be in consecutive order +ERROR HY000: When reorganizing a set of partitions they must be in consecutive order ALTER TABLE TableA REORGANIZE PARTITION partB,Partc,PartD,PartE INTO (PARTITION partD VALUES LESS THAN (8) COMMENT="Previously partB and partly Partc", @@ -793,7 +793,7 @@ PARTITION partF VALUES IN (3,9) COMMENT = "Mix 2 of old parta and Partc", PARTITION parta VALUES IN (4,8) COMMENT = "Mix 3 of old parta and Partc"); -ERROR HY000: When reorganising a set of partitions they must be in consecutive order +ERROR HY000: When reorganizing a set of partitions they must be in consecutive order ALTER TABLE TableA REORGANIZE PARTITION parta,partB,Partc INTO (PARTITION Partc VALUES IN (1,7) COMMENT = "Mix 1 of old parta and Partc", diff --git a/mysql-test/suite/parts/r/partition_mgm_lc0_ndb.result b/mysql-test/suite/parts/r/partition_mgm_lc0_ndb.result index a1d0b78aac4..45b674638e7 100644 --- a/mysql-test/suite/parts/r/partition_mgm_lc0_ndb.result +++ b/mysql-test/suite/parts/r/partition_mgm_lc0_ndb.result @@ -93,11 +93,11 @@ TableA CREATE TABLE `TableA` ( ALTER TABLE TableA REORGANIZE PARTITION parta,partB,Partc INTO (PARTITION PARTA , PARTITION partc ); -ERROR HY000: REORGANISE PARTITION can only be used to reorganise partitions not to change their numbers +ERROR HY000: REORGANIZE PARTITION can only be used to reorganize partitions not to change their numbers ALTER TABLE TableA REORGANIZE PARTITION parta,Partc INTO (PARTITION partB , PARTITION parta ); -ERROR HY000: When reorganising a set of partitions they must be in consecutive order +ERROR HY000: When reorganizing a set of partitions they must be in consecutive order ALTER TABLE TableA REORGANIZE PARTITION parta,partB INTO (PARTITION partB COMMENT="Previusly named parta", PARTITION parta COMMENT="Previusly named partB"); diff --git a/mysql-test/suite/parts/r/partition_mgm_lc1_archive.result b/mysql-test/suite/parts/r/partition_mgm_lc1_archive.result index f8238bb9382..443453a2d70 100644 --- a/mysql-test/suite/parts/r/partition_mgm_lc1_archive.result +++ b/mysql-test/suite/parts/r/partition_mgm_lc1_archive.result @@ -93,11 +93,11 @@ TableA CREATE TABLE `tablea` ( ALTER TABLE TableA REORGANIZE PARTITION parta,partB,Partc INTO (PARTITION PARTA , PARTITION partc ); -ERROR HY000: REORGANISE PARTITION can only be used to reorganise partitions not to change their numbers +ERROR HY000: REORGANIZE PARTITION can only be used to reorganize partitions not to change their numbers ALTER TABLE TableA REORGANIZE PARTITION parta,Partc INTO (PARTITION partB , PARTITION parta ); -ERROR HY000: When reorganising a set of partitions they must be in consecutive order +ERROR HY000: When reorganizing a set of partitions they must be in consecutive order ALTER TABLE TableA REORGANIZE PARTITION parta,partB INTO (PARTITION partB COMMENT="Previusly named parta", PARTITION parta COMMENT="Previusly named partB"); @@ -320,11 +320,11 @@ TableA CREATE TABLE `tablea` ( ALTER TABLE TableA REORGANIZE PARTITION parta,partB,Partc INTO (PARTITION PARTA , PARTITION partc ); -ERROR HY000: REORGANISE PARTITION can only be used to reorganise partitions not to change their numbers +ERROR HY000: REORGANIZE PARTITION can only be used to reorganize partitions not to change their numbers ALTER TABLE TableA REORGANIZE PARTITION parta,Partc INTO (PARTITION partB , PARTITION parta ); -ERROR HY000: When reorganising a set of partitions they must be in consecutive order +ERROR HY000: When reorganizing a set of partitions they must be in consecutive order ALTER TABLE TableA REORGANIZE PARTITION parta,partB INTO (PARTITION partB COMMENT="Previusly named parta", PARTITION parta COMMENT="Previusly named partB"); @@ -541,7 +541,7 @@ TableA CREATE TABLE `tablea` ( ALTER TABLE TableA REORGANIZE PARTITION parta,Partc INTO (PARTITION partB VALUES LESS THAN (3) , PARTITION parta VALUES LESS THAN (11) ); -ERROR HY000: When reorganising a set of partitions they must be in consecutive order +ERROR HY000: When reorganizing a set of partitions they must be in consecutive order ALTER TABLE TableA REORGANIZE PARTITION partB,Partc,PartD,PartE INTO (PARTITION partD VALUES LESS THAN (8) COMMENT="Previously partB and partly Partc", @@ -767,7 +767,7 @@ PARTITION partF VALUES IN (3,9) COMMENT = "Mix 2 of old parta and Partc", PARTITION parta VALUES IN (4,8) COMMENT = "Mix 3 of old parta and Partc"); -ERROR HY000: When reorganising a set of partitions they must be in consecutive order +ERROR HY000: When reorganizing a set of partitions they must be in consecutive order ALTER TABLE TableA REORGANIZE PARTITION parta,partB,Partc INTO (PARTITION Partc VALUES IN (1,7) COMMENT = "Mix 1 of old parta and Partc", diff --git a/mysql-test/suite/parts/r/partition_mgm_lc1_innodb.result b/mysql-test/suite/parts/r/partition_mgm_lc1_innodb.result index 5f7ccc3ed51..49ccc7b1808 100644 --- a/mysql-test/suite/parts/r/partition_mgm_lc1_innodb.result +++ b/mysql-test/suite/parts/r/partition_mgm_lc1_innodb.result @@ -93,11 +93,11 @@ TableA CREATE TABLE `tablea` ( ALTER TABLE TableA REORGANIZE PARTITION parta,partB,Partc INTO (PARTITION PARTA , PARTITION partc ); -ERROR HY000: REORGANISE PARTITION can only be used to reorganise partitions not to change their numbers +ERROR HY000: REORGANIZE PARTITION can only be used to reorganize partitions not to change their numbers ALTER TABLE TableA REORGANIZE PARTITION parta,Partc INTO (PARTITION partB , PARTITION parta ); -ERROR HY000: When reorganising a set of partitions they must be in consecutive order +ERROR HY000: When reorganizing a set of partitions they must be in consecutive order ALTER TABLE TableA REORGANIZE PARTITION parta,partB INTO (PARTITION partB COMMENT="Previusly named parta", PARTITION parta COMMENT="Previusly named partB"); @@ -320,11 +320,11 @@ TableA CREATE TABLE `tablea` ( ALTER TABLE TableA REORGANIZE PARTITION parta,partB,Partc INTO (PARTITION PARTA , PARTITION partc ); -ERROR HY000: REORGANISE PARTITION can only be used to reorganise partitions not to change their numbers +ERROR HY000: REORGANIZE PARTITION can only be used to reorganize partitions not to change their numbers ALTER TABLE TableA REORGANIZE PARTITION parta,Partc INTO (PARTITION partB , PARTITION parta ); -ERROR HY000: When reorganising a set of partitions they must be in consecutive order +ERROR HY000: When reorganizing a set of partitions they must be in consecutive order ALTER TABLE TableA REORGANIZE PARTITION parta,partB INTO (PARTITION partB COMMENT="Previusly named parta", PARTITION parta COMMENT="Previusly named partB"); @@ -541,7 +541,7 @@ TableA CREATE TABLE `tablea` ( ALTER TABLE TableA REORGANIZE PARTITION parta,Partc INTO (PARTITION partB VALUES LESS THAN (3) , PARTITION parta VALUES LESS THAN (11) ); -ERROR HY000: When reorganising a set of partitions they must be in consecutive order +ERROR HY000: When reorganizing a set of partitions they must be in consecutive order ALTER TABLE TableA REORGANIZE PARTITION partB,Partc,PartD,PartE INTO (PARTITION partD VALUES LESS THAN (8) COMMENT="Previously partB and partly Partc", @@ -767,7 +767,7 @@ PARTITION partF VALUES IN (3,9) COMMENT = "Mix 2 of old parta and Partc", PARTITION parta VALUES IN (4,8) COMMENT = "Mix 3 of old parta and Partc"); -ERROR HY000: When reorganising a set of partitions they must be in consecutive order +ERROR HY000: When reorganizing a set of partitions they must be in consecutive order ALTER TABLE TableA REORGANIZE PARTITION parta,partB,Partc INTO (PARTITION Partc VALUES IN (1,7) COMMENT = "Mix 1 of old parta and Partc", diff --git a/mysql-test/suite/parts/r/partition_mgm_lc1_memory.result b/mysql-test/suite/parts/r/partition_mgm_lc1_memory.result index c72666f7717..6f34054428c 100644 --- a/mysql-test/suite/parts/r/partition_mgm_lc1_memory.result +++ b/mysql-test/suite/parts/r/partition_mgm_lc1_memory.result @@ -93,11 +93,11 @@ TableA CREATE TABLE `tablea` ( ALTER TABLE TableA REORGANIZE PARTITION parta,partB,Partc INTO (PARTITION PARTA , PARTITION partc ); -ERROR HY000: REORGANISE PARTITION can only be used to reorganise partitions not to change their numbers +ERROR HY000: REORGANIZE PARTITION can only be used to reorganize partitions not to change their numbers ALTER TABLE TableA REORGANIZE PARTITION parta,Partc INTO (PARTITION partB , PARTITION parta ); -ERROR HY000: When reorganising a set of partitions they must be in consecutive order +ERROR HY000: When reorganizing a set of partitions they must be in consecutive order ALTER TABLE TableA REORGANIZE PARTITION parta,partB INTO (PARTITION partB COMMENT="Previusly named parta", PARTITION parta COMMENT="Previusly named partB"); @@ -320,11 +320,11 @@ TableA CREATE TABLE `tablea` ( ALTER TABLE TableA REORGANIZE PARTITION parta,partB,Partc INTO (PARTITION PARTA , PARTITION partc ); -ERROR HY000: REORGANISE PARTITION can only be used to reorganise partitions not to change their numbers +ERROR HY000: REORGANIZE PARTITION can only be used to reorganize partitions not to change their numbers ALTER TABLE TableA REORGANIZE PARTITION parta,Partc INTO (PARTITION partB , PARTITION parta ); -ERROR HY000: When reorganising a set of partitions they must be in consecutive order +ERROR HY000: When reorganizing a set of partitions they must be in consecutive order ALTER TABLE TableA REORGANIZE PARTITION parta,partB INTO (PARTITION partB COMMENT="Previusly named parta", PARTITION parta COMMENT="Previusly named partB"); @@ -541,7 +541,7 @@ TableA CREATE TABLE `tablea` ( ALTER TABLE TableA REORGANIZE PARTITION parta,Partc INTO (PARTITION partB VALUES LESS THAN (3) , PARTITION parta VALUES LESS THAN (11) ); -ERROR HY000: When reorganising a set of partitions they must be in consecutive order +ERROR HY000: When reorganizing a set of partitions they must be in consecutive order ALTER TABLE TableA REORGANIZE PARTITION partB,Partc,PartD,PartE INTO (PARTITION partD VALUES LESS THAN (8) COMMENT="Previously partB and partly Partc", @@ -767,7 +767,7 @@ PARTITION partF VALUES IN (3,9) COMMENT = "Mix 2 of old parta and Partc", PARTITION parta VALUES IN (4,8) COMMENT = "Mix 3 of old parta and Partc"); -ERROR HY000: When reorganising a set of partitions they must be in consecutive order +ERROR HY000: When reorganizing a set of partitions they must be in consecutive order ALTER TABLE TableA REORGANIZE PARTITION parta,partB,Partc INTO (PARTITION Partc VALUES IN (1,7) COMMENT = "Mix 1 of old parta and Partc", diff --git a/mysql-test/suite/parts/r/partition_mgm_lc1_myisam.result b/mysql-test/suite/parts/r/partition_mgm_lc1_myisam.result index 66f9f852108..ac230e29c66 100644 --- a/mysql-test/suite/parts/r/partition_mgm_lc1_myisam.result +++ b/mysql-test/suite/parts/r/partition_mgm_lc1_myisam.result @@ -93,11 +93,11 @@ TableA CREATE TABLE `tablea` ( ALTER TABLE TableA REORGANIZE PARTITION parta,partB,Partc INTO (PARTITION PARTA , PARTITION partc ); -ERROR HY000: REORGANISE PARTITION can only be used to reorganise partitions not to change their numbers +ERROR HY000: REORGANIZE PARTITION can only be used to reorganize partitions not to change their numbers ALTER TABLE TableA REORGANIZE PARTITION parta,Partc INTO (PARTITION partB , PARTITION parta ); -ERROR HY000: When reorganising a set of partitions they must be in consecutive order +ERROR HY000: When reorganizing a set of partitions they must be in consecutive order ALTER TABLE TableA REORGANIZE PARTITION parta,partB INTO (PARTITION partB COMMENT="Previusly named parta", PARTITION parta COMMENT="Previusly named partB"); @@ -320,11 +320,11 @@ TableA CREATE TABLE `tablea` ( ALTER TABLE TableA REORGANIZE PARTITION parta,partB,Partc INTO (PARTITION PARTA , PARTITION partc ); -ERROR HY000: REORGANISE PARTITION can only be used to reorganise partitions not to change their numbers +ERROR HY000: REORGANIZE PARTITION can only be used to reorganize partitions not to change their numbers ALTER TABLE TableA REORGANIZE PARTITION parta,Partc INTO (PARTITION partB , PARTITION parta ); -ERROR HY000: When reorganising a set of partitions they must be in consecutive order +ERROR HY000: When reorganizing a set of partitions they must be in consecutive order ALTER TABLE TableA REORGANIZE PARTITION parta,partB INTO (PARTITION partB COMMENT="Previusly named parta", PARTITION parta COMMENT="Previusly named partB"); @@ -541,7 +541,7 @@ TableA CREATE TABLE `tablea` ( ALTER TABLE TableA REORGANIZE PARTITION parta,Partc INTO (PARTITION partB VALUES LESS THAN (3) , PARTITION parta VALUES LESS THAN (11) ); -ERROR HY000: When reorganising a set of partitions they must be in consecutive order +ERROR HY000: When reorganizing a set of partitions they must be in consecutive order ALTER TABLE TableA REORGANIZE PARTITION partB,Partc,PartD,PartE INTO (PARTITION partD VALUES LESS THAN (8) COMMENT="Previously partB and partly Partc", @@ -767,7 +767,7 @@ PARTITION partF VALUES IN (3,9) COMMENT = "Mix 2 of old parta and Partc", PARTITION parta VALUES IN (4,8) COMMENT = "Mix 3 of old parta and Partc"); -ERROR HY000: When reorganising a set of partitions they must be in consecutive order +ERROR HY000: When reorganizing a set of partitions they must be in consecutive order ALTER TABLE TableA REORGANIZE PARTITION parta,partB,Partc INTO (PARTITION Partc VALUES IN (1,7) COMMENT = "Mix 1 of old parta and Partc", diff --git a/mysql-test/suite/parts/r/partition_mgm_lc1_ndb.result b/mysql-test/suite/parts/r/partition_mgm_lc1_ndb.result index c27f769ad72..0a53e1b4a9b 100644 --- a/mysql-test/suite/parts/r/partition_mgm_lc1_ndb.result +++ b/mysql-test/suite/parts/r/partition_mgm_lc1_ndb.result @@ -93,11 +93,11 @@ TableA CREATE TABLE `tablea` ( ALTER TABLE TableA REORGANIZE PARTITION parta,partB,Partc INTO (PARTITION PARTA , PARTITION partc ); -ERROR HY000: REORGANISE PARTITION can only be used to reorganise partitions not to change their numbers +ERROR HY000: REORGANIZE PARTITION can only be used to reorganize partitions not to change their numbers ALTER TABLE TableA REORGANIZE PARTITION parta,Partc INTO (PARTITION partB , PARTITION parta ); -ERROR HY000: When reorganising a set of partitions they must be in consecutive order +ERROR HY000: When reorganizing a set of partitions they must be in consecutive order ALTER TABLE TableA REORGANIZE PARTITION parta,partB INTO (PARTITION partB COMMENT="Previusly named parta", PARTITION parta COMMENT="Previusly named partB"); diff --git a/mysql-test/suite/parts/r/partition_mgm_lc2_archive.result b/mysql-test/suite/parts/r/partition_mgm_lc2_archive.result index 70020ee54a6..fc0390c238d 100644 --- a/mysql-test/suite/parts/r/partition_mgm_lc2_archive.result +++ b/mysql-test/suite/parts/r/partition_mgm_lc2_archive.result @@ -93,11 +93,11 @@ TableA CREATE TABLE `TableA` ( ALTER TABLE TableA REORGANIZE PARTITION parta,partB,Partc INTO (PARTITION PARTA , PARTITION partc ); -ERROR HY000: REORGANISE PARTITION can only be used to reorganise partitions not to change their numbers +ERROR HY000: REORGANIZE PARTITION can only be used to reorganize partitions not to change their numbers ALTER TABLE TableA REORGANIZE PARTITION parta,Partc INTO (PARTITION partB , PARTITION parta ); -ERROR HY000: When reorganising a set of partitions they must be in consecutive order +ERROR HY000: When reorganizing a set of partitions they must be in consecutive order ALTER TABLE TableA REORGANIZE PARTITION parta,partB INTO (PARTITION partB COMMENT="Previusly named parta", PARTITION parta COMMENT="Previusly named partB"); @@ -320,11 +320,11 @@ TableA CREATE TABLE `TableA` ( ALTER TABLE TableA REORGANIZE PARTITION parta,partB,Partc INTO (PARTITION PARTA , PARTITION partc ); -ERROR HY000: REORGANISE PARTITION can only be used to reorganise partitions not to change their numbers +ERROR HY000: REORGANIZE PARTITION can only be used to reorganize partitions not to change their numbers ALTER TABLE TableA REORGANIZE PARTITION parta,Partc INTO (PARTITION partB , PARTITION parta ); -ERROR HY000: When reorganising a set of partitions they must be in consecutive order +ERROR HY000: When reorganizing a set of partitions they must be in consecutive order ALTER TABLE TableA REORGANIZE PARTITION parta,partB INTO (PARTITION partB COMMENT="Previusly named parta", PARTITION parta COMMENT="Previusly named partB"); @@ -541,7 +541,7 @@ TableA CREATE TABLE `TableA` ( ALTER TABLE TableA REORGANIZE PARTITION parta,Partc INTO (PARTITION partB VALUES LESS THAN (3) , PARTITION parta VALUES LESS THAN (11) ); -ERROR HY000: When reorganising a set of partitions they must be in consecutive order +ERROR HY000: When reorganizing a set of partitions they must be in consecutive order ALTER TABLE TableA REORGANIZE PARTITION partB,Partc,PartD,PartE INTO (PARTITION partD VALUES LESS THAN (8) COMMENT="Previously partB and partly Partc", @@ -767,7 +767,7 @@ PARTITION partF VALUES IN (3,9) COMMENT = "Mix 2 of old parta and Partc", PARTITION parta VALUES IN (4,8) COMMENT = "Mix 3 of old parta and Partc"); -ERROR HY000: When reorganising a set of partitions they must be in consecutive order +ERROR HY000: When reorganizing a set of partitions they must be in consecutive order ALTER TABLE TableA REORGANIZE PARTITION parta,partB,Partc INTO (PARTITION Partc VALUES IN (1,7) COMMENT = "Mix 1 of old parta and Partc", diff --git a/mysql-test/suite/parts/r/partition_mgm_lc2_innodb.result b/mysql-test/suite/parts/r/partition_mgm_lc2_innodb.result index 7392056b7a5..da111137068 100644 --- a/mysql-test/suite/parts/r/partition_mgm_lc2_innodb.result +++ b/mysql-test/suite/parts/r/partition_mgm_lc2_innodb.result @@ -93,11 +93,11 @@ TableA CREATE TABLE `TableA` ( ALTER TABLE TableA REORGANIZE PARTITION parta,partB,Partc INTO (PARTITION PARTA , PARTITION partc ); -ERROR HY000: REORGANISE PARTITION can only be used to reorganise partitions not to change their numbers +ERROR HY000: REORGANIZE PARTITION can only be used to reorganize partitions not to change their numbers ALTER TABLE TableA REORGANIZE PARTITION parta,Partc INTO (PARTITION partB , PARTITION parta ); -ERROR HY000: When reorganising a set of partitions they must be in consecutive order +ERROR HY000: When reorganizing a set of partitions they must be in consecutive order ALTER TABLE TableA REORGANIZE PARTITION parta,partB INTO (PARTITION partB COMMENT="Previusly named parta", PARTITION parta COMMENT="Previusly named partB"); @@ -320,11 +320,11 @@ TableA CREATE TABLE `TableA` ( ALTER TABLE TableA REORGANIZE PARTITION parta,partB,Partc INTO (PARTITION PARTA , PARTITION partc ); -ERROR HY000: REORGANISE PARTITION can only be used to reorganise partitions not to change their numbers +ERROR HY000: REORGANIZE PARTITION can only be used to reorganize partitions not to change their numbers ALTER TABLE TableA REORGANIZE PARTITION parta,Partc INTO (PARTITION partB , PARTITION parta ); -ERROR HY000: When reorganising a set of partitions they must be in consecutive order +ERROR HY000: When reorganizing a set of partitions they must be in consecutive order ALTER TABLE TableA REORGANIZE PARTITION parta,partB INTO (PARTITION partB COMMENT="Previusly named parta", PARTITION parta COMMENT="Previusly named partB"); @@ -541,7 +541,7 @@ TableA CREATE TABLE `TableA` ( ALTER TABLE TableA REORGANIZE PARTITION parta,Partc INTO (PARTITION partB VALUES LESS THAN (3) , PARTITION parta VALUES LESS THAN (11) ); -ERROR HY000: When reorganising a set of partitions they must be in consecutive order +ERROR HY000: When reorganizing a set of partitions they must be in consecutive order ALTER TABLE TableA REORGANIZE PARTITION partB,Partc,PartD,PartE INTO (PARTITION partD VALUES LESS THAN (8) COMMENT="Previously partB and partly Partc", @@ -767,7 +767,7 @@ PARTITION partF VALUES IN (3,9) COMMENT = "Mix 2 of old parta and Partc", PARTITION parta VALUES IN (4,8) COMMENT = "Mix 3 of old parta and Partc"); -ERROR HY000: When reorganising a set of partitions they must be in consecutive order +ERROR HY000: When reorganizing a set of partitions they must be in consecutive order ALTER TABLE TableA REORGANIZE PARTITION parta,partB,Partc INTO (PARTITION Partc VALUES IN (1,7) COMMENT = "Mix 1 of old parta and Partc", diff --git a/mysql-test/suite/parts/r/partition_mgm_lc2_memory.result b/mysql-test/suite/parts/r/partition_mgm_lc2_memory.result index a71bbfea5e3..a1716ea36c8 100644 --- a/mysql-test/suite/parts/r/partition_mgm_lc2_memory.result +++ b/mysql-test/suite/parts/r/partition_mgm_lc2_memory.result @@ -93,11 +93,11 @@ TableA CREATE TABLE `TableA` ( ALTER TABLE TableA REORGANIZE PARTITION parta,partB,Partc INTO (PARTITION PARTA , PARTITION partc ); -ERROR HY000: REORGANISE PARTITION can only be used to reorganise partitions not to change their numbers +ERROR HY000: REORGANIZE PARTITION can only be used to reorganize partitions not to change their numbers ALTER TABLE TableA REORGANIZE PARTITION parta,Partc INTO (PARTITION partB , PARTITION parta ); -ERROR HY000: When reorganising a set of partitions they must be in consecutive order +ERROR HY000: When reorganizing a set of partitions they must be in consecutive order ALTER TABLE TableA REORGANIZE PARTITION parta,partB INTO (PARTITION partB COMMENT="Previusly named parta", PARTITION parta COMMENT="Previusly named partB"); @@ -320,11 +320,11 @@ TableA CREATE TABLE `TableA` ( ALTER TABLE TableA REORGANIZE PARTITION parta,partB,Partc INTO (PARTITION PARTA , PARTITION partc ); -ERROR HY000: REORGANISE PARTITION can only be used to reorganise partitions not to change their numbers +ERROR HY000: REORGANIZE PARTITION can only be used to reorganize partitions not to change their numbers ALTER TABLE TableA REORGANIZE PARTITION parta,Partc INTO (PARTITION partB , PARTITION parta ); -ERROR HY000: When reorganising a set of partitions they must be in consecutive order +ERROR HY000: When reorganizing a set of partitions they must be in consecutive order ALTER TABLE TableA REORGANIZE PARTITION parta,partB INTO (PARTITION partB COMMENT="Previusly named parta", PARTITION parta COMMENT="Previusly named partB"); @@ -541,7 +541,7 @@ TableA CREATE TABLE `TableA` ( ALTER TABLE TableA REORGANIZE PARTITION parta,Partc INTO (PARTITION partB VALUES LESS THAN (3) , PARTITION parta VALUES LESS THAN (11) ); -ERROR HY000: When reorganising a set of partitions they must be in consecutive order +ERROR HY000: When reorganizing a set of partitions they must be in consecutive order ALTER TABLE TableA REORGANIZE PARTITION partB,Partc,PartD,PartE INTO (PARTITION partD VALUES LESS THAN (8) COMMENT="Previously partB and partly Partc", @@ -767,7 +767,7 @@ PARTITION partF VALUES IN (3,9) COMMENT = "Mix 2 of old parta and Partc", PARTITION parta VALUES IN (4,8) COMMENT = "Mix 3 of old parta and Partc"); -ERROR HY000: When reorganising a set of partitions they must be in consecutive order +ERROR HY000: When reorganizing a set of partitions they must be in consecutive order ALTER TABLE TableA REORGANIZE PARTITION parta,partB,Partc INTO (PARTITION Partc VALUES IN (1,7) COMMENT = "Mix 1 of old parta and Partc", diff --git a/mysql-test/suite/parts/r/partition_mgm_lc2_myisam.result b/mysql-test/suite/parts/r/partition_mgm_lc2_myisam.result index 92b64e4d26c..6bdfa149de0 100644 --- a/mysql-test/suite/parts/r/partition_mgm_lc2_myisam.result +++ b/mysql-test/suite/parts/r/partition_mgm_lc2_myisam.result @@ -93,11 +93,11 @@ TableA CREATE TABLE `TableA` ( ALTER TABLE TableA REORGANIZE PARTITION parta,partB,Partc INTO (PARTITION PARTA , PARTITION partc ); -ERROR HY000: REORGANISE PARTITION can only be used to reorganise partitions not to change their numbers +ERROR HY000: REORGANIZE PARTITION can only be used to reorganize partitions not to change their numbers ALTER TABLE TableA REORGANIZE PARTITION parta,Partc INTO (PARTITION partB , PARTITION parta ); -ERROR HY000: When reorganising a set of partitions they must be in consecutive order +ERROR HY000: When reorganizing a set of partitions they must be in consecutive order ALTER TABLE TableA REORGANIZE PARTITION parta,partB INTO (PARTITION partB COMMENT="Previusly named parta", PARTITION parta COMMENT="Previusly named partB"); @@ -320,11 +320,11 @@ TableA CREATE TABLE `TableA` ( ALTER TABLE TableA REORGANIZE PARTITION parta,partB,Partc INTO (PARTITION PARTA , PARTITION partc ); -ERROR HY000: REORGANISE PARTITION can only be used to reorganise partitions not to change their numbers +ERROR HY000: REORGANIZE PARTITION can only be used to reorganize partitions not to change their numbers ALTER TABLE TableA REORGANIZE PARTITION parta,Partc INTO (PARTITION partB , PARTITION parta ); -ERROR HY000: When reorganising a set of partitions they must be in consecutive order +ERROR HY000: When reorganizing a set of partitions they must be in consecutive order ALTER TABLE TableA REORGANIZE PARTITION parta,partB INTO (PARTITION partB COMMENT="Previusly named parta", PARTITION parta COMMENT="Previusly named partB"); @@ -541,7 +541,7 @@ TableA CREATE TABLE `TableA` ( ALTER TABLE TableA REORGANIZE PARTITION parta,Partc INTO (PARTITION partB VALUES LESS THAN (3) , PARTITION parta VALUES LESS THAN (11) ); -ERROR HY000: When reorganising a set of partitions they must be in consecutive order +ERROR HY000: When reorganizing a set of partitions they must be in consecutive order ALTER TABLE TableA REORGANIZE PARTITION partB,Partc,PartD,PartE INTO (PARTITION partD VALUES LESS THAN (8) COMMENT="Previously partB and partly Partc", @@ -767,7 +767,7 @@ PARTITION partF VALUES IN (3,9) COMMENT = "Mix 2 of old parta and Partc", PARTITION parta VALUES IN (4,8) COMMENT = "Mix 3 of old parta and Partc"); -ERROR HY000: When reorganising a set of partitions they must be in consecutive order +ERROR HY000: When reorganizing a set of partitions they must be in consecutive order ALTER TABLE TableA REORGANIZE PARTITION parta,partB,Partc INTO (PARTITION Partc VALUES IN (1,7) COMMENT = "Mix 1 of old parta and Partc", diff --git a/mysql-test/suite/parts/r/partition_mgm_lc2_ndb.result b/mysql-test/suite/parts/r/partition_mgm_lc2_ndb.result index b234de0efdb..8b9c5be1fb6 100644 --- a/mysql-test/suite/parts/r/partition_mgm_lc2_ndb.result +++ b/mysql-test/suite/parts/r/partition_mgm_lc2_ndb.result @@ -93,11 +93,11 @@ TableA CREATE TABLE `TableA` ( ALTER TABLE TableA REORGANIZE PARTITION parta,partB,Partc INTO (PARTITION PARTA , PARTITION partc ); -ERROR HY000: REORGANISE PARTITION can only be used to reorganise partitions not to change their numbers +ERROR HY000: REORGANIZE PARTITION can only be used to reorganize partitions not to change their numbers ALTER TABLE TableA REORGANIZE PARTITION parta,Partc INTO (PARTITION partB , PARTITION parta ); -ERROR HY000: When reorganising a set of partitions they must be in consecutive order +ERROR HY000: When reorganizing a set of partitions they must be in consecutive order ALTER TABLE TableA REORGANIZE PARTITION parta,partB INTO (PARTITION partB COMMENT="Previusly named parta", PARTITION parta COMMENT="Previusly named partB"); From 830c42a06a6d28e38d0aa3e53e90618e28d957ef Mon Sep 17 00:00:00 2001 From: Mattias Jonsson Date: Wed, 18 Feb 2009 21:29:30 +0100 Subject: [PATCH 100/219] Backport of bug#38719 from 6.0 to 5.1 handler::get_dup_key used the called handler for the info call, but used table->file handler for errkey. Fixed by using table->file->info instead. mysql-test/r/partition_error.result: Bug#38719: Partitioning returns a different error code for a duplicate key error Added test for verification mysql-test/t/partition_error.test: Bug#38719: Partitioning returns a different error code for a duplicate key error Added test for verification --- mysql-test/r/partition_error.result | 9 +++++++++ mysql-test/t/partition_error.test | 15 ++++++++++++++- sql/handler.cc | 2 +- 3 files changed, 24 insertions(+), 2 deletions(-) diff --git a/mysql-test/r/partition_error.result b/mysql-test/r/partition_error.result index 547ce1ca316..511806d64bd 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 INTEGER NOT NULL, PRIMARY KEY (a)); +INSERT INTO t1 VALUES (1),(1); +ERROR 23000: Duplicate entry '1' for key 'PRIMARY' +DROP TABLE t1; +CREATE TABLE t1 (a INTEGER NOT NULL, PRIMARY KEY (a)) +PARTITION BY KEY (a) PARTITIONS 2; +INSERT INTO t1 VALUES (1),(1); +ERROR 23000: Duplicate entry '1' for key 'PRIMARY' +DROP TABLE t1; CREATE TABLE t1 (a INT) PARTITION BY HASH (a) ( PARTITION p0 ENGINE=MyISAM, diff --git a/mysql-test/t/partition_error.test b/mysql-test/t/partition_error.test index 41b904b876f..49632f95dfb 100644 --- a/mysql-test/t/partition_error.test +++ b/mysql-test/t/partition_error.test @@ -1,5 +1,5 @@ # -# Simple test for the erroneos create statements using the +# Simple test for the erroneos statements using the # partition storage engine # -- source include/have_partition.inc @@ -7,6 +7,19 @@ --disable_warnings drop table if exists t1; --enable_warnings + +# +# Bug#38719: Partitioning returns a different error code for a +# duplicate key error +CREATE TABLE t1 (a INTEGER NOT NULL, PRIMARY KEY (a)); +-- error ER_DUP_ENTRY +INSERT INTO t1 VALUES (1),(1); +DROP TABLE t1; +CREATE TABLE t1 (a INTEGER NOT NULL, PRIMARY KEY (a)) +PARTITION BY KEY (a) PARTITIONS 2; +-- error ER_DUP_ENTRY +INSERT INTO t1 VALUES (1),(1); +DROP TABLE t1; # # Bug#31931: Mix of handlers error message diff --git a/sql/handler.cc b/sql/handler.cc index 853ab29d38a..18c8e6c1f5a 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -2932,7 +2932,7 @@ uint handler::get_dup_key(int error) if (error == HA_ERR_FOUND_DUPP_KEY || error == HA_ERR_FOREIGN_DUPLICATE_KEY || error == HA_ERR_FOUND_DUPP_UNIQUE || error == HA_ERR_NULL_IN_SPATIAL || error == HA_ERR_DROP_INDEX_FK) - info(HA_STATUS_ERRKEY | HA_STATUS_NO_LOCK); + table->file->info(HA_STATUS_ERRKEY | HA_STATUS_NO_LOCK); DBUG_RETURN(table->file->errkey); } From 5f58510a096fc238e8d29811d1340ae9ccb841d4 Mon Sep 17 00:00:00 2001 From: Mattias Jonsson Date: Wed, 18 Feb 2009 22:35:28 +0100 Subject: [PATCH 101/219] Backport of test results for Bug#38719 from 6.0 to 5.1 post push fix, Bug#38719, additional test cases updated --- .../parts/inc/partition_auto_increment.inc | 39 ++-- .../r/partition_alter1_1_2_innodb.result | 112 +++++----- .../r/partition_alter1_1_2_myisam.result | 32 +-- .../parts/r/partition_alter1_1_innodb.result | 64 +++--- .../parts/r/partition_alter1_1_myisam.result | 32 +-- .../parts/r/partition_alter2_1_innodb.result | 192 +++++++++--------- .../parts/r/partition_alter2_1_myisam.result | 96 ++++----- .../partition_auto_increment_blackhole.result | 7 + .../r/partition_auto_increment_ndb.result | 1 + .../parts/r/partition_basic_innodb.result | 96 ++++----- .../parts/r/partition_basic_myisam.result | 32 +-- .../r/partition_basic_symlink_myisam.result | 46 ++--- 12 files changed, 382 insertions(+), 367 deletions(-) diff --git a/mysql-test/suite/parts/inc/partition_auto_increment.inc b/mysql-test/suite/parts/inc/partition_auto_increment.inc index 26375c72c0c..6963de90c83 100644 --- a/mysql-test/suite/parts/inc/partition_auto_increment.inc +++ b/mysql-test/suite/parts/inc/partition_auto_increment.inc @@ -29,10 +29,11 @@ INSERT INTO t1 VALUES (5), (16); if (!$mysql_errno) { echo # ERROR (only OK if Blackhole) should give ER_DUP_KEY or ER_DUP_ENTRY; + echo # mysql_errno: $mysql_errno; } INSERT INTO t1 VALUES (17); INSERT INTO t1 VALUES (19), (NULL); --- error 0, ER_DUP_KEY +-- error 0, ER_DUP_ENTRY, ER_DUP_KEY INSERT INTO t1 VALUES (NULL), (10), (NULL); if ($mysql_errno) { @@ -116,16 +117,17 @@ ENGINE=$engine PARTITION BY HASH(c2) PARTITIONS 2; INSERT INTO t1 VALUES (1, NULL); --- error 0, ER_DUP_KEY +-- error 0, ER_DUP_KEY, ER_DUP_ENTRY INSERT INTO t1 VALUES (1, 1), (99, 99); if (!$mysql_errno) { echo # ERROR (only OK if Blackhole) should give ER_DUP_KEY or ER_DUP_ENTRY; + echo # mysql_errno: $mysql_errno; } INSERT INTO t1 VALUES (1, NULL); let $old_sql_mode = `select @@session.sql_mode`; SET @@session.sql_mode = 'NO_AUTO_VALUE_ON_ZERO'; --- error 0, ER_DUP_KEY +-- error 0, ER_DUP_ENTRY, ER_DUP_KEY INSERT INTO t1 VALUES (1, 0); if ($mysql_errno) { @@ -140,7 +142,7 @@ eval CREATE TABLE t1 ( ENGINE=$engine PARTITION BY HASH(c2) PARTITIONS 2; --- error 0, ER_DUP_KEY +-- error 0, ER_DUP_ENTRY, ER_DUP_KEY INSERT INTO t1 VALUES (1, 0); if ($mysql_errno) { @@ -163,26 +165,27 @@ PARTITION BY HASH(c1) PARTITIONS 2; INSERT INTO t1 VALUES (2), (4), (NULL); INSERT INTO t1 VALUES (0); --- error 0, ER_DUP_KEY +-- error 0, ER_DUP_KEY, ER_DUP_ENTRY INSERT INTO t1 VALUES (5), (16); if (!$mysql_errno) { echo # ERROR (only OK if Blackhole) should give ER_DUP_KEY or ER_DUP_ENTRY; + echo # mysql_errno: $mysql_errno; } INSERT INTO t1 VALUES (17), (19), (NULL); --- error 0, ER_DUP_KEY +-- error 0, ER_DUP_ENTRY, ER_DUP_KEY INSERT INTO t1 VALUES (NULL), (10), (NULL); if ($mysql_errno) { echo # ERROR (only OK if Archive) mysql_errno: $mysql_errno; } --- error 0, ER_DUP_KEY +-- error 0, ER_DUP_ENTRY, ER_DUP_KEY INSERT INTO t1 VALUES (NULL), (9); if ($mysql_errno) { echo # ERROR (only OK if Archive) mysql_errno: $mysql_errno; } --- error 0, ER_DUP_KEY +-- error 0, ER_DUP_ENTRY, ER_DUP_KEY INSERT INTO t1 VALUES (59), (55); if ($mysql_errno) { @@ -270,7 +273,7 @@ SELECT AUTO_INCREMENT FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA='test' AND TABLE_NAME='t1'; SELECT AUTO_INCREMENT FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA='test' AND TABLE_NAME='t1'; --- error 0, ER_DUP_KEY +-- error 0, ER_DUP_ENTRY, ER_DUP_KEY INSERT INTO t1 VALUES (10); if ($mysql_errno) { @@ -281,7 +284,7 @@ INSERT INTO t1 VALUES (NULL); SELECT AUTO_INCREMENT FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA='test' AND TABLE_NAME='t1'; INSERT INTO t1 VALUES (NULL); --- error 0, ER_DUP_KEY +-- error 0, ER_DUP_ENTRY, ER_DUP_KEY INSERT INTO t1 VALUES (15); if ($mysql_errno) { @@ -340,7 +343,7 @@ connection con1; INSERT INTO t1 (c1) VALUES (NULL); connection default; -- echo # con default --- error 0, ER_DUP_KEY +-- error 0, ER_DUP_ENTRY, ER_DUP_KEY INSERT INTO t1 (c1) VALUES (16); if ($mysql_errno) { @@ -426,7 +429,7 @@ connection con1; INSERT INTO t1 (c1) VALUES (NULL); connection default; -- echo # con default --- error 0, ER_DUP_KEY +-- error 0, ER_DUP_ENTRY, ER_DUP_KEY INSERT INTO t1 (c1) VALUES (16); if ($mysql_errno) { @@ -483,6 +486,7 @@ INSERT INTO t1 VALUES (1, 1); if (!$mysql_errno) { echo # ERROR (only OK if Blackhole) should give ER_DUP_KEY or ER_DUP_ENTRY; + echo # mysql_errno: $mysql_errno; } INSERT INTO t1 VALUES (1, NULL); INSERT INTO t1 VALUES (2, NULL), (3, 11), (3, NULL), (2, 0); @@ -492,6 +496,7 @@ INSERT INTO t1 VALUES (2, 2); if (!$mysql_errno) { echo # ERROR (only OK if Blackhole) should give ER_DUP_KEY or ER_DUP_ENTRY; + echo # mysql_errno: $mysql_errno; } INSERT INTO t1 VALUES (2, 22); INSERT INTO t1 VALUES (2, NULL); @@ -527,16 +532,18 @@ INSERT INTO t1 VALUES (1, 1); if (!$mysql_errno) { echo # ERROR (only OK if Blackhole) should give ER_DUP_KEY or ER_DUP_ENTRY; + echo # mysql_errno: $mysql_errno; } INSERT INTO t1 VALUES (1, NULL); INSERT INTO t1 VALUES (2, NULL); INSERT INTO t1 VALUES (3, NULL); INSERT INTO t1 VALUES (3, NULL), (2, 0), (2, NULL); --- error 0, ER_DUP_KEY +-- error 0, ER_DUP_ENTRY, ER_DUP_KEY INSERT INTO t1 VALUES (2, 2); if (!$mysql_errno) { -echo # ERROR (only OK if Blackhole/NDB) should give ER_DUP_KEY or ER_DUP_ENTRY; + echo # ERROR (only OK if Blackhole/NDB) should give ER_DUP_KEY or ER_DUP_ENTRY; + echo # mysql_errno: $mysql_errno; } INSERT INTO t1 VALUES (2, 22), (2, NULL); SELECT * FROM t1 ORDER BY c1,c2; @@ -550,7 +557,7 @@ eval CREATE TABLE t1 (c1 INT NOT NULL AUTO_INCREMENT, PRIMARY KEY (c1)) PARTITION BY HASH(c1) PARTITIONS 2; SHOW CREATE TABLE t1; --- error 0, ER_DUP_KEY +-- error 0, ER_DUP_ENTRY, ER_DUP_KEY INSERT INTO t1 (c1) VALUES (4); if ($mysql_errno) { @@ -568,7 +575,7 @@ let $old_sql_mode = `select @@session.sql_mode`; SET @@session.sql_mode = 'NO_AUTO_VALUE_ON_ZERO'; INSERT INTO t1 (c1) VALUES (300); SHOW CREATE TABLE t1; --- error 0, ER_DUP_KEY +-- error 0, ER_DUP_ENTRY, ER_DUP_KEY INSERT INTO t1 (c1) VALUES (0); if ($mysql_errno) { diff --git a/mysql-test/suite/parts/r/partition_alter1_1_2_innodb.result b/mysql-test/suite/parts/r/partition_alter1_1_2_innodb.result index 7ab726136af..5d584e1da8b 100644 --- a/mysql-test/suite/parts/r/partition_alter1_1_2_innodb.result +++ b/mysql-test/suite/parts/r/partition_alter1_1_2_innodb.result @@ -86,7 +86,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'PRIMARY' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -578,7 +578,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'PRIMARY' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -1085,7 +1085,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'PRIMARY' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -1588,7 +1588,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'PRIMARY' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -2087,7 +2087,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'PRIMARY' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -2597,7 +2597,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'PRIMARY' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -3107,7 +3107,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'PRIMARY' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -3607,7 +3607,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'PRIMARY' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -4100,7 +4100,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'PRIMARY' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -4592,7 +4592,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'PRIMARY' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -5099,7 +5099,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'PRIMARY' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -5602,7 +5602,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'PRIMARY' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -6101,7 +6101,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'PRIMARY' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -6611,7 +6611,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'PRIMARY' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -7121,7 +7121,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'PRIMARY' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -7621,7 +7621,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'PRIMARY' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -8115,7 +8115,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx1' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -8623,7 +8623,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx1' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -9146,7 +9146,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx1' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -9665,7 +9665,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx1' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -10180,7 +10180,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx1' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -10706,7 +10706,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx1' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -11232,7 +11232,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx1' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -11748,7 +11748,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx1' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -12257,7 +12257,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx1' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -12765,7 +12765,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx1' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -13288,7 +13288,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx1' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -13807,7 +13807,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx1' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -14322,7 +14322,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx1' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -14848,7 +14848,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx1' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -15374,7 +15374,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx1' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -15890,7 +15890,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx1' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -16401,7 +16401,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'PRIMARY' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -16894,7 +16894,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'PRIMARY' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -17402,7 +17402,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'PRIMARY' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -17906,7 +17906,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'PRIMARY' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -18406,7 +18406,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'PRIMARY' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -18917,7 +18917,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'PRIMARY' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -19428,7 +19428,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'PRIMARY' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -19929,7 +19929,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'PRIMARY' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -20423,7 +20423,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'PRIMARY' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -20916,7 +20916,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'PRIMARY' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -21424,7 +21424,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'PRIMARY' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -21928,7 +21928,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'PRIMARY' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -22428,7 +22428,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'PRIMARY' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -22939,7 +22939,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'PRIMARY' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -23450,7 +23450,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'PRIMARY' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -23951,7 +23951,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'PRIMARY' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -24445,7 +24445,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'PRIMARY' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -24938,7 +24938,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'PRIMARY' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -25446,7 +25446,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'PRIMARY' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -25950,7 +25950,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'PRIMARY' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -26450,7 +26450,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'PRIMARY' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -26961,7 +26961,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'PRIMARY' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -27472,7 +27472,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'PRIMARY' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -27973,7 +27973,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'PRIMARY' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) diff --git a/mysql-test/suite/parts/r/partition_alter1_1_2_myisam.result b/mysql-test/suite/parts/r/partition_alter1_1_2_myisam.result index 69f2bfa472e..dda69f141df 100644 --- a/mysql-test/suite/parts/r/partition_alter1_1_2_myisam.result +++ b/mysql-test/suite/parts/r/partition_alter1_1_2_myisam.result @@ -94,7 +94,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx1' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -617,7 +617,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx1' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -1161,7 +1161,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx1' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -1697,7 +1697,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx1' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -2233,7 +2233,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx1' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -2780,7 +2780,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx1' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -3327,7 +3327,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx1' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -3866,7 +3866,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx1' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -4384,7 +4384,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx1' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -4907,7 +4907,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx1' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -5451,7 +5451,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx1' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -5987,7 +5987,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx1' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -6523,7 +6523,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx1' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -7070,7 +7070,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx1' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -7617,7 +7617,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx1' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -8156,7 +8156,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx1' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) diff --git a/mysql-test/suite/parts/r/partition_alter1_1_innodb.result b/mysql-test/suite/parts/r/partition_alter1_1_innodb.result index eeb55488d93..075346cfe94 100644 --- a/mysql-test/suite/parts/r/partition_alter1_1_innodb.result +++ b/mysql-test/suite/parts/r/partition_alter1_1_innodb.result @@ -404,7 +404,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'PRIMARY' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -896,7 +896,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'PRIMARY' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -1403,7 +1403,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'PRIMARY' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -1906,7 +1906,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'PRIMARY' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -2405,7 +2405,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'PRIMARY' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -2917,7 +2917,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'PRIMARY' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -3427,7 +3427,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'PRIMARY' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -3927,7 +3927,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'PRIMARY' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -4420,7 +4420,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'PRIMARY' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -4912,7 +4912,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'PRIMARY' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -5419,7 +5419,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'PRIMARY' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -5922,7 +5922,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'PRIMARY' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -6421,7 +6421,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'PRIMARY' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -6933,7 +6933,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'PRIMARY' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -7443,7 +7443,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'PRIMARY' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -7943,7 +7943,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'PRIMARY' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -8437,7 +8437,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx1' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -8945,7 +8945,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx1' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -9468,7 +9468,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx1' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -9987,7 +9987,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx1' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -10502,7 +10502,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx1' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -11030,7 +11030,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx1' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -11556,7 +11556,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx1' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -12072,7 +12072,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx1' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -12581,7 +12581,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx1' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -13089,7 +13089,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx1' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -13612,7 +13612,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx1' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -14131,7 +14131,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx1' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -14646,7 +14646,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx1' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -15174,7 +15174,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx1' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -15700,7 +15700,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx1' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -16216,7 +16216,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx1' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) diff --git a/mysql-test/suite/parts/r/partition_alter1_1_myisam.result b/mysql-test/suite/parts/r/partition_alter1_1_myisam.result index 2137c37c3a2..9f616d04df3 100644 --- a/mysql-test/suite/parts/r/partition_alter1_1_myisam.result +++ b/mysql-test/suite/parts/r/partition_alter1_1_myisam.result @@ -253,7 +253,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx1' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -776,7 +776,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx1' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -1320,7 +1320,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx1' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -1856,7 +1856,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx1' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -2392,7 +2392,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx1' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -2941,7 +2941,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx1' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -3488,7 +3488,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx1' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -4027,7 +4027,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx1' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -4545,7 +4545,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx1' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -5068,7 +5068,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx1' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -5612,7 +5612,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx1' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -6148,7 +6148,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx1' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -6684,7 +6684,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx1' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -7233,7 +7233,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx1' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -7780,7 +7780,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx1' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -8319,7 +8319,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx1' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) diff --git a/mysql-test/suite/parts/r/partition_alter2_1_innodb.result b/mysql-test/suite/parts/r/partition_alter2_1_innodb.result index 17d2c1384e0..fcccd52f571 100644 --- a/mysql-test/suite/parts/r/partition_alter2_1_innodb.result +++ b/mysql-test/suite/parts/r/partition_alter2_1_innodb.result @@ -3815,7 +3815,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'PRIMARY' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -4307,7 +4307,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'PRIMARY' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -4814,7 +4814,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'PRIMARY' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -5317,7 +5317,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'PRIMARY' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -5816,7 +5816,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'PRIMARY' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -6328,7 +6328,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'PRIMARY' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -6838,7 +6838,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'PRIMARY' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -7338,7 +7338,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'PRIMARY' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -7831,7 +7831,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'PRIMARY' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -8323,7 +8323,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'PRIMARY' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -8830,7 +8830,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'PRIMARY' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -9333,7 +9333,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'PRIMARY' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -9832,7 +9832,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'PRIMARY' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -10344,7 +10344,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'PRIMARY' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -10854,7 +10854,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'PRIMARY' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -11354,7 +11354,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'PRIMARY' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -11848,7 +11848,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx1' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -12356,7 +12356,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx1' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -12879,7 +12879,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx1' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -13398,7 +13398,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx1' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -13913,7 +13913,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx1' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -14441,7 +14441,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx1' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -14967,7 +14967,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx1' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -15483,7 +15483,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx1' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -15992,7 +15992,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx1' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -16500,7 +16500,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx1' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -17023,7 +17023,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx1' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -17542,7 +17542,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx1' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -18057,7 +18057,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx1' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -18585,7 +18585,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx1' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -19111,7 +19111,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx1' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -19627,7 +19627,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx1' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -27596,7 +27596,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'PRIMARY' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -28088,7 +28088,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'PRIMARY' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -28595,7 +28595,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'PRIMARY' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -29098,7 +29098,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'PRIMARY' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -29597,7 +29597,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'PRIMARY' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -30109,7 +30109,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'PRIMARY' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -30619,7 +30619,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'PRIMARY' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -31119,7 +31119,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'PRIMARY' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -31612,7 +31612,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'PRIMARY' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -32104,7 +32104,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'PRIMARY' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -32611,7 +32611,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'PRIMARY' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -33114,7 +33114,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'PRIMARY' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -33613,7 +33613,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'PRIMARY' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -34123,7 +34123,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'PRIMARY' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -34633,7 +34633,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'PRIMARY' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -35133,7 +35133,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'PRIMARY' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -35626,7 +35626,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'PRIMARY' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -36118,7 +36118,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'PRIMARY' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -36625,7 +36625,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'PRIMARY' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -37128,7 +37128,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'PRIMARY' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -37627,7 +37627,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'PRIMARY' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -38139,7 +38139,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'PRIMARY' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -38649,7 +38649,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'PRIMARY' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -39149,7 +39149,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'PRIMARY' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -39642,7 +39642,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'PRIMARY' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -40134,7 +40134,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'PRIMARY' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -40641,7 +40641,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'PRIMARY' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -41144,7 +41144,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'PRIMARY' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -41643,7 +41643,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'PRIMARY' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -42153,7 +42153,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'PRIMARY' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -42663,7 +42663,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'PRIMARY' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -43163,7 +43163,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'PRIMARY' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -43657,7 +43657,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -44165,7 +44165,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -44688,7 +44688,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -45207,7 +45207,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -45722,7 +45722,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -46250,7 +46250,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -46776,7 +46776,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -47292,7 +47292,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -47801,7 +47801,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -48309,7 +48309,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -48832,7 +48832,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -49351,7 +49351,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -49866,7 +49866,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -50392,7 +50392,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -50918,7 +50918,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -51434,7 +51434,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -51943,7 +51943,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -52451,7 +52451,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -52974,7 +52974,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -53493,7 +53493,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -54008,7 +54008,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -54536,7 +54536,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -55062,7 +55062,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -55578,7 +55578,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -56087,7 +56087,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -56595,7 +56595,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -57118,7 +57118,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -57637,7 +57637,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -58152,7 +58152,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -58678,7 +58678,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -59204,7 +59204,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -59720,7 +59720,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) diff --git a/mysql-test/suite/parts/r/partition_alter2_1_myisam.result b/mysql-test/suite/parts/r/partition_alter2_1_myisam.result index 0e0428af48e..902ce9711be 100644 --- a/mysql-test/suite/parts/r/partition_alter2_1_myisam.result +++ b/mysql-test/suite/parts/r/partition_alter2_1_myisam.result @@ -3971,7 +3971,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx1' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -4494,7 +4494,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx1' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -5038,7 +5038,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx1' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -5574,7 +5574,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx1' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -6110,7 +6110,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx1' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -6659,7 +6659,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx1' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -7206,7 +7206,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx1' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -7745,7 +7745,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx1' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -8263,7 +8263,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx1' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -8786,7 +8786,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx1' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -9330,7 +9330,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx1' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -9866,7 +9866,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx1' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -10402,7 +10402,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx1' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -10951,7 +10951,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx1' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -11498,7 +11498,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx1' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -12037,7 +12037,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx1' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -20311,7 +20311,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -20834,7 +20834,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -21378,7 +21378,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -21914,7 +21914,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -22450,7 +22450,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -22999,7 +22999,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -23546,7 +23546,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -24085,7 +24085,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -24603,7 +24603,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -25126,7 +25126,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -25670,7 +25670,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -26206,7 +26206,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -26742,7 +26742,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -27289,7 +27289,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -27836,7 +27836,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -28375,7 +28375,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -28893,7 +28893,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -29416,7 +29416,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -29960,7 +29960,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -30496,7 +30496,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -31032,7 +31032,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -31581,7 +31581,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -32128,7 +32128,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -32667,7 +32667,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -33185,7 +33185,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -33708,7 +33708,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -34252,7 +34252,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -34788,7 +34788,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -35324,7 +35324,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -35871,7 +35871,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -36418,7 +36418,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -36957,7 +36957,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) diff --git a/mysql-test/suite/parts/r/partition_auto_increment_blackhole.result b/mysql-test/suite/parts/r/partition_auto_increment_blackhole.result index ac39d038c56..7ef5ff88499 100644 --- a/mysql-test/suite/parts/r/partition_auto_increment_blackhole.result +++ b/mysql-test/suite/parts/r/partition_auto_increment_blackhole.result @@ -28,6 +28,7 @@ AUTO_INCREMENT INSERT INTO t1 VALUES (0); INSERT INTO t1 VALUES (5), (16); # ERROR (only OK if Blackhole) should give ER_DUP_KEY or ER_DUP_ENTRY +# mysql_errno: 0 INSERT INTO t1 VALUES (17); INSERT INTO t1 VALUES (19), (NULL); INSERT INTO t1 VALUES (NULL), (10), (NULL); @@ -144,6 +145,7 @@ PARTITIONS 2; INSERT INTO t1 VALUES (1, NULL); INSERT INTO t1 VALUES (1, 1), (99, 99); # ERROR (only OK if Blackhole) should give ER_DUP_KEY or ER_DUP_ENTRY +# mysql_errno: 0 INSERT INTO t1 VALUES (1, NULL); SET @@session.sql_mode = 'NO_AUTO_VALUE_ON_ZERO'; INSERT INTO t1 VALUES (1, 0); @@ -176,6 +178,7 @@ INSERT INTO t1 VALUES (2), (4), (NULL); INSERT INTO t1 VALUES (0); INSERT INTO t1 VALUES (5), (16); # ERROR (only OK if Blackhole) should give ER_DUP_KEY or ER_DUP_ENTRY +# mysql_errno: 0 INSERT INTO t1 VALUES (17), (19), (NULL); INSERT INTO t1 VALUES (NULL), (10), (NULL); INSERT INTO t1 VALUES (NULL), (9); @@ -441,11 +444,13 @@ PARTITIONS 2; INSERT INTO t1 VALUES (1, 0); INSERT INTO t1 VALUES (1, 1); # ERROR (only OK if Blackhole) should give ER_DUP_KEY or ER_DUP_ENTRY +# mysql_errno: 0 INSERT INTO t1 VALUES (1, NULL); INSERT INTO t1 VALUES (2, NULL), (3, 11), (3, NULL), (2, 0); INSERT INTO t1 VALUES (2, NULL); INSERT INTO t1 VALUES (2, 2); # ERROR (only OK if Blackhole) should give ER_DUP_KEY or ER_DUP_ENTRY +# mysql_errno: 0 INSERT INTO t1 VALUES (2, 22); INSERT INTO t1 VALUES (2, NULL); SELECT * FROM t1 ORDER BY c1,c2; @@ -462,12 +467,14 @@ PARTITIONS 2; INSERT INTO t1 VALUES (1, 0); INSERT INTO t1 VALUES (1, 1); # ERROR (only OK if Blackhole) should give ER_DUP_KEY or ER_DUP_ENTRY +# mysql_errno: 0 INSERT INTO t1 VALUES (1, NULL); INSERT INTO t1 VALUES (2, NULL); INSERT INTO t1 VALUES (3, NULL); INSERT INTO t1 VALUES (3, NULL), (2, 0), (2, NULL); INSERT INTO t1 VALUES (2, 2); # ERROR (only OK if Blackhole/NDB) should give ER_DUP_KEY or ER_DUP_ENTRY +# mysql_errno: 0 INSERT INTO t1 VALUES (2, 22), (2, NULL); SELECT * FROM t1 ORDER BY c1,c2; c1 c2 diff --git a/mysql-test/suite/parts/r/partition_auto_increment_ndb.result b/mysql-test/suite/parts/r/partition_auto_increment_ndb.result index 408f32cce78..5a1c5b06b36 100644 --- a/mysql-test/suite/parts/r/partition_auto_increment_ndb.result +++ b/mysql-test/suite/parts/r/partition_auto_increment_ndb.result @@ -649,6 +649,7 @@ INSERT INTO t1 VALUES (3, NULL); INSERT INTO t1 VALUES (3, NULL), (2, 0), (2, NULL); INSERT INTO t1 VALUES (2, 2); # ERROR (only OK if Blackhole/NDB) should give ER_DUP_KEY or ER_DUP_ENTRY +# mysql_errno: 0 INSERT INTO t1 VALUES (2, 22), (2, NULL); SELECT * FROM t1 ORDER BY c1,c2; c1 c2 diff --git a/mysql-test/suite/parts/r/partition_basic_innodb.result b/mysql-test/suite/parts/r/partition_basic_innodb.result index 15452792f3d..21c5d70e6e3 100644 --- a/mysql-test/suite/parts/r/partition_basic_innodb.result +++ b/mysql-test/suite/parts/r/partition_basic_innodb.result @@ -7538,7 +7538,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'PRIMARY' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -8030,7 +8030,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'PRIMARY' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -8537,7 +8537,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'PRIMARY' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -9040,7 +9040,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'PRIMARY' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -9539,7 +9539,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'PRIMARY' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -10051,7 +10051,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'PRIMARY' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -10565,7 +10565,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'PRIMARY' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -11065,7 +11065,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'PRIMARY' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -11558,7 +11558,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'PRIMARY' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -12050,7 +12050,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'PRIMARY' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -12557,7 +12557,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'PRIMARY' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -13060,7 +13060,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'PRIMARY' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -13559,7 +13559,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'PRIMARY' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -14071,7 +14071,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'PRIMARY' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -14585,7 +14585,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'PRIMARY' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -15085,7 +15085,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'PRIMARY' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -15578,7 +15578,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx1' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -16086,7 +16086,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx1' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -16609,7 +16609,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx1' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -17128,7 +17128,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx1' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -17643,7 +17643,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx1' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -18171,7 +18171,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx1' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -18701,7 +18701,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx1' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -19217,7 +19217,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx1' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -19731,7 +19731,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'PRIMARY' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -20223,7 +20223,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'PRIMARY' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -20730,7 +20730,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'PRIMARY' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -21233,7 +21233,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'PRIMARY' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -21732,7 +21732,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'PRIMARY' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -22242,7 +22242,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'PRIMARY' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -22752,7 +22752,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'PRIMARY' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -23252,7 +23252,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'PRIMARY' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -23745,7 +23745,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'PRIMARY' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -24237,7 +24237,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'PRIMARY' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -24744,7 +24744,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'PRIMARY' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -25247,7 +25247,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'PRIMARY' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -25746,7 +25746,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'PRIMARY' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -26256,7 +26256,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'PRIMARY' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -26766,7 +26766,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'PRIMARY' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -27266,7 +27266,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'PRIMARY' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -27759,7 +27759,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx1' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -28267,7 +28267,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx1' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -28790,7 +28790,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx1' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -29309,7 +29309,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx1' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -29824,7 +29824,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx1' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -30350,7 +30350,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx1' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -30876,7 +30876,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx1' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -31392,7 +31392,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx1' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) diff --git a/mysql-test/suite/parts/r/partition_basic_myisam.result b/mysql-test/suite/parts/r/partition_basic_myisam.result index 84d623e63a2..f70dae13bb6 100644 --- a/mysql-test/suite/parts/r/partition_basic_myisam.result +++ b/mysql-test/suite/parts/r/partition_basic_myisam.result @@ -7774,7 +7774,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx1' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -8293,7 +8293,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx1' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -8833,7 +8833,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx1' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -9365,7 +9365,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx1' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -9897,7 +9897,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx1' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -10442,7 +10442,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx1' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -10989,7 +10989,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx1' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -11524,7 +11524,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx1' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -12043,7 +12043,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx1' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -12562,7 +12562,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx1' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -13102,7 +13102,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx1' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -13634,7 +13634,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx1' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -14166,7 +14166,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx1' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -14709,7 +14709,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx1' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -15252,7 +15252,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx1' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -15787,7 +15787,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx1' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) diff --git a/mysql-test/suite/parts/r/partition_basic_symlink_myisam.result b/mysql-test/suite/parts/r/partition_basic_symlink_myisam.result index 602a114c318..146b3d361fb 100644 --- a/mysql-test/suite/parts/r/partition_basic_symlink_myisam.result +++ b/mysql-test/suite/parts/r/partition_basic_symlink_myisam.result @@ -8177,7 +8177,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx1' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -8725,7 +8725,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx1' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -9289,7 +9289,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx1' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -9845,7 +9845,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx1' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -10401,7 +10401,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx1' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -10966,7 +10966,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx1' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -11549,7 +11549,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx1' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -12108,7 +12108,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx1' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -12638,7 +12638,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx1' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -13186,7 +13186,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx1' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -13750,7 +13750,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx1' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -14306,7 +14306,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx1' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -14862,7 +14862,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx1' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -15425,7 +15425,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx1' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -16008,7 +16008,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx1' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -16567,7 +16567,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx1' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -17091,7 +17091,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx1' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -17629,7 +17629,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx1' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -18186,7 +18186,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx1' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -18730,7 +18730,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx1' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -19274,7 +19274,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx1' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -19832,7 +19832,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx1' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -20381,7 +20381,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx1' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) From 1d0b5cc9dbc338df3a9698bfc25b591ee5becd60 Mon Sep 17 00:00:00 2001 From: "Tatiana A. Nurnberg" Date: Thu, 19 Feb 2009 04:58:10 +0100 Subject: [PATCH 102/219] Bug#37400: mysql: Bad help message for charset command Typo existed in help-text for command "charset" in mysql client, making the parameter-name different for long and short forms of the command for no good reason. Fixed. client/mysql.cc: Make parameter-name in help-text the same for long and short forms, for consistency. --- client/mysql.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/mysql.cc b/client/mysql.cc index 2ecfd637453..d1d36d79565 100644 --- a/client/mysql.cc +++ b/client/mysql.cc @@ -2832,7 +2832,7 @@ com_charset(String *buffer __attribute__((unused)), char *line) param= get_arg(buff, 0); if (!param || !*param) { - return put_info("Usage: \\C char_setname | charset charset_name", + return put_info("Usage: \\C charset_name | charset charset_name", INFO_ERROR, 0); } new_cs= get_charset_by_csname(param, MY_CS_PRIMARY, MYF(MY_WME)); From 321646095d943c62b975126d059f22f672b41e46 Mon Sep 17 00:00:00 2001 From: Alexey Kopytov Date: Thu, 19 Feb 2009 11:49:35 +0300 Subject: [PATCH 103/219] Fix for bug #41078: With CURSOR_TYPE_READ_ONLY mysql_stmt_fetch() returns short string value. Multibyte character sets were not taken into account when calculating max_length in Item_param::convert_str_value(). As a result, string parameters of a prepared statement could be truncated later when calculating string length in characters by dividing length in bytes by the charset's mbmaxlen value (e.g. in Field_varstring::store()). Fixed by taking charset's mbmaxlen into account when calculating max_length in Item_param::convert_str_value(). sql/item.cc: Multiply string's length in characters by charset's mbmaxlen when calculating max_length. tests/mysql_client_test.c: Added a test case for bug #41078. --- sql/item.cc | 2 +- tests/mysql_client_test.c | 64 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 65 insertions(+), 1 deletion(-) diff --git a/sql/item.cc b/sql/item.cc index bc1ae683e93..c9edb7b8f6c 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -3010,7 +3010,7 @@ bool Item_param::convert_str_value(THD *thd) str_value.set_charset(value.cs_info.final_character_set_of_str_value); /* Here str_value is guaranteed to be in final_character_set_of_str_value */ - max_length= str_value.length(); + max_length= str_value.numchars() * str_value.charset()->mbmaxlen; decimals= 0; /* str_value_ptr is returned from val_str(). It must be not alloced diff --git a/tests/mysql_client_test.c b/tests/mysql_client_test.c index 0fddffebf82..f848e93a5c6 100644 --- a/tests/mysql_client_test.c +++ b/tests/mysql_client_test.c @@ -16410,6 +16410,69 @@ static void test_bug36326() #endif +/** + Bug#41078: With CURSOR_TYPE_READ_ONLY mysql_stmt_fetch() returns short + string value. +*/ + +static void test_bug41078(void) +{ + uint rc; + MYSQL_STMT *stmt= 0; + MYSQL_BIND param, result; + ulong cursor_type= CURSOR_TYPE_READ_ONLY; + ulong len; + char str[64]; + const char param_str[]= "abcdefghijklmn"; + my_bool is_null, error; + + DBUG_ENTER("test_bug41078"); + + rc= mysql_query(mysql, "SET NAMES UTF8"); + myquery(rc); + + stmt= mysql_simple_prepare(mysql, "SELECT ?"); + check_stmt(stmt); + verify_param_count(stmt, 1); + + rc= mysql_stmt_attr_set(stmt, STMT_ATTR_CURSOR_TYPE, &cursor_type); + check_execute(stmt, rc); + + bzero(¶m, sizeof(param)); + param.buffer_type= MYSQL_TYPE_STRING; + param.buffer= (void *) param_str; + len= sizeof(param_str) - 1; + param.length= &len; + + rc= mysql_stmt_bind_param(stmt, ¶m); + check_execute(stmt, rc); + + rc= mysql_stmt_execute(stmt); + check_execute(stmt, rc); + + bzero(&result, sizeof(result)); + result.buffer_type= MYSQL_TYPE_STRING; + result.buffer= str; + result.buffer_length= sizeof(str); + result.is_null= &is_null; + result.length= &len; + result.error= &error; + + rc= mysql_stmt_bind_result(stmt, &result); + check_execute(stmt, rc); + + rc= mysql_stmt_store_result(stmt); + check_execute(stmt, rc); + + rc= mysql_stmt_fetch(stmt); + check_execute(stmt, rc); + + DIE_UNLESS(len == sizeof(param_str) - 1 && !strcmp(str, param_str)); + + mysql_stmt_close(stmt); + + DBUG_VOID_RETURN; +} /* Read and parse arguments and MySQL options from my.cnf @@ -16713,6 +16776,7 @@ static struct my_tests_st my_tests[]= { #ifdef HAVE_QUERY_CACHE { "test_bug36326", test_bug36326 }, #endif + { "test_bug41078", test_bug41078 }, { 0, 0 } }; From b2a8faebea8b83c2d90096dac2627290f090bb07 Mon Sep 17 00:00:00 2001 From: Staale Smedseng Date: Thu, 19 Feb 2009 11:24:52 +0100 Subject: [PATCH 104/219] Bug#31506 detection of function's availability is wrong in configure.in Replacing AC_CHECK_FUNC+AC_CHECK_LIB combination with AC_SEARCH_LIBS. --- configure.in | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/configure.in b/configure.in index bdeb0f24c40..dc6841e5cf8 100644 --- a/configure.in +++ b/configure.in @@ -838,19 +838,17 @@ AC_CHECK_LIB(nsl_r, gethostbyname_r, [], AC_CHECK_LIB(nsl, gethostbyname_r)) AC_CHECK_FUNC(gethostbyname_r) -AC_CHECK_FUNC(setsockopt, , AC_CHECK_LIB(socket, setsockopt)) -AC_CHECK_FUNC(yp_get_default_domain, , - AC_CHECK_LIB(nsl, yp_get_default_domain)) -AC_CHECK_FUNC(p2open, , AC_CHECK_LIB(gen, p2open)) +AC_SEARCH_LIBS(setsockopt, socket) # This may get things to compile even if bind-8 is installed -AC_CHECK_FUNC(bind, , AC_CHECK_LIB(bind, bind)) +AC_SEARCH_LIBS(bind, bind) # Check if crypt() exists in libc or libcrypt, sets LIBS if needed AC_SEARCH_LIBS(crypt, crypt, AC_DEFINE(HAVE_CRYPT, 1, [crypt])) # See if we need a library for address lookup. AC_SEARCH_LIBS(inet_aton, [socket nsl resolv]) # For the sched_yield() function on Solaris -AC_CHECK_FUNC(sched_yield, , AC_CHECK_LIB(posix4, sched_yield)) +AC_SEARCH_LIBS(sched_yield, posix4, + AC_DEFINE(HAVE_SCHED_YIELD, 1, [sched_yield])) MYSQL_CHECK_ZLIB_WITH_COMPRESS @@ -956,7 +954,7 @@ AC_MSG_RESULT([$USE_PSTACK]) # Check for gtty if termio.h doesn't exists if test "$ac_cv_header_termio_h" = "no" -a "$ac_cv_header_termios_h" = "no" then - AC_CHECK_FUNC(gtty, , AC_CHECK_LIB(compat, gtty)) + AC_SEARCH_LIBS(gtty, compat) fi # We make a special variable for non-threaded version of LIBS to avoid From c2e23208ef7ae6b315ca4988e903bff2bc0284d4 Mon Sep 17 00:00:00 2001 From: Sergey Glukhov Date: Thu, 19 Feb 2009 17:20:44 +0400 Subject: [PATCH 105/219] Bug#37601 Cast Is Not Done On Row Comparison In case of ROW item each compared pair does not check if argumet collations can be aggregated and thus appropiriate item conversion does not happen. The fix is to add the check and convertion for ROW pairs. mysql-test/r/row.result: test result mysql-test/t/row.test: test case sql/item.cc: added agg_item_set_converter() function which was a part of agg_item_charsets() func. The only difference is that agg_item_set_converter() checks and converts items using already known collation. sql/item.h: added agg_item_set_converter() function sql/item_cmpfunc.cc: In case of ROW item each compared pair does not check if argumet collations can be aggregated and thus appropiriate item conversion does not happen. The fix is to add the check and convertion for ROW pairs. --- mysql-test/r/row.result | 14 ++++++++ mysql-test/t/row.test | 18 ++++++++++ sql/item.cc | 76 +++++++++++++++++++++++------------------ sql/item.h | 2 ++ sql/item_cmpfunc.cc | 13 ++++++- 5 files changed, 89 insertions(+), 34 deletions(-) diff --git a/mysql-test/r/row.result b/mysql-test/r/row.result index 98c79d4bc00..9afb528b6dd 100644 --- a/mysql-test/r/row.result +++ b/mysql-test/r/row.result @@ -443,3 +443,17 @@ SELECT ROW(a, 1) IN (SELECT SUM(b), 3) FROM t1 GROUP BY a; ROW(a, 1) IN (SELECT SUM(b), 3) 0 DROP TABLE t1; +create table t1 (a varchar(200), +b int unsigned not null primary key auto_increment) +default character set 'utf8'; +create table t2 (c varchar(200), +d int unsigned not null primary key auto_increment) +default character set 'latin1'; +insert into t1 (a) values('abc'); +insert into t2 (c) values('abc'); +select * from t1,t2 where (a,b) = (c,d); +a b c d +abc 1 abc 1 +select host,user from mysql.user where (host,user) = ('localhost','test'); +host user +drop table t1,t2; diff --git a/mysql-test/t/row.test b/mysql-test/t/row.test index 1601f7afd0e..fcc4259168b 100644 --- a/mysql-test/t/row.test +++ b/mysql-test/t/row.test @@ -237,3 +237,21 @@ SELECT ROW(a, 1) IN (SELECT SUM(b), 1) FROM t1 GROUP BY a; SELECT ROW(a, 1) IN (SELECT SUM(b), 3) FROM t1 GROUP BY a; DROP TABLE t1; + +# +# Bug#37601 Cast Is Not Done On Row Comparison +# +create table t1 (a varchar(200), + b int unsigned not null primary key auto_increment) +default character set 'utf8'; + +create table t2 (c varchar(200), + d int unsigned not null primary key auto_increment) +default character set 'latin1'; + +insert into t1 (a) values('abc'); +insert into t2 (c) values('abc'); +select * from t1,t2 where (a,b) = (c,d); + +select host,user from mysql.user where (host,user) = ('localhost','test'); +drop table t1,t2; diff --git a/sql/item.cc b/sql/item.cc index c9edb7b8f6c..14422bd3e92 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -1608,42 +1608,11 @@ bool agg_item_collations_for_comparison(DTCollation &c, const char *fname, } -/* - Collect arguments' character sets together. - We allow to apply automatic character set conversion in some cases. - The conditions when conversion is possible are: - - arguments A and B have different charsets - - A wins according to coercibility rules - (i.e. a column is stronger than a string constant, - an explicit COLLATE clause is stronger than a column) - - character set of A is either superset for character set of B, - or B is a string constant which can be converted into the - character set of A without data loss. - - If all of the above is true, then it's possible to convert - B into the character set of A, and then compare according - to the collation of A. - - For functions with more than two arguments: - collect(A,B,C) ::= collect(collect(A,B),C) - - Since this function calls THD::change_item_tree() on the passed Item ** - pointers, it is necessary to pass the original Item **'s, not copies. - Otherwise their values will not be properly restored (see BUG#20769). - If the items are not consecutive (eg. args[2] and args[5]), use the - item_sep argument, ie. - - agg_item_charsets(coll, fname, &args[2], 2, flags, 3) - -*/ - -bool agg_item_charsets(DTCollation &coll, const char *fname, - Item **args, uint nargs, uint flags, int item_sep) +bool agg_item_set_converter(DTCollation &coll, const char *fname, + Item **args, uint nargs, uint flags, int item_sep) { Item **arg, *safe_args[2]; - if (agg_item_collations(coll, fname, args, nargs, flags, item_sep)) - return TRUE; /* For better error reporting: save the first and the second argument. @@ -1724,6 +1693,47 @@ bool agg_item_charsets(DTCollation &coll, const char *fname, } +/* + Collect arguments' character sets together. + We allow to apply automatic character set conversion in some cases. + The conditions when conversion is possible are: + - arguments A and B have different charsets + - A wins according to coercibility rules + (i.e. a column is stronger than a string constant, + an explicit COLLATE clause is stronger than a column) + - character set of A is either superset for character set of B, + or B is a string constant which can be converted into the + character set of A without data loss. + + If all of the above is true, then it's possible to convert + B into the character set of A, and then compare according + to the collation of A. + + For functions with more than two arguments: + + collect(A,B,C) ::= collect(collect(A,B),C) + + Since this function calls THD::change_item_tree() on the passed Item ** + pointers, it is necessary to pass the original Item **'s, not copies. + Otherwise their values will not be properly restored (see BUG#20769). + If the items are not consecutive (eg. args[2] and args[5]), use the + item_sep argument, ie. + + agg_item_charsets(coll, fname, &args[2], 2, flags, 3) + +*/ + +bool agg_item_charsets(DTCollation &coll, const char *fname, + Item **args, uint nargs, uint flags, int item_sep) +{ + Item **arg, *safe_args[2]; + if (agg_item_collations(coll, fname, args, nargs, flags, item_sep)) + return TRUE; + + return agg_item_set_converter(coll, fname, args, nargs, flags, item_sep); +} + + void Item_ident_for_show::make_field(Send_field *tmp_field) { tmp_field->table_name= tmp_field->org_table_name= table_name; diff --git a/sql/item.h b/sql/item.h index 1058cc5dbb8..852b0fcc1ba 100644 --- a/sql/item.h +++ b/sql/item.h @@ -1169,6 +1169,8 @@ bool agg_item_collations(DTCollation &c, const char *name, Item **items, uint nitems, uint flags, int item_sep); bool agg_item_collations_for_comparison(DTCollation &c, const char *name, Item **items, uint nitems, uint flags); +bool agg_item_set_converter(DTCollation &coll, const char *fname, + Item **args, uint nargs, uint flags, int item_sep); bool agg_item_charsets(DTCollation &c, const char *name, Item **items, uint nitems, uint flags, int item_sep); diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index 3b1d18b4252..01d3e9bed52 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -490,7 +490,8 @@ int Arg_comparator::set_compare_func(Item_bool_func2 *item, Item_result type) my_error(ER_OPERAND_COLUMNS, MYF(0), (*a)->element_index(i)->cols()); return 1; } - comparators[i].set_cmp_func(owner, (*a)->addr(i), (*b)->addr(i)); + if (comparators[i].set_cmp_func(owner, (*a)->addr(i), (*b)->addr(i))) + return 1; } break; } @@ -835,6 +836,16 @@ int Arg_comparator::set_cmp_func(Item_bool_func2 *owner_arg, get_value_func= &get_time_value; return 0; } + else if (type == STRING_RESULT && + (*a)->result_type() == STRING_RESULT && + (*b)->result_type() == STRING_RESULT) + { + DTCollation coll; + coll.set((*a)->collation.collation); + if (agg_item_set_converter(coll, owner_arg->func_name(), + b, 1, MY_COLL_CMP_CONV, 1)) + return 1; + } return set_compare_func(owner_arg, type); } From 29476d879f85a81c9376b556ad9c233f2a5e073b Mon Sep 17 00:00:00 2001 From: Georgi Kodinov Date: Thu, 19 Feb 2009 17:30:03 +0200 Subject: [PATCH 106/219] Bug #42419: Server crash with "Pure virtual method called" on two concurrent connections The problem is that tables can enter open table cache for a thread without being properly cleaned up. This can happen if make_join_statistics() fails to read a const table because of e.g. a deadlock. It does set a member of TABLE structure to a value it allocates, but doesn't clean-up this setting on error nor does it set the rest of the members in JOIN to allow for automatic cleanup. As a result when such an error occurs and the next statement depends re-uses the table from the open tables cache it will get it with this TABLE::reginfo.join_tab pointing to a memory area that's freed. Fixed by making sure make_join_statistics() cleans up TABLE::reginfo.join_tab on error. mysql-test/r/innodb_mysql.result: Bug #42419: test case mysql-test/t/innodb_mysql-master.opt: Bug #42419: increase the timeout so it covers te conservative sleep 3 in the test mysql-test/t/innodb_mysql.test: Bug #42419: test case sql/sql_select.cc: Bug #42419: clean up the members of TABLE on failure in make_join_statisitcs() --- mysql-test/r/innodb_mysql.result | 16 +++++++++ mysql-test/t/innodb_mysql-master.opt | 2 +- mysql-test/t/innodb_mysql.test | 51 ++++++++++++++++++++++++++++ sql/sql_select.cc | 36 +++++++++++++------- 4 files changed, 92 insertions(+), 13 deletions(-) diff --git a/mysql-test/r/innodb_mysql.result b/mysql-test/r/innodb_mysql.result index 682cc2e82e2..78a56cddb08 100644 --- a/mysql-test/r/innodb_mysql.result +++ b/mysql-test/r/innodb_mysql.result @@ -1267,4 +1267,20 @@ CREATE INDEX i1 on t1 (a(3)); SELECT * FROM t1 WHERE a = 'abcde'; a DROP TABLE t1; +CREATE TABLE t1 (a INT NOT NULL AUTO_INCREMENT PRIMARY KEY, b INT) +ENGINE=InnoDB; +INSERT INTO t1 VALUES (1,1),(2,2),(3,3); +SET AUTOCOMMIT = 0; +CREATE TEMPORARY TABLE t1_tmp (b INT); +INSERT INTO t1_tmp SELECT b FROM t1 WHERE a = 3; +INSERT INTO t1_tmp SELECT b FROM t1 WHERE a = 2; +SET AUTOCOMMIT = 0; +CREATE TEMPORARY TABLE t2_tmp ( a INT, new_a INT); +INSERT INTO t2_tmp VALUES (1,51),(2,52),(3,53); +UPDATE t1 SET a = (SELECT new_a FROM t2_tmp WHERE t2_tmp.a = t1.a) WHERE a = 1; +UPDATE t1 SET a = (SELECT new_a FROM t2_tmp WHERE t2_tmp.a = t1.a) WHERE a = 2; +INSERT INTO t1_tmp SELECT b FROM t1 WHERE a = 1; +ERROR 40001: Deadlock found when trying to get lock; try restarting transaction +UPDATE t1 SET a = (SELECT new_a FROM t2_tmp WHERE t2_tmp.a = t1.a) WHERE a = 3; +DROP TABLE t1; End of 5.0 tests diff --git a/mysql-test/t/innodb_mysql-master.opt b/mysql-test/t/innodb_mysql-master.opt index 205c733455d..c8613e0ccd5 100644 --- a/mysql-test/t/innodb_mysql-master.opt +++ b/mysql-test/t/innodb_mysql-master.opt @@ -1 +1 @@ ---innodb-lock-wait-timeout=2 +--innodb-lock-wait-timeout=3 diff --git a/mysql-test/t/innodb_mysql.test b/mysql-test/t/innodb_mysql.test index b4fc425cb7c..eb23739386e 100644 --- a/mysql-test/t/innodb_mysql.test +++ b/mysql-test/t/innodb_mysql.test @@ -1025,4 +1025,55 @@ CREATE INDEX i1 on t1 (a(3)); SELECT * FROM t1 WHERE a = 'abcde'; DROP TABLE t1; +# +# Bug #42419: Server crash with "Pure virtual method called" on two +# concurrent connections +# + +connect (c1, localhost, root,,); +connect (c2, localhost, root,,); + +CREATE TABLE t1 (a INT NOT NULL AUTO_INCREMENT PRIMARY KEY, b INT) + ENGINE=InnoDB; + +INSERT INTO t1 VALUES (1,1),(2,2),(3,3); + +connection c1; + +SET AUTOCOMMIT = 0; + +CREATE TEMPORARY TABLE t1_tmp (b INT); + +INSERT INTO t1_tmp SELECT b FROM t1 WHERE a = 3; +INSERT INTO t1_tmp SELECT b FROM t1 WHERE a = 2; + +connection c2; + +SET AUTOCOMMIT = 0; + +CREATE TEMPORARY TABLE t2_tmp ( a INT, new_a INT); +INSERT INTO t2_tmp VALUES (1,51),(2,52),(3,53); + +UPDATE t1 SET a = (SELECT new_a FROM t2_tmp WHERE t2_tmp.a = t1.a) WHERE a = 1; + +--send +UPDATE t1 SET a = (SELECT new_a FROM t2_tmp WHERE t2_tmp.a = t1.a) WHERE a = 2; + +--sleep 3 + +connection c1; + +--error ER_LOCK_DEADLOCK +INSERT INTO t1_tmp SELECT b FROM t1 WHERE a = 1; + +connection c2; + +--reap +UPDATE t1 SET a = (SELECT new_a FROM t2_tmp WHERE t2_tmp.a = t1.a) WHERE a = 3; + +connection default; +disconnect c1; +disconnect c2; +DROP TABLE t1; + --echo End of 5.0 tests diff --git a/sql/sql_select.cc b/sql/sql_select.cc index a341cf5e0e9..a820e9966dc 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -2373,11 +2373,12 @@ typedef struct st_sargable_param */ static bool -make_join_statistics(JOIN *join, TABLE_LIST *tables, COND *conds, +make_join_statistics(JOIN *join, TABLE_LIST *tables_arg, COND *conds, DYNAMIC_ARRAY *keyuse_array) { int error; TABLE *table; + TABLE_LIST *tables= tables_arg; uint i,table_count,const_count,key; table_map found_const_table_map, all_table_map, found_ref, refs; key_map const_ref, eq_part; @@ -2415,10 +2416,10 @@ make_join_statistics(JOIN *join, TABLE_LIST *tables, COND *conds, table_vector[i]=s->table=table=tables->table; table->pos_in_table_list= tables; error= table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK); - if(error) + if (error) { - table->file->print_error(error, MYF(0)); - DBUG_RETURN(1); + table->file->print_error(error, MYF(0)); + goto error; } table->quick_keys.clear_all(); table->reginfo.join_tab=s; @@ -2503,7 +2504,7 @@ make_join_statistics(JOIN *join, TABLE_LIST *tables, COND *conds, { join->tables=0; // Don't use join->table my_message(ER_WRONG_OUTER_JOIN, ER(ER_WRONG_OUTER_JOIN), MYF(0)); - DBUG_RETURN(1); + goto error; } s->key_dependent= s->dependent; } @@ -2513,7 +2514,7 @@ make_join_statistics(JOIN *join, TABLE_LIST *tables, COND *conds, if (update_ref_and_keys(join->thd, keyuse_array, stat, join->tables, conds, join->cond_equal, ~outer_join, join->select_lex, &sargables)) - DBUG_RETURN(1); + goto error; /* Read tables with 0 or 1 rows (system tables) */ join->const_table_map= 0; @@ -2529,7 +2530,7 @@ make_join_statistics(JOIN *join, TABLE_LIST *tables, COND *conds, if ((tmp=join_read_const_table(s, p_pos))) { if (tmp > 0) - DBUG_RETURN(1); // Fatal error + goto error; // Fatal error } else found_const_table_map|= s->table->map; @@ -2601,7 +2602,7 @@ make_join_statistics(JOIN *join, TABLE_LIST *tables, COND *conds, if ((tmp= join_read_const_table(s, join->positions+const_count-1))) { if (tmp > 0) - DBUG_RETURN(1); // Fatal error + goto error; // Fatal error } else found_const_table_map|= table->map; @@ -2650,12 +2651,12 @@ make_join_statistics(JOIN *join, TABLE_LIST *tables, COND *conds, set_position(join,const_count++,s,start_keyuse); if (create_ref_for_key(join, s, start_keyuse, found_const_table_map)) - DBUG_RETURN(1); + goto error; if ((tmp=join_read_const_table(s, join->positions+const_count-1))) { if (tmp > 0) - DBUG_RETURN(1); // Fatal error + goto error; // Fatal error } else found_const_table_map|= table->map; @@ -2732,7 +2733,7 @@ make_join_statistics(JOIN *join, TABLE_LIST *tables, COND *conds, *s->on_expr_ref ? *s->on_expr_ref : conds, 1, &error); if (!select) - DBUG_RETURN(1); + goto error; records= get_quick_record_count(join->thd, select, s->table, &s->const_keys, join->row_limit); s->quick=select->quick; @@ -2778,7 +2779,7 @@ make_join_statistics(JOIN *join, TABLE_LIST *tables, COND *conds, { optimize_keyuse(join, keyuse_array); if (choose_plan(join, all_table_map & ~join->const_table_map)) - DBUG_RETURN(TRUE); + goto error; } else { @@ -2788,6 +2789,17 @@ make_join_statistics(JOIN *join, TABLE_LIST *tables, COND *conds, } /* Generate an execution plan from the found optimal join order. */ DBUG_RETURN(join->thd->killed || get_best_combination(join)); + +error: + /* + Need to clean up join_tab from TABLEs in case of error. + They won't get cleaned up by JOIN::cleanup() because JOIN::join_tab + may not be assigned yet by this function (which is building join_tab). + Dangling TABLE::reginfo.join_tab may cause part_of_refkey to choke. + */ + for (tables= tables_arg; tables; tables= tables->next_leaf) + tables->table->reginfo.join_tab= NULL; + DBUG_RETURN (1); } From b86dc86ee9841cb35d363992579299355f9245c9 Mon Sep 17 00:00:00 2001 From: Serge Kozlov Date: Thu, 19 Feb 2009 23:29:12 +0300 Subject: [PATCH 107/219] Bug#41423. 1. Constant values of binlog positions replaced by seeking them in binlog/relay log. 2. Updated result file --- mysql-test/suite/rpl/r/rpl_row_until.result | 77 +++++----- mysql-test/suite/rpl/t/rpl_row_until.test | 147 +++++++++++++------- 2 files changed, 132 insertions(+), 92 deletions(-) diff --git a/mysql-test/suite/rpl/r/rpl_row_until.result b/mysql-test/suite/rpl/r/rpl_row_until.result index be1ec51f74a..ad54450af74 100644 --- a/mysql-test/suite/rpl/r/rpl_row_until.result +++ b/mysql-test/suite/rpl/r/rpl_row_until.result @@ -4,16 +4,17 @@ reset master; reset slave; drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; start slave; +CREATE TABLE t1(n INT NOT NULL AUTO_INCREMENT PRIMARY KEY); +INSERT INTO t1 VALUES (1),(2),(3),(4); +DROP TABLE t1; +CREATE TABLE t2(n INT NOT NULL AUTO_INCREMENT PRIMARY KEY); +INSERT INTO t2 VALUES (1),(2); +INSERT INTO t2 VALUES (3),(4); +DROP TABLE t2; include/stop_slave.inc -create table t1(n int not null auto_increment primary key); -insert into t1 values (1),(2),(3),(4); -drop table t1; -create table t2(n int not null auto_increment primary key); -insert into t2 values (1),(2); -insert into t2 values (3),(4); -drop table t2; -start slave until master_log_file='master-bin.000001', master_log_pos=311; -select * from t1; +RESET SLAVE; +START SLAVE UNTIL MASTER_LOG_FILE='master-bin.000001', MASTER_LOG_POS=master_pos_drop_t1 +SELECT * FROM t1; n 1 2 @@ -23,10 +24,10 @@ SHOW SLAVE STATUS; Slave_IO_State # Master_Host 127.0.0.1 Master_User root -Master_Port MASTER_PORT +Master_Port # Connect_Retry 1 Master_Log_File master-bin.000001 -Read_Master_Log_Pos 1161 +Read_Master_Log_Pos # Relay_Log_File # Relay_Log_Pos # Relay_Master_Log_File master-bin.000001 @@ -41,11 +42,11 @@ Replicate_Wild_Ignore_Table Last_Errno 0 Last_Error Skip_Counter 0 -Exec_Master_Log_Pos 454 +Exec_Master_Log_Pos MASTER_POS_DROP_T1 Relay_Log_Space # Until_Condition Master Until_Log_File master-bin.000001 -Until_Log_Pos 311 +Until_Log_Pos MASTER_POS_DROP_T1 Master_SSL_Allowed No Master_SSL_CA_File Master_SSL_CA_Path @@ -58,8 +59,8 @@ Last_IO_Errno # Last_IO_Error # Last_SQL_Errno 0 Last_SQL_Error -start slave until master_log_file='master-no-such-bin.000001', master_log_pos=291; -select * from t1; +START SLAVE UNTIL MASTER_LOG_FILE='master-no-such-bin.000001', MASTER_LOG_POS=291; +SELECT * FROM t1; n 1 2 @@ -69,10 +70,10 @@ SHOW SLAVE STATUS; Slave_IO_State # Master_Host 127.0.0.1 Master_User root -Master_Port MASTER_PORT +Master_Port # Connect_Retry 1 Master_Log_File master-bin.000001 -Read_Master_Log_Pos 1161 +Read_Master_Log_Pos # Relay_Log_File # Relay_Log_Pos # Relay_Master_Log_File master-bin.000001 @@ -87,7 +88,7 @@ Replicate_Wild_Ignore_Table Last_Errno 0 Last_Error Skip_Counter 0 -Exec_Master_Log_Pos 454 +Exec_Master_Log_Pos MASTER_POS_DROP_T1 Relay_Log_Space # Until_Condition Master Until_Log_File master-no-such-bin.000001 @@ -104,8 +105,8 @@ Last_IO_Errno # Last_IO_Error # Last_SQL_Errno 0 Last_SQL_Error -start slave until relay_log_file='slave-relay-bin.000004', relay_log_pos=1014; -select * from t2; +START SLAVE UNTIL RELAY_LOG_FILE='slave-relay-bin.000002', RELAY_LOG_POS=relay_pos_insert1_t2 +SELECT * FROM t2; n 1 2 @@ -113,10 +114,10 @@ SHOW SLAVE STATUS; Slave_IO_State # Master_Host 127.0.0.1 Master_User root -Master_Port MASTER_PORT +Master_Port # Connect_Retry 1 Master_Log_File master-bin.000001 -Read_Master_Log_Pos 1161 +Read_Master_Log_Pos # Relay_Log_File # Relay_Log_Pos # Relay_Master_Log_File master-bin.000001 @@ -131,11 +132,11 @@ Replicate_Wild_Ignore_Table Last_Errno 0 Last_Error Skip_Counter 0 -Exec_Master_Log_Pos 868 +Exec_Master_Log_Pos MASTER_POS_INSERT1_T2 Relay_Log_Space # Until_Condition Relay -Until_Log_File slave-relay-bin.000004 -Until_Log_Pos 1014 +Until_Log_File slave-relay-bin.000002 +Until_Log_Pos RELAY_POS_INSERT1_T2 Master_SSL_Allowed No Master_SSL_CA_File Master_SSL_CA_Path @@ -148,17 +149,17 @@ Last_IO_Errno # Last_IO_Error # Last_SQL_Errno 0 Last_SQL_Error -start slave; +START SLAVE; include/stop_slave.inc -start slave sql_thread until master_log_file='master-bin.000001', master_log_pos=740; +START SLAVE SQL_THREAD UNTIL MASTER_LOG_FILE='master-bin.000001', MASTER_LOG_POS=master_pos_create_t2 SHOW SLAVE STATUS; Slave_IO_State # Master_Host 127.0.0.1 Master_User root -Master_Port MASTER_PORT +Master_Port # Connect_Retry 1 Master_Log_File master-bin.000001 -Read_Master_Log_Pos 1161 +Read_Master_Log_Pos # Relay_Log_File # Relay_Log_Pos # Relay_Master_Log_File master-bin.000001 @@ -173,11 +174,11 @@ Replicate_Wild_Ignore_Table Last_Errno 0 Last_Error Skip_Counter 0 -Exec_Master_Log_Pos 1161 +Exec_Master_Log_Pos MASTER_POS_DROP_T2 Relay_Log_Space # Until_Condition Master Until_Log_File master-bin.000001 -Until_Log_Pos 740 +Until_Log_Pos MASTER_POS_CREATE_T2 Master_SSL_Allowed No Master_SSL_CA_File Master_SSL_CA_Path @@ -190,17 +191,17 @@ Last_IO_Errno # Last_IO_Error # Last_SQL_Errno 0 Last_SQL_Error -start slave until master_log_file='master-bin', master_log_pos=561; +START SLAVE UNTIL MASTER_LOG_FILE='master-bin', MASTER_LOG_POS=561; ERROR HY000: Incorrect parameter or combination of parameters for START SLAVE UNTIL -start slave until master_log_file='master-bin.000001', master_log_pos=561, relay_log_pos=12; +START SLAVE UNTIL MASTER_LOG_FILE='master-bin.000001', MASTER_LOG_POS=561, RELAY_LOG_POS=12; ERROR HY000: Incorrect parameter or combination of parameters for START SLAVE UNTIL -start slave until master_log_file='master-bin.000001'; +START SLAVE UNTIL MASTER_LOG_FILE='master-bin.000001'; ERROR HY000: Incorrect parameter or combination of parameters for START SLAVE UNTIL -start slave until relay_log_file='slave-relay-bin.000002'; +START SLAVE UNTIL RELAY_LOG_FILE='slave-relay-bin.000009'; ERROR HY000: Incorrect parameter or combination of parameters for START SLAVE UNTIL -start slave until relay_log_file='slave-relay-bin.000002', master_log_pos=561; +START SLAVE UNTIL RELAY_LOG_FILE='slave-relay-bin.000002', MASTER_LOG_POS=561; ERROR HY000: Incorrect parameter or combination of parameters for START SLAVE UNTIL -start slave; -start slave until master_log_file='master-bin.000001', master_log_pos=740; +START SLAVE; +START SLAVE UNTIL MASTER_LOG_FILE='master-bin.000001', MASTER_LOG_POS=740; Warnings: Note 1254 Slave is already running diff --git a/mysql-test/suite/rpl/t/rpl_row_until.test b/mysql-test/suite/rpl/t/rpl_row_until.test index d89de7d9ebd..fe859218ed3 100644 --- a/mysql-test/suite/rpl/t/rpl_row_until.test +++ b/mysql-test/suite/rpl/t/rpl_row_until.test @@ -2,76 +2,115 @@ -- source include/have_binlog_format_row.inc -- source include/master-slave.inc -# Test is dependent on binlog positions +# Note: The test is dependent on binlog positions # prepare version for substitutions let $VERSION=`select version()`; -# stop slave before he will start replication also sync with master -# for avoiding undetermenistic behaviour +# Create some events on master +connection master; +CREATE TABLE t1(n INT NOT NULL AUTO_INCREMENT PRIMARY KEY); +INSERT INTO t1 VALUES (1),(2),(3),(4); +DROP TABLE t1; +# Save master log postion for query DROP TABLE t1 +save_master_pos; +let $master_pos_drop_t1= query_get_value(SHOW BINLOG EVENTS, Pos, 7); + +CREATE TABLE t2(n INT NOT NULL AUTO_INCREMENT PRIMARY KEY); +# Save master log postion for query CREATE TABLE t2 +save_master_pos; +let $master_pos_create_t2= query_get_value(SHOW BINLOG EVENTS, Pos, 8); + +INSERT INTO t2 VALUES (1),(2); +save_master_pos; +# Save master log postion for query INSERT INTO t2 VALUES (1),(2); +let $master_pos_insert1_t2= query_get_value(SHOW BINLOG EVENTS, End_log_pos, 12); +sync_slave_with_master; + +# Save relay log postion for query INSERT INTO t2 VALUES (1),(2); +let $relay_pos_insert1_t2= query_get_value(show slave status, Relay_Log_Pos, 1); + +connection master; +INSERT INTO t2 VALUES (3),(4); +DROP TABLE t2; +# Save master log postion for query INSERT INTO t2 VALUES (1),(2); +let $master_pos_drop_t2= query_get_value(SHOW BINLOG EVENTS, End_log_pos, 17); +sync_slave_with_master; + +--source include/stop_slave.inc +# Reset slave. +RESET SLAVE; +--disable_query_log +eval CHANGE MASTER TO MASTER_USER='root', MASTER_CONNECT_RETRY=1, MASTER_HOST='127.0.0.1', MASTER_PORT=$MASTER_MYPORT; +--enable_query_log + +# Try to replicate all queries until drop of t1 +connection slave; +echo START SLAVE UNTIL MASTER_LOG_FILE='master-bin.000001', MASTER_LOG_POS=master_pos_drop_t1; +--disable_query_log +eval START SLAVE UNTIL MASTER_LOG_FILE='master-bin.000001', MASTER_LOG_POS=$master_pos_drop_t1; +--enable_query_log +--source include/wait_for_slave_sql_to_stop.inc + +# Here table should be still not deleted +SELECT * FROM t1; +--replace_result $master_pos_drop_t1 MASTER_POS_DROP_T1 +--replace_column 1 # 4 # 7 # 8 # 9 # 16 # 23 # 33 # 35 # 36 # +query_vertical SHOW SLAVE STATUS; + +# This should fail right after start +START SLAVE UNTIL MASTER_LOG_FILE='master-no-such-bin.000001', MASTER_LOG_POS=291; +--source include/wait_for_slave_sql_to_stop.inc +# again this table should be still not deleted +SELECT * FROM t1; +--replace_result $master_pos_drop_t1 MASTER_POS_DROP_T1 +--replace_column 1 # 4 # 7 # 8 # 9 # 16 # 23 # 33 # 35 # 36 # +query_vertical SHOW SLAVE STATUS; + +# Try replicate all up to and not including the second insert to t2; +echo START SLAVE UNTIL RELAY_LOG_FILE='slave-relay-bin.000002', RELAY_LOG_POS=relay_pos_insert1_t2; +--disable_query_log +eval START SLAVE UNTIL RELAY_LOG_FILE='slave-relay-bin.000002', RELAY_LOG_POS=$relay_pos_insert1_t2; +--enable_query_log +--source include/wait_for_slave_sql_to_stop.inc +SELECT * FROM t2; +--replace_result $relay_pos_insert1_t2 RELAY_POS_INSERT1_T2 $master_pos_insert1_t2 MASTER_POS_INSERT1_T2 +--replace_column 1 # 4 # 7 # 8 # 9 # 16 # 23 # 33 # 35 # 36 # +query_vertical SHOW SLAVE STATUS; + +# clean up +START SLAVE; +--source include/wait_for_slave_to_start.inc +connection master; sync_slave_with_master; --source include/stop_slave.inc -connection master; -# create some events on master -create table t1(n int not null auto_increment primary key); -insert into t1 values (1),(2),(3),(4); -drop table t1; -create table t2(n int not null auto_increment primary key); -insert into t2 values (1),(2); -insert into t2 values (3),(4); -drop table t2; - -# try to replicate all queries until drop of t1 -connection slave; -start slave until master_log_file='master-bin.000001', master_log_pos=311; ---source include/wait_for_slave_sql_to_stop.inc -# here table should be still not deleted -select * from t1; -source include/show_slave_status.inc; - -# this should fail right after start -start slave until master_log_file='master-no-such-bin.000001', master_log_pos=291; ---source include/wait_for_slave_sql_to_stop.inc -# again this table should be still not deleted -select * from t1; -source include/show_slave_status.inc; - -# try replicate all up to and not including the second insert to t2; -start slave until relay_log_file='slave-relay-bin.000004', relay_log_pos=1014; ---source include/wait_for_slave_sql_to_stop.inc -select * from t2; -source include/show_slave_status.inc; - -# clean up -start slave; -connection master; -save_master_pos; -connection slave; -sync_with_master; ---source include/stop_slave.inc - -# this should stop immediately as we are already there -start slave sql_thread until master_log_file='master-bin.000001', master_log_pos=740; ---let $slave_param= Until_Log_Pos ---let $slave_param_value= 740 +# This should stop immediately as we are already there +echo START SLAVE SQL_THREAD UNTIL MASTER_LOG_FILE='master-bin.000001', MASTER_LOG_POS=master_pos_create_t2; +--disable_query_log +eval START SLAVE SQL_THREAD UNTIL MASTER_LOG_FILE='master-bin.000001', MASTER_LOG_POS=$master_pos_create_t2; +--enable_query_log +let $slave_param= Until_Log_Pos; +let $slave_param_value= $master_pos_create_t2; --source include/wait_for_slave_param.inc --source include/wait_for_slave_sql_to_stop.inc # here the sql slave thread should be stopped --replace_result bin.000005 bin.000004 bin.000006 bin.000004 bin.000007 bin.000004 -source include/show_slave_status.inc; +--replace_result $master_pos_create_t2 MASTER_POS_CREATE_T2 $master_pos_drop_t2 MASTER_POS_DROP_T2 +--replace_column 1 # 4 # 7 # 8 # 9 # 16 # 23 # 33 # 35 # 36 # +query_vertical SHOW SLAVE STATUS; #testing various error conditions --error 1277 -start slave until master_log_file='master-bin', master_log_pos=561; +START SLAVE UNTIL MASTER_LOG_FILE='master-bin', MASTER_LOG_POS=561; --error 1277 -start slave until master_log_file='master-bin.000001', master_log_pos=561, relay_log_pos=12; +START SLAVE UNTIL MASTER_LOG_FILE='master-bin.000001', MASTER_LOG_POS=561, RELAY_LOG_POS=12; --error 1277 -start slave until master_log_file='master-bin.000001'; +START SLAVE UNTIL MASTER_LOG_FILE='master-bin.000001'; --error 1277 -start slave until relay_log_file='slave-relay-bin.000002'; +START SLAVE UNTIL RELAY_LOG_FILE='slave-relay-bin.000009'; --error 1277 -start slave until relay_log_file='slave-relay-bin.000002', master_log_pos=561; +START SLAVE UNTIL RELAY_LOG_FILE='slave-relay-bin.000002', MASTER_LOG_POS=561; # Warning should be given for second command -start slave; -start slave until master_log_file='master-bin.000001', master_log_pos=740; +START SLAVE; +START SLAVE UNTIL MASTER_LOG_FILE='master-bin.000001', MASTER_LOG_POS=740; From 79300d6f7fb5cd22b9d3c2d14b6eb443e2ae28ed Mon Sep 17 00:00:00 2001 From: Patrick Crews Date: Thu, 19 Feb 2009 15:37:40 -0500 Subject: [PATCH 108/219] Bug#38831: 11 test cases fail on Windows due to missing commands Replaced Unix calls with mysql-test-run's built-in functions / SQL manipulation where possible. Replaced error codes with error names as well. Disabled two tests on Windows due to more complex Unix command usage See Bug#41307, Bug#41308 --- mysql-test/include/ndb_backup.inc | 7 ++ mysql-test/r/mysqlbinlog.result | 9 ++- mysql-test/r/mysqltest.result | 2 - mysql-test/r/trigger-compat.result | 4 +- mysql-test/t/mysqlbinlog.test | 28 +++++++- mysql-test/t/mysqltest.test | 108 ++++++++++++++++++----------- mysql-test/t/ndb_autodiscover.test | 6 ++ mysql-test/t/rpl_trigger.test | 3 +- mysql-test/t/trigger-compat.test | 24 +++++-- 9 files changed, 136 insertions(+), 55 deletions(-) diff --git a/mysql-test/include/ndb_backup.inc b/mysql-test/include/ndb_backup.inc index f0a883d4e11..3239030bb64 100644 --- a/mysql-test/include/ndb_backup.inc +++ b/mysql-test/include/ndb_backup.inc @@ -2,6 +2,13 @@ # By JBM 2006-02-16 So that the code is not repeated # # in test cases and can be reused. # ###################################################### + +# Bug#41307: Tests using include/ndb_backup.inc won't work on Windows due to +# 'grep' call +# This test is disabled on Windows via the next line until the above bug is +# resolved +--source include/not_windows.inc + --exec $NDB_MGM --no-defaults --ndb-connectstring="localhost:$NDBCLUSTER_PORT" -e "start backup" >> $NDB_TOOLS_OUTPUT # there is no neat way to find the backupid, this is a hack to find it... diff --git a/mysql-test/r/mysqlbinlog.result b/mysql-test/r/mysqlbinlog.result index 4fd87861ded..fe536950b4c 100644 --- a/mysql-test/r/mysqlbinlog.result +++ b/mysql-test/r/mysqlbinlog.result @@ -353,7 +353,14 @@ flush logs; INSERT INTO t1 VALUES ('0123456789'); flush logs; DROP TABLE t1; -# Query thread_id=REMOVED exec_time=REMOVED error_code=REMOVED +We expect this value to be 1 +The bug being tested was that 'Query' lines were not preceded by '#' +If the line is in the table, it had to have been preceded by a '#' + +SELECT COUNT(*) AS `BUG#28293_expect_1` FROM patch WHERE a LIKE '%Query%'; +BUG#28293_expect_1 +1 +DROP TABLE patch; flush logs; create table t1(a int); insert into t1 values(connection_id()); diff --git a/mysql-test/r/mysqltest.result b/mysql-test/r/mysqltest.result index a7df1a523cf..e445bf3cc9b 100644 --- a/mysql-test/r/mysqltest.result +++ b/mysql-test/r/mysqltest.result @@ -210,7 +210,6 @@ source database "MySQL: The world's most popular ;open source database" echo message echo message -mysqltest: At line 1: command "false" failed mysqltest: At line 1: Missing argument in exec MySQL "MySQL" @@ -378,7 +377,6 @@ mysqltest: At line 1: The argument to dec must be a variable (start with $) mysqltest: At line 1: End of line junk detected: "1000" mysqltest: At line 1: Missing arguments to system, nothing to do! mysqltest: At line 1: Missing arguments to system, nothing to do! -mysqltest: At line 1: system command 'false' failed system command 'NonExistsinfComamdn 2> /dev/null' failed test test2 diff --git a/mysql-test/r/trigger-compat.result b/mysql-test/r/trigger-compat.result index 6839cacab43..81c7a14c173 100644 --- a/mysql-test/r/trigger-compat.result +++ b/mysql-test/r/trigger-compat.result @@ -13,9 +13,7 @@ GRANT CREATE ON mysqltest_db1.* TO mysqltest_dfn@localhost; ---> connection: wl2818_definer_con CREATE TABLE t1(num_value INT); CREATE TABLE t2(user_str TEXT); -CREATE TRIGGER wl2818_trg1 BEFORE INSERT ON t1 -FOR EACH ROW -INSERT INTO t2 VALUES(CURRENT_USER()); +CREATE TRIGGER wl2818_trg1 BEFORE INSERT ON t1 FOR EACH ROW INSERT INTO t2 VALUES(CURRENT_USER()); ---> patching t1.TRG... diff --git a/mysql-test/t/mysqlbinlog.test b/mysql-test/t/mysqlbinlog.test index 5b4a43c8fe8..1f3d0fed334 100644 --- a/mysql-test/t/mysqlbinlog.test +++ b/mysql-test/t/mysqlbinlog.test @@ -1,7 +1,9 @@ # We are using .opt file since we need small binlog size - -- source include/have_log_bin.inc +# Currently disabling this test on Windows due to use of grep and sed +--source include/not_windows.inc + # we need this for getting fixed timestamps inside of this test set timestamp=1000000000; @@ -174,7 +176,8 @@ delimiter ;// flush logs; call p1(); drop procedure p1; ---error 1305 +--error ER_SP_DOES_NOT_EXIST + call p1(); --replace_regex /SQL_LOAD_MB-[0-9]-[0-9]/SQL_LOAD_MB-#-#/ --exec $MYSQL_BINLOG --short-form $MYSQLTEST_VARDIR/log/master-bin.000007 @@ -226,7 +229,26 @@ flush logs; INSERT INTO t1 VALUES ('0123456789'); flush logs; DROP TABLE t1; ---exec $MYSQL_BINLOG --hexdump --local-load=$MYSQLTEST_VARDIR/tmp/ $MYSQLTEST_VARDIR/log/master-bin.000011 | grep 'Query' | sed 's/[0-9]\{1,\}/REMOVED/g' + +# We create a table, patch, and load the output into it +# By using LINES STARTING BY '#' + SELECT WHERE a LIKE 'Query' +# We can easily see if a 'Query' line is missing the '#' character +# as described in the original bug + +--disable_query_log +CREATE TABLE patch (a blob); +--exec $MYSQL_BINLOG --hexdump --local-load=$MYSQLTEST_VARDIR/tmp/ $MYSQLTEST_VARDIR/log/master-bin.000011 > $MYSQLTEST_VARDIR/tmp/mysqlbinlog_tmp.dat +eval LOAD DATA LOCAL INFILE '$MYSQLTEST_VARDIR/tmp/mysqlbinlog_tmp.dat' + INTO TABLE patch FIELDS TERMINATED by '' LINES STARTING BY '#'; +--remove_file $MYSQLTEST_VARDIR/tmp/mysqlbinlog_tmp.dat +--enable_query_log + +--echo We expect this value to be 1 +--echo The bug being tested was that 'Query' lines were not preceded by '#' +--echo If the line is in the table, it had to have been preceded by a '#' +--echo +SELECT COUNT(*) AS `BUG#28293_expect_1` FROM patch WHERE a LIKE '%Query%'; +DROP TABLE patch; # # Bug #29928: incorrect connection_id() restoring from mysqlbinlog out diff --git a/mysql-test/t/mysqltest.test b/mysql-test/t/mysqltest.test index 5856bfff036..93528f81449 100644 --- a/mysql-test/t/mysqltest.test +++ b/mysql-test/t/mysqltest.test @@ -62,7 +62,8 @@ select otto from (select 1 as otto) as t1; --exec echo "select friedrich from (select 1 as otto) as t1;" | $MYSQL_TEST 2>&1 # expectation = response ---error 1054 +--error ER_BAD_FIELD_ERROR + select friedrich from (select 1 as otto) as t1; # The following unmasked unsuccessful statement must give @@ -131,14 +132,16 @@ eval select $mysql_errno as "after_successful_stmt_errno" ; #---------------------------------------------------------------------------- # check mysql_errno = 1064 after statement with wrong syntax # ---------------------------------------------------------------------------- ---error 1064 +--error ER_PARSE_ERROR + garbage ; eval select $mysql_errno as "after_wrong_syntax_errno" ; # ---------------------------------------------------------------------------- # check if let $my_var= 'abc' ; affects $mysql_errno # ---------------------------------------------------------------------------- ---error 1064 +--error ER_PARSE_ERROR + garbage ; let $my_var= 'abc' ; eval select $mysql_errno as "after_let_var_equal_value" ; @@ -146,7 +149,8 @@ eval select $mysql_errno as "after_let_var_equal_value" ; # ---------------------------------------------------------------------------- # check if set @my_var= 'abc' ; affects $mysql_errno # ---------------------------------------------------------------------------- ---error 1064 +--error ER_PARSE_ERROR + garbage ; set @my_var= 'abc' ; eval select $mysql_errno as "after_set_var_equal_value" ; @@ -155,7 +159,8 @@ eval select $mysql_errno as "after_set_var_equal_value" ; # check if the setting of --disable-warnings itself affects $mysql_errno # (May be -- modifies $mysql_errno.) # ---------------------------------------------------------------------------- ---error 1064 +--error ER_PARSE_ERROR + garbage ; --disable_warnings eval select $mysql_errno as "after_disable_warnings_command" ; @@ -166,7 +171,8 @@ eval select $mysql_errno as "after_disable_warnings_command" ; # (May be disabled warnings affect $mysql_errno.) # ---------------------------------------------------------------------------- drop table if exists t1 ; ---error 1064 +--error ER_PARSE_ERROR + garbage ; drop table if exists t1 ; eval select $mysql_errno as "after_disable_warnings" ; @@ -175,21 +181,26 @@ eval select $mysql_errno as "after_disable_warnings" ; # ---------------------------------------------------------------------------- # check if masked errors affect $mysql_errno # ---------------------------------------------------------------------------- ---error 1064 +--error ER_PARSE_ERROR + garbage ; ---error 1146 +--error ER_NO_SUCH_TABLE + select 3 from t1 ; eval select $mysql_errno as "after_minus_masked" ; ---error 1064 +--error ER_PARSE_ERROR + garbage ; ---error 1146 +--error ER_NO_SUCH_TABLE + select 3 from t1 ; eval select $mysql_errno as "after_!_masked" ; # ---------------------------------------------------------------------------- # Will manipulations of $mysql_errno be possible and visible ? # ---------------------------------------------------------------------------- ---error 1064 +--error ER_PARSE_ERROR + garbage ; let $mysql_errno= -1; eval select $mysql_errno as "after_let_errno_equal_value" ; @@ -198,50 +209,61 @@ eval select $mysql_errno as "after_let_errno_equal_value" ; # How affect actions on prepared statements $mysql_errno ? # ---------------------------------------------------------------------------- # failing prepare ---error 1064 +--error ER_PARSE_ERROR + garbage ; ---error 1146 +--error ER_NO_SUCH_TABLE + prepare stmt from "select 3 from t1" ; eval select $mysql_errno as "after_failing_prepare" ; create table t1 ( f1 char(10)); # successful prepare ---error 1064 +--error ER_PARSE_ERROR + garbage ; prepare stmt from "select 3 from t1" ; eval select $mysql_errno as "after_successful_prepare" ; # successful execute ---error 1064 +--error ER_PARSE_ERROR + garbage ; execute stmt; eval select $mysql_errno as "after_successful_execute" ; # failing execute (table has been dropped) drop table t1; ---error 1064 +--error ER_PARSE_ERROR + garbage ; ---error 1146 +--error ER_NO_SUCH_TABLE + execute stmt; eval select $mysql_errno as "after_failing_execute" ; # failing execute (unknown statement) ---error 1064 +--error ER_PARSE_ERROR + garbage ; ---error 1243 +--error ER_UNKNOWN_STMT_HANDLER + execute __stmt_; eval select $mysql_errno as "after_failing_execute" ; # successful deallocate ---error 1064 +--error ER_PARSE_ERROR + garbage ; deallocate prepare stmt; eval select $mysql_errno as "after_successful_deallocate" ; # failing deallocate ( statement handle does not exist ) ---error 1064 +--error ER_PARSE_ERROR + garbage ; ---error 1243 +--error ER_UNKNOWN_STMT_HANDLER + deallocate prepare __stmt_; eval select $mysql_errno as "after_failing_deallocate" ; @@ -266,7 +288,8 @@ eval select $mysql_errno as "after_failing_deallocate" ; # ---------------------------------------------------------------------------- # Switch off the abort on error and check the effect on $mysql_errno # ---------------------------------------------------------------------------- ---error 1064 +--error ER_PARSE_ERROR + garbage ; --disable_abort_on_error eval select $mysql_errno as "after_--disable_abort_on_error" ; @@ -280,9 +303,11 @@ select 3 from t1 ; # masked failing statements # ---------------------------------------------------------------------------- # expected error = response ---error 1146 +--error ER_NO_SUCH_TABLE + select 3 from t1 ; ---error 1146 +--error ER_NO_SUCH_TABLE + select 3 from t1 ; eval select $mysql_errno as "after_!errno_masked_error" ; # expected error <> response @@ -296,7 +321,8 @@ eval select $mysql_errno as "after_!errno_masked_error" ; # ---------------------------------------------------------------------------- # Switch the abort on error on and check the effect on $mysql_errno # ---------------------------------------------------------------------------- ---error 1064 +--error ER_PARSE_ERROR + garbage ; --enable_abort_on_error eval select $mysql_errno as "after_--enable_abort_on_error" ; @@ -305,7 +331,8 @@ eval select $mysql_errno as "after_--enable_abort_on_error" ; # masked failing statements # ---------------------------------------------------------------------------- # expected error = response ---error 1146 +--error ER_NO_SUCH_TABLE + select 3 from t1 ; # ---------------------------------------------------------------------------- @@ -568,9 +595,6 @@ echo ; # ---------------------------------------------------------------------------- # Illegal use of exec ---error 1 ---exec echo "--exec false" | $MYSQL_TEST 2>&1 - --error 1 --exec echo "--exec " | $MYSQL_TEST 2>&1 @@ -951,8 +975,6 @@ system echo "hej" > /dev/null; --exec echo "system;" | $MYSQL_TEST 2>&1 --error 1 --exec echo "system $NONEXISTSINFVAREABLI;" | $MYSQL_TEST 2>&1 ---error 1 ---exec echo "system false;" | $MYSQL_TEST 2>&1 --disable_abort_on_error system NonExistsinfComamdn 2> /dev/null; @@ -1370,7 +1392,8 @@ connection default; let $num= 2; while ($num) { - --error 1064 + --error ER_PARSE_ERROR + failing_statement; dec $num; @@ -1429,7 +1452,7 @@ select "this will be executed"; # # Test zero length result file. Should not pass # ---exec touch $MYSQLTEST_VARDIR/tmp/zero_length_file.result +--exec echo '' > $MYSQLTEST_VARDIR/tmp/zero_length_file.result --exec echo "echo ok;" > $MYSQLTEST_VARDIR/tmp/query.sql --error 1 --exec $MYSQL_TEST -x $MYSQLTEST_VARDIR/tmp/query.sql -R $MYSQLTEST_VARDIR/tmp/zero_length_file.result > /dev/null 2>&1 @@ -1482,7 +1505,8 @@ drop table t1; --error 1 --exec $MYSQL_TEST --record -x $MYSQLTEST_VARDIR/tmp/bug11731.sql -R $MYSQLTEST_VARDIR/tmp/bug11731.out 2>&1 # The .out file should be non existent ---exec test ! -s $MYSQLTEST_VARDIR/tmp/bug11731.out +--error 1 +--file_exists $MYSQLTEST_VARDIR/tmp/bug11731.out drop table t1; @@ -1503,7 +1527,7 @@ drop table t1; --exec $MYSQL_TEST --record -x $MYSQLTEST_VARDIR/tmp/bug11731.sql -R $MYSQLTEST_VARDIR/tmp/bug11731.out 2>&1 # The .out file should exist ---exec test -s $MYSQLTEST_VARDIR/tmp/bug11731.out +--file_exists $MYSQLTEST_VARDIR/tmp/bug11731.out drop table t1; remove_file $MYSQLTEST_VARDIR/tmp/bug11731.out; remove_file $MYSQLTEST_VARDIR/log/bug11731.log; @@ -1515,14 +1539,17 @@ remove_file $MYSQLTEST_VARDIR/tmp/bug11731.sql; # It should be possible to use the command "query" to force mysqltest to # send the command to the server although it's a builtin mysqltest command. ---error 1064 +--error ER_PARSE_ERROR + query sleep; ---error 1064 +--error ER_PARSE_ERROR + --query sleep # Just an empty query command ---error 1065 +--error ER_EMPTY_QUERY + query ; # test for replace_regex @@ -1915,7 +1942,8 @@ eval $my_stmt; # 8. Ensure that "sorted_result " does not change the semantics of # "--error ...." or the protocol output after such an expected failure --sorted_result ---error 1146 +--error ER_NO_SUCH_TABLE + SELECT '2' as "my_col1",2 as "my_col2" UNION SELECT '1',1 from t2; diff --git a/mysql-test/t/ndb_autodiscover.test b/mysql-test/t/ndb_autodiscover.test index dc450aeb9cf..73c04ad6764 100644 --- a/mysql-test/t/ndb_autodiscover.test +++ b/mysql-test/t/ndb_autodiscover.test @@ -1,6 +1,12 @@ -- source include/have_ndb.inc -- source include/not_embedded.inc +# Bug#41308: Test main.ndb_autodiscover.test doesn't work on Windows due +# to 'grep' calls +# Test is currently disabled on Windows via the next line until this bug +# can be resolved. +--source include/not_windows.inc + --disable_warnings drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9,t10; --enable_warnings diff --git a/mysql-test/t/rpl_trigger.test b/mysql-test/t/rpl_trigger.test index da6cea10698..d5472b47b7b 100644 --- a/mysql-test/t/rpl_trigger.test +++ b/mysql-test/t/rpl_trigger.test @@ -293,7 +293,8 @@ STOP SLAVE; connection master; FLUSH LOGS; -exec cp $MYSQL_TEST_DIR/std_data/bug16266.000001 $MYSQLTEST_VARDIR/log/master-bin.000001; +--remove_file $MYSQLTEST_VARDIR/log/master-bin.000001 +--copy_file $MYSQL_TEST_DIR/std_data/bug16266.000001 $MYSQLTEST_VARDIR/log/master-bin.000001 # Make the slave to replay the new binlog. diff --git a/mysql-test/t/trigger-compat.test b/mysql-test/t/trigger-compat.test index f2e350cb161..db410ba2f18 100644 --- a/mysql-test/t/trigger-compat.test +++ b/mysql-test/t/trigger-compat.test @@ -50,9 +50,7 @@ GRANT CREATE ON mysqltest_db1.* TO mysqltest_dfn@localhost; CREATE TABLE t1(num_value INT); CREATE TABLE t2(user_str TEXT); -CREATE TRIGGER wl2818_trg1 BEFORE INSERT ON t1 - FOR EACH ROW - INSERT INTO t2 VALUES(CURRENT_USER()); +CREATE TRIGGER wl2818_trg1 BEFORE INSERT ON t1 FOR EACH ROW INSERT INTO t2 VALUES(CURRENT_USER()); # # Remove definers from TRG file. @@ -61,8 +59,24 @@ CREATE TRIGGER wl2818_trg1 BEFORE INSERT ON t1 --echo --echo ---> patching t1.TRG... ---exec grep -v 'definers=' $MYSQLTEST_VARDIR/master-data/mysqltest_db1/t1.TRG > $MYSQLTEST_VARDIR/tmp/t1.TRG ---exec mv $MYSQLTEST_VARDIR/tmp/t1.TRG $MYSQLTEST_VARDIR/master-data/mysqltest_db1/t1.TRG +# Here we remove definers. This is somewhat complex than the original test +# Previously, the test only used grep -v 'definers=' t1.TRG, but grep is not +# portable and we have to load the file into a table, exclude the definers line, +# then load the data to an outfile to accomplish the same effect + +--disable_query_log +--connection default +CREATE TABLE patch (a blob); +eval LOAD DATA LOCAL INFILE '$MYSQLTEST_VARDIR/master-data/mysqltest_db1/t1.TRG' INTO TABLE patch; +# remove original t1.TRG file so SELECT INTO OUTFILE won't fail +--remove_file $MYSQLTEST_VARDIR/master-data/mysqltest_db1/t1.TRG +eval SELECT SUBSTRING_INDEX(a,'definers=',1) INTO OUTFILE + '$MYSQLTEST_VARDIR/master-data/mysqltest_db1/t1.TRG' +FROM patch; +DROP TABLE patch; +--connection wl2818_definer_con +--enable_query_log + # # Create a new trigger. From 664bb23a30572e89da319c9d2f201a7de3828c1b Mon Sep 17 00:00:00 2001 From: Davi Arnaut Date: Thu, 19 Feb 2009 18:09:35 -0300 Subject: [PATCH 109/219] Bug#41098: Query Cache returns wrong result with concurrent insert The problem is that select queries executed concurrently with a concurrent insert on a MyISAM table could be cached if the select started after the query cache invalidation but before the unlock of tables performed by the concurrent insert. This race could happen because the concurrent insert was failing to prevent cache of select queries happening at the same time. The solution is to add a 'uncacheable' status flag to signal that a concurrent insert is being performed on the table and that queries executing at the same time shouldn't cache the results. mysql-test/r/query_cache_debug.result: Add test case result for Bug#41098 mysql-test/t/disabled.def: Re-enable test case. mysql-test/t/query_cache_debug.test: Add test case for Bug#41098 sql/sql_cache.cc: Debug sync point for regression testing purposes. sql/sql_insert.cc: Remove meaningless query cache invalidate. There is already a preceding invalidate for queries that started before the concurrent insert. storage/myisam/ha_myisam.cc: Check for a active concurrent insert. storage/myisam/mi_locking.c: Signal the start of a concurrent insert. Flag is zeroed once the state is updated back. storage/myisam/myisamdef.h: Add flag to signal a active concurrent insert. --- mysql-test/r/query_cache_debug.result | 49 +++++++++++++++++++ mysql-test/t/disabled.def | 1 - mysql-test/t/query_cache_debug.test | 68 +++++++++++++++++++++++++++ sql/sql_cache.cc | 3 ++ sql/sql_insert.cc | 14 ------ storage/myisam/ha_myisam.cc | 9 ++++ storage/myisam/mi_locking.c | 2 + storage/myisam/myisamdef.h | 1 + 8 files changed, 132 insertions(+), 15 deletions(-) diff --git a/mysql-test/r/query_cache_debug.result b/mysql-test/r/query_cache_debug.result index c90165368e3..b03a71d3fec 100644 --- a/mysql-test/r/query_cache_debug.result +++ b/mysql-test/r/query_cache_debug.result @@ -22,3 +22,52 @@ Qcache_queries_in_cache 0 set global query_cache_size= 0; use test; drop table t1; +SET @old_concurrent_insert= @@GLOBAL.concurrent_insert; +SET @old_query_cache_size= @@GLOBAL.query_cache_size; +DROP TABLE IF EXISTS t1, t2; +CREATE TABLE t1 (a INT); +CREATE TABLE t2 (a INT); +INSERT INTO t1 VALUES (1),(2),(3); +SET GLOBAL concurrent_insert= 1; +SET GLOBAL query_cache_size= 1024*512; +SET GLOBAL query_cache_type= ON; +# Switch to connection con1 +SET SESSION debug='+d,wait_after_query_cache_invalidate'; +# Send concurrent insert, will wait in the query cache table invalidate +INSERT INTO t1 VALUES (4); +# Switch to connection default +# Wait for concurrent insert to reach the debug point +# Switch to connection con2 +# Send SELECT that shouldn't be cached +SELECT * FROM t1; +a +1 +2 +3 +# Switch to connection default +# Notify the concurrent insert to proceed +SELECT ID FROM INFORMATION_SCHEMA.PROCESSLIST +WHERE STATE = 'wait_after_query_cache_invalidate' INTO @thread_id; +KILL QUERY @thread_id; +# Switch to connection con1 +# Gather insert result +SHOW STATUS LIKE "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 0 +# Test that it's cacheable +SELECT * FROM t1; +a +1 +2 +3 +4 +SHOW STATUS LIKE "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 1 +# Disconnect +# Restore defaults +RESET QUERY CACHE; +DROP TABLE t1,t2; +SET GLOBAL concurrent_insert= DEFAULT; +SET GLOBAL query_cache_size= DEFAULT; +SET GLOBAL query_cache_type= DEFAULT; diff --git a/mysql-test/t/disabled.def b/mysql-test/t/disabled.def index f61090102ff..3f61176e37b 100644 --- a/mysql-test/t/disabled.def +++ b/mysql-test/t/disabled.def @@ -10,5 +10,4 @@ # ############################################################################## kill : Bug#37780 2008-12-03 HHunger need some changes to be robust enough for pushbuild. -query_cache_28249 : Bug#41098 Query Cache returns wrong result with concurrent insert innodb_bug39438 : BUG#42383 2009-01-28 lsoares "This fails in embedded and on windows. Note that this test is not run on windows and on embedded in PB for main trees currently" diff --git a/mysql-test/t/query_cache_debug.test b/mysql-test/t/query_cache_debug.test index 18dfe487ac3..8cf5e9d4b16 100644 --- a/mysql-test/t/query_cache_debug.test +++ b/mysql-test/t/query_cache_debug.test @@ -44,3 +44,71 @@ set global query_cache_size= 0; use test; drop table t1; +# +# Bug#41098: Query Cache returns wrong result with concurrent insert +# + +SET @old_concurrent_insert= @@GLOBAL.concurrent_insert; +SET @old_query_cache_size= @@GLOBAL.query_cache_size; + +--disable_warnings +DROP TABLE IF EXISTS t1, t2; +--enable_warnings +CREATE TABLE t1 (a INT); +CREATE TABLE t2 (a INT); +INSERT INTO t1 VALUES (1),(2),(3); + +SET GLOBAL concurrent_insert= 1; +SET GLOBAL query_cache_size= 1024*512; +SET GLOBAL query_cache_type= ON; + +connect(con1,localhost,root,,test,,); +connect(con2,localhost,root,,test,,); + +connection con1; +--echo # Switch to connection con1 +SET SESSION debug='+d,wait_after_query_cache_invalidate'; +--echo # Send concurrent insert, will wait in the query cache table invalidate +--send INSERT INTO t1 VALUES (4) + +connection default; +--echo # Switch to connection default +--echo # Wait for concurrent insert to reach the debug point +let $wait_condition= + SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST + WHERE STATE = "wait_after_query_cache_invalidate" AND + INFO = "INSERT INTO t1 VALUES (4)"; +--source include/wait_condition.inc + +connection con2; +--echo # Switch to connection con2 +--echo # Send SELECT that shouldn't be cached +SELECT * FROM t1; + +connection default; +--echo # Switch to connection default +--echo # Notify the concurrent insert to proceed +SELECT ID FROM INFORMATION_SCHEMA.PROCESSLIST + WHERE STATE = 'wait_after_query_cache_invalidate' INTO @thread_id; +KILL QUERY @thread_id; + +connection con1; +--echo # Switch to connection con1 +--echo # Gather insert result +--reap +SHOW STATUS LIKE "Qcache_queries_in_cache"; +--echo # Test that it's cacheable +SELECT * FROM t1; +SHOW STATUS LIKE "Qcache_queries_in_cache"; + +--echo # Disconnect +disconnect con1; +disconnect con2; + +connection default; +--echo # Restore defaults +RESET QUERY CACHE; +DROP TABLE t1,t2; +SET GLOBAL concurrent_insert= DEFAULT; +SET GLOBAL query_cache_size= DEFAULT; +SET GLOBAL query_cache_type= DEFAULT; diff --git a/sql/sql_cache.cc b/sql/sql_cache.cc index 7c97ee4cf32..4a5b75c4f78 100644 --- a/sql/sql_cache.cc +++ b/sql/sql_cache.cc @@ -1518,6 +1518,9 @@ void Query_cache::invalidate(THD *thd, TABLE_LIST *tables_used, invalidate_table(thd, tables_used); } + DBUG_EXECUTE_IF("wait_after_query_cache_invalidate", + debug_wait_for_kill("wait_after_query_cache_invalidate");); + DBUG_VOID_RETURN; } diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index fcf86edeaa9..e712727a78b 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -904,20 +904,6 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list, } DBUG_ASSERT(transactional_table || !changed || thd->transaction.stmt.modified_non_trans_table); - - if (thd->lock) - { - /* - Invalidate the table in the query cache if something changed - after unlocking when changes become fisible. - TODO: this is workaround. right way will be move invalidating in - the unlock procedure. - */ - if (lock_type == TL_WRITE_CONCURRENT_INSERT && changed) - { - query_cache_invalidate3(thd, table_list, 1); - } - } } thd_proc_info(thd, "end"); /* diff --git a/storage/myisam/ha_myisam.cc b/storage/myisam/ha_myisam.cc index 4073044bf63..ad06ea4b7f0 100644 --- a/storage/myisam/ha_myisam.cc +++ b/storage/myisam/ha_myisam.cc @@ -2152,6 +2152,15 @@ my_bool ha_myisam::register_query_cache_table(THD *thd, char *table_name, } } + /* + This query execution might have started after the query cache was flushed + by a concurrent INSERT. In this case, don't cache this statement as the + data file length difference might not be visible yet if the tables haven't + been unlocked by the concurrent insert thread. + */ + if (file->state->uncacheable) + DBUG_RETURN(FALSE); + /* It is ok to try to cache current statement. */ DBUG_RETURN(TRUE); } diff --git a/storage/myisam/mi_locking.c b/storage/myisam/mi_locking.c index ec359d13a14..6a4c21160f4 100644 --- a/storage/myisam/mi_locking.c +++ b/storage/myisam/mi_locking.c @@ -293,6 +293,8 @@ void mi_get_status(void* param, int concurrent_insert) info->save_state=info->s->state.state; info->state= &info->save_state; info->append_insert_at_end= concurrent_insert; + if (concurrent_insert) + info->s->state.state.uncacheable= TRUE; DBUG_VOID_RETURN; } diff --git a/storage/myisam/myisamdef.h b/storage/myisam/myisamdef.h index 9af3f652c5f..b64c7f6bd7f 100644 --- a/storage/myisam/myisamdef.h +++ b/storage/myisam/myisamdef.h @@ -38,6 +38,7 @@ typedef struct st_mi_status_info my_off_t key_file_length; my_off_t data_file_length; ha_checksum checksum; + my_bool uncacheable; /* Active concurrent insert */ } MI_STATUS_INFO; typedef struct st_mi_state_info From cf571967ad8625643e0a7251e20246207cee46a9 Mon Sep 17 00:00:00 2001 From: Patrick Crews Date: Thu, 19 Feb 2009 16:35:29 -0500 Subject: [PATCH 110/219] Bug#38831: 11 test cases fail on Windows due to missing commands Re-enabling mysqlbinlog.test on Windows - removed the use of grep/sed --- mysql-test/t/mysqlbinlog.test | 3 --- 1 file changed, 3 deletions(-) diff --git a/mysql-test/t/mysqlbinlog.test b/mysql-test/t/mysqlbinlog.test index 1f3d0fed334..b52ab9c5496 100644 --- a/mysql-test/t/mysqlbinlog.test +++ b/mysql-test/t/mysqlbinlog.test @@ -1,9 +1,6 @@ # We are using .opt file since we need small binlog size -- source include/have_log_bin.inc -# Currently disabling this test on Windows due to use of grep and sed ---source include/not_windows.inc - # we need this for getting fixed timestamps inside of this test set timestamp=1000000000; From a67725ac75ded8d6f4f9eb8dac4c23fc03e82738 Mon Sep 17 00:00:00 2001 From: Georgi Kodinov Date: Fri, 20 Feb 2009 11:12:06 +0200 Subject: [PATCH 111/219] Bug #42419: test suite fix Moved the test case for the bug into a separate file (and restored the original innodb_mysql test setup). Used the new wait_show_condition test macro to avoid the usage of sleep mysql-test/include/wait_show_condition.inc: Bug #42419: new test macro to wait for a row in SHOW to have a certain value. mysql-test/r/innodb_bug42419.result: Bug #42419: test case mysql-test/r/innodb_mysql.result: Bug #42419: revert to the original innodb_mysql test mysql-test/t/innodb_bug42419.test: Bug #42419: test case mysql-test/t/innodb_mysql-master.opt: Bug #42419: revert to the original innodb_mysql test mysql-test/t/innodb_mysql.test: Bug #42419: revert to the original innodb_mysql test --- mysql-test/include/wait_show_condition.inc | 78 ++++++++++++++++++++++ mysql-test/r/innodb_bug42419.result | 17 +++++ mysql-test/r/innodb_mysql.result | 16 ----- mysql-test/t/innodb_bug42419.test | 77 +++++++++++++++++++++ mysql-test/t/innodb_mysql-master.opt | 2 +- mysql-test/t/innodb_mysql.test | 51 -------------- 6 files changed, 173 insertions(+), 68 deletions(-) create mode 100644 mysql-test/include/wait_show_condition.inc create mode 100644 mysql-test/r/innodb_bug42419.result create mode 100644 mysql-test/t/innodb_bug42419.test diff --git a/mysql-test/include/wait_show_condition.inc b/mysql-test/include/wait_show_condition.inc new file mode 100644 index 00000000000..253101d1e07 --- /dev/null +++ b/mysql-test/include/wait_show_condition.inc @@ -0,0 +1,78 @@ +# include/wait_show_condition.inc +# +# SUMMARY +# +# Waits until the show statement ($show_statement) has at least within one of +# the rows of the result set for the field ($field) a value which fulfils +# a condition ($condition), or the operation times out. +# +# +# USAGE +# +# let $show_statement= SHOW PROCESSLIST; +# let $field= State; +# let $condition= = 'Updating'; +# --source include/wait_show_condition.inc +# +# OR +# +# let $wait_timeout= 60; # Override default of 30 seconds with 60. +# let $show_statement= SHOW PROCESSLIST; +# let $field= State; +# let $condition= = 'Updating'; +# --source include/wait_show_condition.inc +# +# Please do not use this use routine if you can replace the SHOW statement +# with a select. In such a case include/wait_condition.inc is recommended. +# +# Created: 2009-02-18 mleich +# + +let $max_run_time= 30; +if ($wait_timeout) +{ + let $max_run_time= $wait_timeout; +} +# Reset $wait_timeout so that its value won't be used on subsequent +# calls, and default will be used instead. +let $wait_timeout= 0; + +# The smallest timespan till UNIX_TIMESTAMP() gets incremented is ~0 seconds. +# We add one second to avoid the case that somebody measures timespans on a +# real clock with fractions of seconds, detects that n seconds are sufficient, +# assigns n to this routine and suffers because he sometimes gets n - 1 +# seconds in reality. +inc $max_run_time; + +let $found= 0; +let $max_end_time= `SELECT UNIX_TIMESTAMP() + $max_run_time`; +while (`SELECT UNIX_TIMESTAMP() <= $max_end_time AND $found = 0`) +{ + # Sleep a bit to avoid too heavy load. + real_sleep 0.2; + let $rowno= 1; + let $process_result= 1; + while (`SELECT $process_result = 1 AND $found = 0`) + { + let $field_value= query_get_value($show_statement, $field, $rowno); + if (`SELECT '$field_value' $condition`) + { + let $found= 1; + } + if (`SELECT '$field_value' = 'No such row'`) + { + # We are behind the last row of the result set. + let $process_result= 0; + } + inc $rowno; + } +} +if (!$found) +{ + echo # Timeout in include/wait_show_condition.inc for $wait_condition; + echo # show_statement : $show_statement; + echo # field : $field; + echo # condition : $condition; + echo # max_run_time : $max_run_time; +} + diff --git a/mysql-test/r/innodb_bug42419.result b/mysql-test/r/innodb_bug42419.result new file mode 100644 index 00000000000..f304bb634cb --- /dev/null +++ b/mysql-test/r/innodb_bug42419.result @@ -0,0 +1,17 @@ +CREATE TABLE t1 (a INT AUTO_INCREMENT PRIMARY KEY, b INT) ENGINE = InnoDB; +INSERT INTO t1 VALUES (1,1),(2,2),(3,3); +COMMIT; +SET AUTOCOMMIT = 0; +CREATE TEMPORARY TABLE t1_tmp ( b INT ); +INSERT INTO t1_tmp (b) SELECT b FROM t1 WHERE a = 3; +INSERT INTO t1_tmp (b) SELECT b FROM t1 WHERE a = 2; +SET AUTOCOMMIT = 0; +CREATE TEMPORARY TABLE t2_tmp ( a int, new_a int ); +INSERT INTO t2_tmp VALUES (1,51),(2,52),(3,53); +UPDATE t1 SET a = (SELECT new_a FROM t2_tmp WHERE t2_tmp.a = t1.a) WHERE a = 1; +UPDATE t1 SET a = (SELECT new_a FROM t2_tmp WHERE t2_tmp.a = t1.a) WHERE a = 2; +INSERT INTO t1_tmp (b) SELECT b FROM t1 WHERE a = 1; +ERROR 40001: Deadlock found when trying to get lock; try restarting transaction +Reap the server message for connection user2 UPDATE t1 ... +UPDATE t1 SET a = (SELECT new_a FROM t2_tmp WHERE t2_tmp.a = t1.a) WHERE a = 3; +DROP TABLE t1; diff --git a/mysql-test/r/innodb_mysql.result b/mysql-test/r/innodb_mysql.result index 78a56cddb08..682cc2e82e2 100644 --- a/mysql-test/r/innodb_mysql.result +++ b/mysql-test/r/innodb_mysql.result @@ -1267,20 +1267,4 @@ CREATE INDEX i1 on t1 (a(3)); SELECT * FROM t1 WHERE a = 'abcde'; a DROP TABLE t1; -CREATE TABLE t1 (a INT NOT NULL AUTO_INCREMENT PRIMARY KEY, b INT) -ENGINE=InnoDB; -INSERT INTO t1 VALUES (1,1),(2,2),(3,3); -SET AUTOCOMMIT = 0; -CREATE TEMPORARY TABLE t1_tmp (b INT); -INSERT INTO t1_tmp SELECT b FROM t1 WHERE a = 3; -INSERT INTO t1_tmp SELECT b FROM t1 WHERE a = 2; -SET AUTOCOMMIT = 0; -CREATE TEMPORARY TABLE t2_tmp ( a INT, new_a INT); -INSERT INTO t2_tmp VALUES (1,51),(2,52),(3,53); -UPDATE t1 SET a = (SELECT new_a FROM t2_tmp WHERE t2_tmp.a = t1.a) WHERE a = 1; -UPDATE t1 SET a = (SELECT new_a FROM t2_tmp WHERE t2_tmp.a = t1.a) WHERE a = 2; -INSERT INTO t1_tmp SELECT b FROM t1 WHERE a = 1; -ERROR 40001: Deadlock found when trying to get lock; try restarting transaction -UPDATE t1 SET a = (SELECT new_a FROM t2_tmp WHERE t2_tmp.a = t1.a) WHERE a = 3; -DROP TABLE t1; End of 5.0 tests diff --git a/mysql-test/t/innodb_bug42419.test b/mysql-test/t/innodb_bug42419.test new file mode 100644 index 00000000000..389093a8465 --- /dev/null +++ b/mysql-test/t/innodb_bug42419.test @@ -0,0 +1,77 @@ +# +# Testcase for InnoDB +# Bug#42419 Server crash with "Pure virtual method called" on two concurrent connections +# + +--source include/have_innodb.inc + +let $innodb_lock_wait_timeout= query_get_value(SHOW VARIABLES LIKE 'innodb_lock_wait_timeout%', Value, 1); +if (`SELECT $innodb_lock_wait_timeout < 10`) +{ + --echo # innodb_lock_wait_timeout must be >= 10 seconds + --echo # so that this test can work all time fine on an overloaded testing box + SHOW VARIABLES LIKE 'innodb_lock_wait_timeout'; + exit; +} + +# Save the initial number of concurrent sessions +--source include/count_sessions.inc + +# First session +connection default; + + +--enable_warnings +CREATE TABLE t1 (a INT AUTO_INCREMENT PRIMARY KEY, b INT) ENGINE = InnoDB; + +INSERT INTO t1 VALUES (1,1),(2,2),(3,3); +COMMIT; +SET AUTOCOMMIT = 0; + +CREATE TEMPORARY TABLE t1_tmp ( b INT ); + +INSERT INTO t1_tmp (b) SELECT b FROM t1 WHERE a = 3; +INSERT INTO t1_tmp (b) SELECT b FROM t1 WHERE a = 2; + +# Second session +connect (user2,localhost,root,,,$MASTER_MYPORT,$MASTER_MYSOCK); + +SET AUTOCOMMIT = 0; + +CREATE TEMPORARY TABLE t2_tmp ( a int, new_a int ); +INSERT INTO t2_tmp VALUES (1,51),(2,52),(3,53); + +UPDATE t1 SET a = (SELECT new_a FROM t2_tmp WHERE t2_tmp.a = t1.a) WHERE a = 1; +send +UPDATE t1 SET a = (SELECT new_a FROM t2_tmp WHERE t2_tmp.a = t1.a) WHERE a = 2; + +# The last update will wait for a lock held by the first session + +# First session +connection default; + +# Poll till the UPDATE of the second session waits for lock +let $show_statement= SHOW PROCESSLIST; +let $field= State; +let $condition= = 'Updating'; +--source include/wait_show_condition.inc + +# If the testing box is overloadeded and innodb_lock_wait_timeout is too small +# we might get here ER_LOCK_WAIT_TIMEOUT. +--error ER_LOCK_DEADLOCK +INSERT INTO t1_tmp (b) SELECT b FROM t1 WHERE a = 1; + +# Second session +connection user2; +--echo Reap the server message for connection user2 UPDATE t1 ... +reap; + +# The server crashed when executing this UPDATE or the succeeding SQL command. +UPDATE t1 SET a = (SELECT new_a FROM t2_tmp WHERE t2_tmp.a = t1.a) WHERE a = 3; + +connection default; +disconnect user2; +DROP TABLE t1; + +# Wait till all disconnects are completed +--source include/wait_until_count_sessions.inc diff --git a/mysql-test/t/innodb_mysql-master.opt b/mysql-test/t/innodb_mysql-master.opt index c8613e0ccd5..205c733455d 100644 --- a/mysql-test/t/innodb_mysql-master.opt +++ b/mysql-test/t/innodb_mysql-master.opt @@ -1 +1 @@ ---innodb-lock-wait-timeout=3 +--innodb-lock-wait-timeout=2 diff --git a/mysql-test/t/innodb_mysql.test b/mysql-test/t/innodb_mysql.test index eb23739386e..b4fc425cb7c 100644 --- a/mysql-test/t/innodb_mysql.test +++ b/mysql-test/t/innodb_mysql.test @@ -1025,55 +1025,4 @@ CREATE INDEX i1 on t1 (a(3)); SELECT * FROM t1 WHERE a = 'abcde'; DROP TABLE t1; -# -# Bug #42419: Server crash with "Pure virtual method called" on two -# concurrent connections -# - -connect (c1, localhost, root,,); -connect (c2, localhost, root,,); - -CREATE TABLE t1 (a INT NOT NULL AUTO_INCREMENT PRIMARY KEY, b INT) - ENGINE=InnoDB; - -INSERT INTO t1 VALUES (1,1),(2,2),(3,3); - -connection c1; - -SET AUTOCOMMIT = 0; - -CREATE TEMPORARY TABLE t1_tmp (b INT); - -INSERT INTO t1_tmp SELECT b FROM t1 WHERE a = 3; -INSERT INTO t1_tmp SELECT b FROM t1 WHERE a = 2; - -connection c2; - -SET AUTOCOMMIT = 0; - -CREATE TEMPORARY TABLE t2_tmp ( a INT, new_a INT); -INSERT INTO t2_tmp VALUES (1,51),(2,52),(3,53); - -UPDATE t1 SET a = (SELECT new_a FROM t2_tmp WHERE t2_tmp.a = t1.a) WHERE a = 1; - ---send -UPDATE t1 SET a = (SELECT new_a FROM t2_tmp WHERE t2_tmp.a = t1.a) WHERE a = 2; - ---sleep 3 - -connection c1; - ---error ER_LOCK_DEADLOCK -INSERT INTO t1_tmp SELECT b FROM t1 WHERE a = 1; - -connection c2; - ---reap -UPDATE t1 SET a = (SELECT new_a FROM t2_tmp WHERE t2_tmp.a = t1.a) WHERE a = 3; - -connection default; -disconnect c1; -disconnect c2; -DROP TABLE t1; - --echo End of 5.0 tests From 3d156e223efc5567333c2d41e27c4403a8608d27 Mon Sep 17 00:00:00 2001 From: Mattias Jonsson Date: Fri, 20 Feb 2009 10:27:32 +0100 Subject: [PATCH 112/219] pre push test result update for bug#38719 Updated with the correct error message. --- .../parts/r/partition_alter2_2_innodb.result | 192 +++++++++--------- .../parts/r/partition_alter2_2_myisam.result | 96 ++++----- 2 files changed, 144 insertions(+), 144 deletions(-) diff --git a/mysql-test/suite/parts/r/partition_alter2_2_innodb.result b/mysql-test/suite/parts/r/partition_alter2_2_innodb.result index e2cf04c35b3..cb9ea4ed60a 100644 --- a/mysql-test/suite/parts/r/partition_alter2_2_innodb.result +++ b/mysql-test/suite/parts/r/partition_alter2_2_innodb.result @@ -3826,7 +3826,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'PRIMARY' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -4320,7 +4320,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'PRIMARY' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -4829,7 +4829,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'PRIMARY' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -5334,7 +5334,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'PRIMARY' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -5833,7 +5833,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'PRIMARY' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -6347,7 +6347,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'PRIMARY' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -6857,7 +6857,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'PRIMARY' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -7359,7 +7359,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'PRIMARY' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -7854,7 +7854,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'PRIMARY' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -8348,7 +8348,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'PRIMARY' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -8857,7 +8857,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'PRIMARY' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -9362,7 +9362,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'PRIMARY' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -9861,7 +9861,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'PRIMARY' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -10375,7 +10375,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'PRIMARY' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -10885,7 +10885,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'PRIMARY' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -11387,7 +11387,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'PRIMARY' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -11883,7 +11883,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx1' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -12393,7 +12393,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx1' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -12918,7 +12918,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx1' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -13439,7 +13439,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx1' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -13954,7 +13954,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx1' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -14484,7 +14484,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx1' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -15010,7 +15010,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx1' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -15528,7 +15528,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx1' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -16039,7 +16039,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx1' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -16549,7 +16549,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx1' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -17074,7 +17074,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx1' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -17595,7 +17595,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx1' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -18110,7 +18110,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx1' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -18640,7 +18640,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx1' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -19166,7 +19166,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx1' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -19684,7 +19684,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx1' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -27712,7 +27712,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'PRIMARY' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -28207,7 +28207,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'PRIMARY' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -28717,7 +28717,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'PRIMARY' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -29223,7 +29223,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'PRIMARY' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -29727,7 +29727,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'PRIMARY' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -30242,7 +30242,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'PRIMARY' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -30757,7 +30757,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'PRIMARY' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -31260,7 +31260,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'PRIMARY' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -31756,7 +31756,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'PRIMARY' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -32251,7 +32251,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'PRIMARY' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -32761,7 +32761,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'PRIMARY' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -33267,7 +33267,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'PRIMARY' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -33771,7 +33771,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'PRIMARY' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -34286,7 +34286,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'PRIMARY' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -34801,7 +34801,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'PRIMARY' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -35304,7 +35304,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'PRIMARY' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -35800,7 +35800,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'PRIMARY' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -36295,7 +36295,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'PRIMARY' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -36805,7 +36805,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'PRIMARY' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -37311,7 +37311,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'PRIMARY' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -37815,7 +37815,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'PRIMARY' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -38330,7 +38330,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'PRIMARY' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -38845,7 +38845,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'PRIMARY' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -39348,7 +39348,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'PRIMARY' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -39844,7 +39844,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'PRIMARY' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -40339,7 +40339,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'PRIMARY' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -40849,7 +40849,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'PRIMARY' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -41355,7 +41355,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'PRIMARY' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -41859,7 +41859,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'PRIMARY' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -42374,7 +42374,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'PRIMARY' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -42889,7 +42889,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'PRIMARY' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -43392,7 +43392,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'PRIMARY' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -43889,7 +43889,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -44400,7 +44400,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -44926,7 +44926,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -45448,7 +45448,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -45968,7 +45968,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -46499,7 +46499,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -47030,7 +47030,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -47549,7 +47549,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -48061,7 +48061,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -48572,7 +48572,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -49098,7 +49098,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -49620,7 +49620,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -50140,7 +50140,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -50671,7 +50671,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -51202,7 +51202,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -51721,7 +51721,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -52233,7 +52233,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -52744,7 +52744,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -53270,7 +53270,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -53792,7 +53792,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -54312,7 +54312,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -54843,7 +54843,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -55374,7 +55374,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -55893,7 +55893,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -56405,7 +56405,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -56916,7 +56916,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -57442,7 +57442,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -57964,7 +57964,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -58484,7 +58484,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -59015,7 +59015,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -59546,7 +59546,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -60065,7 +60065,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) diff --git a/mysql-test/suite/parts/r/partition_alter2_2_myisam.result b/mysql-test/suite/parts/r/partition_alter2_2_myisam.result index c63e8495f26..630ad0aaf08 100644 --- a/mysql-test/suite/parts/r/partition_alter2_2_myisam.result +++ b/mysql-test/suite/parts/r/partition_alter2_2_myisam.result @@ -3983,7 +3983,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx1' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -4508,7 +4508,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx1' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -5054,7 +5054,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx1' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -5592,7 +5592,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx1' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -6128,7 +6128,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx1' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -6679,7 +6679,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx1' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -7226,7 +7226,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx1' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -7767,7 +7767,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx1' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -8287,7 +8287,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx1' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -8812,7 +8812,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx1' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -9358,7 +9358,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx1' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -9896,7 +9896,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx1' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -10432,7 +10432,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx1' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -10983,7 +10983,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx1' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -11530,7 +11530,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx1' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -12071,7 +12071,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx1' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -20404,7 +20404,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -20930,7 +20930,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -21477,7 +21477,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -22016,7 +22016,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -22557,7 +22557,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -23109,7 +23109,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -23661,7 +23661,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -24203,7 +24203,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -24724,7 +24724,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -25250,7 +25250,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -25797,7 +25797,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -26336,7 +26336,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -26877,7 +26877,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -27429,7 +27429,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -27981,7 +27981,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -28523,7 +28523,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -29044,7 +29044,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -29570,7 +29570,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -30117,7 +30117,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -30656,7 +30656,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -31197,7 +31197,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -31749,7 +31749,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -32301,7 +32301,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -32843,7 +32843,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -33364,7 +33364,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -33890,7 +33890,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -34437,7 +34437,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -34976,7 +34976,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -35517,7 +35517,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -36069,7 +36069,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -36621,7 +36621,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) @@ -37163,7 +37163,7 @@ INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) SELECT f_int1, f_int1, CAST(f_int1 AS CHAR), CAST(f_int1 AS CHAR), 'delete me' FROM t0_template WHERE f_int1 IN (2,3); -ERROR 23000: Can't write; duplicate key in table 't1' +ERROR 23000: Duplicate entry '2-2' for key 'uidx' # check prerequisites-3 success: 1 # INFO: f_int1 AND/OR f_int2 AND/OR (f_int1,f_int2) is UNIQUE INSERT INTO t1 (f_int1, f_int2, f_char1, f_char2, f_charbig) From c1ddc60c695e49a44555049768cb8557676840aa Mon Sep 17 00:00:00 2001 From: Georgi Kodinov Date: Fri, 20 Feb 2009 11:42:35 +0200 Subject: [PATCH 113/219] fixed a warning --- sql/item.cc | 1 - 1 file changed, 1 deletion(-) diff --git a/sql/item.cc b/sql/item.cc index 14422bd3e92..f32828629cf 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -1726,7 +1726,6 @@ bool agg_item_set_converter(DTCollation &coll, const char *fname, bool agg_item_charsets(DTCollation &coll, const char *fname, Item **args, uint nargs, uint flags, int item_sep) { - Item **arg, *safe_args[2]; if (agg_item_collations(coll, fname, args, nargs, flags, item_sep)) return TRUE; From 4712e6b9b8e61e468ee94ec65105e61881f77421 Mon Sep 17 00:00:00 2001 From: Andrei Elkin Date: Fri, 20 Feb 2009 13:55:43 +0200 Subject: [PATCH 114/219] Bug #37313 BINLOG Contains Incorrect server id Signed integer format specifier forced to print the binlog header with server_id negative if the unsigned value sets the sign-bit ON. Fixed with correcting the specifier to correspond to typeof(server_id) == ulong. mysql-test/r/mysqlbinlog.result: results changed. mysql-test/t/mysqlbinlog.test: displaying the expected unsignedly formatted server_id value, bug#37313. sql/log_event.cc: Format specifier is corrected to correspond to typeof(server_id). --- mysql-test/r/mysqlbinlog.result | 10 ++++++++++ mysql-test/t/mysqlbinlog.test | 20 ++++++++++++++++++++ sql/log_event.cc | 2 +- 3 files changed, 31 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/mysqlbinlog.result b/mysql-test/r/mysqlbinlog.result index 4fd87861ded..b5ac22437cd 100644 --- a/mysql-test/r/mysqlbinlog.result +++ b/mysql-test/r/mysqlbinlog.result @@ -362,4 +362,14 @@ drop table t1; 1 drop table t1; shell> mysqlbinlog std_data/corrupt-relay-bin.000624 > var/tmp/bug31793.sql +set @@global.server_id= 4294967295; +reset master; +select +(@a:=load_file("MYSQLTEST_VARDIR/tmp/mysqlbinlog_bug37313.binlog")) +is not null; +(@a:=load_file("MYSQLTEST_VARDIR/tmp/mysqlbinlog_bug37313.binlog")) +is not null +1 +*** Unsigned server_id 4294967295 is found: 1 *** +set @@global.server_id= 1; End of 5.0 tests diff --git a/mysql-test/t/mysqlbinlog.test b/mysql-test/t/mysqlbinlog.test index 5b4a43c8fe8..cf4bc1523df 100644 --- a/mysql-test/t/mysqlbinlog.test +++ b/mysql-test/t/mysqlbinlog.test @@ -253,4 +253,24 @@ echo shell> mysqlbinlog std_data/corrupt-relay-bin.000624 > var/tmp/bug31793.sql error 1; exec $MYSQL_BINLOG $MYSQL_TEST_DIR/std_data/corrupt-relay-bin.000624 > $MYSQLTEST_VARDIR/tmp/bug31793.sql; +# +# Bug #37313 BINLOG Contains Incorrect server id +# + +let $save_server_id= `select @@global.server_id`; +let $s_id_max=`select (1 << 32) - 1`; +eval set @@global.server_id= $s_id_max; + +reset master; +--exec $MYSQL_BINLOG $MYSQLTEST_VARDIR/log/master-bin.000001 > $MYSQLTEST_VARDIR/tmp/mysqlbinlog_bug37313.binlog +--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR +eval select +(@a:=load_file("$MYSQLTEST_VARDIR/tmp/mysqlbinlog_bug37313.binlog")) +is not null; +let $s_id_unsigned= `select @a like "%server id $s_id_max%" /* must return 1 */`; +echo *** Unsigned server_id $s_id_max is found: $s_id_unsigned ***; + +eval set @@global.server_id= $save_server_id; +--remove_file $MYSQLTEST_VARDIR/tmp/mysqlbinlog_bug37313.binlog + --echo End of 5.0 tests diff --git a/sql/log_event.cc b/sql/log_event.cc index ef419aaee40..90805877502 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -976,7 +976,7 @@ void Log_event::print_header(FILE* file, PRINT_EVENT_INFO* print_event_info) fputc('#', file); print_timestamp(file); - fprintf(file, " server id %d end_log_pos %s ", server_id, + fprintf(file, " server id %lu end_log_pos %s ", server_id, llstr(log_pos,llbuff)); /* mysqlbinlog --hexdump */ From e7e5443a01aae834224eeff8c1b4afa8cf85117a Mon Sep 17 00:00:00 2001 From: Mattias Jonsson Date: Fri, 20 Feb 2009 16:56:32 +0100 Subject: [PATCH 115/219] Backport of patch for bug#40003 from 6.0 to 5.1, related to the backport of the patch for bug#38719 sql/ha_partition.cc: bug#40003, archive does not handle dup_key. --- mysql-test/t/innodb_bug42419.test | 1 + sql/ha_partition.cc | 5 +++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/mysql-test/t/innodb_bug42419.test b/mysql-test/t/innodb_bug42419.test index 389093a8465..93c4764252a 100644 --- a/mysql-test/t/innodb_bug42419.test +++ b/mysql-test/t/innodb_bug42419.test @@ -3,6 +3,7 @@ # Bug#42419 Server crash with "Pure virtual method called" on two concurrent connections # +--source include/not_embedded.inc --source include/have_innodb.inc let $innodb_lock_wait_timeout= query_get_value(SHOW VARIABLES LIKE 'innodb_lock_wait_timeout%', Value, 1); diff --git a/sql/ha_partition.cc b/sql/ha_partition.cc index 0e36a868b3e..67bc3156260 100644 --- a/sql/ha_partition.cc +++ b/sql/ha_partition.cc @@ -4928,10 +4928,11 @@ int ha_partition::info(uint flag) This flag is used to get index number of the unique index that reported duplicate key We will report the errkey on the last handler used and ignore the rest + Note: all engines does not support HA_STATUS_ERRKEY, so set errkey. */ + file->errkey= errkey; file->info(HA_STATUS_ERRKEY); - if (file->errkey != (uint) -1) - errkey= file->errkey; + errkey= file->errkey; } if (flag & HA_STATUS_TIME) { From d822ab8957ad636de01eaabfc4981f0e0d0c5b47 Mon Sep 17 00:00:00 2001 From: Alfranio Correia Date: Sat, 21 Feb 2009 09:36:07 +0000 Subject: [PATCH 116/219] BUG#38174 secure-file-priv breaks LOAD DATA INFILE replication in statement mode If secure-file-priv was set on slave, it became unable to execute LOAD DATA INFILE statements sent from master using mixed or statement-based replication. This patch fixes the issue by ignoring this security restriction and checking if the files are created and read by the slave in the --slave-load-tmpdir while executing the SQL Thread. --- .../suite/rpl/r/rpl_slave_load_in.result | 10 ++++++ mysql-test/suite/rpl/t/rpl_slave_load_in.test | 35 +++++++++++++++++++ sql/log_event.cc | 4 +-- sql/log_event.h | 2 ++ sql/rpl_rli.cc | 6 ++++ sql/rpl_rli.h | 7 ++++ sql/sql_load.cc | 29 +++++++++++++-- 7 files changed, 88 insertions(+), 5 deletions(-) create mode 100644 mysql-test/suite/rpl/r/rpl_slave_load_in.result create mode 100644 mysql-test/suite/rpl/t/rpl_slave_load_in.test diff --git a/mysql-test/suite/rpl/r/rpl_slave_load_in.result b/mysql-test/suite/rpl/r/rpl_slave_load_in.result new file mode 100644 index 00000000000..0685d024f26 --- /dev/null +++ b/mysql-test/suite/rpl/r/rpl_slave_load_in.result @@ -0,0 +1,10 @@ +stop slave; +drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; +reset master; +reset slave; +drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; +start slave; +create table t1(a int not null auto_increment, b int, primary key(a)); +load data infile '../../std_data/rpl_loaddata.dat' into table t1; +Comparing tables master:test.t1 and slave:test.t1 +drop table t1; diff --git a/mysql-test/suite/rpl/t/rpl_slave_load_in.test b/mysql-test/suite/rpl/t/rpl_slave_load_in.test new file mode 100644 index 00000000000..f920c136d43 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_slave_load_in.test @@ -0,0 +1,35 @@ +########################################################################## +# This test verifies if a slave is able to process a "LOAD DATA INFILE" +# event while the "--secure-file-priv" option is set. +# +# The test is divided in two steps: +# 1 - Creates a table and populates it through "LOAD DATA INFILE". +# 2 - Compares the master and slave. +########################################################################## +source include/master-slave.inc; + +########################################################################## +# Loading data +########################################################################## +connection master; + +create table t1(a int not null auto_increment, b int, primary key(a)); +load data infile '../../std_data/rpl_loaddata.dat' into table t1; + +########################################################################## +# Checking Consistency +########################################################################## +sync_slave_with_master; + +let $diff_table_1=master:test.t1; +let $diff_table_2=slave:test.t1; +source include/diff_tables.inc; + +########################################################################## +# Clean up +########################################################################## +connection master; + +drop table t1; + +sync_slave_with_master; diff --git a/sql/log_event.cc b/sql/log_event.cc index 0e400ac2705..243790c7d76 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -354,7 +354,7 @@ static char *slave_load_file_stem(char *buf, uint file_id, int event_server_id, const char *ext) { char *res; - fn_format(buf,"SQL_LOAD-",slave_load_tmpdir, "", MY_UNPACK_FILENAME); + fn_format(buf,PREFIX_SQL_LOAD,slave_load_tmpdir, "", MY_UNPACK_FILENAME); to_unix_path(buf); buf = strend(buf); @@ -393,7 +393,7 @@ static void cleanup_load_tmpdir() we cannot meet Start_log event in the middle of events from one LOAD DATA. */ - p= strmake(prefbuf, STRING_WITH_LEN("SQL_LOAD-")); + p= strmake(prefbuf, STRING_WITH_LEN(PREFIX_SQL_LOAD)); p= int10_to_str(::server_id, p, 10); *(p++)= '-'; *p= 0; diff --git a/sql/log_event.h b/sql/log_event.h index 1d11d7e2d5f..82fc8d771e1 100644 --- a/sql/log_event.h +++ b/sql/log_event.h @@ -47,6 +47,8 @@ #include "rpl_reporting.h" #endif +#define PREFIX_SQL_LOAD "SQL_LOAD-" + /** Either assert or return an error. diff --git a/sql/rpl_rli.cc b/sql/rpl_rli.cc index 3a0f784d195..6077c17e1f0 100644 --- a/sql/rpl_rli.cc +++ b/sql/rpl_rli.cc @@ -104,6 +104,12 @@ int init_relay_log_info(Relay_log_info* rli, rli->tables_to_lock= 0; rli->tables_to_lock_count= 0; + fn_format(rli->slave_patternload_file, PREFIX_SQL_LOAD, slave_load_tmpdir, "", + MY_PACK_FILENAME | MY_UNPACK_FILENAME | + MY_RETURN_REAL_PATH); + to_unix_path(rli->slave_patternload_file); + rli->slave_patternload_file_size= strlen(rli->slave_patternload_file); + /* The relay log will now be opened, as a SEQ_READ_APPEND IO_CACHE. Note that the I/O thread flushes it to disk after writing every diff --git a/sql/rpl_rli.h b/sql/rpl_rli.h index e13ea93842c..171778d9675 100644 --- a/sql/rpl_rli.h +++ b/sql/rpl_rli.h @@ -260,6 +260,13 @@ public: char ign_master_log_name_end[FN_REFLEN]; ulonglong ign_master_log_pos_end; + /* + Indentifies where the SQL Thread should create temporary files for the + LOAD DATA INFILE. This is used for security reasons. + */ + char slave_patternload_file[FN_REFLEN]; + size_t slave_patternload_file_size; + Relay_log_info(); ~Relay_log_info(); diff --git a/sql/sql_load.cc b/sql/sql_load.cc index 239fb1d49f3..0acc22c3daf 100644 --- a/sql/sql_load.cc +++ b/sql/sql_load.cc @@ -15,10 +15,10 @@ /* Copy data from a textfile to table */ - #include "mysql_priv.h" #include #include +#include "rpl_mi.h" #include "sql_repl.h" #include "sp_head.h" #include "sql_trigger.h" @@ -310,8 +310,31 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list, is_fifo = 1; #endif - if (opt_secure_file_priv && - strncmp(opt_secure_file_priv, name, strlen(opt_secure_file_priv))) + if (thd->slave_thread) + { +#if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT) + if (strncmp(active_mi->rli.slave_patternload_file, name, + active_mi->rli.slave_patternload_file_size)) + { + /* + LOAD DATA INFILE in the slave SQL Thread can only read from + --slave-load-tmpdir". This should never happen. Please, report a bug. + */ + + sql_print_error("LOAD DATA INFILE in the slave SQL Thread can only read from --slave-load-tmpdir. " \ + "Please, report a bug."); + my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), "--slave-load-tmpdir"); + DBUG_RETURN(TRUE); + } +#else + /* + This is impossible and should never happen. + */ + DBUG_ASSERT(FALSE); +#endif + } + else if (opt_secure_file_priv && + strncmp(opt_secure_file_priv, name, strlen(opt_secure_file_priv))) { /* Read only allowed from within dir specified by secure_file_priv */ my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), "--secure-file-priv"); From 2d3ac117a482b550ba71540b44e49ce149c5d165 Mon Sep 17 00:00:00 2001 From: Alfranio Correia Date: Sun, 22 Feb 2009 13:40:52 +0000 Subject: [PATCH 117/219] Post-fix for BUG#38174. --- sql/rpl_rli.cc | 1 - 1 file changed, 1 deletion(-) diff --git a/sql/rpl_rli.cc b/sql/rpl_rli.cc index 6077c17e1f0..e93417374fe 100644 --- a/sql/rpl_rli.cc +++ b/sql/rpl_rli.cc @@ -107,7 +107,6 @@ int init_relay_log_info(Relay_log_info* rli, fn_format(rli->slave_patternload_file, PREFIX_SQL_LOAD, slave_load_tmpdir, "", MY_PACK_FILENAME | MY_UNPACK_FILENAME | MY_RETURN_REAL_PATH); - to_unix_path(rli->slave_patternload_file); rli->slave_patternload_file_size= strlen(rli->slave_patternload_file); /* From 61d706a4f04906632e461aa6a2756429b1be9c2c Mon Sep 17 00:00:00 2001 From: Leonard Zhou Date: Mon, 23 Feb 2009 11:26:38 +0800 Subject: [PATCH 118/219] Bug#40013 mixed replication: row based format could lead to stale tmp tables on the slave. In mixed mode, if we create a temporary table and do some update which switch to ROW format, the format will keep in ROW format until the session ends or the table is dropped explicitly. When the session ends, the temp table is dropped automaticly at cleanup time. but it checks only current binlog format and so skip insertion of DROP TABLE instructions into binlog. So the temp table can't be dropped correctly at slave. Our solution is that when closing temp tables at cleanup time we check both binlog format and binlog mode, and we could write DROP TABLE instructions into binlog if current binlog format is ROW but in MIX mode. mysql-test/suite/rpl/r/rpl_temp_table_mix_row.result: Test result file. mysql-test/suite/rpl/t/rpl_temp_table_mix_row.test: Test file. sql/sql_base.cc: Didn't do binloging when both current format and default format are ROW. --- .../suite/rpl/r/rpl_temp_table_mix_row.result | 26 ++++++++++ .../suite/rpl/t/rpl_temp_table_mix_row.test | 49 +++++++++++++++++++ sql/sql_base.cc | 3 +- 3 files changed, 77 insertions(+), 1 deletion(-) create mode 100644 mysql-test/suite/rpl/r/rpl_temp_table_mix_row.result create mode 100644 mysql-test/suite/rpl/t/rpl_temp_table_mix_row.test diff --git a/mysql-test/suite/rpl/r/rpl_temp_table_mix_row.result b/mysql-test/suite/rpl/r/rpl_temp_table_mix_row.result new file mode 100644 index 00000000000..feffefc9dad --- /dev/null +++ b/mysql-test/suite/rpl/r/rpl_temp_table_mix_row.result @@ -0,0 +1,26 @@ +stop slave; +drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; +reset master; +reset slave; +drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; +start slave; +==== Initialize ==== +[on master] +CREATE TABLE t1 (a CHAR(48)); +CREATE TEMPORARY TABLE t1_tmp1(a INT); +INSERT INTO t1 VALUES (UUID()); +[on slave] +==== Verify results on slave ==== +SHOW STATUS LIKE "Slave_open_temp_tables"; +Variable_name Value +Slave_open_temp_tables 1 +[on master] +[on slave] +==== Verify results on slave ==== +SHOW STATUS LIKE "Slave_open_temp_tables"; +Variable_name Value +Slave_open_temp_tables 0 +==== Clean up ==== +[on master] +DROP TABLE t1; +[on slave] diff --git a/mysql-test/suite/rpl/t/rpl_temp_table_mix_row.test b/mysql-test/suite/rpl/t/rpl_temp_table_mix_row.test new file mode 100644 index 00000000000..1fe484b7c27 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_temp_table_mix_row.test @@ -0,0 +1,49 @@ +# ==== Purpose ==== +# +# Test that temporary tables are correctly replicated after switching to ROW format in MIX mode. +# This test case will test the condition of the bug#40013. +# The test step is: +# 1: create temp table on connection 'master'; +# 2: switch to ROW format using 'INSERT INTO t1 VALUES (UUID());' +# 3: disconnect 'master' and connect to a new connection 'master1'; +# 4: sync to slave and check the number of temp tables on slave. +# + +source include/master-slave.inc; +source include/have_binlog_format_mixed.inc; + +--echo ==== Initialize ==== + +--echo [on master] +--connection master + +CREATE TABLE t1 (a CHAR(48)); +CREATE TEMPORARY TABLE t1_tmp1(a INT); +INSERT INTO t1 VALUES (UUID()); + +--echo [on slave] +sync_slave_with_master; + +--echo ==== Verify results on slave ==== +SHOW STATUS LIKE "Slave_open_temp_tables"; + +--echo [on master] +--connection master + +disconnect master; +--connection master1 + +--echo [on slave] +sync_slave_with_master; + +--echo ==== Verify results on slave ==== +SHOW STATUS LIKE "Slave_open_temp_tables"; + +--echo ==== Clean up ==== + +--echo [on master] +--connection master1 +DROP TABLE t1; + +--echo [on slave] +sync_slave_with_master; diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 6db9f1df0f2..7602b1187aa 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -1440,7 +1440,8 @@ void close_temporary_tables(THD *thd) if (!thd->temporary_tables) return; - if (!mysql_bin_log.is_open() || thd->current_stmt_binlog_row_based) + if (!mysql_bin_log.is_open() || + (thd->current_stmt_binlog_row_based && thd->variables.binlog_format == BINLOG_FORMAT_ROW)) { TABLE *tmp_next; for (table= thd->temporary_tables; table; table= tmp_next) From 9fc083bd9ade238ed53f82978b5588f687b033c6 Mon Sep 17 00:00:00 2001 From: Davi Arnaut Date: Mon, 23 Feb 2009 09:03:31 +0100 Subject: [PATCH 119/219] Post-merge fix: test depends on feature not available under embedded. mysql-test/t/query_cache_28249.test: Test depends on process state (not updated under embedded) --- mysql-test/t/query_cache_28249.test | 1 + 1 file changed, 1 insertion(+) diff --git a/mysql-test/t/query_cache_28249.test b/mysql-test/t/query_cache_28249.test index 3cf6c89369e..390a1ce6e3d 100644 --- a/mysql-test/t/query_cache_28249.test +++ b/mysql-test/t/query_cache_28249.test @@ -11,6 +11,7 @@ # --source include/have_query_cache.inc +--source include/not_embedded.inc SET @query_cache_type= @@global.query_cache_type; SET @query_cache_limit= @@global.query_cache_limit; From 0e62c9aa6301de71164496ec7c81c871d78ce8cd Mon Sep 17 00:00:00 2001 From: Alexey Kopytov Date: Mon, 23 Feb 2009 14:28:26 +0200 Subject: [PATCH 120/219] Fix for bug #15936: "round" differs on Windows to Unix Both of our own implementations of rint(3) were inconsistent with the most common behavior of rint() on those platforms that have it: round to nearest, break ties by rounding to nearest even. Fixed by leaving just one implementation of rint() in our source tree, and changing its behavior to match the most common native implementations on other platforms. configure.in: Added checks for fenv.h and fesetround(). include/config-win.h: Removed the incorrect implementation of rint() for Windows. include/my_global.h: Added an rint() implementation for platforms that do not have it. mysql-test/r/func_math.result: Added a test case for bug #15936. mysql-test/t/func_math.test: Added a test case for bug #15936. sql/mysqld.cc: Explicitly set the FPU rounding mode with fesetround(). --- configure.in | 4 +-- include/config-win.h | 9 ------ include/my_global.h | 35 +++++++++++++++++++++-- mysql-test/r/func_math.result | 30 ++++++++++++++++++++ mysql-test/t/func_math.test | 20 +++++++++++++ sql/mysqld.cc | 53 +++++++++++++++++++---------------- 6 files changed, 114 insertions(+), 37 deletions(-) diff --git a/configure.in b/configure.in index 9591b5bbc5a..8c2c4a9cf79 100644 --- a/configure.in +++ b/configure.in @@ -825,7 +825,7 @@ AC_TYPE_SIZE_T AC_HEADER_DIRENT AC_HEADER_STDC AC_HEADER_SYS_WAIT -AC_CHECK_HEADERS(fcntl.h float.h floatingpoint.h ieeefp.h limits.h \ +AC_CHECK_HEADERS(fcntl.h fenv.h float.h floatingpoint.h ieeefp.h limits.h \ memory.h pwd.h select.h \ stdlib.h stddef.h \ strings.h string.h synch.h sys/mman.h sys/socket.h netinet/in.h arpa/inet.h \ @@ -2060,7 +2060,7 @@ AC_FUNC_UTIME_NULL AC_FUNC_VPRINTF AC_CHECK_FUNCS(alarm bcmp bfill bmove bzero chsize cuserid fchmod fcntl \ - fconvert fdatasync finite fpresetsticky fpsetmask fsync ftruncate \ + fconvert fdatasync fesetround finite fpresetsticky fpsetmask fsync ftruncate \ getcwd gethostbyaddr_r gethostbyname_r getpass getpassphrase getpwnam \ getpwuid getrlimit getrusage getwd gmtime_r index initgroups isnan \ localtime_r locking longjmp lrand48 madvise mallinfo memcpy memmove \ diff --git a/include/config-win.h b/include/config-win.h index eba699159c7..ab463a7c142 100644 --- a/include/config-win.h +++ b/include/config-win.h @@ -31,7 +31,6 @@ functions */ #include #include -#include /* Because of rint() */ #include #include #include @@ -223,13 +222,6 @@ typedef uint rf_SetTimer; #define inline __inline #endif /* __cplusplus */ -inline double rint(double nr) -{ - double f = floor(nr); - double c = ceil(nr); - return (((c-nr) >= (nr-f)) ? f :c); -} - #ifdef _WIN64 #define ulonglong2double(A) ((double) (ulonglong) (A)) #define my_off_t2double(A) ((double) (my_off_t) (A)) @@ -281,7 +273,6 @@ inline ulonglong double2ulonglong(double d) #define HAVE_FLOAT_H #define HAVE_LIMITS_H #define HAVE_STDDEF_H -#define HAVE_RINT /* defined in this file */ #define NO_FCNTL_NONBLOCK /* No FCNTL */ #define HAVE_ALLOCA #define HAVE_STRPBRK diff --git a/include/my_global.h b/include/my_global.h index 845ae042a42..3f872bfc855 100644 --- a/include/my_global.h +++ b/include/my_global.h @@ -484,8 +484,39 @@ typedef unsigned short ushort; #define set_bits(type, bit_count) (sizeof(type)*8 <= (bit_count) ? ~(type) 0 : ((((type) 1) << (bit_count)) - (type) 1)) #define array_elements(A) ((uint) (sizeof(A)/sizeof(A[0]))) #ifndef HAVE_RINT -#define rint(A) floor((A)+(((A) < 0)? -0.5 : 0.5)) -#endif +/** + All integers up to this number can be represented exactly as double precision + values (DBL_MANT_DIG == 53 for IEEE 754 hardware). +*/ +#define MAX_EXACT_INTEGER ((1LL << DBL_MANT_DIG) - 1) + +/** + rint(3) implementation for platforms that do not have it. + Always rounds to the nearest integer with ties being rounded to the nearest + even integer to mimic glibc's rint() behavior in the "round-to-nearest" + FPU mode. Hardware-specific optimizations are possible (frndint on x86). + Unlike this implementation, hardware will also honor the FPU rounding mode. +*/ + +static inline double rint(double x) +{ + double f, i; + f = modf(x, &i); + /* + All doubles with absolute values > MAX_EXACT_INTEGER are even anyway, + no need to check it. + */ + if (x > 0.0) + i += (double) ((f > 0.5) || (f == 0.5 && + i <= (double) MAX_EXACT_INTEGER && + (longlong) i % 2)); + else + i -= (double) ((f < -0.5) || (f == -0.5 && + i >= (double) -MAX_EXACT_INTEGER && + (longlong) i % 2)); + return i; +} +#endif /* HAVE_RINT */ /* Define some general constants */ #ifndef TRUE diff --git a/mysql-test/r/func_math.result b/mysql-test/r/func_math.result index 0d7adbbba5e..87cfb5b86a5 100644 --- a/mysql-test/r/func_math.result +++ b/mysql-test/r/func_math.result @@ -360,4 +360,34 @@ SELECT a DIV 2 FROM t1 UNION SELECT a DIV 2 FROM t1; a DIV 2 0 DROP TABLE t1; +CREATE TABLE t1 (a DOUBLE); +INSERT INTO t1 VALUES (-1.1), (1.1), +(-1.5), (1.5), +(-1.9), (1.9), +(-2.1), (2.1), +(-2.5), (2.5), +(-2.9), (2.9), +# Check numbers with absolute values > 2^53 - 1 +# (see comments for MAX_EXACT_INTEGER) +(-1e16 - 0.5), (1e16 + 0.5), +(-1e16 - 1.5), (1e16 + 1.5); +SELECT a, ROUND(a) FROM t1; +a ROUND(a) +-1.1 -1 +1.1 1 +-1.5 -2 +1.5 2 +-1.9 -2 +1.9 2 +-2.1 -2 +2.1 2 +-2.5 -2 +2.5 2 +-2.9 -3 +2.9 3 +-1e+16 -10000000000000000 +1e+16 10000000000000000 +-1e+16 -10000000000000002 +1e+16 10000000000000002 +DROP TABLE t1; End of 5.0 tests diff --git a/mysql-test/t/func_math.test b/mysql-test/t/func_math.test index 9f12fdd696e..593cfe90c1b 100644 --- a/mysql-test/t/func_math.test +++ b/mysql-test/t/func_math.test @@ -229,5 +229,25 @@ INSERT INTO t1 VALUES ('a'); SELECT a DIV 2 FROM t1 UNION SELECT a DIV 2 FROM t1; DROP TABLE t1; +# +# Bug #15936: "round" differs on Windows to Unix +# + +CREATE TABLE t1 (a DOUBLE); + +INSERT INTO t1 VALUES (-1.1), (1.1), + (-1.5), (1.5), + (-1.9), (1.9), + (-2.1), (2.1), + (-2.5), (2.5), + (-2.9), (2.9), +# Check numbers with absolute values > 2^53 - 1 +# (see comments for MAX_EXACT_INTEGER) + (-1e16 - 0.5), (1e16 + 0.5), + (-1e16 - 1.5), (1e16 + 1.5); + +SELECT a, ROUND(a) FROM t1; + +DROP TABLE t1; --echo End of 5.0 tests diff --git a/sql/mysqld.cc b/sql/mysqld.cc index ca68976d939..7856309b095 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -186,39 +186,44 @@ int initgroups(const char *,unsigned int); #ifdef HAVE_FP_EXCEPT // Fix type conflict typedef fp_except fp_except_t; #endif +#endif /* __FreeBSD__ && HAVE_IEEEFP_H */ +#ifdef HAVE_FENV_H +#include +#endif +#ifdef HAVE_SYS_FPU_H +/* for IRIX to use set_fpc_csr() */ +#include +#endif +inline void setup_fpu() +{ +#if defined(__FreeBSD__) && defined(HAVE_IEEEFP_H) /* We can't handle floating point exceptions with threads, so disable this on freebsd + Don't fall for overflow, underflow,divide-by-zero or loss of precision */ - -inline void set_proper_floating_point_mode() -{ - /* Don't fall for overflow, underflow,divide-by-zero or loss of precision */ #if defined(__i386__) fpsetmask(~(FP_X_INV | FP_X_DNML | FP_X_OFL | FP_X_UFL | FP_X_DZ | FP_X_IMP)); #else - fpsetmask(~(FP_X_INV | FP_X_OFL | FP_X_UFL | FP_X_DZ | - FP_X_IMP)); + fpsetmask(~(FP_X_INV | FP_X_OFL | FP_X_UFL | FP_X_DZ | + FP_X_IMP)); +#endif /* __i386__ */ +#endif /* __FreeBSD__ && HAVE_IEEEFP_H */ + +#ifdef HAVE_FESETROUND + /* Set FPU rounding mode to "round-to-nearest" */ + fesetround(FE_TONEAREST); +#endif /* HAVE_FESETROUND */ + +#if defined(__sgi) && defined(HAVE_SYS_FPU_H) + /* Enable denormalized DOUBLE values support for IRIX */ + union fpc_csr n; + n.fc_word = get_fpc_csr(); + n.fc_struct.flush = 0; + set_fpc_csr(n.fc_word); #endif } -#elif defined(__sgi) -/* for IRIX to use set_fpc_csr() */ -#include - -inline void set_proper_floating_point_mode() -{ - /* Enable denormalized DOUBLE values support for IRIX */ - { - union fpc_csr n; - n.fc_word = get_fpc_csr(); - n.fc_struct.flush = 0; - set_fpc_csr(n.fc_word); - } -} -#else -#define set_proper_floating_point_mode() -#endif /* __FreeBSD__ && HAVE_IEEEFP_H */ } /* cplusplus */ @@ -3279,7 +3284,7 @@ static int init_server_components() query_cache_init(); query_cache_resize(query_cache_size); randominit(&sql_rand,(ulong) server_start_time,(ulong) server_start_time/2); - set_proper_floating_point_mode(); + setup_fpu(); init_thr_lock(); #ifdef HAVE_REPLICATION init_slave_list(); From c7d0de370679c65b663c7bddcc8081d7c3c85842 Mon Sep 17 00:00:00 2001 From: Magnus Svensson Date: Mon, 23 Feb 2009 15:52:23 +0100 Subject: [PATCH 121/219] Bug#43112 mtr.pl --embedded fails to stop cluster processes --- mysql-test/mysql-test-run.pl | 6 ------ 1 file changed, 6 deletions(-) diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl index ba426446075..82ed1ff67fc 100755 --- a/mysql-test/mysql-test-run.pl +++ b/mysql-test/mysql-test-run.pl @@ -4090,12 +4090,6 @@ sub server_need_restart { return 0; } - if ( $opt_embedded_server ) - { - mtr_verbose_restart($server, "no start or restart for embedded server"); - return 0; - } - if ( $tinfo->{'force_restart'} ) { mtr_verbose_restart($server, "forced in .opt file"); return 1; From 11b20f27affcdaeb528feb2d08c920771bd875ef Mon Sep 17 00:00:00 2001 From: Davi Arnaut Date: Tue, 24 Feb 2009 10:15:21 +0100 Subject: [PATCH 122/219] Bug#41110: crash with handler command when used concurrently with alter table Bug#41112: crash in mysql_ha_close_table/get_lock_data with alter table The problem is that the server wasn't handling robustly failures to re-open a table during a HANDLER .. READ statement. If the table needed to be re-opened due to it's storage engine being altered to one that doesn't support HANDLER, a reference (dangling pointer) to a closed table could be left in place and accessed in later attempts to fetch from the table using the handler. Also, if the server failed to set a error message if the re-open failed. These problems could lead to server crashes or hangs. The solution is to remove any references to a closed table and to set a error if reopening a table during a HANDLER .. READ statement fails. There is no test case in this change set as the test depends on a testing feature only available on 5.1 and later. sql/sql_handler.cc: Remove redundant reopen check. Set errors even if reopening table. Reset TABLE_LIST::table reference when the table is closed. --- sql/sql_handler.cc | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/sql/sql_handler.cc b/sql/sql_handler.cc index 822f2b2c419..f58a4ec4921 100644 --- a/sql/sql_handler.cc +++ b/sql/sql_handler.cc @@ -151,6 +151,9 @@ static void mysql_ha_close_table(THD *thd, TABLE_LIST *tables) } VOID(pthread_mutex_unlock(&LOCK_open)); } + + /* Mark table as closed, ready for re-open if necessary. */ + tables->table= NULL; } /* @@ -168,8 +171,7 @@ static void mysql_ha_close_table(THD *thd, TABLE_LIST *tables) 'reopen' is set when a handler table is to be re-opened. In this case, 'tables' is the pointer to the hashed TABLE_LIST object which has been saved on the original open. - 'reopen' is also used to suppress the sending of an 'ok' message or - error messages. + 'reopen' is also used to suppress the sending of an 'ok' message. RETURN FALSE OK @@ -205,8 +207,7 @@ bool mysql_ha_open(THD *thd, TABLE_LIST *tables, bool reopen) strlen(tables->alias) + 1)) { DBUG_PRINT("info",("duplicate '%s'", tables->alias)); - if (! reopen) - my_error(ER_NONUNIQ_TABLE, MYF(0), tables->alias); + my_error(ER_NONUNIQ_TABLE, MYF(0), tables->alias); goto err; } } @@ -251,8 +252,7 @@ bool mysql_ha_open(THD *thd, TABLE_LIST *tables, bool reopen) /* There can be only one table in '*tables'. */ if (! (tables->table->file->table_flags() & HA_CAN_SQL_HANDLER)) { - if (! reopen) - my_error(ER_ILLEGAL_HA, MYF(0), tables->alias); + my_error(ER_ILLEGAL_HA, MYF(0), tables->alias); goto err; } @@ -464,8 +464,7 @@ retry: if (need_reopen) { - mysql_ha_close_table(thd, tables); - hash_tables->table= NULL; + mysql_ha_close_table(thd, hash_tables); /* The lock might have been aborted, we need to manually reset thd->some_tables_deleted because handler's tables are closed From 00aa5ad58a5dab3a9108e9c6ead5880664c7bef5 Mon Sep 17 00:00:00 2001 From: Chad MILLER Date: Tue, 24 Feb 2009 12:05:37 +0200 Subject: [PATCH 123/219] Bug#39370: wrong output for error code 153 Add all HA error numbers and descriptions to perror. Add reminder to header. This is already fixed in smarter ways in future codebases, and this codebase is unlikely to change, since new development is forbidden here. --- extra/perror.c | 11 +++++++++++ include/my_base.h | 1 + 2 files changed, 12 insertions(+) diff --git a/extra/perror.c b/extra/perror.c index 37d6b45c8dd..ba638aca819 100644 --- a/extra/perror.c +++ b/extra/perror.c @@ -97,6 +97,17 @@ static HA_ERRORS ha_errlist[]= { 150,"Foreign key constraint is incorrectly formed"}, { 151,"Cannot add a child row"}, { 152,"Cannot delete a parent row"}, + { 153,"No savepoint with that name"}, + { 154,"Non unique key block size"}, + { 155,"The table does not exist in engine"}, + { 156,"The table existed in storage engine"}, + { 157,"Could not connect to storage engine"}, + { 158,"NULLs are not supported in spatial index"}, + { 159,"The table changed in storage engine"}, + { 160,"The table changed in storage engine"}, + { 161,"The table is not writable"}, + { 162,"Failed to get the next autoinc value"}, + { 163,"Failed to set the row autoinc value"}, { -30999, "DB_INCOMPLETE: Sync didn't finish"}, { -30998, "DB_KEYEMPTY: Key/data deleted or never created"}, { -30997, "DB_KEYEXIST: The key/data pair already exists"}, diff --git a/include/my_base.h b/include/my_base.h index 9240b01a9f1..e45a73d68ed 100644 --- a/include/my_base.h +++ b/include/my_base.h @@ -377,6 +377,7 @@ enum ha_base_keytype { #define HA_ERR_TABLE_READONLY 161 /* The table is not writable */ #define HA_ERR_AUTOINC_READ_FAILED 162/* Failed to get the next autoinc value */ #define HA_ERR_AUTOINC_ERANGE 163 /* Failed to set the row autoinc value */ +/* You must also add numbers and description to extra/perror.c ! */ #define HA_ERR_LAST 163 /*Copy last error nr.*/ /* Add error numbers before HA_ERR_LAST and change it accordingly. */ From 54d05087f7fb1514584f04f9bb89a55930c7fdcb Mon Sep 17 00:00:00 2001 From: Daniel Fischer Date: Tue, 24 Feb 2009 11:42:11 +0100 Subject: [PATCH 124/219] bug#42888: Add collections of test runs to make it both configurable and transparent what kinds of tests we run during integration testing. --- mysql-test/collections/README | 30 +++++++++++++++++++++++++++ mysql-test/collections/default.daily | 0 mysql-test/collections/default.push | 2 ++ mysql-test/collections/default.weekly | 0 4 files changed, 32 insertions(+) create mode 100644 mysql-test/collections/README create mode 100644 mysql-test/collections/default.daily create mode 100644 mysql-test/collections/default.push create mode 100644 mysql-test/collections/default.weekly diff --git a/mysql-test/collections/README b/mysql-test/collections/README new file mode 100644 index 00000000000..9af84646a40 --- /dev/null +++ b/mysql-test/collections/README @@ -0,0 +1,30 @@ +This directory contains collections of test runs that we run during our +integration and release testing. Each file contains zero or more lines, +with one invocation of mysql-test-run.pl on each. These invocations are +written so that, with the assumption that perl is in your search path, +any collection can run as a shell script or a batch file, with the parent +mysql-test directory being the current working directory. + +During integration testing, we choose the collection to run by following +these steps: + +1) We choose the extension to look for, based on these rules: + - If we're running a per-push test, we choose ".push" as the extension. + - If we're running a daily test, we choose ".daily" as the extension. + - If we're running a weekly test, we choose ".weekly" as the extension. + +2) If there is a collection that has the same name as the branch we're + testing plus the extension as determined in step 1, we choose that + collection. + +3) If the branch is unknown or we have removed all characters from it + and still not found a matching collection, we choose the name "default" + plus the extension determined in step 1. If there is no such file, + we give up and don't test anything at all. + +4) If we haven't found a collection yet, we remove the last character from + the branch name and go back to step 2. + +5) The commands from the collection are run line by line via execv() or + similar system calls. They are not run as a shell script. Shell + expansions are not guaranteed to work and most likely won't. diff --git a/mysql-test/collections/default.daily b/mysql-test/collections/default.daily new file mode 100644 index 00000000000..e69de29bb2d diff --git a/mysql-test/collections/default.push b/mysql-test/collections/default.push new file mode 100644 index 00000000000..0f4115c8565 --- /dev/null +++ b/mysql-test/collections/default.push @@ -0,0 +1,2 @@ +perl mysql-test-run.pl --timer --force --comment=n_stm +perl mysql-test-run.pl --timer --force --comment=ps_stm --ps-protocol diff --git a/mysql-test/collections/default.weekly b/mysql-test/collections/default.weekly new file mode 100644 index 00000000000..e69de29bb2d From 85ea3740ffa44454d7d3cb03f90857bfa43d2aad Mon Sep 17 00:00:00 2001 From: Georgi Kodinov Date: Tue, 24 Feb 2009 15:06:28 +0200 Subject: [PATCH 125/219] Bug #31060: MySQL CLI parser bug 2 There was a problem when a DELIMITER COMMAND is not the first command on the line. I this case an extra line feed was added to the glob buffer and this was causing subsequent attempts to enter this delimiter to fail. Fixed by not adding a new line to the glob buffer if the command being added is a DELIMITER client/mysql.cc: Bug #31060: Don't add a new line if DELIMTER is added to the glob buffer mysql-test/r/mysql.result: Bug #31060: test case mysql-test/t/mysql.test: Bug #31060: test case --- client/mysql.cc | 16 +++++++++++++++- mysql-test/r/mysql.result | 4 ++++ mysql-test/t/mysql.test | 17 +++++++++++++++++ 3 files changed, 36 insertions(+), 1 deletion(-) diff --git a/client/mysql.cc b/client/mysql.cc index d1d36d79565..1a025345190 100644 --- a/client/mysql.cc +++ b/client/mysql.cc @@ -2222,8 +2222,22 @@ static bool add_line(String &buffer,char *line,char *in_string, } if (out != line || !buffer.is_empty()) { - *out++='\n'; uint length=(uint) (out-line); + + if (length < 9 || + my_strnncoll (charset_info, + (uchar *)line, 9, (const uchar *) "delimiter", 9)) + { + /* + Don't add a new line in case there's a DELIMITER command to be + added to the glob buffer (e.g. on processing a line like + ";DELIMITER ") : similar to how a new line is + not added in the case when the DELIMITER is the first command + entered with an empty glob buffer. + */ + *out++='\n'; + length++; + } if (buffer.length() + length >= buffer.alloced_length()) buffer.realloc(buffer.length()+length+IO_SIZE); if ((!*ml_comment || preserve_comments) && buffer.append(line, length)) diff --git a/mysql-test/r/mysql.result b/mysql-test/r/mysql.result index 9bad3b9f791..10537f6da16 100644 --- a/mysql-test/r/mysql.result +++ b/mysql-test/r/mysql.result @@ -188,4 +188,8 @@ delimiter 2 @z:='1' @z=database() 1 NULL +1 +1 +1 +1 End of 5.0 tests diff --git a/mysql-test/t/mysql.test b/mysql-test/t/mysql.test index 68a01a309d4..594d10e46a5 100644 --- a/mysql-test/t/mysql.test +++ b/mysql-test/t/mysql.test @@ -314,4 +314,21 @@ remove_file $MYSQLTEST_VARDIR/tmp/bug38158.sql; # --exec $MYSQL -e "select @z:='1',@z=database()" + +# +# Bug #31060: MySQL CLI parser bug 2 +# + +--write_file $MYSQLTEST_VARDIR/tmp/bug31060.sql +;DELIMITER DELIMITER +; +SELECT 1DELIMITER +DELIMITER ; +SELECT 1; +EOF + +--exec $MYSQL < $MYSQLTEST_VARDIR/tmp/bug31060.sql 2>&1 + +remove_file $MYSQLTEST_VARDIR/tmp/bug31060.sql; + --echo End of 5.0 tests From 4b05db5cfdfa9d56c7185a8c03ddfaaf4333c963 Mon Sep 17 00:00:00 2001 From: Georgi Kodinov Date: Tue, 24 Feb 2009 15:06:28 +0200 Subject: [PATCH 126/219] Bug #31060: MySQL CLI parser bug 2 There was a problem when a DELIMITER COMMAND is not the first command on the line. I this case an extra line feed was added to the glob buffer and this was causing subsequent attempts to enter this delimiter to fail. Fixed by not adding a new line to the glob buffer if the command being added is a DELIMITER client/mysql.cc: Bug #31060: Don't add a new line if DELIMTER is added to the glob buffer mysql-test/r/mysql.result: Bug #31060: test case mysql-test/t/mysql.test: Bug #31060: test case --- client/mysql.cc | 16 +++++++++++++++- mysql-test/r/mysql.result | 4 ++++ mysql-test/t/mysql.test | 17 +++++++++++++++++ 3 files changed, 36 insertions(+), 1 deletion(-) diff --git a/client/mysql.cc b/client/mysql.cc index d1d36d79565..1a025345190 100644 --- a/client/mysql.cc +++ b/client/mysql.cc @@ -2222,8 +2222,22 @@ static bool add_line(String &buffer,char *line,char *in_string, } if (out != line || !buffer.is_empty()) { - *out++='\n'; uint length=(uint) (out-line); + + if (length < 9 || + my_strnncoll (charset_info, + (uchar *)line, 9, (const uchar *) "delimiter", 9)) + { + /* + Don't add a new line in case there's a DELIMITER command to be + added to the glob buffer (e.g. on processing a line like + ";DELIMITER ") : similar to how a new line is + not added in the case when the DELIMITER is the first command + entered with an empty glob buffer. + */ + *out++='\n'; + length++; + } if (buffer.length() + length >= buffer.alloced_length()) buffer.realloc(buffer.length()+length+IO_SIZE); if ((!*ml_comment || preserve_comments) && buffer.append(line, length)) diff --git a/mysql-test/r/mysql.result b/mysql-test/r/mysql.result index 9bad3b9f791..10537f6da16 100644 --- a/mysql-test/r/mysql.result +++ b/mysql-test/r/mysql.result @@ -188,4 +188,8 @@ delimiter 2 @z:='1' @z=database() 1 NULL +1 +1 +1 +1 End of 5.0 tests diff --git a/mysql-test/t/mysql.test b/mysql-test/t/mysql.test index 68a01a309d4..594d10e46a5 100644 --- a/mysql-test/t/mysql.test +++ b/mysql-test/t/mysql.test @@ -314,4 +314,21 @@ remove_file $MYSQLTEST_VARDIR/tmp/bug38158.sql; # --exec $MYSQL -e "select @z:='1',@z=database()" + +# +# Bug #31060: MySQL CLI parser bug 2 +# + +--write_file $MYSQLTEST_VARDIR/tmp/bug31060.sql +;DELIMITER DELIMITER +; +SELECT 1DELIMITER +DELIMITER ; +SELECT 1; +EOF + +--exec $MYSQL < $MYSQLTEST_VARDIR/tmp/bug31060.sql 2>&1 + +remove_file $MYSQLTEST_VARDIR/tmp/bug31060.sql; + --echo End of 5.0 tests From aa9646c8bc25a19b312e663e0a81726bfa83c00d Mon Sep 17 00:00:00 2001 From: Daniel Fischer Date: Tue, 24 Feb 2009 14:54:04 +0100 Subject: [PATCH 127/219] include collections in dist --- mysql-test/Makefile.am | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/mysql-test/Makefile.am b/mysql-test/Makefile.am index 0c4a708dd14..cdb2d9fd598 100644 --- a/mysql-test/Makefile.am +++ b/mysql-test/Makefile.am @@ -33,7 +33,7 @@ endif benchdir_root= $(prefix) testdir = $(benchdir_root)/mysql-test EXTRA_SCRIPTS = mysql-test-run-shell.sh install_test_db.sh valgrind.supp $(PRESCRIPTS) -EXTRA_DIST = $(EXTRA_SCRIPTS) suite +EXTRA_DIST = $(EXTRA_SCRIPTS) suite collections GENSCRIPTS = mysql-test-run-shell mysql-test-run install_test_db mtr PRESCRIPTS = mysql-test-run.pl mysql-stress-test.pl test_SCRIPTS = $(GENSCRIPTS) $(PRESCRIPTS) @@ -80,6 +80,7 @@ install-data-local: $(DESTDIR)$(testdir)/std_data/ndb_backup50_data_be \ $(DESTDIR)$(testdir)/std_data/ndb_backup50_data_le \ $(DESTDIR)$(testdir)/lib \ + $(DESTDIR)$(testdir)/collections \ $(DESTDIR)$(testdir)/std_data/funcs_1 $(INSTALL_DATA) $(srcdir)/README $(DESTDIR)$(testdir) -$(INSTALL_DATA) $(srcdir)/t/*.def $(DESTDIR)$(testdir)/t From d091deaf89a09881a34ef67335d042354da75c11 Mon Sep 17 00:00:00 2001 From: Andrei Elkin Date: Tue, 24 Feb 2009 16:17:34 +0200 Subject: [PATCH 128/219] fixing compilation warning and adding flush logs to test of bug#37313 --- mysql-test/r/mysqlbinlog.result | 1 + mysql-test/t/mysqlbinlog.test | 1 + sql/log_event.cc | 2 +- 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/mysqlbinlog.result b/mysql-test/r/mysqlbinlog.result index b5ac22437cd..dbbf49e7920 100644 --- a/mysql-test/r/mysqlbinlog.result +++ b/mysql-test/r/mysqlbinlog.result @@ -364,6 +364,7 @@ drop table t1; shell> mysqlbinlog std_data/corrupt-relay-bin.000624 > var/tmp/bug31793.sql set @@global.server_id= 4294967295; reset master; +flush logs; select (@a:=load_file("MYSQLTEST_VARDIR/tmp/mysqlbinlog_bug37313.binlog")) is not null; diff --git a/mysql-test/t/mysqlbinlog.test b/mysql-test/t/mysqlbinlog.test index cf4bc1523df..d88ca7d0504 100644 --- a/mysql-test/t/mysqlbinlog.test +++ b/mysql-test/t/mysqlbinlog.test @@ -262,6 +262,7 @@ let $s_id_max=`select (1 << 32) - 1`; eval set @@global.server_id= $s_id_max; reset master; +flush logs; --exec $MYSQL_BINLOG $MYSQLTEST_VARDIR/log/master-bin.000001 > $MYSQLTEST_VARDIR/tmp/mysqlbinlog_bug37313.binlog --replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR eval select diff --git a/sql/log_event.cc b/sql/log_event.cc index 90805877502..b74b38e55b2 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -976,7 +976,7 @@ void Log_event::print_header(FILE* file, PRINT_EVENT_INFO* print_event_info) fputc('#', file); print_timestamp(file); - fprintf(file, " server id %lu end_log_pos %s ", server_id, + fprintf(file, " server id %lu end_log_pos %s ", (ulong) server_id, llstr(log_pos,llbuff)); /* mysqlbinlog --hexdump */ From df09ddaced71af470a23f882dc03621490810e1b Mon Sep 17 00:00:00 2001 From: Patrick Crews Date: Tue, 24 Feb 2009 16:20:00 +0200 Subject: [PATCH 129/219] Bug#40178: Test main.completion_type_func does not clean up / needs to be rewritten Revised the test to include a test of completion_type = 1 as well as making the test more readable / worthwhile Removed the master.opt file as it was redundant / unnecessary. mysql-test/suite/sys_vars/t/completion_type_func-master.opt: Removed as redundant. Test uses include/have_innodb.inc. --- .../sys_vars/r/completion_type_func.result | 161 +++++++++++++++--- .../t/completion_type_func-master.opt | 1 - .../sys_vars/t/completion_type_func.test | 144 ++++++++++++---- 3 files changed, 243 insertions(+), 63 deletions(-) delete mode 100644 mysql-test/suite/sys_vars/t/completion_type_func-master.opt diff --git a/mysql-test/suite/sys_vars/r/completion_type_func.result b/mysql-test/suite/sys_vars/r/completion_type_func.result index daee738c10d..f3ddcd287b6 100644 --- a/mysql-test/suite/sys_vars/r/completion_type_func.result +++ b/mysql-test/suite/sys_vars/r/completion_type_func.result @@ -2,76 +2,187 @@ DROP TABLE IF EXISTS t1; ## Creating new table ## CREATE TABLE t1 ( -id INT NOT NULL AUTO_INCREMENT, +id INT NOT NULL, PRIMARY KEY (id), name VARCHAR(30) ) ENGINE = INNODB; -'#--------------------FN_DYNVARS_017_01-------------------------#' -## Creating new connection ## -INSERT INTO t1(name) VALUES('Record_1'); -SET @@autocommit = 0; +## Creating new connections test_con1, test_con2 ## +######################################################### +# Setting initial value of completion_type to zero # +######################################################### +INSERT INTO t1 VALUES(1,'Record_1'); SELECT * FROM t1; id name 1 Record_1 ## Setting value of variable to 0 ## SET @@session.completion_type = 0; ## Here commit & rollback should work normally ## +## test commit ## START TRANSACTION; -SELECT * FROM t1; -id name -1 Record_1 -INSERT INTO t1(name) VALUES('Record_2'); -INSERT INTO t1(name) VALUES('Record_3'); +INSERT INTO t1 VALUES(2,'Record_2'); +INSERT INTO t1 VALUES(3,'Record_3'); SELECT * FROM t1; id name 1 Record_1 2 Record_2 3 Record_3 -DELETE FROM t1 WHERE id = 2; +Switching to connection test_con1 +## Don't expect to see id's 2 and 3 in the table w/o COMMIT ## SELECT * FROM t1; id name 1 Record_1 +Switching to default connection +COMMIT; +## test rollback ## +START TRANSACTION; +INSERT INTO t1 VALUES(4,'Record_4'); +INSERT INTO t1 VALUES(5,'Record_5'); +SELECT * FROM t1; +id name +1 Record_1 +2 Record_2 3 Record_3 +4 Record_4 +5 Record_5 +Switching to connection test_con1 +## Don't expect to see id's 4 and 5 here ## +## Expect to see 3, Record_3 ## +SELECT * FROM t1; +id name +1 Record_1 +2 Record_2 +3 Record_3 +Switching to connection default; +ROLLBACK; +## Don't expect to see id's 4 and 5 now ## +SELECT * FROM t1; +id name +1 Record_1 +2 Record_2 +3 Record_3 + +######################################################### +# Setting initial value of completion_type to one # +######################################################### +Switching to connection test_con1; +SET @@session.completion_type = 1; START TRANSACTION; SELECT * FROM t1; id name 1 Record_1 +2 Record_2 3 Record_3 -INSERT INTO t1(name) VALUES('Record_4'); -INSERT INTO t1(name) VALUES('Record_5'); +INSERT INTO t1 VALUES(6,'Record_6'); +INSERT INTO t1 VALUES(7,'Record_7'); COMMIT; -'#--------------------FN_DYNVARS_017_02-------------------------#' +## Expect to immediately have a new transaction ## +INSERT INTO t1 VALUES(8,'Record_8'); +SELECT * FROM t1; +id name +1 Record_1 +2 Record_2 +3 Record_3 +6 Record_6 +7 Record_7 +8 Record_8 +switching to test_con2 +## Do not expect to see 8, Record_8 as no COMMIT has occurred ## +SELECT * FROM t1; +id name +1 Record_1 +2 Record_2 +3 Record_3 +6 Record_6 +7 Record_7 +switch to connection test_con1 +## Testing ROLLBACK behavior +START TRANSACTION; +INSERT INTO t1 VALUES(9, 'Record_9'); +INSERT INTO t1 VALUES(10, 'Record_10'); +## Expect to see id's 8, 9, 10 here ## +## 8, Record_8 COMMITted with the start of this transaction ## +SELECT * FROM t1; +id name +1 Record_1 +2 Record_2 +3 Record_3 +6 Record_6 +7 Record_7 +8 Record_8 +9 Record_9 +10 Record_10 +ROLLBACK; +## id's 9 and 10 are gone now due to ROLLBACK ## +SELECT * FROM t1; +id name +1 Record_1 +2 Record_2 +3 Record_3 +6 Record_6 +7 Record_7 +8 Record_8 +## Expect a new transaction ## +INSERT INTO t1 VALUES(9, 'Record_9'); +Switching to connection test_con2 +## Don't expect to see 9, Record_9 due to no COMMIT yet ## +SELECT * FROM t1; +id name +1 Record_1 +2 Record_2 +3 Record_3 +6 Record_6 +7 Record_7 +8 Record_8 +Switching to connection test_con1 +ROLLBACK; +## Don't expect to see 9, Record_9 +SELECT * FROM t1; +id name +1 Record_1 +2 Record_2 +3 Record_3 +6 Record_6 +7 Record_7 +8 Record_8 +######################################################### +# Setting initial value of completion_type to 2 # +######################################################### SET @@session.completion_type = 2; ## Here commit should work as COMMIT RELEASE ## START TRANSACTION; SELECT * FROM t1; id name 1 Record_1 +2 Record_2 3 Record_3 -4 Record_4 -5 Record_5 -INSERT INTO t1(name) VALUES('Record_6'); -INSERT INTO t1(name) VALUES('Record_7'); +6 Record_6 +7 Record_7 +8 Record_8 +INSERT INTO t1 VALUES(9,'Record_9'); +INSERT INTO t1 VALUES(10,'Record_10'); COMMIT; ## Inserting rows should give error here because connection should ## ## disconnect after using COMMIT ## -INSERT INTO t1(name) VALUES('Record_4'); +INSERT INTO t1 VALUES(4,'Record_4'); Got one of the listed errors -## Creating new connection test_con2 ## +switch to connection test_con2 SET @@session.completion_type = 2; ## Inserting rows and using Rollback which should Rollback & release ## START TRANSACTION; SELECT * FROM t1; id name 1 Record_1 +2 Record_2 3 Record_3 -4 Record_4 -5 Record_5 6 Record_6 7 Record_7 -INSERT INTO t1(name) VALUES('Record_8'); -INSERT INTO t1(name) VALUES('Record_9'); +8 Record_8 +9 Record_9 +10 Record_10 +INSERT INTO t1 VALUES(11,'Record_11'); +INSERT INTO t1 VALUES(12,'Record_12'); ROLLBACK; -INSERT INTO t1(name) VALUES('Record_4'); +## Expect a failure due to COMMIT/ROLLBACK AND RELEASE behavior ## +INSERT INTO t1 VALUES(4,'Record_4'); Got one of the listed errors DROP TABLE t1; diff --git a/mysql-test/suite/sys_vars/t/completion_type_func-master.opt b/mysql-test/suite/sys_vars/t/completion_type_func-master.opt deleted file mode 100644 index 627becdbfb5..00000000000 --- a/mysql-test/suite/sys_vars/t/completion_type_func-master.opt +++ /dev/null @@ -1 +0,0 @@ ---innodb diff --git a/mysql-test/suite/sys_vars/t/completion_type_func.test b/mysql-test/suite/sys_vars/t/completion_type_func.test index ed0f04c37b4..8e363ed2a7d 100644 --- a/mysql-test/suite/sys_vars/t/completion_type_func.test +++ b/mysql-test/suite/sys_vars/t/completion_type_func.test @@ -1,4 +1,4 @@ -############## mysql-test\t\completion_type_func.test ########################## +############## mysql-test/suite/sys_vars/t/completion_type_func.test ########### # # # Variable Name: completion_type # # Scope: GLOBAL & SESSION # @@ -25,84 +25,154 @@ DROP TABLE IF EXISTS t1; --enable_warnings -######################### -# Creating new table # -######################### +############################## +# Setup: Table + connections # +############################## --echo ## Creating new table ## CREATE TABLE t1 ( -id INT NOT NULL AUTO_INCREMENT, +id INT NOT NULL, PRIMARY KEY (id), name VARCHAR(30) ) ENGINE = INNODB; ---echo '#--------------------FN_DYNVARS_017_01-------------------------#' -######################################################### -# Setting initial value of completion_type to zero # -######################################################### - ---echo ## Creating new connection ## +--echo ## Creating new connections test_con1, test_con2 ## connect (test_con1,localhost,root,,); -connection test_con1; +connect (test_con2,localhost,root,,); -INSERT INTO t1(name) VALUES('Record_1'); -SET @@autocommit = 0; +connection default; + +--echo ######################################################### +--echo # Setting initial value of completion_type to zero # +--echo ######################################################### + +INSERT INTO t1 VALUES(1,'Record_1'); SELECT * FROM t1; --echo ## Setting value of variable to 0 ## SET @@session.completion_type = 0; --echo ## Here commit & rollback should work normally ## +--echo ## test commit ## START TRANSACTION; -SELECT * FROM t1; -INSERT INTO t1(name) VALUES('Record_2'); -INSERT INTO t1(name) VALUES('Record_3'); -SELECT * FROM t1; -DELETE FROM t1 WHERE id = 2; +INSERT INTO t1 VALUES(2,'Record_2'); +INSERT INTO t1 VALUES(3,'Record_3'); SELECT * FROM t1; - -START TRANSACTION; +--echo Switching to connection test_con1 +connection test_con1; +--echo ## Don't expect to see id's 2 and 3 in the table w/o COMMIT ## SELECT * FROM t1; -INSERT INTO t1(name) VALUES('Record_4'); -INSERT INTO t1(name) VALUES('Record_5'); + +--echo Switching to default connection +connection default; COMMIT; +--echo ## test rollback ## +START TRANSACTION; +INSERT INTO t1 VALUES(4,'Record_4'); +INSERT INTO t1 VALUES(5,'Record_5'); +SELECT * FROM t1; ---echo '#--------------------FN_DYNVARS_017_02-------------------------#' -######################################################### -# Setting initial value of completion_type to 2 # -######################################################### +--echo Switching to connection test_con1 +connection test_con1; +--echo ## Don't expect to see id's 4 and 5 here ## +--echo ## Expect to see 3, Record_3 ## +SELECT * FROM t1; + +--echo Switching to connection default; +connection default; + + +ROLLBACK; +--echo ## Don't expect to see id's 4 and 5 now ## +SELECT * FROM t1; + +--echo +--echo ######################################################### +--echo # Setting initial value of completion_type to one # +--echo ######################################################### + +--echo Switching to connection test_con1; +connection test_con1; +SET @@session.completion_type = 1; + +START TRANSACTION; +SELECT * FROM t1; +INSERT INTO t1 VALUES(6,'Record_6'); +INSERT INTO t1 VALUES(7,'Record_7'); +COMMIT; + +--echo ## Expect to immediately have a new transaction ## +INSERT INTO t1 VALUES(8,'Record_8'); +SELECT * FROM t1; + +connection test_con2; +--echo switching to test_con2 +--echo ## Do not expect to see 8, Record_8 as no COMMIT has occurred ## +SELECT * FROM t1; + +--echo switch to connection test_con1 +connection test_con1; + +--echo ## Testing ROLLBACK behavior +START TRANSACTION; +INSERT INTO t1 VALUES(9, 'Record_9'); +INSERT INTO t1 VALUES(10, 'Record_10'); +--echo ## Expect to see id's 8, 9, 10 here ## +--echo ## 8, Record_8 COMMITted with the start of this transaction ## +SELECT * FROM t1; +ROLLBACK; +--echo ## id's 9 and 10 are gone now due to ROLLBACK ## +SELECT * FROM t1; + +--echo ## Expect a new transaction ## +INSERT INTO t1 VALUES(9, 'Record_9'); + +--echo Switching to connection test_con2 +connection test_con2; +--echo ## Don't expect to see 9, Record_9 due to no COMMIT yet ## +SELECT * FROM t1; + +--echo Switching to connection test_con1 +connection test_con1; +ROLLBACK; +--echo ## Don't expect to see 9, Record_9 +SELECT * FROM t1; + +--echo ######################################################### +--echo # Setting initial value of completion_type to 2 # +--echo ######################################################### SET @@session.completion_type = 2; --echo ## Here commit should work as COMMIT RELEASE ## START TRANSACTION; SELECT * FROM t1; -INSERT INTO t1(name) VALUES('Record_6'); -INSERT INTO t1(name) VALUES('Record_7'); +INSERT INTO t1 VALUES(9,'Record_9'); +INSERT INTO t1 VALUES(10,'Record_10'); COMMIT; --echo ## Inserting rows should give error here because connection should ## --echo ## disconnect after using COMMIT ## ---Error 2006,2013,1053 -INSERT INTO t1(name) VALUES('Record_4'); +--Error 2006,2013,ER_SERVER_SHUTDOWN +INSERT INTO t1 VALUES(4,'Record_4'); ---echo ## Creating new connection test_con2 ## -connect (test_con2,localhost,root,,); +--echo switch to connection test_con2 connection test_con2; SET @@session.completion_type = 2; --echo ## Inserting rows and using Rollback which should Rollback & release ## START TRANSACTION; SELECT * FROM t1; -INSERT INTO t1(name) VALUES('Record_8'); -INSERT INTO t1(name) VALUES('Record_9'); +INSERT INTO t1 VALUES(11,'Record_11'); +INSERT INTO t1 VALUES(12,'Record_12'); ROLLBACK; ---Error 2006,2013,1053 -INSERT INTO t1(name) VALUES('Record_4'); +--echo ## Expect a failure due to COMMIT/ROLLBACK AND RELEASE behavior ## +--Error 2006,2013,ER_SERVER_SHUTDOWN, +INSERT INTO t1 VALUES(4,'Record_4'); connection default; disconnect test_con1; From da3c773166f7c5c4d4ad653ae27a0d762f2ce7e8 Mon Sep 17 00:00:00 2001 From: Anurag Shekhar Date: Tue, 24 Feb 2009 20:44:47 +0530 Subject: [PATCH 130/219] Bug #38103 myisamchk: --help output incomplete In the output message for --help entry for -H --HELP was missing. Added this entry while printing the help text. storage/myisam/myisamchk.c: Added entry for -H --HELP while printing message for -? --help --- storage/myisam/myisamchk.c | 1 + 1 file changed, 1 insertion(+) diff --git a/storage/myisam/myisamchk.c b/storage/myisam/myisamchk.c index f8fcdcb6fab..8165bd191b1 100644 --- a/storage/myisam/myisamchk.c +++ b/storage/myisam/myisamchk.c @@ -363,6 +363,7 @@ static void usage(void) -#, --debug=... Output debug log. Often this is 'd:t:o,filename'.\n"); #endif printf("\ + -H, --HELP Display this help and exit.\n\ -?, --help Display this help and exit.\n\ -O, --set-variable var=option.\n\ Change the value of a variable. Please note that\n\ From 7099d7bc2bdf4513abcc8e4b20d583ac1262e156 Mon Sep 17 00:00:00 2001 From: "Tatiana A. Nurnberg" Date: Tue, 24 Feb 2009 16:42:18 +0100 Subject: [PATCH 131/219] Bug#40657: assertion with out of range variables and traditional sql_mode In STRICT mode, out-of-bounds values caused an error message to be queued (rather than just a warning), without any further error-like processing happening. (The error is queued during update, at which time it's too late. For it to be processed properly, it would need to be queued during check-stage.) The assertion rightfully complains that we're trying to send an OK while having an error queued. Changeset breaks a lot of tests out into check-stage. This also allows us to send more correct warnings/error messages. sql/set_var.cc: cleanup: fold get_unsigned() and fix_unsigned() into one, as well as all the semi-common code from the ::check functions. --- sql/set_var.cc | 184 ++++++++++++++++++++++--------------------------- 1 file changed, 81 insertions(+), 103 deletions(-) diff --git a/sql/set_var.cc b/sql/set_var.cc index e2f3590311c..ff32ec2458e 100644 --- a/sql/set_var.cc +++ b/sql/set_var.cc @@ -134,8 +134,6 @@ static int check_max_delayed_threads(THD *thd, set_var *var); static void fix_thd_mem_root(THD *thd, enum_var_type type); static void fix_trans_mem_root(THD *thd, enum_var_type type); static void fix_server_id(THD *thd, enum_var_type type); -static int get_unsigned(THD *thd, set_var *var); -static bool fix_unsigned(THD *, ulonglong *, bool, const struct my_option *); bool throw_bounds_warning(THD *thd, bool fixed, bool unsignd, const char *name, longlong val); static KEY_CACHE *create_key_cache(const char *name, uint length); @@ -1406,42 +1404,49 @@ bool throw_bounds_warning(THD *thd, bool fixed, bool unsignd, /** check an unsigned user-supplied value for a systemvariable against bounds. - if we needed to adjust the value, throw a warning/error. @param thd thread handle - @param num the value the user gave - @param warn throw warning/error (FALSE if we get here from - get_unsigned(), so we don't throw two warnings if - user supplies negative value to an unsigned variable) - @param option_limits the bounds-record + @param num the value to limit + @param option_limits the bounds-record, or NULL - @retval TRUE on error, FALSE otherwise (warning or OK) + @retval whether or not we needed to bound */ -static bool fix_unsigned(THD *thd, ulonglong *num, bool warn, - const struct my_option *option_limits) +static my_bool bound_unsigned(THD *thd, ulonglong *num, + const struct my_option *option_limits) { my_bool fixed = FALSE; ulonglong unadjusted= *num; - *num= getopt_ull_limit_value(unadjusted, option_limits, &fixed); - - return warn && throw_bounds_warning(thd, fixed, TRUE, option_limits->name, - (longlong) unadjusted); + if (option_limits) + *num= getopt_ull_limit_value(unadjusted, option_limits, &fixed); + return fixed; } /** Get unsigned system-variable. Negative value does not wrap around, but becomes zero. + Check user-supplied value for a systemvariable against bounds. + If we needed to adjust the value, throw a warning or error depending + on SQL-mode. - @param thd thread handle - @param var the system-variable to get + @param thd thread handle + @param var the system-variable to get + @param user_max a limit given with --maximum-variable-name=... or 0 + @param bound2ulong pass TRUE if size is ulong, not ulonglong. function + will then bound on systems where it's necessary. - @retval 0 - OK, 1 - warning, 2 - error + @retval TRUE on error, FALSE otherwise (warning or OK) */ -static int get_unsigned(THD *thd, set_var *var) +static bool get_unsigned(THD *thd, set_var *var, ulonglong user_max, + my_bool bound2ulong) { + int warnings= 0; + ulonglong unadjusted; + const struct my_option *limits= var->var->option_limits; + + /* get_unsigned() */ if (var->value->unsigned_flag) var->save_result.ulonglong_value= (ulonglong) var->value->val_int(); else @@ -1449,9 +1454,57 @@ static int get_unsigned(THD *thd, set_var *var) longlong v= var->value->val_int(); var->save_result.ulonglong_value= (ulonglong) ((v < 0) ? 0 : v); if (v < 0) - return throw_bounds_warning(thd, TRUE, FALSE, var->var->name, v) ? 2 : 1; + { + warnings++; + if (throw_bounds_warning(thd, TRUE, FALSE, var->var->name, v)) + return TRUE; /* warning was promoted to error, give up */ + } } - return 0; + + unadjusted= var->save_result.ulonglong_value; + + /* max, if any */ + + if ((user_max > 0) && (unadjusted > user_max)) + { + var->save_result.ulonglong_value= user_max; + + if ((warnings == 0) && throw_bounds_warning(thd, TRUE, TRUE, + var->var->name, + (longlong) unadjusted)) + return TRUE; + + warnings++; + } + + /* fix_unsigned() */ + if (limits) + { + my_bool fixed; + + var->save_result.ulonglong_value= getopt_ull_limit_value(unadjusted, + limits, &fixed); + + if ((warnings == 0) && throw_bounds_warning(thd, fixed, TRUE, limits->name, + (longlong) unadjusted)) + return TRUE; + } + else if (bound2ulong) + { +#if SIZEOF_LONG < SIZEOF_LONG_LONG + /* Avoid overflows on 32 bit systems */ + if (var->save_result.ulonglong_value > ULONG_MAX) + { + var->save_result.ulonglong_value= ULONG_MAX; + if ((warnings == 0) && throw_bounds_warning(thd, TRUE, TRUE, + var->var->name, + (longlong) unadjusted)) + return TRUE; + } +#endif + } + + return FALSE; } @@ -1465,27 +1518,7 @@ sys_var_long_ptr(sys_var_chain *chain, const char *name_arg, ulong *value_ptr_ar bool sys_var_long_ptr_global::check(THD *thd, set_var *var) { - bool ret = FALSE; - int got_warnings= get_unsigned(thd, var); - - if (got_warnings == 2) - ret= TRUE; - else if (option_limits) - ret= fix_unsigned(thd, &var->save_result.ulonglong_value, - (got_warnings == 0), option_limits); - else - { -#if SIZEOF_LONG < SIZEOF_LONG_LONG - /* Avoid overflows on 32 bit systems */ - if (var->save_result.ulonglong_value > ULONG_MAX) - { - ret= throw_bounds_warning(thd, TRUE, TRUE, name, - (longlong) var->save_result.ulonglong_value); - var->save_result.ulonglong_value= ULONG_MAX; - } -#endif - } - return ret; + return get_unsigned(thd, var, 0, TRUE); } bool sys_var_long_ptr_global::update(THD *thd, set_var *var) @@ -1511,8 +1544,7 @@ bool sys_var_ulonglong_ptr::update(THD *thd, set_var *var) { ulonglong tmp= var->save_result.ulonglong_value; pthread_mutex_lock(&LOCK_global_system_variables); - if (option_limits) - fix_unsigned(thd, &tmp, FALSE, option_limits); + bound_unsigned(thd, &tmp, option_limits); *value= (ulonglong) tmp; pthread_mutex_unlock(&LOCK_global_system_variables); return 0; @@ -1563,38 +1595,8 @@ uchar *sys_var_enum_const::value_ptr(THD *thd, enum_var_type type, bool sys_var_thd_ulong::check(THD *thd, set_var *var) { - ulonglong tmp; - int got_warnings= get_unsigned(thd, var); - - if (got_warnings == 2) + if (get_unsigned(thd, var, max_system_variables.*offset, TRUE)) return TRUE; - - tmp= var->save_result.ulonglong_value; - - /* Don't use bigger value than given with --maximum-variable-name=.. */ - if ((ulong) tmp > max_system_variables.*offset) - { - if (throw_bounds_warning(thd, TRUE, TRUE, name, (longlong) tmp)) - return TRUE; - tmp= max_system_variables.*offset; - } - - if (option_limits) - { - if (fix_unsigned(thd, &tmp, (got_warnings == 0), option_limits)) - return TRUE; - } -#if SIZEOF_LONG < SIZEOF_LONG_LONG - else if (tmp > ULONG_MAX) - { - if (throw_bounds_warning(thd, TRUE, TRUE, name, (longlong) tmp)) - return TRUE; - tmp= ULONG_MAX; - } -#endif - - var->save_result.ulonglong_value= (ulong) tmp; - return ((check_func && (*check_func)(thd, var))); } @@ -1641,8 +1643,7 @@ bool sys_var_thd_ha_rows::update(THD *thd, set_var *var) if ((ha_rows) tmp > max_system_variables.*offset) tmp= max_system_variables.*offset; - if (option_limits) - fix_unsigned(thd, &tmp, FALSE, option_limits); + bound_unsigned(thd, &tmp, option_limits); if (var->type == OPT_GLOBAL) { @@ -1684,30 +1685,7 @@ uchar *sys_var_thd_ha_rows::value_ptr(THD *thd, enum_var_type type, bool sys_var_thd_ulonglong::check(THD *thd, set_var *var) { - ulonglong tmp; - int got_warnings= get_unsigned(thd, var); - - if (got_warnings == 2) - return TRUE; - - tmp= var->save_result.ulonglong_value; - - if (tmp > max_system_variables.*offset) - { - if (throw_bounds_warning(thd, TRUE, TRUE, name, (longlong) tmp)) - return TRUE; - tmp= max_system_variables.*offset; - } - - if (option_limits) - { - if (fix_unsigned(thd, &tmp, (got_warnings == 0), option_limits)) - return TRUE; - } - - var->save_result.ulonglong_value= tmp; - - return FALSE; + return get_unsigned(thd, var, max_system_variables.*offset, FALSE); } bool sys_var_thd_ulonglong::update(THD *thd, set_var *var) @@ -2353,7 +2331,7 @@ bool sys_var_key_buffer_size::update(THD *thd, set_var *var) goto end; } - fix_unsigned(thd, &tmp, FALSE, option_limits); + bound_unsigned(thd, &tmp, option_limits); key_cache->param_buff_size= (ulonglong) tmp; /* If key cache didn't existed initialize it, else resize it */ @@ -2407,7 +2385,7 @@ bool sys_var_key_cache_long::update(THD *thd, set_var *var) if (key_cache->in_init) goto end; - fix_unsigned(thd, &tmp, FALSE, option_limits); + bound_unsigned(thd, &tmp, option_limits); *((ulong*) (((char*) key_cache) + offset))= (ulong) tmp; /* From 4da0c708b51f5b6df3da7ca759ccac3819030f6e Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 24 Feb 2009 17:54:03 +0100 Subject: [PATCH 132/219] Insert current year as last copyright year for the product Don't use both "License" and "license" as RPM macro, they are the same --- configure.in | 2 ++ support-files/Makefile.am | 1 + support-files/mysql.spec.sh | 12 ++++++------ 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/configure.in b/configure.in index b5beb7a24f5..ef2771f5d67 100644 --- a/configure.in +++ b/configure.in @@ -36,6 +36,7 @@ MYSQL_NUMERIC_VERSION=`echo $MYSQL_NO_DASH_VERSION | sed -e "s|[[a-z]][[a-z0-9]] MYSQL_BASE_VERSION=`echo $MYSQL_NUMERIC_VERSION | sed -e "s|\.[[^.]]*$||"` MYSQL_VERSION_ID=`echo $MYSQL_NUMERIC_VERSION | \ awk -F. '{printf "%d%0.2d%0.2d", $1, $2, $3}'` +MYSQL_COPYRIGHT_YEAR=`date '+%Y'` # Add previous major version for debian package upgrade path MYSQL_PREVIOUS_BASE_VERSION=5.0 @@ -70,6 +71,7 @@ AC_SUBST(MYSQL_NO_DASH_VERSION) AC_SUBST(MYSQL_BASE_VERSION) AC_SUBST(MYSQL_VERSION_ID) AC_SUBST(MYSQL_PREVIOUS_BASE_VERSION) +AC_SUBST(MYSQL_COPYRIGHT_YEAR) AC_SUBST(PROTOCOL_VERSION) AC_DEFINE_UNQUOTED([PROTOCOL_VERSION], [$PROTOCOL_VERSION], [mysql client protocol version]) diff --git a/support-files/Makefile.am b/support-files/Makefile.am index a6001e635e6..77eddea3227 100644 --- a/support-files/Makefile.am +++ b/support-files/Makefile.am @@ -119,6 +119,7 @@ SUFFIXES = .sh -e 's!@''SHARED_LIB_VERSION''@!@SHARED_LIB_VERSION@!' \ -e 's!@''MYSQL_BASE_VERSION''@!@MYSQL_BASE_VERSION@!' \ -e 's!@''MYSQL_NO_DASH_VERSION''@!@MYSQL_NO_DASH_VERSION@!' \ + -e 's!@''MYSQL_COPYRIGHT_YEAR''@!@MYSQL_COPYRIGHT_YEAR@!' \ -e 's!@''MYSQL_TCP_PORT''@!@MYSQL_TCP_PORT@!' \ -e 's!@''PERL_DBI_VERSION''@!@PERL_DBI_VERSION@!' \ -e 's!@''PERL_DBD_VERSION''@!@PERL_DBD_VERSION@!' \ diff --git a/support-files/mysql.spec.sh b/support-files/mysql.spec.sh index 7c08fdf4734..9c790675608 100644 --- a/support-files/mysql.spec.sh +++ b/support-files/mysql.spec.sh @@ -41,7 +41,7 @@ %else %define release 0.glibc23 %endif -%define license GPL +%define mysql_license GPL %define mysqld_user mysql %define mysqld_group mysql %define server_suffix -standard @@ -75,7 +75,7 @@ Summary: MySQL: a very fast and reliable SQL database server Group: Applications/Databases Version: @MYSQL_NO_DASH_VERSION@ Release: %{release} -License: Copyright 2000-2008 MySQL AB, 2008 Sun Microsystems, Inc. All rights reserved. Use is subject to license terms. Under %{license} license as shown in the Description field. +License: Copyright 2000-2008 MySQL AB, 2008-@MYSQL_COPYRIGHT_YEAR@ Sun Microsystems, Inc. All rights reserved. Use is subject to license terms. Under %{mysql_license} license as shown in the Description field. Source: http://www.mysql.com/Downloads/MySQL-@MYSQL_BASE_VERSION@/mysql-%{mysql_version}.tar.gz URL: http://www.mysql.com/ Packager: Sun Microsystems, Inc. Product Engineering Team @@ -96,7 +96,7 @@ is intended for mission-critical, heavy-load production systems as well as for embedding into mass-deployed software. MySQL is a trademark of Sun Microsystems, Inc. -Copyright 2000-2008 MySQL AB, 2008 Sun Microsystems, Inc. All rights reserved. +Copyright 2000-2008 MySQL AB, 2008-@MYSQL_COPYRIGHT_YEAR@ Sun Microsystems, Inc. All rights reserved. Use is subject to license terms. This software comes with ABSOLUTELY NO WARRANTY. This is free software, @@ -120,7 +120,7 @@ is intended for mission-critical, heavy-load production systems as well as for embedding into mass-deployed software. MySQL is a trademark of Sun Microsystems, Inc. -Copyright 2000-2008 MySQL AB, 2008 Sun Microsystems, Inc. All rights reserved. +Copyright 2000-2008 MySQL AB, 2008-@MYSQL_COPYRIGHT_YEAR@ Sun Microsystems, Inc. All rights reserved. Use is subject to license terms. This software comes with ABSOLUTELY NO WARRANTY. This is free software, @@ -366,7 +366,7 @@ CFLAGS="$CFLAGS" \ CXXFLAGS="$CXXFLAGS" \ BuildMySQL "\ --with-debug \ - --with-comment=\"MySQL Community Server - Debug (%{license})\"") + --with-comment=\"MySQL Community Server - Debug (%{mysql_license})\"") # We might want to save the config log file if test -n "$MYSQL_DEBUGCONFLOG_DEST" @@ -387,7 +387,7 @@ CFLAGS="$CFLAGS" \ CXXFLAGS="$CXXFLAGS" \ BuildMySQL "\ --with-embedded-server \ - --with-comment=\"MySQL Community Server (%{license})\"") + --with-comment=\"MySQL Community Server (%{mysql_license})\"") # We might want to save the config log file if test -n "$MYSQL_CONFLOG_DEST" then From ff645025e172b61937826b49fb81bc7827475ebd Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 24 Feb 2009 19:09:22 +0100 Subject: [PATCH 133/219] Only specify the current year for the Sun product copyright --- support-files/mysql.spec.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/support-files/mysql.spec.sh b/support-files/mysql.spec.sh index 9c790675608..778b04b30fe 100644 --- a/support-files/mysql.spec.sh +++ b/support-files/mysql.spec.sh @@ -75,7 +75,7 @@ Summary: MySQL: a very fast and reliable SQL database server Group: Applications/Databases Version: @MYSQL_NO_DASH_VERSION@ Release: %{release} -License: Copyright 2000-2008 MySQL AB, 2008-@MYSQL_COPYRIGHT_YEAR@ Sun Microsystems, Inc. All rights reserved. Use is subject to license terms. Under %{mysql_license} license as shown in the Description field. +License: Copyright 2000-2008 MySQL AB, @MYSQL_COPYRIGHT_YEAR@ Sun Microsystems, Inc. All rights reserved. Use is subject to license terms. Under %{mysql_license} license as shown in the Description field. Source: http://www.mysql.com/Downloads/MySQL-@MYSQL_BASE_VERSION@/mysql-%{mysql_version}.tar.gz URL: http://www.mysql.com/ Packager: Sun Microsystems, Inc. Product Engineering Team @@ -96,7 +96,7 @@ is intended for mission-critical, heavy-load production systems as well as for embedding into mass-deployed software. MySQL is a trademark of Sun Microsystems, Inc. -Copyright 2000-2008 MySQL AB, 2008-@MYSQL_COPYRIGHT_YEAR@ Sun Microsystems, Inc. All rights reserved. +Copyright 2000-2008 MySQL AB, @MYSQL_COPYRIGHT_YEAR@ Sun Microsystems, Inc. All rights reserved. Use is subject to license terms. This software comes with ABSOLUTELY NO WARRANTY. This is free software, @@ -120,7 +120,7 @@ is intended for mission-critical, heavy-load production systems as well as for embedding into mass-deployed software. MySQL is a trademark of Sun Microsystems, Inc. -Copyright 2000-2008 MySQL AB, 2008-@MYSQL_COPYRIGHT_YEAR@ Sun Microsystems, Inc. All rights reserved. +Copyright 2000-2008 MySQL AB, @MYSQL_COPYRIGHT_YEAR@ Sun Microsystems, Inc. All rights reserved. Use is subject to license terms. This software comes with ABSOLUTELY NO WARRANTY. This is free software, From 0f6e7f11761cb696103b01f452b5d5afe10bea97 Mon Sep 17 00:00:00 2001 From: Alexey Kopytov Date: Wed, 25 Feb 2009 10:36:11 +0200 Subject: [PATCH 134/219] Fixed a build failure on Ubuntu 8.10 introduced by the patch for bug #15936. On some platforms fenv.h may #undef the min/max macros defined in my_global.h. Fixed by moving the #include directive for fenv.h from mysqld.cc to my_global.h before definitions for min/max. include/my_global.h: Moved #include from mysqld.cc. sql/mysqld.cc: Moved #include to my_global.h. --- include/my_global.h | 3 +++ sql/mysqld.cc | 3 --- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/include/my_global.h b/include/my_global.h index 3f872bfc855..f5a3016bb1e 100644 --- a/include/my_global.h +++ b/include/my_global.h @@ -324,6 +324,9 @@ C_MODE_END #ifdef HAVE_FLOAT_H #include #endif +#ifdef HAVE_FENV_H +#include /* For fesetround() */ +#endif #ifdef HAVE_SYS_TYPES_H #include diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 7856309b095..fcde4e2b626 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -187,9 +187,6 @@ int initgroups(const char *,unsigned int); typedef fp_except fp_except_t; #endif #endif /* __FreeBSD__ && HAVE_IEEEFP_H */ -#ifdef HAVE_FENV_H -#include -#endif #ifdef HAVE_SYS_FPU_H /* for IRIX to use set_fpc_csr() */ #include From e0c6aad83a364d3cc9aaa6b258bdfa31aa699e37 Mon Sep 17 00:00:00 2001 From: Bjorn Munch Date: Wed, 25 Feb 2009 10:32:13 +0100 Subject: [PATCH 135/219] Bug #43172 MTR leaves test files in /tmp after check_socket_path_length finds path too long Faulty logic in cleanup Put test file into tmpdir, cleanup by removing tmpdir --- mysql-test/lib/My/Platform.pm | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/mysql-test/lib/My/Platform.pm b/mysql-test/lib/My/Platform.pm index 3dd5c552b10..69ffdfbb4ce 100644 --- a/mysql-test/lib/My/Platform.pm +++ b/mysql-test/lib/My/Platform.pm @@ -113,8 +113,8 @@ sub check_socket_path_length { # Create a tempfile name with same length as "path" my $tmpdir = tempdir( CLEANUP => 0); - my $len = length($path) - length($tmpdir); - my $testfile = $tmpdir . "x" x ($len > 0 ? $len : 1); + my $len = length($path) - length($tmpdir) - 1; + my $testfile = $tmpdir . "/" . "x" x ($len > 0 ? $len : 1); my $sock; eval { $sock= new IO::Socket::UNIX @@ -126,17 +126,15 @@ sub check_socket_path_length { die "Could not create UNIX domain socket: $!" unless defined $sock; - die "UNIX domain socket patch was truncated" + die "UNIX domain socket path was truncated" unless ($testfile eq $sock->hostpath()); $truncated= 0; # Yes, it worked! }; - #print "check_socket_path_length, failed: ", $@, '\n' if ($@); $sock= undef; # Close socket - unlink($testfile); # Remove the physical file - rmdir($tmpdir); # Remove the tempdir + rmtree($tmpdir); # Remove the tempdir and any socket file created return $truncated; } From 620438fdaef079216609bfcb0a8cb7b58c950e1e Mon Sep 17 00:00:00 2001 From: Georgi Kodinov Date: Wed, 25 Feb 2009 12:19:29 +0200 Subject: [PATCH 136/219] backport the fix for bug #37191 to 5.1-bugteam --- mysql-test/r/view_grant.result | 21 ++++++++++++++ mysql-test/t/view_grant.test | 38 +++++++++++++++++++++++++ sql/sql_view.cc | 52 ++++++++++++++++++++-------------- 3 files changed, 90 insertions(+), 21 deletions(-) diff --git a/mysql-test/r/view_grant.result b/mysql-test/r/view_grant.result index 1821e50e294..3e280e47bee 100644 --- a/mysql-test/r/view_grant.result +++ b/mysql-test/r/view_grant.result @@ -956,6 +956,27 @@ Warnings: Warning 1356 View 'test.v1' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them DROP VIEW v1; DROP TABLE t1; +CREATE USER mysqluser1@localhost; +CREATE DATABASE mysqltest1; +USE mysqltest1; +CREATE TABLE t1 ( a INT ); +CREATE TABLE t2 ( b INT ); +INSERT INTO t1 VALUES (1), (2); +INSERT INTO t2 VALUES (1), (2); +GRANT CREATE VIEW ON mysqltest1.* TO mysqluser1@localhost; +GRANT SELECT ON t1 TO mysqluser1@localhost; +GRANT INSERT ON t2 TO mysqluser1@localhost; +This would lead to failed assertion. +CREATE VIEW v1 AS SELECT a, b FROM t1, t2; +SELECT * FROM v1; +ERROR 42000: SELECT command denied to user 'mysqluser1'@'localhost' for table 'v1' +SELECT b FROM v1; +ERROR 42000: SELECT command denied to user 'mysqluser1'@'localhost' for table 'v1' +DROP TABLE t1, t2; +DROP VIEW v1; +DROP DATABASE mysqltest1; +DROP USER mysqluser1@localhost; +USE test; End of 5.1 tests. CREATE USER mysqluser1@localhost; CREATE DATABASE mysqltest1; diff --git a/mysql-test/t/view_grant.test b/mysql-test/t/view_grant.test index 4e8d97e4444..f3794a6ba73 100644 --- a/mysql-test/t/view_grant.test +++ b/mysql-test/t/view_grant.test @@ -1218,6 +1218,44 @@ SHOW CREATE VIEW v1; DROP VIEW v1; DROP TABLE t1; +# +# Bug#37191: Failed assertion in CREATE VIEW +# +CREATE USER mysqluser1@localhost; +CREATE DATABASE mysqltest1; + +USE mysqltest1; + +CREATE TABLE t1 ( a INT ); +CREATE TABLE t2 ( b INT ); + +INSERT INTO t1 VALUES (1), (2); +INSERT INTO t2 VALUES (1), (2); + +GRANT CREATE VIEW ON mysqltest1.* TO mysqluser1@localhost; + +GRANT SELECT ON t1 TO mysqluser1@localhost; +GRANT INSERT ON t2 TO mysqluser1@localhost; + +--connect (connection1, localhost, mysqluser1, , mysqltest1) + +--echo This would lead to failed assertion. +CREATE VIEW v1 AS SELECT a, b FROM t1, t2; + +--error ER_TABLEACCESS_DENIED_ERROR +SELECT * FROM v1; +--error ER_TABLEACCESS_DENIED_ERROR +SELECT b FROM v1; + +--disconnect connection1 +--connection default + +DROP TABLE t1, t2; +DROP VIEW v1; +DROP DATABASE mysqltest1; +DROP USER mysqluser1@localhost; +USE test; + --echo End of 5.1 tests. # diff --git a/sql/sql_view.cc b/sql/sql_view.cc index be66f7c2d80..b6ea6579d08 100644 --- a/sql/sql_view.cc +++ b/sql/sql_view.cc @@ -564,24 +564,36 @@ bool mysql_create_view(THD *thd, TABLE_LIST *views, fill_effective_table_privileges(thd, &view->grant, view->db, view->table_name); + /* + Make sure that the current user does not have more column-level privileges + on the newly created view than he/she does on the underlying + tables. E.g. it must not be so that the user has UPDATE privileges on a + view column of he/she doesn't have it on the underlying table's + corresponding column. In that case, return an error for CREATE VIEW. + */ { Item *report_item= NULL; + /* + This will hold the intersection of the priviliges on all columns in the + view. + */ uint final_priv= VIEW_ANY_ACL; - - for (sl= select_lex; sl; sl= sl->next_select()) - { - DBUG_ASSERT(view->db); /* Must be set in the parser */ - List_iterator_fast it(sl->item_list); - Item *item; - while ((item= it++)) + + for (sl= select_lex; sl; sl= sl->next_select()) { + DBUG_ASSERT(view->db); /* Must be set in the parser */ + List_iterator_fast it(sl->item_list); + Item *item; + while ((item= it++)) + { Item_field *fld= item->filed_for_view_update(); - uint priv= (get_column_grant(thd, &view->grant, view->db, - view->table_name, item->name) & - VIEW_ANY_ACL); + uint priv= (get_column_grant(thd, &view->grant, view->db, + view->table_name, item->name) & + VIEW_ANY_ACL); if (fld && !fld->field->table->s->tmp_table) - { + { + final_priv&= fld->have_privileges; if (~fld->have_privileges & priv) @@ -589,17 +601,15 @@ bool mysql_create_view(THD *thd, TABLE_LIST *views, } } } - - if (!final_priv) - { - DBUG_ASSERT(report_item); - - my_error(ER_COLUMNACCESS_DENIED_ERROR, MYF(0), - "create view", thd->security_ctx->priv_user, + + if (!final_priv && report_item) + { + my_error(ER_COLUMNACCESS_DENIED_ERROR, MYF(0), + "create view", thd->security_ctx->priv_user, thd->security_ctx->priv_host, report_item->name, - view->table_name); - res= TRUE; - goto err; + view->table_name); + res= TRUE; + goto err; } } #endif From 2bc4ad4f1f0faa191d9b5844677030fbea402db0 Mon Sep 17 00:00:00 2001 From: Sergey Glukhov Date: Wed, 25 Feb 2009 14:20:20 +0400 Subject: [PATCH 137/219] Bug#30305 Create routine in wrong context in SHOW PRIVILEGES Changed context of Create routine to Databases. mysql-test/r/grant.result: result fix mysql-test/r/sp.result: result fix sql/sql_show.cc: Changed context of Create routine to Databases. --- mysql-test/r/grant.result | 2 +- mysql-test/r/sp.result | 4 ++-- sql/sql_show.cc | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/mysql-test/r/grant.result b/mysql-test/r/grant.result index 97945a702d8..7a5b0520f7c 100644 --- a/mysql-test/r/grant.result +++ b/mysql-test/r/grant.result @@ -457,7 +457,7 @@ Privilege Context Comment Alter Tables To alter the table Alter routine Functions,Procedures To alter or drop stored functions/procedures Create Databases,Tables,Indexes To create new databases and tables -Create routine Functions,Procedures To use CREATE FUNCTION/PROCEDURE +Create routine Databases To use CREATE FUNCTION/PROCEDURE Create temporary tables Databases To use CREATE TEMPORARY TABLE Create view Tables To create new views Create user Server Admin To create new users diff --git a/mysql-test/r/sp.result b/mysql-test/r/sp.result index bfa2f51e4fc..84a4166a45d 100644 --- a/mysql-test/r/sp.result +++ b/mysql-test/r/sp.result @@ -2475,7 +2475,7 @@ Privilege Context Comment Alter Tables To alter the table Alter routine Functions,Procedures To alter or drop stored functions/procedures Create Databases,Tables,Indexes To create new databases and tables -Create routine Functions,Procedures To use CREATE FUNCTION/PROCEDURE +Create routine Databases To use CREATE FUNCTION/PROCEDURE Create temporary tables Databases To use CREATE TEMPORARY TABLE Create view Tables To create new views Create user Server Admin To create new users @@ -2527,7 +2527,7 @@ Privilege Context Comment Alter Tables To alter the table Alter routine Functions,Procedures To alter or drop stored functions/procedures Create Databases,Tables,Indexes To create new databases and tables -Create routine Functions,Procedures To use CREATE FUNCTION/PROCEDURE +Create routine Databases To use CREATE FUNCTION/PROCEDURE Create temporary tables Databases To use CREATE TEMPORARY TABLE Create view Tables To create new views Create user Server Admin To create new users diff --git a/sql/sql_show.cc b/sql/sql_show.cc index 19155eec06b..50bbdeb2771 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -106,7 +106,7 @@ static struct show_privileges_st sys_privileges[]= {"Alter", "Tables", "To alter the table"}, {"Alter routine", "Functions,Procedures", "To alter or drop stored functions/procedures"}, {"Create", "Databases,Tables,Indexes", "To create new databases and tables"}, - {"Create routine","Functions,Procedures","To use CREATE FUNCTION/PROCEDURE"}, + {"Create routine","Databases","To use CREATE FUNCTION/PROCEDURE"}, {"Create temporary tables","Databases","To use CREATE TEMPORARY TABLE"}, {"Create view", "Tables", "To create new views"}, {"Create user", "Server Admin", "To create new users"}, From b63c6f566632a8da78f57ca93d405bd1782876ba Mon Sep 17 00:00:00 2001 From: Bjorn Munch Date: Wed, 25 Feb 2009 11:29:50 +0100 Subject: [PATCH 138/219] fixing bzr tree name --- .bzr-mysql/default.conf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.bzr-mysql/default.conf b/.bzr-mysql/default.conf index f044f8e62da..63057f42ac6 100644 --- a/.bzr-mysql/default.conf +++ b/.bzr-mysql/default.conf @@ -1,4 +1,4 @@ [MYSQL] post_commit_to = "commits@lists.mysql.com" post_push_to = "commits@lists.mysql.com" -tree_name = "mysql-5.1" +tree_name = "mysql-5.1-mtr" From 5a6fa28226530cadb3ec571d1d76f848dd32d647 Mon Sep 17 00:00:00 2001 From: "Bernt M. Johnsen" Date: Wed, 25 Feb 2009 11:37:30 +0100 Subject: [PATCH 139/219] Prepare for push of BUG#43111 --- mysql-test/r/ps.result | 2 +- mysql-test/t/ps.test | 9 ++++++++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/mysql-test/r/ps.result b/mysql-test/r/ps.result index 09deaf2f322..d3fbbf0d538 100644 --- a/mysql-test/r/ps.result +++ b/mysql-test/r/ps.result @@ -235,7 +235,7 @@ execute stmt1; prepare stmt1 from "insert into t1 select i from t1"; execute stmt1; execute stmt1; -prepare stmt1 from "select * from t1 into outfile 'f1.txt'"; +prepare stmt1 from "select * from t1 into outfile '/tmp/f1.txt'"; execute stmt1; deallocate prepare stmt1; drop table t1; diff --git a/mysql-test/t/ps.test b/mysql-test/t/ps.test index 6c3f98f6a1a..d9e593fd76f 100644 --- a/mysql-test/t/ps.test +++ b/mysql-test/t/ps.test @@ -228,6 +228,10 @@ drop table t1; # statements or are correctly created and deleted on each execute # +--let $outfile=$MYSQLTEST_VARDIR/tmp/f1.txt +--error 0,1 +--remove_file $outfile + prepare stmt1 from "select 1 into @var"; execute stmt1; execute stmt1; @@ -238,11 +242,14 @@ execute stmt1; prepare stmt1 from "insert into t1 select i from t1"; execute stmt1; execute stmt1; -prepare stmt1 from "select * from t1 into outfile 'f1.txt'"; +--replace_result $MYSQLTEST_VARDIR +eval prepare stmt1 from "select * from t1 into outfile '$outfile'"; execute stmt1; deallocate prepare stmt1; drop table t1; +--remove_file $outfile + # # BUG#5242 "Prepared statement names are case sensitive" # From da3c4375cfe9530c04525ff6694e5f59f354c144 Mon Sep 17 00:00:00 2001 From: Davi Arnaut Date: Wed, 25 Feb 2009 11:42:58 +0100 Subject: [PATCH 140/219] Clean up test case to not leave open connections. mysql-test/include/handler.inc: Disconnect open connections once they are not being used. --- mysql-test/include/handler.inc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/mysql-test/include/handler.inc b/mysql-test/include/handler.inc index 04f4cac831d..4eb9e413822 100644 --- a/mysql-test/include/handler.inc +++ b/mysql-test/include/handler.inc @@ -479,6 +479,7 @@ handler t1 open; --echo --> client 1 connection default; drop table t1; +disconnect con2; # # Bug#30632 HANDLER read failure causes hang @@ -717,4 +718,5 @@ handler t1 close; connection con1; --reap drop table t1; +disconnect con1; connection default; From 5d2fc5335411bdd05a08a9b062d3441d4308dcaa Mon Sep 17 00:00:00 2001 From: Sergey Glukhov Date: Wed, 25 Feb 2009 15:44:50 +0400 Subject: [PATCH 141/219] Bug#40345 MySQLDump prefixes view name with database name when view references other db print compact view name if the view belongs to the current database mysql-test/r/information_schema_db.result: result fix mysql-test/r/mysqldump.result: result fix mysql-test/r/view_grant.result: result fix sql/sql_show.cc: print compact view name if the view belongs to the current database --- mysql-test/r/information_schema_db.result | 2 +- mysql-test/r/mysqldump.result | 2 +- mysql-test/r/view_grant.result | 4 ++-- sql/sql_show.cc | 18 +++++++++++------- 4 files changed, 15 insertions(+), 11 deletions(-) diff --git a/mysql-test/r/information_schema_db.result b/mysql-test/r/information_schema_db.result index b9c3358f47e..67c9921e1ca 100644 --- a/mysql-test/r/information_schema_db.result +++ b/mysql-test/r/information_schema_db.result @@ -188,7 +188,7 @@ Field Type Null Key Default Extra f1 char(4) YES NULL show create view v2; View Create View -v2 CREATE ALGORITHM=UNDEFINED DEFINER=`testdb_2`@`localhost` SQL SECURITY DEFINER VIEW `test`.`v2` AS select `v1`.`f1` AS `f1` from `testdb_1`.`v1` +v2 CREATE ALGORITHM=UNDEFINED DEFINER=`testdb_2`@`localhost` SQL SECURITY DEFINER VIEW `v2` AS select `v1`.`f1` AS `f1` from `testdb_1`.`v1` show create view testdb_1.v1; ERROR 42000: SHOW VIEW command denied to user 'testdb_2'@'localhost' for table 'v1' select table_name from information_schema.columns a diff --git a/mysql-test/r/mysqldump.result b/mysql-test/r/mysqldump.result index c612f6c5073..49430a5c62d 100644 --- a/mysql-test/r/mysqldump.result +++ b/mysql-test/r/mysqldump.result @@ -3246,7 +3246,7 @@ USE `mysqldump_views`; /*!50001 DROP TABLE `nasishnasifu`*/; /*!50001 CREATE ALGORITHM=UNDEFINED */ /*!50013 DEFINER=`root`@`localhost` SQL SECURITY DEFINER */ -/*!50001 VIEW `mysqldump_views`.`nasishnasifu` AS select `mysqldump_tables`.`basetable`.`id` AS `id` from `mysqldump_tables`.`basetable` */; +/*!50001 VIEW `nasishnasifu` AS select `mysqldump_tables`.`basetable`.`id` AS `id` from `mysqldump_tables`.`basetable` */; drop view nasishnasifu; drop database mysqldump_views; drop table mysqldump_tables.basetable; diff --git a/mysql-test/r/view_grant.result b/mysql-test/r/view_grant.result index 53ad8642ba4..2f8462045ca 100644 --- a/mysql-test/r/view_grant.result +++ b/mysql-test/r/view_grant.result @@ -26,7 +26,7 @@ create view v2 as select * from mysqltest.t2; ERROR 42000: ANY command denied to user 'mysqltest_1'@'localhost' for table 't2' show create view v1; View Create View -v1 CREATE ALGORITHM=UNDEFINED DEFINER=`mysqltest_1`@`localhost` SQL SECURITY DEFINER VIEW `test`.`v1` AS select `mysqltest`.`t1`.`a` AS `a`,`mysqltest`.`t1`.`b` AS `b` from `mysqltest`.`t1` +v1 CREATE ALGORITHM=UNDEFINED DEFINER=`mysqltest_1`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select `mysqltest`.`t1`.`a` AS `a`,`mysqltest`.`t1`.`b` AS `b` from `mysqltest`.`t1` grant create view,drop,select on test.* to mysqltest_1@localhost; use test; alter view v1 as select * from mysqltest.t1; @@ -307,7 +307,7 @@ grant create view,select on test.* to mysqltest_1@localhost; create view v1 as select * from mysqltest.t1; show create view v1; View Create View -v1 CREATE ALGORITHM=UNDEFINED DEFINER=`mysqltest_1`@`localhost` SQL SECURITY DEFINER VIEW `test`.`v1` AS select `mysqltest`.`t1`.`a` AS `a`,`mysqltest`.`t1`.`b` AS `b` from `mysqltest`.`t1` +v1 CREATE ALGORITHM=UNDEFINED DEFINER=`mysqltest_1`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select `mysqltest`.`t1`.`a` AS `a`,`mysqltest`.`t1`.`b` AS `b` from `mysqltest`.`t1` revoke select on mysqltest.t1 from mysqltest_1@localhost; select * from v1; ERROR HY000: View 'test.v1' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them diff --git a/sql/sql_show.cc b/sql/sql_show.cc index 50bbdeb2771..a3ccf770a3c 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -1232,21 +1232,25 @@ void append_definer(THD *thd, String *buffer, const LEX_STRING *definer_user, static int view_store_create_info(THD *thd, TABLE_LIST *table, String *buff) { + my_bool compact_view_name= TRUE; my_bool foreign_db_mode= (thd->variables.sql_mode & (MODE_POSTGRESQL | MODE_ORACLE | MODE_MSSQL | MODE_DB2 | MODE_MAXDB | MODE_ANSI)) != 0; - /* - Compact output format for view can be used - - if user has db of this view as current db - - if this view only references table inside it's own db - */ + if (!thd->db || strcmp(thd->db, table->view_db.str)) - table->compact_view_format= FALSE; + /* + print compact view name if the view belongs to the current database + */ + compact_view_name= table->compact_view_format= FALSE; else { + /* + Compact output format for view body can be used + if this view only references table inside it's own db + */ TABLE_LIST *tbl; table->compact_view_format= TRUE; for (tbl= thd->lex->query_tables; @@ -1267,7 +1271,7 @@ view_store_create_info(THD *thd, TABLE_LIST *table, String *buff) view_store_options(thd, table, buff); } buff->append(STRING_WITH_LEN("VIEW ")); - if (!table->compact_view_format) + if (!compact_view_name) { append_identifier(thd, buff, table->view_db.str, table->view_db.length); buff->append('.'); From fff57e9dfc851b80a99a6f83c0138b0010c750f2 Mon Sep 17 00:00:00 2001 From: Daniel Fischer Date: Wed, 25 Feb 2009 15:00:17 +0100 Subject: [PATCH 142/219] address review comments --- mysql-test/collections/README.experimental | 2 +- mysql-test/lib/mtr_report.pm | 16 ++++++--- mysql-test/mysql-test-run.pl | 38 +++++++++++++--------- 3 files changed, 34 insertions(+), 22 deletions(-) diff --git a/mysql-test/collections/README.experimental b/mysql-test/collections/README.experimental index d06e55f1246..9eee2394423 100644 --- a/mysql-test/collections/README.experimental +++ b/mysql-test/collections/README.experimental @@ -11,7 +11,7 @@ The syntax is as follows: 2) Empty lines and lines starting with a hash (#) are ignored. -3) If any other line contains a black followed by a hash (#), the hash +3) If any other line contains a blank followed by a hash (#), the hash and any subsequent characters are ignored. 4) The full test case name including the suite and execution mode diff --git a/mysql-test/lib/mtr_report.pm b/mysql-test/lib/mtr_report.pm index d1cae6324cb..73401dc4b33 100644 --- a/mysql-test/lib/mtr_report.pm +++ b/mysql-test/lib/mtr_report.pm @@ -109,10 +109,10 @@ sub mtr_report_test ($) { my ($tinfo)= @_; my $test_name = _mtr_report_test_name($tinfo); - my $comment= $tinfo->{'comment'}; - my $logfile= $tinfo->{'logfile'}; - my $warnings= $tinfo->{'warnings'}; - my $result= $tinfo->{'result'}; + my $comment= $tinfo->{'comment'}; + my $logfile= $tinfo->{'logfile'}; + my $warnings= $tinfo->{'warnings'}; + my $result= $tinfo->{'result'}; if ($result eq 'MTR_RES_FAILED'){ @@ -123,14 +123,20 @@ sub mtr_report_test ($) { { # Find out if this test case is an experimental one, so we can treat # the failure as an expected failure instead of a regression. - for my $exp ( @$::opt_experimental ) { + for my $exp ( @$::experimental_test_cases ) { if ( $exp ne $test_name ) { + # if the expression is not the name of this test case, but has + # an asterisk at the end, determine if the characters up to + # but excluding the asterisk are the same if ( $exp ne "" && substr($exp, -1, 1) eq "*" ) { $exp = substr($exp, 0, length($exp) - 1); if ( substr($test_name, 0, length($exp)) ne $exp ) { + # no match, try next entry next; } + # if yes, fall through to set the exp-fail status } else { + # no match, try next entry next; } } diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl index 8e772279aa3..89a6d89687a 100755 --- a/mysql-test/mysql-test-run.pl +++ b/mysql-test/mysql-test-run.pl @@ -170,6 +170,7 @@ my $config; # The currently running config my $current_config_name; # The currently running config file template our $opt_experimental; +our $experimental_test_cases; my $baseport; my $opt_build_thread= $ENV{'MTR_BUILD_THREAD'} || "auto"; @@ -963,24 +964,29 @@ sub command_line_setup { if ( $opt_experimental ) { - if ( open(FILE, "<", $opt_experimental) ) { - mtr_report("Using experimental file: $opt_experimental"); - $opt_experimental = []; - while() { - chomp; - s/( +|^)#.*$//; - s/^ +//; - s/ +$//; - if ( $_ eq "" ) { - next; - } - print " - $_\n"; - push @$opt_experimental, $_; + # read the list of experimental test cases from the file specified on + # the command line + open(FILE, "<", $opt_experimental) or mtr_error("Can't read experimental file: $opt_experimental"); + mtr_report("Using experimental file: $opt_experimental"); + $experimental_test_cases = []; + while() { + chomp; + # remove comments (# foo) at the beginning of the line, or after a + # blank at the end of the line + s/( +|^)#.*$//; + # remove whitespace + s/^ +//; + s/ +$//; + # if nothing left, don't need to remember this line + if ( $_ eq "" ) { + next; } - close FILE; - } else { - mtr_error("Can't read experimental file: $opt_experimental"); + # remember what is left as the name of another test case that should be + # treated as experimental + print " - $_\n"; + push @$experimental_test_cases, $_; } + close FILE; } foreach my $arg ( @ARGV ) From 00ac598a44fb38b888ccec14befc38348ddeae53 Mon Sep 17 00:00:00 2001 From: "Bernt M. Johnsen" Date: Wed, 25 Feb 2009 16:53:49 +0100 Subject: [PATCH 143/219] Prepared for push (BUG#43110) --- mysql-test/t/ps.test | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/mysql-test/t/ps.test b/mysql-test/t/ps.test index 6b20fd14394..db5994d434b 100644 --- a/mysql-test/t/ps.test +++ b/mysql-test/t/ps.test @@ -946,8 +946,13 @@ set global max_prepared_stmt_count=3; select @@max_prepared_stmt_count; show status like 'prepared_stmt_count'; prepare stmt from "select 1"; + connect (con1,localhost,root,,); + +# Switch to connection con1 connection con1; +let $con1_id=`SELECT CONNECTION_ID()`; + prepare stmt from "select 2"; prepare stmt1 from "select 3"; --error ER_MAX_PREPARED_STMT_COUNT_REACHED @@ -957,18 +962,17 @@ connection default; prepare stmt2 from "select 4"; select @@max_prepared_stmt_count; show status like 'prepared_stmt_count'; + +# Disconnect connection con1 and switch to default connection disconnect con1; connection default; -# Wait for the connection to die: deal with a possible race + +# Wait for the connection con1 to die +let $wait_condition=SELECT COUNT(*)=0 FROM information_schema.processlist WHERE id=$con1_id; +--source include/wait_condition.inc + deallocate prepare stmt; -let $query= select variable_value from information_schema.global_status - where variable_name = 'prepared_stmt_count'; -let $count= `$query`; -if ($count) -{ ---sleep 1 - let $count= `$query`; -} + select @@max_prepared_stmt_count; show status like 'prepared_stmt_count'; # From 1a11c2236fa096b8f9618cb4e5ffbf3d5add2787 Mon Sep 17 00:00:00 2001 From: Vladislav Vaintroub Date: Wed, 25 Feb 2009 16:57:49 +0100 Subject: [PATCH 144/219] Bug#43082: mysqld 32 bit cannot use big buffers due to 2GB usermode address space limit. Fix: use /LARGEADDRESSAWARE link option when linking 32 bit executables --- CMakeLists.txt | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index ae069498da1..f66453ef492 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -114,7 +114,13 @@ IF(MSVC) STRING(REPLACE "/EHsc" "" CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS}) STRING(REPLACE "/EHsc" "" CMAKE_CXX_FLAGS_INIT ${CMAKE_CXX_FLAGS_INIT}) STRING(REPLACE "/EHsc" "" CMAKE_CXX_FLAGS_DEBUG_INIT ${CMAKE_CXX_FLAGS_DEBUG_INIT}) - + + # Mark 32 bit executables large address aware so they can + # use > 2GB address space + IF(CMAKE_SIZEOF_VOID_P MATCHES 4) + SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /LARGEADDRESSAWARE") + ENDIF(CMAKE_SIZEOF_VOID_P MATCHES 4) + # Disable automatic manifest generation. STRING(REPLACE "/MANIFEST" "/MANIFEST:NO" CMAKE_EXE_LINKER_FLAGS ${CMAKE_EXE_LINKER_FLAGS}) From c9e1884cd6e70d89f0a0c2bce1b80f84b913f59a Mon Sep 17 00:00:00 2001 From: Ramil Kalimullin Date: Thu, 26 Feb 2009 12:34:15 +0400 Subject: [PATCH 145/219] Fix for bug#19829:make test Failed in mysql_client_test *with --with-charset=utf8* Problem: wrong LONG TEXT field length is sent to a client when multibyte server character set used. Fix: always limit field length sent to a client to 2^32, as we store it in 4 byte slot. Note: mysql_client_test changed accordingly. sql/protocol.cc: Fix for bug#19829:make test Failed in mysql_client_test *with --with-charset=utf8* - limit field length sent to client to UINT_MAX32 as it may exceeds 32 bit slot for LONG TEXT fields if thd_charset->mbmaxlen > 1. tests/mysql_client_test.c: Fix for bug#19829:make test Failed in mysql_client_test *with --with-charset=utf8* - checking field members have in mind that field length is limited to UINT_MAX32. --- sql/protocol.cc | 22 ++++++++++++++++------ tests/mysql_client_test.c | 15 +++++++++------ 2 files changed, 25 insertions(+), 12 deletions(-) diff --git a/sql/protocol.cc b/sql/protocol.cc index ff58d96f59b..2309bac88a9 100644 --- a/sql/protocol.cc +++ b/sql/protocol.cc @@ -616,7 +616,8 @@ bool Protocol::send_fields(List *list, uint flags) else { /* With conversion */ - uint max_char_len; + ulonglong max_length; + uint32 field_length; int2store(pos, thd_charset->number); /* For TEXT/BLOB columns, field_length describes the maximum data @@ -627,12 +628,21 @@ bool Protocol::send_fields(List *list, uint flags) char_count * mbmaxlen, where character count is taken from the definition of the column. In other words, the maximum number of characters here is limited by the column definition. + + When one has a LONG TEXT column with a single-byte + character set, and the connection character set is multi-byte, the + client may get fields longer than UINT_MAX32, due to + -> conversion. + In that case column max length does not fit into the 4 bytes + reserved for it in the protocol. */ - max_char_len= (field.type >= (int) MYSQL_TYPE_TINY_BLOB && - field.type <= (int) MYSQL_TYPE_BLOB) ? - field.length / item->collation.collation->mbminlen : - field.length / item->collation.collation->mbmaxlen; - int4store(pos+2, max_char_len * thd_charset->mbmaxlen); + max_length= (field.type >= MYSQL_TYPE_TINY_BLOB && + field.type <= MYSQL_TYPE_BLOB) ? + field.length / item->collation.collation->mbminlen : + field.length / item->collation.collation->mbmaxlen; + max_length*= thd_charset->mbmaxlen; + field_length= (max_length > UINT_MAX32) ? UINT_MAX32 : max_length; + int4store(pos + 2, field_length); } pos[6]= field.type; int2store(pos+7,field.flags); diff --git a/tests/mysql_client_test.c b/tests/mysql_client_test.c index f848e93a5c6..7df84c600c9 100644 --- a/tests/mysql_client_test.c +++ b/tests/mysql_client_test.c @@ -714,6 +714,7 @@ static void do_verify_prepare_field(MYSQL_RES *result, { MYSQL_FIELD *field; CHARSET_INFO *cs; + ulonglong expected_field_length; if (!(field= mysql_fetch_field_direct(result, no))) { @@ -722,6 +723,8 @@ static void do_verify_prepare_field(MYSQL_RES *result, } cs= get_charset(field->charsetnr, 0); DIE_UNLESS(cs); + if ((expected_field_length= length * cs->mbmaxlen) > UINT_MAX32) + expected_field_length= UINT_MAX32; if (!opt_silent) { fprintf(stdout, "\n field[%d]:", no); @@ -736,8 +739,8 @@ static void do_verify_prepare_field(MYSQL_RES *result, fprintf(stdout, "\n org_table:`%s`\t(expected: `%s`)", field->org_table, org_table); fprintf(stdout, "\n database :`%s`\t(expected: `%s`)", field->db, db); - fprintf(stdout, "\n length :`%lu`\t(expected: `%lu`)", - field->length, length * cs->mbmaxlen); + fprintf(stdout, "\n length :`%lu`\t(expected: `%llu`)", + field->length, expected_field_length); fprintf(stdout, "\n maxlength:`%ld`", field->max_length); fprintf(stdout, "\n charsetnr:`%d`", field->charsetnr); fprintf(stdout, "\n default :`%s`\t(expected: `%s`)", @@ -773,11 +776,11 @@ static void do_verify_prepare_field(MYSQL_RES *result, as utf8. Field length is calculated as number of characters * maximum number of bytes a character can occupy. */ - if (length && field->length != length * cs->mbmaxlen) + if (length && (field->length != expected_field_length)) { - fprintf(stderr, "Expected field length: %d, got length: %d\n", - (int) (length * cs->mbmaxlen), (int) field->length); - DIE_UNLESS(field->length == length * cs->mbmaxlen); + fprintf(stderr, "Expected field length: %llu, got length: %lu\n", + expected_field_length, field->length); + DIE_UNLESS(field->length == expected_field_length); } if (def) DIE_UNLESS(strcmp(field->def, def) == 0); From 6877425f2f41717a329d757a5f98c57b4e0c1eb5 Mon Sep 17 00:00:00 2001 From: Patrick Crews Date: Thu, 26 Feb 2009 10:57:33 +0200 Subject: [PATCH 146/219] Bug#41893: main.variables mysql-test fails if new variable like '%alloc%' is added. Started fix in 5.0 as the same issue is here. Revising queries used given what appears to be the scope of this test to only select the manipulated variables. Added tests for values that are / are not multiples of 1024 to test rounding / constraints. This behavior is not currently documented (docs bug has been opened) --- mysql-test/r/variables.result | 46 ++++++++++++++++++++++++++++++----- mysql-test/t/variables.test | 38 +++++++++++++++++++++++++---- 2 files changed, 73 insertions(+), 11 deletions(-) diff --git a/mysql-test/r/variables.result b/mysql-test/r/variables.result index 376a8ffa38e..04ccf3d688c 100644 --- a/mysql-test/r/variables.result +++ b/mysql-test/r/variables.result @@ -236,32 +236,66 @@ set @@rand_seed1=10000000,@@rand_seed2=1000000; select ROUND(RAND(),5); ROUND(RAND(),5) 0.02887 -show variables like '%alloc%'; + +==+ Testing %alloc% system variables +== +==+ NOTE: These values *must* be a multiple of 1024 +== +==+ Other values will be rounded down to nearest multiple +== + +==+ Show initial values +== +SHOW VARIABLES WHERE variable_name IN ('range_alloc_block_size', +'query_alloc_block_size', 'query_prealloc_size', +'transaction_alloc_block_size', 'transaction_prealloc_size'); Variable_name Value query_alloc_block_size 8192 query_prealloc_size 8192 range_alloc_block_size 4096 transaction_alloc_block_size 8192 transaction_prealloc_size 4096 -set @@range_alloc_block_size=1024*16; +==+ Manipulate variable values += +Testing values that are multiples of 1024 +set @@range_alloc_block_size=1024*15+1024; +set @@query_alloc_block_size=1024*15+1024*2; +set @@query_prealloc_size=1024*18-1024; +set @@transaction_alloc_block_size=1024*21-1024*1; +set @@transaction_prealloc_size=1024*21-2048; +==+ Check manipulated values ==+ +SHOW VARIABLES WHERE variable_name IN ('range_alloc_block_size', +'query_alloc_block_size', 'query_prealloc_size', +'transaction_alloc_block_size', 'transaction_prealloc_size'); +Variable_name Value +query_alloc_block_size 17408 +query_prealloc_size 17408 +range_alloc_block_size 16384 +transaction_alloc_block_size 20480 +transaction_prealloc_size 19456 +==+ Manipulate variable values +== +Testing values that are not 1024 multiples +set @@range_alloc_block_size=1024*16+1023; set @@query_alloc_block_size=1024*17+2; -set @@query_prealloc_size=1024*18; +set @@query_prealloc_size=1024*18-1023; set @@transaction_alloc_block_size=1024*20-1; set @@transaction_prealloc_size=1024*21-1; select @@query_alloc_block_size; @@query_alloc_block_size 17408 -show variables like '%alloc%'; +==+ Check manipulated values ==+ +SHOW VARIABLES WHERE variable_name IN ('range_alloc_block_size', +'query_alloc_block_size', 'query_prealloc_size', +'transaction_alloc_block_size', 'transaction_prealloc_size'); Variable_name Value query_alloc_block_size 17408 -query_prealloc_size 18432 +query_prealloc_size 17408 range_alloc_block_size 16384 transaction_alloc_block_size 19456 transaction_prealloc_size 20480 +==+ Set values back to the default values +== set @@range_alloc_block_size=default; set @@query_alloc_block_size=default, @@query_prealloc_size=default; set transaction_alloc_block_size=default, @@transaction_prealloc_size=default; -show variables like '%alloc%'; +==+ Check the values not that they are reset +== +SHOW VARIABLES WHERE variable_name IN ('range_alloc_block_size', +'query_alloc_block_size', 'query_prealloc_size', +'transaction_alloc_block_size', 'transaction_prealloc_size'); Variable_name Value query_alloc_block_size 8192 query_prealloc_size 8192 diff --git a/mysql-test/t/variables.test b/mysql-test/t/variables.test index 60254ad9a1d..173be9d87c6 100644 --- a/mysql-test/t/variables.test +++ b/mysql-test/t/variables.test @@ -150,18 +150,46 @@ select @@timestamp>0; set @@rand_seed1=10000000,@@rand_seed2=1000000; select ROUND(RAND(),5); -show variables like '%alloc%'; -set @@range_alloc_block_size=1024*16; +--echo +--echo ==+ Testing %alloc% system variables +== +--echo ==+ NOTE: These values *must* be a multiple of 1024 +== +--echo ==+ Other values will be rounded down to nearest multiple +== +--echo +--echo ==+ Show initial values +== +SHOW VARIABLES WHERE variable_name IN ('range_alloc_block_size', +'query_alloc_block_size', 'query_prealloc_size', +'transaction_alloc_block_size', 'transaction_prealloc_size'); +--echo ==+ Manipulate variable values += +--echo Testing values that are multiples of 1024 +set @@range_alloc_block_size=1024*15+1024; +set @@query_alloc_block_size=1024*15+1024*2; +set @@query_prealloc_size=1024*18-1024; +set @@transaction_alloc_block_size=1024*21-1024*1; +set @@transaction_prealloc_size=1024*21-2048; +--echo ==+ Check manipulated values ==+ +SHOW VARIABLES WHERE variable_name IN ('range_alloc_block_size', +'query_alloc_block_size', 'query_prealloc_size', +'transaction_alloc_block_size', 'transaction_prealloc_size'); +--echo ==+ Manipulate variable values +== +--echo Testing values that are not 1024 multiples +set @@range_alloc_block_size=1024*16+1023; set @@query_alloc_block_size=1024*17+2; -set @@query_prealloc_size=1024*18; +set @@query_prealloc_size=1024*18-1023; set @@transaction_alloc_block_size=1024*20-1; set @@transaction_prealloc_size=1024*21-1; select @@query_alloc_block_size; -show variables like '%alloc%'; +--echo ==+ Check manipulated values ==+ +SHOW VARIABLES WHERE variable_name IN ('range_alloc_block_size', +'query_alloc_block_size', 'query_prealloc_size', +'transaction_alloc_block_size', 'transaction_prealloc_size'); +--echo ==+ Set values back to the default values +== set @@range_alloc_block_size=default; set @@query_alloc_block_size=default, @@query_prealloc_size=default; set transaction_alloc_block_size=default, @@transaction_prealloc_size=default; -show variables like '%alloc%'; +--echo ==+ Check the values not that they are reset +== +SHOW VARIABLES WHERE variable_name IN ('range_alloc_block_size', +'query_alloc_block_size', 'query_prealloc_size', +'transaction_alloc_block_size', 'transaction_prealloc_size'); # # Bug #10904 Illegal mix of collations between From a7fe00afb5442800f54e50636c7ee829c8194d60 Mon Sep 17 00:00:00 2001 From: Magnus Svensson Date: Thu, 26 Feb 2009 15:01:57 +0100 Subject: [PATCH 147/219] Bug#43215 6 error codes changed from 5.1 to 6.0 sql/share/errmsg.txt: - Reserve released error codes in 5.1 --- sql/share/errmsg.txt | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/sql/share/errmsg.txt b/sql/share/errmsg.txt index 5dc75c340ea..23231eefcc2 100644 --- a/sql/share/errmsg.txt +++ b/sql/share/errmsg.txt @@ -6154,3 +6154,18 @@ WARN_PLUGIN_BUSY ER_VARIABLE_IS_READONLY eng "%s variable '%s' is read-only. Use SET %s to assign the value" + +ER_WARN_ENGINE_TRANSACTION_ROLLBACK + eng "Storage engine %s does not support rollback for this statement. Transaction rolled back and must be restarted" + +ER_SLAVE_HEARTBEAT_FAILURE + eng "Unexpected master's heartbeat data: %s" +ER_SLAVE_HEARTBEAT_VALUE_OUT_OF_RANGE + eng "The requested value for the heartbeat period %s %s" + +ER_NDB_REPLICATION_SCHEMA_ERROR + eng "Bad schema for mysql.ndb_replication table. Message: %-.64s" +ER_CONFLICT_FN_PARSE_ERROR + eng "Error in parsing conflict function. Message: %-.64s" +ER_EXCEPTIONS_WRITE_ERROR + eng "Write to exceptions table failed. Message: %-.128s"" From afdf8a447f538a20f61fc4d7cea26975da53e973 Mon Sep 17 00:00:00 2001 From: Patrick Crews Date: Thu, 26 Feb 2009 18:00:47 +0200 Subject: [PATCH 148/219] Bug#41893 - main.variables mysql-test fails if new variable like '%alloc%' is added. Fixed a typo in the bug fix patch. --- mysql-test/t/variables.test | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mysql-test/t/variables.test b/mysql-test/t/variables.test index 173be9d87c6..424776dfda4 100644 --- a/mysql-test/t/variables.test +++ b/mysql-test/t/variables.test @@ -186,7 +186,7 @@ SHOW VARIABLES WHERE variable_name IN ('range_alloc_block_size', set @@range_alloc_block_size=default; set @@query_alloc_block_size=default, @@query_prealloc_size=default; set transaction_alloc_block_size=default, @@transaction_prealloc_size=default; ---echo ==+ Check the values not that they are reset +== +--echo ==+ Check the values now that they are reset +== SHOW VARIABLES WHERE variable_name IN ('range_alloc_block_size', 'query_alloc_block_size', 'query_prealloc_size', 'transaction_alloc_block_size', 'transaction_prealloc_size'); From a9d707037ab527564bb84885e0af69a2bb793219 Mon Sep 17 00:00:00 2001 From: Georgi Kodinov Date: Thu, 26 Feb 2009 19:00:44 +0200 Subject: [PATCH 149/219] Bug #41354: Access control is bypassed when all columns of a view are selected by * wildcard Backported a part of the fix for 36086 to 5.0 mysql-test/r/view_grant.result: Bug #41354: test case mysql-test/t/view_grant.test: Bug #41354: test case sql/sql_acl.cc: Bug #41354: return table error when no access and * sql/sql_base.cc: Bug #41354: backported the check in bug 36086 to 5.0 --- mysql-test/r/view_grant.result | 26 ++++++++++++++++++++++ mysql-test/t/view_grant.test | 40 ++++++++++++++++++++++++++++++++++ sql/sql_acl.cc | 28 +++++++++++++++++++----- sql/sql_base.cc | 2 +- 4 files changed, 89 insertions(+), 7 deletions(-) diff --git a/mysql-test/r/view_grant.result b/mysql-test/r/view_grant.result index 2f8462045ca..1df8ed335a7 100644 --- a/mysql-test/r/view_grant.result +++ b/mysql-test/r/view_grant.result @@ -919,4 +919,30 @@ c4 DROP DATABASE mysqltest1; DROP DATABASE mysqltest2; DROP USER mysqltest_u1@localhost; +CREATE DATABASE db1; +USE db1; +CREATE TABLE t1(f1 INT, f2 INT); +CREATE VIEW v1 AS SELECT f1, f2 FROM t1; +GRANT SELECT (f1) ON t1 TO foo; +GRANT SELECT (f1) ON v1 TO foo; +USE db1; +SELECT f1 FROM t1; +f1 +SELECT f2 FROM t1; +ERROR 42000: SELECT command denied to user 'foo'@'localhost' for column 'f2' in table 't1' +SELECT * FROM t1; +ERROR 42000: SELECT command denied to user 'foo'@'localhost' for table 't1' +SELECT f1 FROM v1; +f1 +SELECT f2 FROM v1; +ERROR 42000: SELECT command denied to user 'foo'@'localhost' for column 'f2' in table 'v1' +SELECT * FROM v1; +ERROR 42000: SELECT command denied to user 'foo'@'localhost' for table 'v1' +USE test; +REVOKE SELECT (f1) ON db1.t1 FROM foo; +REVOKE SELECT (f1) ON db1.v1 FROM foo; +DROP USER foo; +DROP VIEW db1.v1; +DROP TABLE db1.t1; +DROP DATABASE db1; End of 5.0 tests. diff --git a/mysql-test/t/view_grant.test b/mysql-test/t/view_grant.test index be9daacec4f..c8b31f711b5 100644 --- a/mysql-test/t/view_grant.test +++ b/mysql-test/t/view_grant.test @@ -1185,4 +1185,44 @@ DROP DATABASE mysqltest1; DROP DATABASE mysqltest2; DROP USER mysqltest_u1@localhost; + +# +# Bug #41354: Access control is bypassed when all columns of a view are +# selected by * wildcard + +CREATE DATABASE db1; +USE db1; +CREATE TABLE t1(f1 INT, f2 INT); +CREATE VIEW v1 AS SELECT f1, f2 FROM t1; + +GRANT SELECT (f1) ON t1 TO foo; +GRANT SELECT (f1) ON v1 TO foo; + +connect (addconfoo, localhost, foo,,); +connection addconfoo; +USE db1; + + +SELECT f1 FROM t1; +--error ER_COLUMNACCESS_DENIED_ERROR +SELECT f2 FROM t1; +--error ER_TABLEACCESS_DENIED_ERROR +SELECT * FROM t1; + +SELECT f1 FROM v1; +--error ER_COLUMNACCESS_DENIED_ERROR +SELECT f2 FROM v1; +--error ER_TABLEACCESS_DENIED_ERROR +SELECT * FROM v1; + +connection default; +USE test; +disconnect addconfoo; +REVOKE SELECT (f1) ON db1.t1 FROM foo; +REVOKE SELECT (f1) ON db1.v1 FROM foo; +DROP USER foo; +DROP VIEW db1.v1; +DROP TABLE db1.t1; +DROP DATABASE db1; + --echo End of 5.0 tests. diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index 22135d376fe..c59c42d512a 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -3866,6 +3866,11 @@ bool check_grant_all_columns(THD *thd, ulong want_access_arg, Security_context *sctx= thd->security_ctx; ulong want_access= want_access_arg; const char *table_name= NULL; + /* + Flag that gets set if privilege checking has to be performed on column + level. + */ + bool using_column_privileges= FALSE; if (grant_option) { @@ -3909,6 +3914,8 @@ bool check_grant_all_columns(THD *thd, ulong want_access_arg, GRANT_COLUMN *grant_column= column_hash_search(grant_table, field_name, (uint) strlen(field_name)); + if (grant_column) + using_column_privileges= TRUE; if (!grant_column || (~grant_column->rights & want_access)) goto err; } @@ -3924,12 +3931,21 @@ err: char command[128]; get_privilege_desc(command, sizeof(command), want_access); - my_error(ER_COLUMNACCESS_DENIED_ERROR, MYF(0), - command, - sctx->priv_user, - sctx->host_or_ip, - fields->name(), - table_name); + /* + Do not give an error message listing a column name unless the user has + privilege to see all columns. + */ + if (using_column_privileges) + my_error(ER_TABLEACCESS_DENIED_ERROR, MYF(0), + command, sctx->priv_user, + sctx->host_or_ip, table_name); + else + my_error(ER_COLUMNACCESS_DENIED_ERROR, MYF(0), + command, + sctx->priv_user, + sctx->host_or_ip, + fields->name(), + table_name); return 1; } diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 881c6a421e8..781bbc0a553 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -5479,7 +5479,7 @@ insert_fields(THD *thd, Name_resolution_context *context, const char *db_name, #ifndef NO_EMBEDDED_ACCESS_CHECKS /* Ensure that we have access rights to all fields to be inserted. */ - if (!((table && (table->grant.privilege & SELECT_ACL) || + if (!((table && !tables->view && (table->grant.privilege & SELECT_ACL) || tables->view && (tables->grant.privilege & SELECT_ACL))) && !any_privileges) { From 2cca1991bd25fe9a085ccb4d66ed39d1e054d495 Mon Sep 17 00:00:00 2001 From: "Bernt M. Johnsen" Date: Thu, 26 Feb 2009 18:17:06 +0100 Subject: [PATCH 150/219] Prepared for push (BUG#42567) --- mysql-test/r/group_by.result | 12 ++++++++++++ mysql-test/t/func_group.test | 2 ++ mysql-test/t/group_by.test | 18 ++++++++++++++++++ 3 files changed, 32 insertions(+) diff --git a/mysql-test/r/group_by.result b/mysql-test/r/group_by.result index 48f97aeb428..742d4b90807 100644 --- a/mysql-test/r/group_by.result +++ b/mysql-test/r/group_by.result @@ -1691,3 +1691,15 @@ FROM t1; ERROR 21000: Subquery returns more than 1 row DROP TABLE t1; SET @@sql_mode = @old_sql_mode; +SET @old_sql_mode = @@sql_mode; +SET @@sql_mode='ONLY_FULL_GROUP_BY'; +CREATE TABLE t1(i INT); +INSERT INTO t1 VALUES (1), (10); +SELECT COUNT(i) FROM t1; +COUNT(i) +2 +SELECT COUNT(i) FROM t1 WHERE i > 1; +COUNT(i) +1 +DROP TABLE t1; +SET @@sql_mode = @old_sql_mode; diff --git a/mysql-test/t/func_group.test b/mysql-test/t/func_group.test index be4e9c32686..b0a3d0feb79 100644 --- a/mysql-test/t/func_group.test +++ b/mysql-test/t/func_group.test @@ -18,6 +18,8 @@ insert into t1 values (3,5,"C"); insert into t1 values (3,6,"D"); # Test of MySQL field extension with and without matching records. +#### Note: The two following statements may fail if the execution plan +#### or optimizer is changed. The result for column c is undefined. select a,c,sum(a) from t1 group by a; select a,c,sum(a) from t1 where a > 10 group by a; select sum(a) from t1 where a > 10; diff --git a/mysql-test/t/group_by.test b/mysql-test/t/group_by.test index e3cf3ca856d..5b96213034a 100644 --- a/mysql-test/t/group_by.test +++ b/mysql-test/t/group_by.test @@ -1139,4 +1139,22 @@ DROP TABLE t1; SET @@sql_mode = @old_sql_mode; +# +# Bug#42567 Invalid GROUP BY error +# + +# Setup of the subtest +SET @old_sql_mode = @@sql_mode; +SET @@sql_mode='ONLY_FULL_GROUP_BY'; + +CREATE TABLE t1(i INT); +INSERT INTO t1 VALUES (1), (10); + +# The actual test +SELECT COUNT(i) FROM t1; +SELECT COUNT(i) FROM t1 WHERE i > 1; + +# Cleanup of subtest +DROP TABLE t1; +SET @@sql_mode = @old_sql_mode; From ee772168032cde8f6dc7abf8155f573ccd96afeb Mon Sep 17 00:00:00 2001 From: Georgi Kodinov Date: Fri, 27 Feb 2009 09:41:39 +0200 Subject: [PATCH 151/219] addendum to the fix for bug #41354: fixed the error returned by SELECT * --- mysql-test/r/grant2.result | 2 +- mysql-test/t/grant2.test | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/mysql-test/r/grant2.result b/mysql-test/r/grant2.result index 95748c89103..698e602e2e6 100644 --- a/mysql-test/r/grant2.result +++ b/mysql-test/r/grant2.result @@ -433,7 +433,7 @@ USE db1; SELECT c FROM t2; ERROR 42000: SELECT command denied to user 'mysqltest1'@'localhost' for column 'c' in table 't2' SELECT * FROM t2; -ERROR 42000: SELECT command denied to user 'mysqltest1'@'localhost' for column 'c' in table 't2' +ERROR 42000: SELECT command denied to user 'mysqltest1'@'localhost' for table 't2' SELECT * FROM t1 JOIN t2 USING (b); ERROR 42000: SELECT command denied to user 'mysqltest1'@'localhost' for column 'c' in table 't2' USE test; diff --git a/mysql-test/t/grant2.test b/mysql-test/t/grant2.test index 8f83c365170..2393bb1c6d8 100644 --- a/mysql-test/t/grant2.test +++ b/mysql-test/t/grant2.test @@ -615,7 +615,7 @@ connection conn1; USE db1; --error ER_COLUMNACCESS_DENIED_ERROR SELECT c FROM t2; ---error ER_COLUMNACCESS_DENIED_ERROR +--error ER_TABLEACCESS_DENIED_ERROR SELECT * FROM t2; --error ER_COLUMNACCESS_DENIED_ERROR SELECT * FROM t1 JOIN t2 USING (b); From 1f847d1604b9430356133aa379fe242cfc687cc5 Mon Sep 17 00:00:00 2001 From: Patrick Crews Date: Fri, 27 Feb 2009 10:24:57 +0200 Subject: [PATCH 152/219] Bug#41893: main.variables mysql-test fails in new variable like '%alloc%' is added. Added ORDER BY clause to I_S query to ensure consistent order. There were differences between 5.1 and 6.0 output. Correcting it 5.1. --- mysql-test/r/variables.result | 6 +++--- mysql-test/t/variables.test | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/mysql-test/r/variables.result b/mysql-test/r/variables.result index c99d3f314c5..0b56e3c1d52 100644 --- a/mysql-test/r/variables.result +++ b/mysql-test/r/variables.result @@ -318,13 +318,13 @@ transaction_prealloc_size 4096 SELECT * FROM information_schema.session_variables WHERE variable_name IN ('range_alloc_block_size', 'query_alloc_block_size', 'query_prealloc_size', -'transaction_alloc_block_size', 'transaction_prealloc_size'); +'transaction_alloc_block_size', 'transaction_prealloc_size') ORDER BY 1; VARIABLE_NAME VARIABLE_VALUE +QUERY_ALLOC_BLOCK_SIZE 8192 +QUERY_PREALLOC_SIZE 8192 RANGE_ALLOC_BLOCK_SIZE 4096 TRANSACTION_ALLOC_BLOCK_SIZE 8192 TRANSACTION_PREALLOC_SIZE 4096 -QUERY_PREALLOC_SIZE 8192 -QUERY_ALLOC_BLOCK_SIZE 8192 Testing values that are multiples of 1024 set @@range_alloc_block_size=1024*15+1024; set @@query_alloc_block_size=1024*15+1024*2; diff --git a/mysql-test/t/variables.test b/mysql-test/t/variables.test index 5cfa614f94a..6cd5abc3ea2 100644 --- a/mysql-test/t/variables.test +++ b/mysql-test/t/variables.test @@ -188,7 +188,7 @@ SHOW VARIABLES WHERE variable_name IN ('range_alloc_block_size', SELECT * FROM information_schema.session_variables WHERE variable_name IN ('range_alloc_block_size', 'query_alloc_block_size', 'query_prealloc_size', -'transaction_alloc_block_size', 'transaction_prealloc_size'); +'transaction_alloc_block_size', 'transaction_prealloc_size') ORDER BY 1; --echo Testing values that are multiples of 1024 set @@range_alloc_block_size=1024*15+1024; set @@query_alloc_block_size=1024*15+1024*2; From 71913e350a2dc1964d1298d14d4c5d692c419ce1 Mon Sep 17 00:00:00 2001 From: "Tatiana A. Nurnberg" Date: Fri, 27 Feb 2009 10:27:00 +0100 Subject: [PATCH 153/219] Bug#40657: assertion with out of range variables and traditional sql_mode In STRICT mode, out-of-bounds values caused an error message to be queued (rather than just a warning), without any further error-like processing happening. (The error is queued during update, at which time it's too late. For it to be processed properly, it would need to be queued during check-stage.) The assertion rightfully complains that we're trying to send an OK while having an error queued. Changeset breaks a lot of tests out into check-stage. This also allows us to send more correct warnings/error messages. sql/set_var.cc: cleanup: fold get_unsigned() and fix_unsigned() into one, as well as all the semi-common code from the ::check functions. --- sql/set_var.cc | 66 ++++++++++++++++++++++++++++++++------------------ 1 file changed, 42 insertions(+), 24 deletions(-) diff --git a/sql/set_var.cc b/sql/set_var.cc index ff32ec2458e..01cdecfca5b 100644 --- a/sql/set_var.cc +++ b/sql/set_var.cc @@ -1405,22 +1405,38 @@ bool throw_bounds_warning(THD *thd, bool fixed, bool unsignd, /** check an unsigned user-supplied value for a systemvariable against bounds. + TODO: This is a wrapper function to call clipping from within an update() + function. Calling bounds from within update() is fair game in theory, + but we can only send warnings from in there, not errors, and besides, + it violates our model of separating check from update phase. + To avoid breaking out of the server with an ASSERT() in strict mode, + we pretend we're not in strict mode when we go through here. Bug#43233 + was opened to remind us to replace this kludge with The Right Thing, + which of course is to do the check in the actual check phase, and then + throw an error or warning accordingly. + @param thd thread handle @param num the value to limit - @param option_limits the bounds-record, or NULL - - @retval whether or not we needed to bound + @param option_limits the bounds-record, or NULL if none */ -static my_bool bound_unsigned(THD *thd, ulonglong *num, +static void bound_unsigned(THD *thd, ulonglong *num, const struct my_option *option_limits) { - my_bool fixed = FALSE; - ulonglong unadjusted= *num; - if (option_limits) + { + my_bool fixed = FALSE; + ulonglong unadjusted= *num; + *num= getopt_ull_limit_value(unadjusted, option_limits, &fixed); - return fixed; + if (fixed) + { + ulong ssm= thd->variables.sql_mode; + thd->variables.sql_mode&= ~MODE_STRICT_ALL_TABLES; + throw_bounds_warning(thd, fixed, TRUE, option_limits->name, unadjusted); + thd->variables.sql_mode= ssm; + } + } } @@ -1445,6 +1461,7 @@ static bool get_unsigned(THD *thd, set_var *var, ulonglong user_max, int warnings= 0; ulonglong unadjusted; const struct my_option *limits= var->var->option_limits; + struct my_option fallback; /* get_unsigned() */ if (var->value->unsigned_flag) @@ -1477,32 +1494,33 @@ static bool get_unsigned(THD *thd, set_var *var, ulonglong user_max, warnings++; } + /* + if the sysvar doesn't have a proper bounds record but the check + function would like bounding to ULONG where its size differs from + that of ULONGLONG, we make up a bogus limits record here and let + the usual suspects handle the actual limiting. + */ + + if (!limits && bound2ulong) + { + bzero(&fallback, sizeof(fallback)); + fallback.var_type= GET_ULONG; + limits= &fallback; + } + /* fix_unsigned() */ if (limits) { my_bool fixed; - var->save_result.ulonglong_value= getopt_ull_limit_value(unadjusted, + var->save_result.ulonglong_value= getopt_ull_limit_value(var->save_result. + ulonglong_value, limits, &fixed); if ((warnings == 0) && throw_bounds_warning(thd, fixed, TRUE, limits->name, (longlong) unadjusted)) return TRUE; } - else if (bound2ulong) - { -#if SIZEOF_LONG < SIZEOF_LONG_LONG - /* Avoid overflows on 32 bit systems */ - if (var->save_result.ulonglong_value > ULONG_MAX) - { - var->save_result.ulonglong_value= ULONG_MAX; - if ((warnings == 0) && throw_bounds_warning(thd, TRUE, TRUE, - var->var->name, - (longlong) unadjusted)) - return TRUE; - } -#endif - } return FALSE; } @@ -2334,7 +2352,7 @@ bool sys_var_key_buffer_size::update(THD *thd, set_var *var) bound_unsigned(thd, &tmp, option_limits); key_cache->param_buff_size= (ulonglong) tmp; - /* If key cache didn't existed initialize it, else resize it */ + /* If key cache didn't exist initialize it, else resize it */ key_cache->in_init= 1; pthread_mutex_unlock(&LOCK_global_system_variables); From 9573707ffa3c52cfa2a552c03b2b7d884940e979 Mon Sep 17 00:00:00 2001 From: Ingo Struewing Date: Fri, 27 Feb 2009 12:20:53 +0100 Subject: [PATCH 154/219] Bug#40446 - mysql-test-run --gcov is broken Some variable values were missing and perl constructs failed. Initialized the variables and refactored the gcov functions. .bzrignore: Bug#40446 - mysql-test-run --gcov is broken Added gcov log files. mysql-test/lib/mtr_gcov.pl: Bug#40446 - mysql-test-run --gcov is broken Refactored the gcov functions. mysql-test/mysql-test-run.pl: Bug#40446 - mysql-test-run --gcov is broken Initialized gcov variables. Added usage information. --- .bzrignore | 2 ++ mysql-test/lib/mtr_gcov.pl | 58 ++++++++++++++++++++---------------- mysql-test/mysql-test-run.pl | 9 ++++-- 3 files changed, 40 insertions(+), 29 deletions(-) diff --git a/.bzrignore b/.bzrignore index 01ef6f2ffef..fad758b54b8 100644 --- a/.bzrignore +++ b/.bzrignore @@ -1295,6 +1295,8 @@ mysql-test/linux_sys_vars.inc mysql-test/load_sysvars.inc mysql-test/mtr mysql-test/mysql-test-run +mysql-test/mysql-test-gcov.err +mysql-test/mysql-test-gcov.msg mysql-test/mysql-test-run-shell mysql-test/mysql-test-run.log mysql-test/mysql_test_run_new diff --git a/mysql-test/lib/mtr_gcov.pl b/mysql-test/lib/mtr_gcov.pl index 5049fdd6063..f531889b08d 100644 --- a/mysql-test/lib/mtr_gcov.pl +++ b/mysql-test/lib/mtr_gcov.pl @@ -22,40 +22,46 @@ use strict; sub gcov_prepare ($) { my ($dir)= @_; + print "Purging gcov information from '$dir'...\n"; - `find $dir -name \*.gcov \ - -or -name \*.da | xargs rm`; + system("find $dir -name \*.gcov -o -name \*.da" + . " -o -name \*.gcda | grep -v 'README.gcov\$' | xargs rm"); } -my @mysqld_src_dirs= - ( - "strings", - "mysys", - "include", - "extra", - "regex", - "isam", - "merge", - "myisam", - "myisammrg", - "heap", - "sql", - ); - +# +# Collect gcov statistics. +# Arguments: +# $dir basedir, normally source directory +# $gcov gcov utility program [path] name +# $gcov_msg message file name +# $gcov_err error file name +# sub gcov_collect ($$$) { my ($dir, $gcov, $gcov_msg, $gcov_err)= @_; + # Get current directory to return to later. my $start_dir= cwd(); - print "Collecting source coverage info...\n"; - -f $gcov_msg and unlink($gcov_msg); - -f $gcov_err and unlink($gcov_err); - foreach my $d ( @mysqld_src_dirs ) - { - chdir("$dir/$d"); - foreach my $f ( (glob("*.h"), glob("*.cc"), glob("*.c")) ) - { - `$gcov $f 2>>$gcov_err >>$gcov_msg`; + print "Collecting source coverage info using '$gcov'...\n"; + -f "$start_dir/$gcov_msg" and unlink("$start_dir/$gcov_msg"); + -f "$start_dir/$gcov_err" and unlink("$start_dir/$gcov_err"); + + my @dirs= `find "$dir" -type d -print | sort`; + #print "List of directories:\n@dirs\n"; + + foreach my $d ( @dirs ) { + my $dir_reported= 0; + chomp($d); + chdir($d) or next; + + foreach my $f ( (glob("*.h"), glob("*.cc"), glob("*.c")) ) { + $f =~ /(.*)\.[ch]c?/; + -f "$1.gcno" or next; + if (!$dir_reported) { + print "Collecting in '$d'...\n"; + $dir_reported= 1; + } + system("$gcov $f 2>>$start_dir/$gcov_err >>$start_dir/$gcov_msg"); } chdir($start_dir); } diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl index 50617428d0f..b0b044b67f4 100755 --- a/mysql-test/mysql-test-run.pl +++ b/mysql-test/mysql-test-run.pl @@ -163,8 +163,9 @@ our $opt_force; our $opt_mem= $ENV{'MTR_MEM'}; our $opt_gcov; -our $opt_gcov_err; -our $opt_gcov_msg; +our $opt_gcov_exe= "gcov"; +our $opt_gcov_err= "mysql-test-gcov.msg"; +our $opt_gcov_msg= "mysql-test-gcov.err"; our $glob_debugger= 0; our $opt_gdb; @@ -396,7 +397,7 @@ sub main { mtr_print_line(); if ( $opt_gcov ) { - gcov_collect($basedir, $opt_gcov, + gcov_collect($basedir, $opt_gcov_exe, $opt_gcov_msg, $opt_gcov_err); } @@ -5057,6 +5058,8 @@ Misc options to turn off. sleep=SECONDS Passed to mysqltest, will be used as fixed sleep time + gcov Collect coverage information after the test. + The result is a gcov file per source and header file. HERE exit(1); From 090085164629b203d570bc1fe05294ae2a1c5a5f Mon Sep 17 00:00:00 2001 From: Bjorn Munch Date: Fri, 27 Feb 2009 13:07:01 +0100 Subject: [PATCH 155/219] Bug #43256 Bug#39026 got re-surrected Problems with use of share/mysql dir Explicitly look for "english" language file --- mysql-test/mysql-test-run.pl | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl index 82ed1ff67fc..5e85cfe5cac 100755 --- a/mysql-test/mysql-test-run.pl +++ b/mysql-test/mysql-test-run.pl @@ -932,12 +932,12 @@ sub command_line_setup { } # Look for language files and charsetsdir, use same share - my $path_share= mtr_path_exists("$basedir/share/mysql", - "$basedir/sql/share", - "$basedir/share"); + $path_language= mtr_path_exists("$basedir/share/mysql/english", + "$basedir/sql/share/english", + "$basedir/share/english"); - - $path_language= mtr_path_exists("$path_share/english"); + + my $path_share= dirname($path_language); $path_charsetsdir= mtr_path_exists("$path_share/charsets"); if (using_extern()) From e5a0c0281e0c501e66b82b625ebcd92a9c485ce0 Mon Sep 17 00:00:00 2001 From: Patrick Crews Date: Fri, 27 Feb 2009 15:00:49 +0200 Subject: [PATCH 156/219] Bug#41893: Removal of trailing space noise causing Pushbuild failure. --- mysql-test/r/variables.result | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mysql-test/r/variables.result b/mysql-test/r/variables.result index 04ccf3d688c..fbec38c9a9f 100644 --- a/mysql-test/r/variables.result +++ b/mysql-test/r/variables.result @@ -292,7 +292,7 @@ transaction_prealloc_size 20480 set @@range_alloc_block_size=default; set @@query_alloc_block_size=default, @@query_prealloc_size=default; set transaction_alloc_block_size=default, @@transaction_prealloc_size=default; -==+ Check the values not that they are reset +== +==+ Check the values now that they are reset +== SHOW VARIABLES WHERE variable_name IN ('range_alloc_block_size', 'query_alloc_block_size', 'query_prealloc_size', 'transaction_alloc_block_size', 'transaction_prealloc_size'); From 15760fe9d8434dc9c960c123945b13890456bb5f Mon Sep 17 00:00:00 2001 From: Georgi Kodinov Date: Fri, 27 Feb 2009 15:25:06 +0200 Subject: [PATCH 157/219] Bug #41610: key_infix_len can be overwritten causing some group by queries to return no rows The algorithm of determining the best key for loose index scan is doing a loop over the available indexes and selects the one that has the best cost. It retrieves the parameters of the current index into a set of variables. If the cost of using the current index is lower than the best cost so far it copies these variables into another set of variables that contain the information for the best index so far. After having checked all the indexes it uses these variables (outside of the index loop) to create the table read plan object instance. The was a single omission : the key_infix/key_infix_len variables were used outside of the loop without being preserved in the loop for the best index so far. This causes these variables to get overwritten by the next index(es) checked. Fixed by adding variables to hold the data for the current index, passing the new variables to the function that assigns values to them and copying the new variables into the existing ones when selecting a new current best index. To avoid further such problems moved the declarations of the variables used to keep information about the current index inside the loop's compound statement. mysql-test/r/group_min_max.result: Bug #41610: test case mysql-test/t/group_min_max.test: Bug #41610: test case sql/opt_range.cc: Bug #41610: copy the infix data for the current best index --- mysql-test/r/group_min_max.result | 15 ++++++++ mysql-test/t/group_min_max.test | 23 +++++++++++++ sql/opt_range.cc | 57 +++++++++++++++++-------------- 3 files changed, 70 insertions(+), 25 deletions(-) diff --git a/mysql-test/r/group_min_max.result b/mysql-test/r/group_min_max.result index f2f488650d5..58be2af1bb8 100644 --- a/mysql-test/r/group_min_max.result +++ b/mysql-test/r/group_min_max.result @@ -2429,3 +2429,18 @@ id select_type table type possible_keys key key_len ref rows Extra Warnings: Note 1003 select sql_buffer_result `test`.`t1`.`a` AS `a`,(max(`test`.`t1`.`b`) + 1) AS `max(b)+1` from `test`.`t1` where (`test`.`t1`.`a` = 0) group by `test`.`t1`.`a` drop table t1; +CREATE TABLE t1 (a int, b int, c int, d int, +KEY foo (c,d,a,b), KEY bar (c,a,b,d)); +INSERT INTO t1 VALUES (1, 1, 1, 1), (1, 1, 1, 2), (1, 1, 1, 3), (1, 1, 1, 4); +INSERT INTO t1 SELECT * FROM t1; +INSERT INTO t1 SELECT * FROM t1; +INSERT INTO t1 SELECT a,b,c+1,d FROM t1; +EXPLAIN SELECT DISTINCT c FROM t1 WHERE d=4; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 range NULL foo 10 NULL 9 Using where; Using index for group-by +SELECT DISTINCT c FROM t1 WHERE d=4; +c +1 +2 +DROP TABLE t1; +End of 5.0 tests diff --git a/mysql-test/t/group_min_max.test b/mysql-test/t/group_min_max.test index f7aed7301fb..e124bf9e786 100644 --- a/mysql-test/t/group_min_max.test +++ b/mysql-test/t/group_min_max.test @@ -935,3 +935,26 @@ insert into t1 (a,b) select a, max(b)+1 from t1 where a = 0 group by a; select * from t1; explain extended select sql_buffer_result a, max(b)+1 from t1 where a = 0 group by a; drop table t1; + + +# +# Bug #41610: key_infix_len can be overwritten causing some group by queries +# to return no rows +# + +CREATE TABLE t1 (a int, b int, c int, d int, + KEY foo (c,d,a,b), KEY bar (c,a,b,d)); + +INSERT INTO t1 VALUES (1, 1, 1, 1), (1, 1, 1, 2), (1, 1, 1, 3), (1, 1, 1, 4); +INSERT INTO t1 SELECT * FROM t1; +INSERT INTO t1 SELECT * FROM t1; +INSERT INTO t1 SELECT a,b,c+1,d FROM t1; + +#Should be non-empty +--ordered_result +EXPLAIN SELECT DISTINCT c FROM t1 WHERE d=4; +SELECT DISTINCT c FROM t1 WHERE d=4; + +DROP TABLE t1; + +--echo End of 5.0 tests diff --git a/sql/opt_range.cc b/sql/opt_range.cc index ebebfafb5d8..018fc8a9d44 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -7775,32 +7775,37 @@ get_best_group_min_max(PARAM *param, SEL_TREE *tree) */ KEY *cur_index_info= table->key_info; KEY *cur_index_info_end= cur_index_info + table->s->keys; - KEY_PART_INFO *cur_part= NULL; - KEY_PART_INFO *end_part; /* Last part for loops. */ - /* Last index part. */ - KEY_PART_INFO *last_part= NULL; - KEY_PART_INFO *first_non_group_part= NULL; - KEY_PART_INFO *first_non_infix_part= NULL; - uint key_infix_parts= 0; - uint cur_group_key_parts= 0; - uint cur_group_prefix_len= 0; /* Cost-related variables for the best index so far. */ double best_read_cost= DBL_MAX; ha_rows best_records= 0; SEL_ARG *best_index_tree= NULL; ha_rows best_quick_prefix_records= 0; uint best_param_idx= 0; - double cur_read_cost= DBL_MAX; - ha_rows cur_records; + + const uint pk= param->table->s->primary_key; SEL_ARG *cur_index_tree= NULL; ha_rows cur_quick_prefix_records= 0; uint cur_param_idx=MAX_KEY; - key_map cur_used_key_parts; - uint pk= param->table->s->primary_key; for (uint cur_index= 0 ; cur_index_info != cur_index_info_end ; cur_index_info++, cur_index++) { + KEY_PART_INFO *cur_part; + KEY_PART_INFO *end_part; /* Last part for loops. */ + /* Last index part. */ + KEY_PART_INFO *last_part; + KEY_PART_INFO *first_non_group_part; + KEY_PART_INFO *first_non_infix_part; + uint key_infix_parts; + uint cur_group_key_parts= 0; + uint cur_group_prefix_len= 0; + double cur_read_cost; + ha_rows cur_records; + key_map used_key_parts_map; + uint cur_key_infix_len= 0; + byte cur_key_infix[MAX_KEY_LENGTH]; + uint cur_used_key_parts; + /* Check (B1) - if current index is covering. */ if (!table->used_keys.is_set(cur_index)) goto next_index; @@ -7879,7 +7884,7 @@ get_best_group_min_max(PARAM *param, SEL_TREE *tree) else if (join->select_distinct) { select_items_it.rewind(); - cur_used_key_parts.clear_all(); + used_key_parts_map.clear_all(); uint max_key_part= 0; while ((item= select_items_it++)) { @@ -7890,13 +7895,13 @@ get_best_group_min_max(PARAM *param, SEL_TREE *tree) Check if this attribute was already present in the select list. If it was present, then its corresponding key part was alredy used. */ - if (cur_used_key_parts.is_set(key_part_nr)) + if (used_key_parts_map.is_set(key_part_nr)) continue; if (key_part_nr < 1 || key_part_nr > join->fields_list.elements) goto next_index; cur_part= cur_index_info->key_part + key_part_nr - 1; cur_group_prefix_len+= cur_part->store_length; - cur_used_key_parts.set_bit(key_part_nr); + used_key_parts_map.set_bit(key_part_nr); ++cur_group_key_parts; max_key_part= max(max_key_part,key_part_nr); } @@ -7908,7 +7913,7 @@ get_best_group_min_max(PARAM *param, SEL_TREE *tree) */ ulonglong all_parts, cur_parts; all_parts= (1<> 1; + cur_parts= used_key_parts_map.to_ulonglong() >> 1; if (all_parts != cur_parts) goto next_index; } @@ -7958,7 +7963,8 @@ get_best_group_min_max(PARAM *param, SEL_TREE *tree) &dummy); if (!get_constant_key_infix(cur_index_info, index_range_tree, first_non_group_part, min_max_arg_part, - last_part, thd, key_infix, &key_infix_len, + last_part, thd, cur_key_infix, + &cur_key_infix_len, &first_non_infix_part)) goto next_index; } @@ -8010,9 +8016,9 @@ get_best_group_min_max(PARAM *param, SEL_TREE *tree) } /* If we got to this point, cur_index_info passes the test. */ - key_infix_parts= key_infix_len ? + key_infix_parts= cur_key_infix_len ? (first_non_infix_part - first_non_group_part) : 0; - used_key_parts= cur_group_key_parts + key_infix_parts; + cur_used_key_parts= cur_group_key_parts + key_infix_parts; /* Compute the cost of using this index. */ if (tree) @@ -8024,7 +8030,7 @@ get_best_group_min_max(PARAM *param, SEL_TREE *tree) cur_quick_prefix_records= check_quick_select(param, cur_param_idx, cur_index_tree); } - cost_group_min_max(table, cur_index_info, used_key_parts, + cost_group_min_max(table, cur_index_info, cur_used_key_parts, cur_group_key_parts, tree, cur_index_tree, cur_quick_prefix_records, have_min, have_max, &cur_read_cost, &cur_records); @@ -8035,7 +8041,6 @@ get_best_group_min_max(PARAM *param, SEL_TREE *tree) */ if (cur_read_cost < best_read_cost - (DBL_EPSILON * cur_read_cost)) { - DBUG_ASSERT(tree != 0 || cur_param_idx == MAX_KEY); index_info= cur_index_info; index= cur_index; best_read_cost= cur_read_cost; @@ -8045,11 +8050,13 @@ get_best_group_min_max(PARAM *param, SEL_TREE *tree) best_param_idx= cur_param_idx; group_key_parts= cur_group_key_parts; group_prefix_len= cur_group_prefix_len; + key_infix_len= cur_key_infix_len; + if (key_infix_len) + memcpy (key_infix, cur_key_infix, sizeof (key_infix)); + used_key_parts= cur_used_key_parts; } - next_index: - cur_group_key_parts= 0; - cur_group_prefix_len= 0; + next_index:; } if (!index_info) /* No usable index found. */ DBUG_RETURN(NULL); From 97b68934bca29ab88f63d3887071248c0c602a82 Mon Sep 17 00:00:00 2001 From: Staale Smedseng Date: Fri, 27 Feb 2009 16:11:15 +0200 Subject: [PATCH 158/219] Recommit for merging and pushing --- mysql-test/r/preload.result | 4 ++-- mysql-test/r/ps.result | 12 ++++++------ mysql-test/r/repair.result | 2 +- mysql-test/r/rpl_failed_optimize.result | 2 +- mysql-test/suite/funcs_1/r/innodb_views.result | 2 +- mysql-test/suite/funcs_1/r/memory_views.result | 2 +- sql/sql_table.cc | 7 ++++++- 7 files changed, 18 insertions(+), 13 deletions(-) diff --git a/mysql-test/r/preload.result b/mysql-test/r/preload.result index 24a6e594a14..7ed0c62f33a 100644 --- a/mysql-test/r/preload.result +++ b/mysql-test/r/preload.result @@ -144,7 +144,7 @@ Key_reads 0 load index into cache t3, t2 key (primary,b) ; Table Op Msg_type Msg_text test.t3 preload_keys Error Table 'test.t3' doesn't exist -test.t3 preload_keys error Corrupt +test.t3 preload_keys status Operation failed test.t2 preload_keys status OK show status like "key_read%"; Variable_name Value @@ -159,7 +159,7 @@ Key_reads 0 load index into cache t3 key (b), t2 key (c) ; Table Op Msg_type Msg_text test.t3 preload_keys Error Table 'test.t3' doesn't exist -test.t3 preload_keys error Corrupt +test.t3 preload_keys status Operation failed test.t2 preload_keys Error Key 'c' doesn't exist in table 't2' test.t2 preload_keys status Operation failed show status like "key_read%"; diff --git a/mysql-test/r/ps.result b/mysql-test/r/ps.result index 09deaf2f322..116014a38d2 100644 --- a/mysql-test/r/ps.result +++ b/mysql-test/r/ps.result @@ -1386,13 +1386,13 @@ execute stmt; Table Op Msg_type Msg_text test.t1 repair status OK test.t4 repair Error Table 'test.t4' doesn't exist -test.t4 repair error Corrupt +test.t4 repair status Operation failed test.t3 repair status OK execute stmt; Table Op Msg_type Msg_text test.t1 repair status OK test.t4 repair Error Table 'test.t4' doesn't exist -test.t4 repair error Corrupt +test.t4 repair status Operation failed test.t3 repair status OK prepare stmt from "optimize table t1, t3, t4"; execute stmt; @@ -1400,23 +1400,23 @@ Table Op Msg_type Msg_text test.t1 optimize status OK test.t3 optimize status OK test.t4 optimize Error Table 'test.t4' doesn't exist -test.t4 optimize error Corrupt +test.t4 optimize status Operation failed execute stmt; Table Op Msg_type Msg_text test.t1 optimize status Table is already up to date test.t3 optimize status Table is already up to date test.t4 optimize Error Table 'test.t4' doesn't exist -test.t4 optimize error Corrupt +test.t4 optimize status Operation failed prepare stmt from "analyze table t4, t1"; execute stmt; Table Op Msg_type Msg_text test.t4 analyze Error Table 'test.t4' doesn't exist -test.t4 analyze error Corrupt +test.t4 analyze status Operation failed test.t1 analyze status Table is already up to date execute stmt; Table Op Msg_type Msg_text test.t4 analyze Error Table 'test.t4' doesn't exist -test.t4 analyze error Corrupt +test.t4 analyze status Operation failed test.t1 analyze status Table is already up to date deallocate prepare stmt; drop table t1, t2, t3; diff --git a/mysql-test/r/repair.result b/mysql-test/r/repair.result index c59a5300e64..e7866ae7656 100644 --- a/mysql-test/r/repair.result +++ b/mysql-test/r/repair.result @@ -27,7 +27,7 @@ drop table t1; repair table t1 use_frm; Table Op Msg_type Msg_text test.t1 repair Error Table 'test.t1' doesn't exist -test.t1 repair error Corrupt +test.t1 repair status Operation failed create table t1 engine=myisam SELECT 1,"table 1"; flush tables; repair table t1; diff --git a/mysql-test/r/rpl_failed_optimize.result b/mysql-test/r/rpl_failed_optimize.result index 33a8cdc4a2f..ff7f6ad6177 100644 --- a/mysql-test/r/rpl_failed_optimize.result +++ b/mysql-test/r/rpl_failed_optimize.result @@ -16,5 +16,5 @@ Error 1205 Lock wait timeout exceeded; try restarting transaction OPTIMIZE TABLE non_existing; Table Op Msg_type Msg_text test.non_existing optimize Error Table 'test.non_existing' doesn't exist -test.non_existing optimize error Corrupt +test.non_existing optimize status Operation failed drop table t1; diff --git a/mysql-test/suite/funcs_1/r/innodb_views.result b/mysql-test/suite/funcs_1/r/innodb_views.result index d29e38925f6..3d5c5a1e698 100644 --- a/mysql-test/suite/funcs_1/r/innodb_views.result +++ b/mysql-test/suite/funcs_1/r/innodb_views.result @@ -21367,7 +21367,7 @@ ERROR 42S02: Table 'test.v1' doesn't exist CHECK TABLE v1; Table Op Msg_type Msg_text test.v1 check Error Table 'test.v1' doesn't exist -test.v1 check error Corrupt +test.v1 check status Operation failed DESCRIBE v1; ERROR 42S02: Table 'test.v1' doesn't exist EXPLAIN SELECT * FROM v1; diff --git a/mysql-test/suite/funcs_1/r/memory_views.result b/mysql-test/suite/funcs_1/r/memory_views.result index d24d72473fd..9935e17a1dc 100644 --- a/mysql-test/suite/funcs_1/r/memory_views.result +++ b/mysql-test/suite/funcs_1/r/memory_views.result @@ -21368,7 +21368,7 @@ ERROR 42S02: Table 'test.v1' doesn't exist CHECK TABLE v1; Table Op Msg_type Msg_text test.v1 check Error Table 'test.v1' doesn't exist -test.v1 check error Corrupt +test.v1 check status Operation failed DESCRIBE v1; ERROR 42S02: Table 'test.v1' doesn't exist EXPLAIN SELECT * FROM v1; diff --git a/sql/sql_table.cc b/sql/sql_table.cc index eefe2a5596e..ff7f874ffcb 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -2314,7 +2314,12 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables, view_checksum(thd, table) == HA_ADMIN_WRONG_CHECKSUM) push_warning(thd, MYSQL_ERROR::WARN_LEVEL_ERROR, ER_VIEW_CHECKSUM, ER(ER_VIEW_CHECKSUM)); - result_code= HA_ADMIN_CORRUPT; + if (thd->net.last_errno == ER_NO_SUCH_TABLE) + /* A missing table is just issued as a failed command */ + result_code= HA_ADMIN_FAILED; + else + /* Default failure code is corrupt table */ + result_code= HA_ADMIN_CORRUPT; goto send_result; } From 63c9bb320f9541898142a170a1b8c8bcb76a354e Mon Sep 17 00:00:00 2001 From: Leonard Zhou Date: Sat, 28 Feb 2009 09:35:18 +0800 Subject: [PATCH 159/219] BUG#39526 sql_mode not retained in binary log for CREATE PROCEDURE Set wrong sql_mode when creating a procedure. So that the sql_mode can't be writen into binary log correctly. Restore the current session sql_mode right before generating the binlog event when creating a procedure. mysql-test/suite/binlog/r/binlog_sql_mode.result: Test result mysql-test/suite/binlog/t/binlog_sql_mode.test: Test file for sql_mode testing sql/sp.cc: Restore the current session sql_mode right before generating the binlog event. --- .../suite/binlog/r/binlog_sql_mode.result | 46 +++++++++++ .../suite/binlog/t/binlog_sql_mode.test | 76 +++++++++++++++++++ sql/sp.cc | 4 +- 3 files changed, 125 insertions(+), 1 deletion(-) create mode 100644 mysql-test/suite/binlog/r/binlog_sql_mode.result create mode 100644 mysql-test/suite/binlog/t/binlog_sql_mode.test diff --git a/mysql-test/suite/binlog/r/binlog_sql_mode.result b/mysql-test/suite/binlog/r/binlog_sql_mode.result new file mode 100644 index 00000000000..e306040502d --- /dev/null +++ b/mysql-test/suite/binlog/r/binlog_sql_mode.result @@ -0,0 +1,46 @@ +stop slave; +drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; +reset master; +reset slave; +drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; +start slave; +SET @old_sql_mode= @@global.sql_mode; +SET @old_binlog_format=@@session.binlog_format; +SET SESSION sql_mode=8; +Initialization +RESET MASTER; +CREATE TABLE t1 (id INT); +CREATE PROCEDURE testProc() SELECT * FROM t1; +CREATE VIEW testView as SELECT * from t1; +CREATE FUNCTION testFunc() +RETURNS INT +BEGIN +return 1; +END;| +CREATE TRIGGER testTrig BEFORE INSERT ON t1 +FOR EACH ROW BEGIN +UPDATE t1 SET id = id +1; +END;| +CREATE EVENT testEvent ON SCHEDULE +EVERY 1 DAY +DO +BEGIN +UPDATE t1 SET id = id +1; +END;| +Chceck Result +select +(@a:=load_file("MYSQLTEST_VARDIR/tmp/mysqlbinlog_bug39526.binlog")) +is not null; +(@a:=load_file("MYSQLTEST_VARDIR/tmp/mysqlbinlog_bug39526.binlog")) +is not null +1 +*** String sql_mode=0 is found: 0 *** +Clean Up +DROP PROCEDURE testProc; +DROP FUNCTION testFunc; +DROP TRIGGER testTrig; +DROP EVENT testEvent; +DROP VIEW testView; +DROP TABLE t1; +SET @@global.sql_mode= @old_sql_mode; +SET @@session.binlog_format=@old_binlog_format; diff --git a/mysql-test/suite/binlog/t/binlog_sql_mode.test b/mysql-test/suite/binlog/t/binlog_sql_mode.test new file mode 100644 index 00000000000..1777f8cb561 --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_sql_mode.test @@ -0,0 +1,76 @@ +# ==== Purpose ==== +# +# Test that sql_mode can correct restore before generating the binlog event +# when creating CREATEable objects. +# +# ==== Method ==== +# +# Scan binlog file to check if the sql_mode is still set to 0 before generating binlog event +# + +-- source include/master-slave.inc +-- source include/have_log_bin.inc + +# BUG#39526 sql_mode not retained in binary log for CREATE PROCEDURE + +SET @old_sql_mode= @@global.sql_mode; +SET @old_binlog_format=@@session.binlog_format; +let $MYSQLD_DATADIR= `select @@datadir`; +SET SESSION sql_mode=8; + +--echo Initialization + +RESET MASTER; +CREATE TABLE t1 (id INT); + +CREATE PROCEDURE testProc() SELECT * FROM t1; +CREATE VIEW testView as SELECT * from t1; + +DELIMITER |; +CREATE FUNCTION testFunc() + RETURNS INT + BEGIN + return 1; + END;| +DELIMITER ;| + +DELIMITER |; +CREATE TRIGGER testTrig BEFORE INSERT ON t1 + FOR EACH ROW BEGIN + UPDATE t1 SET id = id +1; + END;| +DELIMITER ;| + +DELIMITER |; +CREATE EVENT testEvent ON SCHEDULE + EVERY 1 DAY + DO + BEGIN + UPDATE t1 SET id = id +1; + END;| +DELIMITER ;| + +--echo Chceck Result + +let $MYSQLD_DATADIR= `select @@datadir`; +--exec $MYSQL_BINLOG $MYSQLD_DATADIR/master-bin.000001 > $MYSQLTEST_VARDIR/tmp/mysqlbinlog_bug39526.binlog +--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR +eval select +(@a:=load_file("$MYSQLTEST_VARDIR/tmp/mysqlbinlog_bug39526.binlog")) +is not null; +let $s_mode_unsigned= `select @a like "%@@session.sql_mode=0%" /* must return 0 */`; +echo *** String sql_mode=0 is found: $s_mode_unsigned ***; + +--remove_file $MYSQLTEST_VARDIR/tmp/mysqlbinlog_bug39526.binlog + +--echo Clean Up + +DROP PROCEDURE testProc; +DROP FUNCTION testFunc; +DROP TRIGGER testTrig; +DROP EVENT testEvent; +DROP VIEW testView; +DROP TABLE t1; + +SET @@global.sql_mode= @old_sql_mode; +SET @@session.binlog_format=@old_binlog_format; diff --git a/sql/sp.cc b/sql/sp.cc index cc545992857..b2c7c389136 100644 --- a/sql/sp.cc +++ b/sql/sp.cc @@ -936,10 +936,12 @@ sp_create_routine(THD *thd, int type, sp_head *sp) ret= SP_INTERNAL_ERROR; goto done; } - + /* restore sql_mode when binloging */ + thd->variables.sql_mode= saved_mode; /* Such a statement can always go directly to binlog, no trans cache */ thd->binlog_query(THD::MYSQL_QUERY_TYPE, log_query.c_ptr(), log_query.length(), FALSE, FALSE); + thd->variables.sql_mode= 0; } } From ef165e36d9a9397dad36a23250456f578d88e1d9 Mon Sep 17 00:00:00 2001 From: "Bernt M. Johnsen" Date: Mon, 2 Mar 2009 11:03:13 +0100 Subject: [PATCH 160/219] Prepared BUG#42711 for push --- mysql-test/r/show_check.result | 2 +- mysql-test/t/mysql.test | 56 ++++++++++++++++++------------ mysql-test/t/mysqldump-compat.test | 8 +++-- mysql-test/t/mysqltest.test | 2 +- mysql-test/t/show_check.test | 11 +++--- 5 files changed, 48 insertions(+), 31 deletions(-) diff --git a/mysql-test/r/show_check.result b/mysql-test/r/show_check.result index ad3138e80ea..15f28fb9610 100644 --- a/mysql-test/r/show_check.result +++ b/mysql-test/r/show_check.result @@ -1094,7 +1094,7 @@ CREATE DATABASE mysqltest1; use mysqltest1; CREATE TABLE t1(ËÏÌÏÎËÁ1 INT); ----> Dumping mysqltest1 to show_check.mysqltest1.sql +---> Dumping mysqltest1 to outfile1 DROP DATABASE mysqltest1; diff --git a/mysql-test/t/mysql.test b/mysql-test/t/mysql.test index 594d10e46a5..12431e26596 100644 --- a/mysql-test/t/mysql.test +++ b/mysql-test/t/mysql.test @@ -98,35 +98,43 @@ drop table t1; # Bug #20432: mysql client interprets commands in comments # +--let $file = $MYSQLTEST_VARDIR/tmp/bug20432.sql + # if the client sees the 'use' within the comment, we haven't fixed ---exec echo "/*" > $MYSQLTEST_VARDIR/tmp/bug20432.sql ---exec echo "use" >> $MYSQLTEST_VARDIR/tmp/bug20432.sql ---exec echo "*/" >> $MYSQLTEST_VARDIR/tmp/bug20432.sql ---exec $MYSQL < $MYSQLTEST_VARDIR/tmp/bug20432.sql 2>&1 +--exec echo "/*" > $file +--exec echo "use" >> $file +--exec echo "*/" >> $file +--exec $MYSQL < $file 2>&1 # SQL can have embedded comments => workie ---exec echo "select /*" > $MYSQLTEST_VARDIR/tmp/bug20432.sql ---exec echo "use" >> $MYSQLTEST_VARDIR/tmp/bug20432.sql ---exec echo "*/ 1" >> $MYSQLTEST_VARDIR/tmp/bug20432.sql ---exec $MYSQL < $MYSQLTEST_VARDIR/tmp/bug20432.sql 2>&1 +--exec echo "select /*" > $file +--exec echo "use" >> $file +--exec echo "*/ 1" >> $file +--exec $MYSQL < $file 2>&1 # client commands on the other hand must be at BOL => error ---exec echo "/*" > $MYSQLTEST_VARDIR/tmp/bug20432.sql ---exec echo "xxx" >> $MYSQLTEST_VARDIR/tmp/bug20432.sql ---exec echo "*/ use" >> $MYSQLTEST_VARDIR/tmp/bug20432.sql +--exec echo "/*" > $file +--exec echo "xxx" >> $file +--exec echo "*/ use" >> $file --error 1 ---exec $MYSQL < $MYSQLTEST_VARDIR/tmp/bug20432.sql 2>&1 +--exec $MYSQL < $file 2>&1 # client comment recognized, but parameter missing => error ---exec echo "use" > $MYSQLTEST_VARDIR/tmp/bug20432.sql ---exec $MYSQL < $MYSQLTEST_VARDIR/tmp/bug20432.sql 2>&1 +--exec echo "use" > $file +--exec $MYSQL < $file 2>&1 + +--remove_file $file # # Bug #20328: mysql client interprets commands in comments # ---exec $MYSQL -e "help" > $MYSQLTEST_VARDIR/tmp/bug20328_1.result ---exec $MYSQL -e "help " > $MYSQLTEST_VARDIR/tmp/bug20328_2.result ---diff_files $MYSQLTEST_VARDIR/tmp/bug20328_1.result $MYSQLTEST_VARDIR/tmp/bug20328_2.result +--let $file1 = $MYSQLTEST_VARDIR/tmp/bug20328_1.result +--let $file2 = $MYSQLTEST_VARDIR/tmp/bug20328_2.result +--exec $MYSQL -e "help" > $file1 +--exec $MYSQL -e "help " > $file2 +--diff_files $file1 $file2 +--remove_file $file1 +--remove_file $file2 # # Bug #19216: Client crashes on long SELECT @@ -152,13 +160,15 @@ EOF # # Bug #20103: Escaping with backslash does not work # ---exec echo "SET SQL_MODE = 'NO_BACKSLASH_ESCAPES';" > $MYSQLTEST_VARDIR/tmp/bug20103.sql ---exec echo "SELECT '\';" >> $MYSQLTEST_VARDIR/tmp/bug20103.sql ---exec $MYSQL < $MYSQLTEST_VARDIR/tmp/bug20103.sql 2>&1 +--let $file = $MYSQLTEST_VARDIR/tmp/bug20103.sql +--exec echo "SET SQL_MODE = 'NO_BACKSLASH_ESCAPES';" > $file +--exec echo "SELECT '\';" >> $file +--exec $MYSQL < $file 2>&1 ---exec echo "SET SQL_MODE = '';" > $MYSQLTEST_VARDIR/tmp/bug20103.sql ---exec echo "SELECT '\';';" >> $MYSQLTEST_VARDIR/tmp/bug20103.sql ---exec $MYSQL < $MYSQLTEST_VARDIR/tmp/bug20103.sql 2>&1 +--exec echo "SET SQL_MODE = '';" > $file +--exec echo "SELECT '\';';" >> $file +--exec $MYSQL < $file 2>&1 +--remove_file $file # # Bug#17583: mysql drops connection when stdout is not writable diff --git a/mysql-test/t/mysqldump-compat.test b/mysql-test/t/mysqldump-compat.test index 848d66cc728..9a830b16f26 100644 --- a/mysql-test/t/mysqldump-compat.test +++ b/mysql-test/t/mysqldump-compat.test @@ -5,9 +5,13 @@ # Bug #30126: semicolon before closing */ in /*!... CREATE DATABASE ;*/ # +--let $file = $MYSQLTEST_VARDIR/tmp/bug30126.sql + CREATE DATABASE mysqldump_30126; USE mysqldump_30126; CREATE TABLE t1 (c1 int); ---exec $MYSQL_DUMP --add-drop-database mysqldump_30126 > $MYSQLTEST_VARDIR/tmp/bug30126.sql ---exec $MYSQL mysqldump_30126 < $MYSQLTEST_VARDIR/tmp/bug30126.sql +--exec $MYSQL_DUMP --add-drop-database mysqldump_30126 > $file +--exec $MYSQL mysqldump_30126 < $file DROP DATABASE mysqldump_30126; + +--remove_file $file diff --git a/mysql-test/t/mysqltest.test b/mysql-test/t/mysqltest.test index 93528f81449..d087d38560b 100644 --- a/mysql-test/t/mysqltest.test +++ b/mysql-test/t/mysqltest.test @@ -1459,7 +1459,7 @@ select "this will be executed"; remove_file $MYSQLTEST_VARDIR/tmp/zero_length_file.result; --error 0,1 -remove_file $MYSQLTEST_VARDIR/log/zero_length_file.reject; +remove_file $MYSQLTEST_VARDIR/tmp/zero_length_file.reject; --error 0,1 remove_file $MYSQL_TEST_DIR/r/zero_length_file.reject; diff --git a/mysql-test/t/show_check.test b/mysql-test/t/show_check.test index f4e0b906f60..2d261aa0675 100644 --- a/mysql-test/t/show_check.test +++ b/mysql-test/t/show_check.test @@ -794,10 +794,12 @@ CREATE TABLE t1( # Check: # - Dump mysqltest1; ---echo ---echo ---> Dumping mysqltest1 to show_check.mysqltest1.sql +--let $outfile1=$MYSQLTEST_VARDIR/tmp/show_check.mysqltest1.sql ---exec $MYSQL_DUMP --default-character-set=latin1 --character-sets-dir=$CHARSETSDIR --databases mysqltest1 > $MYSQLTEST_VARDIR/tmp/show_check.mysqltest1.sql +--echo +--echo ---> Dumping mysqltest1 to outfile1 + +--exec $MYSQL_DUMP --default-character-set=latin1 --character-sets-dir=$CHARSETSDIR --databases mysqltest1 > $outfile1 # - Clean mysqltest1; @@ -812,7 +814,8 @@ DROP DATABASE mysqltest1; --echo --echo ---> Restoring mysqltest1... ---exec $MYSQL test < $MYSQLTEST_VARDIR/tmp/show_check.mysqltest1.sql +--exec $MYSQL test < $outfile1 +--remove_file $outfile1 # - Check definition of the table. From 6293a2ea9306449afc1b00eaa8f1b0a1833ed8cc Mon Sep 17 00:00:00 2001 From: Bjorn Munch Date: Mon, 2 Mar 2009 13:48:35 +0100 Subject: [PATCH 161/219] Bug #40978 Error log gets truncated during testsuite, prevents debugging Error log gets truncated when mysqld is restarted by MTR mysql-test/include/check-warnings.test: Since server doesn't have log-error, get it from env. var. set by MTR mysql-test/lib/My/ConfigFactory.pm: "Hide" log-error in a comment mysql-test/mysql-test-run.pl: "Hide" log-error in my.cnf by comment add --console to arguments on Windows Move .err file to var/log --- mysql-test/include/check-warnings.test | 2 +- mysql-test/lib/My/ConfigFactory.pm | 8 ++++---- mysql-test/mysql-test-run.pl | 19 ++++++++++++++----- 3 files changed, 19 insertions(+), 10 deletions(-) diff --git a/mysql-test/include/check-warnings.test b/mysql-test/include/check-warnings.test index 2144957f742..5295dd51a85 100644 --- a/mysql-test/include/check-warnings.test +++ b/mysql-test/include/check-warnings.test @@ -26,7 +26,7 @@ create temporary table error_log ( ) engine=myisam; # Get the name of servers error log -let $log_error= query_get_value(show variables like 'log_error', Value, 1); +let $log_error= $MTR_LOG_ERROR; let $log_warning= $log_error.warnings; # Try tload the warnings into a temporary table, diff --git a/mysql-test/lib/My/ConfigFactory.pm b/mysql-test/lib/My/ConfigFactory.pm index 567a05ac7a1..852f706c858 100644 --- a/mysql-test/lib/My/ConfigFactory.pm +++ b/mysql-test/lib/My/ConfigFactory.pm @@ -116,8 +116,8 @@ sub fix_tmpdir { sub fix_log_error { my ($self, $config, $group_name, $group)= @_; - my $dir= dirname($group->value('datadir')); - return "$dir/mysqld.err"; + my $dir= $self->{ARGS}->{vardir}; + return "$dir/log/$group_name.err"; } sub fix_log { @@ -203,7 +203,7 @@ my @mysqld_rules= { '#host' => \&fix_host }, { 'port' => \&fix_port }, { 'socket' => \&fix_socket }, - { 'log-error' => \&fix_log_error }, + { '#log-error' => \&fix_log_error }, { 'log' => \&fix_log }, { 'log-slow-queries' => \&fix_log_slow_queries }, { '#user' => sub { return shift->{ARGS}->{user} || ""; } }, @@ -389,7 +389,7 @@ sub post_check_embedded_group { my @no_copy = ( - 'log-error', # Embedded server writes stderr to mysqltest's log file + '#log-error', # Embedded server writes stderr to mysqltest's log file 'slave-net-timeout', # Embedded server are not build with replication ); diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl index 5e85cfe5cac..a254180056b 100755 --- a/mysql-test/mysql-test-run.pl +++ b/mysql-test/mysql-test-run.pl @@ -3470,7 +3470,10 @@ sub start_check_warnings ($$) { my $name= "warnings-".$mysqld->name(); - extract_warning_lines($mysqld->value('log-error')); + my $log_error= $mysqld->value('#log-error'); + # To be communicated to the test + $ENV{MTR_LOG_ERROR}= $log_error; + extract_warning_lines($log_error); my $args; mtr_init_args(\$args); @@ -3986,6 +3989,12 @@ sub mysqld_start ($$) { $path_vardir_trace, $mysqld->name()); } + if (IS_WINDOWS) + { + # Trick the server to send output to stderr, with --console + mtr_add_arg($args, "--console"); + } + if ( $opt_gdb || $opt_manual_gdb ) { gdb_arguments(\$args, \$exe, $mysqld->name()); @@ -4018,7 +4027,7 @@ sub mysqld_start ($$) { # Remove the old pidfile if any unlink($mysqld->value('pid-file')); - my $output= $mysqld->value('log-error'); + my $output= $mysqld->value('#log-error'); if ( $opt_valgrind and $opt_debug ) { # When both --valgrind and --debug is selected, send @@ -4319,7 +4328,7 @@ sub start_servers($) { # Already started # Write start of testcase to log file - mark_log($mysqld->value('log-error'), $tinfo); + mark_log($mysqld->value('#log-error'), $tinfo); next; } @@ -4378,7 +4387,7 @@ sub start_servers($) { mkpath($tmpdir) unless -d $tmpdir; # Write start of testcase to log file - mark_log($mysqld->value('log-error'), $tinfo); + mark_log($mysqld->value('#log-error'), $tinfo); # Run -master.sh if ($mysqld->option('#!run-master-sh') and @@ -4429,7 +4438,7 @@ sub start_servers($) { $tinfo->{comment}= "Failed to start ".$mysqld->name(); - my $logfile= $mysqld->value('log-error'); + my $logfile= $mysqld->value('#log-error'); if ( defined $logfile and -f $logfile ) { $tinfo->{logfile}= mtr_fromfile($logfile); From 901b29860d24388b100dba9cb847f74313f7865c Mon Sep 17 00:00:00 2001 From: Timothy Smith Date: Mon, 2 Mar 2009 17:24:23 -0700 Subject: [PATCH 162/219] Applying InnoDB snashot 5.0-ss4007, part 1. Fixes Bug #39939: DROP TABLE/DISCARD TABLESPACE takes long time in buf_LRU_invalidate_tablespace() This was already fixed in 5.1+; this is a backport to 5.0. Detailed revision comments: r2743 | inaam | 2008-10-08 22:18:12 +0300 (Wed, 08 Oct 2008) | 13 lines branches/5.0: Backport of r2742 from branches/5.1: Fix Bug#39939 DROP TABLE/DISCARD TABLESPACE takes long time in buf_LRU_invalidate_tablespace() Improve implementation of buf_LRU_invalidate_tablespace by attempting hash index drop in batches instead of doing it one by one. Reviewed by: Heikki, Sunny, Marko Approved by: Heikki --- innobase/buf/buf0lru.c | 127 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 127 insertions(+) diff --git a/innobase/buf/buf0lru.c b/innobase/buf/buf0lru.c index 0f632f0752a..6984c196701 100644 --- a/innobase/buf/buf0lru.c +++ b/innobase/buf/buf0lru.c @@ -42,6 +42,11 @@ initial segment in buf_LRU_get_recent_limit */ #define BUF_LRU_INITIAL_RATIO 8 +/* When dropping the search hash index entries before deleting an ibd +file, we build a local array of pages belonging to that tablespace +in the buffer pool. Following is the size of that array. */ +#define BUF_LRU_DROP_SEARCH_HASH_SIZE 1024 + /* If we switch on the InnoDB monitor because there are too few available frames in the buffer pool, we set this to TRUE */ ibool buf_lru_switched_on_innodb_mon = FALSE; @@ -65,6 +70,120 @@ buf_LRU_block_free_hashed_page( buf_block_t* block); /* in: block, must contain a file page and be in a state where it can be freed */ +/********************************************************************** +Attempts to drop page hash index on a batch of pages belonging to a +particular space id. */ +static +void +buf_LRU_drop_page_hash_batch( +/*=========================*/ + ulint id, /* in: space id */ + const ulint* arr, /* in: array of page_no */ + ulint count) /* in: number of entries in array */ +{ + ulint i; + + ut_ad(arr != NULL); + ut_ad(count <= BUF_LRU_DROP_SEARCH_HASH_SIZE); + + for (i = 0; i < count; ++i) { + btr_search_drop_page_hash_when_freed(id, arr[i]); + } +} + +/********************************************************************** +When doing a DROP TABLE/DISCARD TABLESPACE we have to drop all page +hash index entries belonging to that table. This function tries to +do that in batch. Note that this is a 'best effort' attempt and does +not guarantee that ALL hash entries will be removed. */ +static +void +buf_LRU_drop_page_hash_for_tablespace( +/*==================================*/ + ulint id) /* in: space id */ +{ + buf_block_t* block; + ulint* page_arr; + ulint num_entries; + + page_arr = ut_malloc(sizeof(ulint) + * BUF_LRU_DROP_SEARCH_HASH_SIZE); + mutex_enter(&buf_pool->mutex); + +scan_again: + num_entries = 0; + block = UT_LIST_GET_LAST(buf_pool->LRU); + + while (block != NULL) { + buf_block_t* prev_block; + + mutex_enter(&block->mutex); + prev_block = UT_LIST_GET_PREV(LRU, block); + + ut_a(block->state == BUF_BLOCK_FILE_PAGE); + + if (block->space != id + || block->buf_fix_count > 0 + || block->io_fix != 0) { + /* We leave the fixed pages as is in this scan. + To be dealt with later in the final scan. */ + mutex_exit(&block->mutex); + goto next_page; + } + + ut_ad(block->space == id); + if (block->is_hashed) { + + /* Store the offset(i.e.: page_no) in the array + so that we can drop hash index in a batch + later. */ + page_arr[num_entries] = block->offset; + mutex_exit(&block->mutex); + ut_a(num_entries < BUF_LRU_DROP_SEARCH_HASH_SIZE); + ++num_entries; + + if (num_entries < BUF_LRU_DROP_SEARCH_HASH_SIZE) { + goto next_page; + } + /* Array full. We release the buf_pool->mutex to + obey the latching order. */ + mutex_exit(&buf_pool->mutex); + + buf_LRU_drop_page_hash_batch(id, page_arr, + num_entries); + num_entries = 0; + mutex_enter(&buf_pool->mutex); + } else { + mutex_exit(&block->mutex); + } + +next_page: + /* Note that we may have released the buf_pool->mutex + above after reading the prev_block during processing + of a page_hash_batch (i.e.: when the array was full). + This means that prev_block can change in LRU list. + This is OK because this function is a 'best effort' + to drop as many search hash entries as possible and + it does not guarantee that ALL such entries will be + dropped. */ + block = prev_block; + + /* If, however, block has been removed from LRU list + to the free list then we should restart the scan. + block->state is protected by buf_pool->mutex. */ + if (block && block->state != BUF_BLOCK_FILE_PAGE) { + ut_a(num_entries == 0); + goto scan_again; + } + } + + mutex_exit(&buf_pool->mutex); + + /* Drop any remaining batch of search hashed pages. */ + buf_LRU_drop_page_hash_batch(id, page_arr, num_entries); + ut_free(page_arr); +} + /********************************************************************** Invalidates all pages belonging to a given tablespace when we are deleting the data file(s) of that tablespace. */ @@ -78,6 +197,14 @@ buf_LRU_invalidate_tablespace( ulint page_no; ibool all_freed; + /* Before we attempt to drop pages one by one we first + attempt to drop page hash index entries in batches to make + it more efficient. The batching attempt is a best effort + attempt and does not guarantee that all pages hash entries + will be dropped. We get rid of remaining page hash entries + one by one below. */ + buf_LRU_drop_page_hash_for_tablespace(id); + scan_again: mutex_enter(&(buf_pool->mutex)); From c3fec5d22ff38388f68718bf77cca183778978a1 Mon Sep 17 00:00:00 2001 From: Timothy Smith Date: Mon, 2 Mar 2009 17:57:09 -0700 Subject: [PATCH 163/219] Applying InnoDB snashot 5.0-ss4007, part 2. Fixes Bug #18828: If InnoDB runs out of undo slots, it returns misleading 'table is full' This is a backport of code already in 5.1+. The error message change referred to in the detailed revision comments is still pending. Detailed revision comments: r3937 | calvin | 2009-01-15 03:11:56 +0200 (Thu, 15 Jan 2009) | 17 lines branches/5.0: Backport the fix for Bug#18828. Return DB_TOO_MANY_CONCURRENT_TRXS when we run out of UNDO slots in the rollback segment. The backport is requested by MySQL under bug#41529 - Safe handling of InnoDB running out of undo log slots. This is a partial fix since the MySQL error code requested to properly report the error condition back to the client has not yet materialized. Currently we have #ifdef'd the error code translation in ha_innodb.cc. This will have to be changed as and when MySQl add the new requested code or an equivalent code that we can then use. Given the above, currently we will get the old behavior, not the "fixed" and intended behavior. Approved by: Heikki (on IM) --- innobase/dict/dict0crea.c | 3 +- innobase/include/db0err.h | 5 ++ innobase/include/trx0undo.h | 13 +++-- innobase/row/row0mysql.c | 3 +- innobase/trx/trx0rec.c | 15 +++--- innobase/trx/trx0undo.c | 105 ++++++++++++++++++++++-------------- sql/ha_innodb.cc | 14 +++++ 7 files changed, 103 insertions(+), 55 deletions(-) diff --git a/innobase/dict/dict0crea.c b/innobase/dict/dict0crea.c index e20d8b6e83a..12d99734796 100644 --- a/innobase/dict/dict0crea.c +++ b/innobase/dict/dict0crea.c @@ -1249,7 +1249,8 @@ dict_create_or_check_foreign_constraint_tables(void) fprintf(stderr, "InnoDB: error %lu in creation\n", (ulong) error); - ut_a(error == DB_OUT_OF_FILE_SPACE); + ut_a(error == DB_OUT_OF_FILE_SPACE + || error == DB_TOO_MANY_CONCURRENT_TRXS); fprintf(stderr, "InnoDB: creation failed\n"); fprintf(stderr, "InnoDB: tablespace is full\n"); diff --git a/innobase/include/db0err.h b/innobase/include/db0err.h index 247c5de67db..68bdcdc8b7f 100644 --- a/innobase/include/db0err.h +++ b/innobase/include/db0err.h @@ -70,6 +70,11 @@ Created 5/24/1996 Heikki Tuuri work with e.g., FT indexes created by a later version of the engine. */ +#define DB_TOO_MANY_CONCURRENT_TRXS 47 /* when InnoDB runs out of the + preconfigured undo slots, this can + only happen when there are too many + concurrent transactions */ + /* The following are partial failure codes */ #define DB_FAIL 1000 #define DB_OVERFLOW 1001 diff --git a/innobase/include/trx0undo.h b/innobase/include/trx0undo.h index 4f1847aa88c..152a09c0f76 100644 --- a/innobase/include/trx0undo.h +++ b/innobase/include/trx0undo.h @@ -222,13 +222,16 @@ trx_undo_lists_init( Assigns an undo log for a transaction. A new undo log is created or a cached undo log reused. */ -trx_undo_t* +ulint trx_undo_assign_undo( /*=================*/ - /* out: the undo log, NULL if did not succeed: out of - space */ - trx_t* trx, /* in: transaction */ - ulint type); /* in: TRX_UNDO_INSERT or TRX_UNDO_UPDATE */ + /* out: DB_SUCCESS if undo log assign + * successful, possible error codes are: + * ER_TOO_MANY_CONCURRENT_TRXS + * DB_OUT_OF_FILE_SPAC + * DB_OUT_OF_MEMORY */ + trx_t* trx, /* in: transaction */ + ulint type); /* in: TRX_UNDO_INSERT or TRX_UNDO_UPDATE */ /********************************************************************** Sets the state of the undo log segment at a transaction finish. */ diff --git a/innobase/row/row0mysql.c b/innobase/row/row0mysql.c index 4bc5f39359c..d7213b25145 100644 --- a/innobase/row/row0mysql.c +++ b/innobase/row/row0mysql.c @@ -494,7 +494,8 @@ handle_new_error: /* MySQL will roll back the latest SQL statement */ } else if (err == DB_ROW_IS_REFERENCED || err == DB_NO_REFERENCED_ROW - || err == DB_CANNOT_ADD_CONSTRAINT) { + || err == DB_CANNOT_ADD_CONSTRAINT + || err == DB_TOO_MANY_CONCURRENT_TRXS) { if (savept) { /* Roll back the latest, possibly incomplete insertion or update */ diff --git a/innobase/trx/trx0rec.c b/innobase/trx/trx0rec.c index 3b7171e6038..44b734625dd 100644 --- a/innobase/trx/trx0rec.c +++ b/innobase/trx/trx0rec.c @@ -1013,6 +1013,7 @@ trx_undo_report_row_operation( ibool is_insert; trx_rseg_t* rseg; mtr_t mtr; + ulint err = DB_SUCCESS; mem_heap_t* heap = NULL; ulint offsets_[REC_OFFS_NORMAL_SIZE]; ulint* offsets = offsets_; @@ -1024,7 +1025,7 @@ trx_undo_report_row_operation( *roll_ptr = ut_dulint_zero; - return(DB_SUCCESS); + return(err); } ut_ad(thr); @@ -1042,7 +1043,7 @@ trx_undo_report_row_operation( if (trx->insert_undo == NULL) { - trx_undo_assign_undo(trx, TRX_UNDO_INSERT); + err = trx_undo_assign_undo(trx, TRX_UNDO_INSERT); } undo = trx->insert_undo; @@ -1052,7 +1053,7 @@ trx_undo_report_row_operation( if (trx->update_undo == NULL) { - trx_undo_assign_undo(trx, TRX_UNDO_UPDATE); + err = trx_undo_assign_undo(trx, TRX_UNDO_UPDATE); } @@ -1060,11 +1061,11 @@ trx_undo_report_row_operation( is_insert = FALSE; } - if (undo == NULL) { - /* Did not succeed: out of space */ + if (err != DB_SUCCESS) { + /* Did not succeed: return the error encountered */ mutex_exit(&(trx->undo_mutex)); - return(DB_OUT_OF_FILE_SPACE); + return(err); } page_no = undo->last_page_no; @@ -1154,7 +1155,7 @@ trx_undo_report_row_operation( if (UNIV_LIKELY_NULL(heap)) { mem_heap_free(heap); } - return(DB_SUCCESS); + return(err); } /*============== BUILDING PREVIOUS VERSION OF A RECORD ===============*/ diff --git a/innobase/trx/trx0undo.c b/innobase/trx/trx0undo.c index 251cd355897..997f25a66d8 100644 --- a/innobase/trx/trx0undo.c +++ b/innobase/trx/trx0undo.c @@ -374,27 +374,32 @@ trx_undo_page_init( /******************************************************************* Creates a new undo log segment in file. */ static -page_t* +ulint trx_undo_seg_create( /*================*/ - /* out: segment header page x-latched, NULL - if no space left */ + /* out: DB_SUCCESS if page creation OK + possible error codes are: + DB_TOO_MANY_CONCURRENT_TRXS + DB_OUT_OF_FILE_SPACE */ trx_rseg_t* rseg __attribute__((unused)),/* in: rollback segment */ trx_rsegf_t* rseg_hdr,/* in: rollback segment header, page x-latched */ ulint type, /* in: type of the segment: TRX_UNDO_INSERT or TRX_UNDO_UPDATE */ ulint* id, /* out: slot index within rseg header */ + page_t** undo_page, + /* out: segment header page x-latched, NULL + if there was an error */ mtr_t* mtr) /* in: mtr */ { ulint slot_no; ulint space; - page_t* undo_page; trx_upagef_t* page_hdr; trx_usegf_t* seg_hdr; ulint n_reserved; ibool success; - + ulint err = DB_SUCCESS; + ut_ad(mtr && id && rseg_hdr); #ifdef UNIV_SYNC_DEBUG ut_ad(mutex_own(&(rseg->mutex))); @@ -411,7 +416,7 @@ trx_undo_seg_create( "InnoDB: Warning: cannot find a free slot for an undo log. Do you have too\n" "InnoDB: many active transactions running concurrently?\n"); - return(NULL); + return(DB_TOO_MANY_CONCURRENT_TRXS); } space = buf_frame_get_space_id(rseg_hdr); @@ -420,29 +425,29 @@ trx_undo_seg_create( mtr); if (!success) { - return(NULL); + return(DB_OUT_OF_FILE_SPACE); } /* Allocate a new file segment for the undo log */ - undo_page = fseg_create_general(space, 0, + *undo_page = fseg_create_general(space, 0, TRX_UNDO_SEG_HDR + TRX_UNDO_FSEG_HEADER, TRUE, mtr); fil_space_release_free_extents(space, n_reserved); - if (undo_page == NULL) { + if (*undo_page == NULL) { /* No space left */ - return(NULL); + return(DB_OUT_OF_FILE_SPACE); } #ifdef UNIV_SYNC_DEBUG - buf_page_dbg_add_level(undo_page, SYNC_TRX_UNDO_PAGE); + buf_page_dbg_add_level(*undo_page, SYNC_TRX_UNDO_PAGE); #endif /* UNIV_SYNC_DEBUG */ - page_hdr = undo_page + TRX_UNDO_PAGE_HDR; - seg_hdr = undo_page + TRX_UNDO_SEG_HDR; + page_hdr = *undo_page + TRX_UNDO_PAGE_HDR; + seg_hdr = *undo_page + TRX_UNDO_SEG_HDR; - trx_undo_page_init(undo_page, type, mtr); + trx_undo_page_init(*undo_page, type, mtr); mlog_write_ulint(page_hdr + TRX_UNDO_PAGE_FREE, TRX_UNDO_SEG_HDR + TRX_UNDO_SEG_HDR_SIZE, @@ -456,10 +461,11 @@ trx_undo_seg_create( page_hdr + TRX_UNDO_PAGE_NODE, mtr); trx_rsegf_set_nth_undo(rseg_hdr, slot_no, - buf_frame_get_page_no(undo_page), mtr); + buf_frame_get_page_no(*undo_page), mtr); + *id = slot_no; - return(undo_page); + return(err); } /************************************************************************** @@ -1400,6 +1406,11 @@ trx_undo_mem_create( undo = mem_alloc(sizeof(trx_undo_t)); + if (undo == NULL) { + + return NULL; + } + undo->id = id; undo->type = type; undo->state = TRX_UNDO_ACTIVE; @@ -1479,11 +1490,15 @@ trx_undo_mem_free( /************************************************************************** Creates a new undo log. */ static -trx_undo_t* +ulint trx_undo_create( /*============*/ - /* out: undo log object, NULL if did not - succeed: out of space */ + /* out: DB_SUCCESS if successful in creating + the new undo lob object, possible error + codes are: + DB_TOO_MANY_CONCURRENT_TRXS + DB_OUT_OF_FILE_SPACE + DB_OUT_OF_MEMORY*/ trx_t* trx, /* in: transaction */ trx_rseg_t* rseg, /* in: rollback segment memory copy */ ulint type, /* in: type of the log: TRX_UNDO_INSERT or @@ -1491,36 +1506,39 @@ trx_undo_create( dulint trx_id, /* in: id of the trx for which the undo log is created */ XID* xid, /* in: X/Open transaction identification*/ + trx_undo_t** undo, /* out: the new undo log object, undefined + * if did not succeed */ mtr_t* mtr) /* in: mtr */ { trx_rsegf_t* rseg_header; ulint page_no; ulint offset; ulint id; - trx_undo_t* undo; page_t* undo_page; - + ulint err; + #ifdef UNIV_SYNC_DEBUG ut_ad(mutex_own(&(rseg->mutex))); #endif /* UNIV_SYNC_DEBUG */ if (rseg->curr_size == rseg->max_size) { - return(NULL); + return(DB_OUT_OF_FILE_SPACE); } rseg->curr_size++; rseg_header = trx_rsegf_get(rseg->space, rseg->page_no, mtr); - undo_page = trx_undo_seg_create(rseg, rseg_header, type, &id, mtr); + err = trx_undo_seg_create(rseg, rseg_header, type, &id, + &undo_page, mtr); - if (undo_page == NULL) { + if (err != DB_SUCCESS) { /* Did not succeed */ rseg->curr_size--; - return(NULL); + return(err); } page_no = buf_frame_get_page_no(undo_page); @@ -1532,9 +1550,14 @@ trx_undo_create( undo_page + offset, mtr); } - undo = trx_undo_mem_create(rseg, id, type, trx_id, xid, + *undo = trx_undo_mem_create(rseg, id, type, trx_id, xid, page_no, offset); - return(undo); + if (*undo == NULL) { + + err = DB_OUT_OF_MEMORY; + } + + return(err); } /*================ UNDO LOG ASSIGNMENT AND CLEANUP =====================*/ @@ -1653,17 +1676,20 @@ trx_undo_mark_as_dict_operation( Assigns an undo log for a transaction. A new undo log is created or a cached undo log reused. */ -trx_undo_t* +ulint trx_undo_assign_undo( /*=================*/ - /* out: the undo log, NULL if did not succeed: out of - space */ - trx_t* trx, /* in: transaction */ - ulint type) /* in: TRX_UNDO_INSERT or TRX_UNDO_UPDATE */ + /* out: DB_SUCCESS if undo log assign + successful, possible error codes are: + DD_TOO_MANY_CONCURRENT_TRXS + DB_OUT_OF_FILE_SPACE DB_OUT_OF_MEMORY*/ + trx_t* trx, /* in: transaction */ + ulint type) /* in: TRX_UNDO_INSERT or TRX_UNDO_UPDATE */ { trx_rseg_t* rseg; trx_undo_t* undo; mtr_t mtr; + ulint err = DB_SUCCESS; ut_ad(trx); ut_ad(trx->rseg); @@ -1684,15 +1710,11 @@ trx_undo_assign_undo( undo = trx_undo_reuse_cached(trx, rseg, type, trx->id, &trx->xid, &mtr); if (undo == NULL) { - undo = trx_undo_create(trx, rseg, type, trx->id, &trx->xid, - &mtr); - if (undo == NULL) { - /* Did not succeed */ + err = trx_undo_create(trx, rseg, type, trx->id, &trx->xid, + &undo, &mtr); + if (err != DB_SUCCESS) { - mutex_exit(&(rseg->mutex)); - mtr_commit(&mtr); - - return(NULL); + goto func_exit; } } @@ -1710,10 +1732,11 @@ trx_undo_assign_undo( trx_undo_mark_as_dict_operation(trx, undo, &mtr); } +func_exit: mutex_exit(&(rseg->mutex)); mtr_commit(&mtr); - return(undo); + return err; } /********************************************************************** diff --git a/sql/ha_innodb.cc b/sql/ha_innodb.cc index e0b7fb6e7f5..3bae0da3e02 100644 --- a/sql/ha_innodb.cc +++ b/sql/ha_innodb.cc @@ -524,6 +524,20 @@ convert_error_code_to_mysql( mark_transaction_to_rollback(thd, TRUE); return(HA_ERR_LOCK_TABLE_FULL); + } else if (error == DB_TOO_MANY_CONCURRENT_TRXS) { + + /* Once MySQL add the appropriate code to errmsg.txt then + we can get rid of this #ifdef. NOTE: The code checked by + the #ifdef is the suggested name for the error condition + and the actual error code name could very well be different. + This will require some monitoring, ie. the status + of this request on our part.*/ +#ifdef ER_TOO_MANY_CONCURRENT_TRXS + return(ER_TOO_MANY_CONCURRENT_TRXS); +#else + return(HA_ERR_RECORD_FILE_FULL); +#endif + } else if (error == DB_UNSUPPORTED) { return(HA_ERR_UNSUPPORTED); From 62d5d85c5d19b113b772ecadbf32f198831b543b Mon Sep 17 00:00:00 2001 From: Timothy Smith Date: Mon, 2 Mar 2009 18:00:23 -0700 Subject: [PATCH 164/219] Applying InnoDB snashot 5.0-ss4007, part 3. Fixes Bug #41571: MySQL segfaults after innodb recovery This 5.0 fix will not be pushed into 5.1; a separate fix (from innodb-5.1-ss4007) will be pushed into 5.1+. Detailed revision comments: r4003 | marko | 2009-01-20 16:12:50 +0200 (Tue, 20 Jan 2009) | 10 lines branches/5.0: rec_set_nth_field(): When the field already is SQL null, do nothing when it is being changed to SQL null. (Bug #41571) Normally, MySQL does not pass "do-nothing" updates to the storage engine. When it does and a column of an InnoDB table that is in ROW_FORMAT=COMPACT is being updated from NULL to NULL, the InnoDB buffer pool will be corrupted without this fix. rb://81 approved by Heikki Tuuri --- innobase/include/rem0rec.h | 11 ++++------- innobase/include/rem0rec.ic | 19 +++++++++---------- 2 files changed, 13 insertions(+), 17 deletions(-) diff --git a/innobase/include/rem0rec.h b/innobase/include/rem0rec.h index 69b397c9682..b573c5d4c3b 100644 --- a/innobase/include/rem0rec.h +++ b/innobase/include/rem0rec.h @@ -368,8 +368,9 @@ rec_set_field_extern_bits( /*************************************************************** This is used to modify the value of an already existing field in a record. The previous value must have exactly the same size as the new value. If len -is UNIV_SQL_NULL then the field is treated as an SQL null for old-style -records. For new-style records, len must not be UNIV_SQL_NULL. */ +is UNIV_SQL_NULL then the field is treated as an SQL null. +For records in ROW_FORMAT=COMPACT (new-style records), len must not be +UNIV_SQL_NULL unless the field already is SQL null. */ UNIV_INLINE void rec_set_nth_field( @@ -378,11 +379,7 @@ rec_set_nth_field( const ulint* offsets,/* in: array returned by rec_get_offsets() */ ulint n, /* in: index number of the field */ const void* data, /* in: pointer to the data if not SQL null */ - ulint len); /* in: length of the data or UNIV_SQL_NULL. - If not SQL null, must have the same - length as the previous value. - If SQL null, previous value must be - SQL null. */ + ulint len); /* in: length of the data or UNIV_SQL_NULL */ /************************************************************** The following function returns the data size of an old-style physical record, that is the sum of field lengths. SQL null fields diff --git a/innobase/include/rem0rec.ic b/innobase/include/rem0rec.ic index 1abbb503bab..64c91724386 100644 --- a/innobase/include/rem0rec.ic +++ b/innobase/include/rem0rec.ic @@ -1204,8 +1204,9 @@ rec_get_nth_field_size( /*************************************************************** This is used to modify the value of an already existing field in a record. The previous value must have exactly the same size as the new value. If len -is UNIV_SQL_NULL then the field is treated as an SQL null for old-style -records. For new-style records, len must not be UNIV_SQL_NULL. */ +is UNIV_SQL_NULL then the field is treated as an SQL null. +For records in ROW_FORMAT=COMPACT (new-style records), len must not be +UNIV_SQL_NULL unless the field already is SQL null. */ UNIV_INLINE void rec_set_nth_field( @@ -1215,11 +1216,7 @@ rec_set_nth_field( ulint n, /* in: index number of the field */ const void* data, /* in: pointer to the data if not SQL null */ - ulint len) /* in: length of the data or UNIV_SQL_NULL. - If not SQL null, must have the same - length as the previous value. - If SQL null, previous value must be - SQL null. */ + ulint len) /* in: length of the data or UNIV_SQL_NULL */ { byte* data2; ulint len2; @@ -1227,9 +1224,11 @@ rec_set_nth_field( ut_ad(rec); ut_ad(rec_offs_validate(rec, NULL, offsets)); - if (len == UNIV_SQL_NULL) { - ut_ad(!rec_offs_comp(offsets)); - rec_set_nth_field_sql_null(rec, n); + if (UNIV_UNLIKELY(len == UNIV_SQL_NULL)) { + if (!rec_offs_nth_sql_null(offsets, n)) { + ut_a(!rec_offs_comp(offsets)); + rec_set_nth_field_sql_null(rec, n); + } return; } From 20b1c21bf0fe4945d9326ec8a88386c2a70ea038 Mon Sep 17 00:00:00 2001 From: Timothy Smith Date: Mon, 2 Mar 2009 18:06:44 -0700 Subject: [PATCH 165/219] Applying InnoDB snashot 5.1-ss3931, part 1. Fixes Bug #38187: Error 153 when creating savepoints Detailed revision comments: r3911 | sunny | 2009-01-13 14:15:24 +0200 (Tue, 13 Jan 2009) | 13 lines branches/5.1: Fix Bug#38187 Error 153 when creating savepoints InnoDB previously treated savepoints as a stack e.g., SAVEPOINT a; SAVEPOINT b; SAVEPOINT c; SAVEPOINT b; <- This would delete b and c. This fix changes the behavior to: SAVEPOINT a; SAVEPOINT b; SAVEPOINT c; SAVEPOINT b; <- Does not delete savepoint c --- storage/innobase/include/trx0roll.h | 14 +++++++- storage/innobase/trx/trx0roll.c | 51 +++++++++++++++-------------- storage/innobase/trx/trx0trx.c | 4 +-- 3 files changed, 41 insertions(+), 28 deletions(-) diff --git a/storage/innobase/include/trx0roll.h b/storage/innobase/include/trx0roll.h index 25546430ba0..c1eca3d5753 100644 --- a/storage/innobase/include/trx0roll.h +++ b/storage/innobase/include/trx0roll.h @@ -15,6 +15,8 @@ Created 3/26/1996 Heikki Tuuri #include "mtr0mtr.h" #include "trx0sys.h" +#define trx_roll_free_all_savepoints(s) trx_roll_savepoints_free((s), NULL) + /*********************************************************************** Returns a transaction savepoint taken at this point in time. */ @@ -237,7 +239,17 @@ trx_release_savepoint_for_mysql( const char* savepoint_name); /* in: savepoint name */ /*********************************************************************** -Frees savepoint structs. */ +Frees a single savepoint struct. */ + +void +trx_roll_savepoint_free( +/*=====================*/ + trx_t* trx, /* in: transaction handle */ + trx_named_savept_t* savep); /* in: savepoint to free */ + +/*********************************************************************** +Frees savepoint structs starting from savep, if savep == NULL then +free all savepoints. */ void trx_roll_savepoints_free( diff --git a/storage/innobase/trx/trx0roll.c b/storage/innobase/trx/trx0roll.c index 91dcf035f96..8934fe87c7e 100644 --- a/storage/innobase/trx/trx0roll.c +++ b/storage/innobase/trx/trx0roll.c @@ -185,7 +185,25 @@ trx_rollback_last_sql_stat_for_mysql( } /*********************************************************************** -Frees savepoint structs. */ +Frees a single savepoint struct. */ + +void +trx_roll_savepoint_free( +/*=====================*/ + trx_t* trx, /* in: transaction handle */ + trx_named_savept_t* savep) /* in: savepoint to free */ +{ + ut_a(savep != NULL); + ut_a(UT_LIST_GET_LEN(trx->trx_savepoints) > 0); + + UT_LIST_REMOVE(trx_savepoints, trx->trx_savepoints, savep); + mem_free(savep->name); + mem_free(savep); +} + +/*********************************************************************** +Frees savepoint structs starting from savep, if savep == NULL then +free all savepoints. */ void trx_roll_savepoints_free( @@ -206,9 +224,7 @@ trx_roll_savepoints_free( while (savep != NULL) { next_savep = UT_LIST_GET_NEXT(trx_savepoints, savep); - UT_LIST_REMOVE(trx_savepoints, trx->trx_savepoints, savep); - mem_free(savep->name); - mem_free(savep); + trx_roll_savepoint_free(trx, savep); savep = next_savep; } @@ -343,8 +359,8 @@ trx_savepoint_for_mysql( } /*********************************************************************** -Releases a named savepoint. Savepoints which -were set after this savepoint are deleted. */ +Releases only the named savepoint. Savepoints which were set after this +savepoint are left as is. */ ulint trx_release_savepoint_for_mysql( @@ -360,31 +376,16 @@ trx_release_savepoint_for_mysql( savep = UT_LIST_GET_FIRST(trx->trx_savepoints); + /* Search for the savepoint by name and free if found. */ while (savep != NULL) { if (0 == ut_strcmp(savep->name, savepoint_name)) { - /* Found */ - break; + trx_roll_savepoint_free(trx, savep); + return(DB_SUCCESS); } savep = UT_LIST_GET_NEXT(trx_savepoints, savep); } - if (savep == NULL) { - - return(DB_NO_SAVEPOINT); - } - - /* We can now free all savepoints strictly later than this one */ - - trx_roll_savepoints_free(trx, savep); - - /* Now we can free this savepoint too */ - - UT_LIST_REMOVE(trx_savepoints, trx->trx_savepoints, savep); - - mem_free(savep->name); - mem_free(savep); - - return(DB_SUCCESS); + return(DB_NO_SAVEPOINT); } /*********************************************************************** diff --git a/storage/innobase/trx/trx0trx.c b/storage/innobase/trx/trx0trx.c index 1fceaa3562c..43456865903 100644 --- a/storage/innobase/trx/trx0trx.c +++ b/storage/innobase/trx/trx0trx.c @@ -930,8 +930,8 @@ trx_commit_off_kernel( mutex_enter(&kernel_mutex); } - /* Free savepoints */ - trx_roll_savepoints_free(trx, NULL); + /* Free all savepoints */ + trx_roll_free_all_savepoints(trx); trx->conc_state = TRX_NOT_STARTED; trx->rseg = NULL; From 39a4ab6ce3340e43a6aee581792131a0da974498 Mon Sep 17 00:00:00 2001 From: Timothy Smith Date: Mon, 2 Mar 2009 18:08:02 -0700 Subject: [PATCH 166/219] Applying InnoDB snashot 5.1-ss3931, part 2. Fixes Bug #42075: dict_load_indexes failure in dict_load_table will corrupt the dictionary cache Detailed revision comments: r3930 | marko | 2009-01-14 15:51:30 +0200 (Wed, 14 Jan 2009) | 4 lines branches/5.1: dict_load_table(): If dict_load_indexes() fails, invoke dict_table_remove_from_cache() instead of dict_mem_table_free(), so that the data dictionary will not point to freed data. (Bug #42075, Issue #153, rb://76 approved by Heikki Tuuri) --- storage/innobase/dict/dict0load.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/storage/innobase/dict/dict0load.c b/storage/innobase/dict/dict0load.c index f594e64f517..65f1c9536bd 100644 --- a/storage/innobase/dict/dict0load.c +++ b/storage/innobase/dict/dict0load.c @@ -868,11 +868,11 @@ err_exit: of the error condition, since the user may want to dump data from the clustered index. However we load the foreign key information only if all indexes were loaded. */ - if (err != DB_SUCCESS && !srv_force_recovery) { - dict_mem_table_free(table); - table = NULL; - } else if (err == DB_SUCCESS) { + if (err == DB_SUCCESS) { err = dict_load_foreigns(table->name, TRUE); + } else if (!srv_force_recovery) { + dict_table_remove_from_cache(table); + table = NULL; } #if 0 if (err != DB_SUCCESS && table != NULL) { From d2e4204a1e9cda6fa64bc4910bbdb07281d7bee3 Mon Sep 17 00:00:00 2001 From: Timothy Smith Date: Mon, 2 Mar 2009 18:09:35 -0700 Subject: [PATCH 167/219] Applying InnoDB snashot 5.1-ss4007, part 1. Fixes Bug #41571: MySQL segfaults after innodb recovery Detailed revision comments: r4004 | marko | 2009-01-20 16:19:00 +0200 (Tue, 20 Jan 2009) | 12 lines branches/5.1: Merge r4003 from branches/5.0: rec_set_nth_field(): When the field already is SQL null, do nothing when it is being changed to SQL null. (Bug #41571) Normally, MySQL does not pass "do-nothing" updates to the storage engine. When it does and a column of an InnoDB table that is in ROW_FORMAT=COMPACT is being updated from NULL to NULL, the InnoDB buffer pool will be corrupted without this fix. rb://81 approved by Heikki Tuuri --- storage/innobase/include/rem0rec.h | 11 ++++------- storage/innobase/include/rem0rec.ic | 19 +++++++++---------- 2 files changed, 13 insertions(+), 17 deletions(-) diff --git a/storage/innobase/include/rem0rec.h b/storage/innobase/include/rem0rec.h index 43ef6650e90..abc204bb583 100644 --- a/storage/innobase/include/rem0rec.h +++ b/storage/innobase/include/rem0rec.h @@ -365,8 +365,9 @@ rec_set_field_extern_bits( /*************************************************************** This is used to modify the value of an already existing field in a record. The previous value must have exactly the same size as the new value. If len -is UNIV_SQL_NULL then the field is treated as an SQL null for old-style -records. For new-style records, len must not be UNIV_SQL_NULL. */ +is UNIV_SQL_NULL then the field is treated as an SQL null. +For records in ROW_FORMAT=COMPACT (new-style records), len must not be +UNIV_SQL_NULL unless the field already is SQL null. */ UNIV_INLINE void rec_set_nth_field( @@ -375,11 +376,7 @@ rec_set_nth_field( const ulint* offsets,/* in: array returned by rec_get_offsets() */ ulint n, /* in: index number of the field */ const void* data, /* in: pointer to the data if not SQL null */ - ulint len); /* in: length of the data or UNIV_SQL_NULL. - If not SQL null, must have the same - length as the previous value. - If SQL null, previous value must be - SQL null. */ + ulint len); /* in: length of the data or UNIV_SQL_NULL */ /************************************************************** The following function returns the data size of an old-style physical record, that is the sum of field lengths. SQL null fields diff --git a/storage/innobase/include/rem0rec.ic b/storage/innobase/include/rem0rec.ic index 5a4a0a0b5df..d91fb4c4391 100644 --- a/storage/innobase/include/rem0rec.ic +++ b/storage/innobase/include/rem0rec.ic @@ -1219,8 +1219,9 @@ rec_get_nth_field_size( /*************************************************************** This is used to modify the value of an already existing field in a record. The previous value must have exactly the same size as the new value. If len -is UNIV_SQL_NULL then the field is treated as an SQL null for old-style -records. For new-style records, len must not be UNIV_SQL_NULL. */ +is UNIV_SQL_NULL then the field is treated as an SQL null. +For records in ROW_FORMAT=COMPACT (new-style records), len must not be +UNIV_SQL_NULL unless the field already is SQL null. */ UNIV_INLINE void rec_set_nth_field( @@ -1230,11 +1231,7 @@ rec_set_nth_field( ulint n, /* in: index number of the field */ const void* data, /* in: pointer to the data if not SQL null */ - ulint len) /* in: length of the data or UNIV_SQL_NULL. - If not SQL null, must have the same - length as the previous value. - If SQL null, previous value must be - SQL null. */ + ulint len) /* in: length of the data or UNIV_SQL_NULL */ { byte* data2; ulint len2; @@ -1242,9 +1239,11 @@ rec_set_nth_field( ut_ad(rec); ut_ad(rec_offs_validate(rec, NULL, offsets)); - if (len == UNIV_SQL_NULL) { - ut_ad(!rec_offs_comp(offsets)); - rec_set_nth_field_sql_null(rec, n); + if (UNIV_UNLIKELY(len == UNIV_SQL_NULL)) { + if (!rec_offs_nth_sql_null(offsets, n)) { + ut_a(!rec_offs_comp(offsets)); + rec_set_nth_field_sql_null(rec, n); + } return; } From 17c0218a1810cf81c361b3cec4d26c51296b6dbf Mon Sep 17 00:00:00 2001 From: Timothy Smith Date: Mon, 2 Mar 2009 18:10:37 -0700 Subject: [PATCH 168/219] Applying InnoDB snashot 5.1-ss4007, part 2. Fixes Bug #42152: Race condition in lock_is_table_exclusive() Detailed revision comments: r4005 | marko | 2009-01-20 16:22:36 +0200 (Tue, 20 Jan 2009) | 8 lines branches/5.1: lock_is_table_exclusive(): Acquire kernel_mutex before accessing table->locks and release kernel_mutex before returning from the function. This fixes a portential race condition in the "commit every 10,000 rows" in ALTER TABLE, CREATE INDEX, DROP INDEX, and OPTIMIZE TABLE. (Bug #42152) rb://80 approved by Heikki Tuuri --- storage/innobase/lock/lock0lock.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/storage/innobase/lock/lock0lock.c b/storage/innobase/lock/lock0lock.c index 173d074cb82..d9bc8ba09e4 100644 --- a/storage/innobase/lock/lock0lock.c +++ b/storage/innobase/lock/lock0lock.c @@ -681,7 +681,10 @@ lock_is_table_exclusive( lock_t* lock; ibool ok = FALSE; - ut_ad(table && trx); + ut_ad(table); + ut_ad(trx); + + lock_mutex_enter_kernel(); for (lock = UT_LIST_GET_FIRST(table->locks); lock; @@ -689,7 +692,7 @@ lock_is_table_exclusive( if (lock->trx != trx) { /* A lock on the table is held by some other transaction. */ - return(FALSE); + goto not_ok; } if (!(lock_get_type(lock) & LOCK_TABLE)) { @@ -706,11 +709,16 @@ lock_is_table_exclusive( auto_increment lock. */ break; default: +not_ok: /* Other table locks than LOCK_IX are not allowed. */ - return(FALSE); + ok = FALSE; + goto func_exit; } } +func_exit: + lock_mutex_exit_kernel(); + return(ok); } @@ -3664,6 +3672,7 @@ lock_table_has_to_wait_in_queue( dict_table_t* table; lock_t* lock; + ut_ad(mutex_own(&kernel_mutex)); ut_ad(lock_get_wait(wait_lock)); table = wait_lock->un_member.tab_lock.table; From 140cc614c944154282fce87064f5e3552406a14c Mon Sep 17 00:00:00 2001 From: Matthias Leich Date: Tue, 3 Mar 2009 21:34:18 +0100 Subject: [PATCH 169/219] Last slice of fix for Bug#42003 tests missing the disconnect of connections <> default + Fix for Bug#43114 wait_until_count_sessions too restrictive, random PB failures + Removal of a lot of other weaknesses found + modifications according to review --- .../include/wait_until_count_sessions.inc | 33 +- mysql-test/r/consistent_snapshot.result | 32 +- mysql-test/r/dirty_close.result | 10 +- mysql-test/r/flush_block_commit.result | 74 +- .../r/flush_block_commit_notembedded.result | 30 +- mysql-test/r/flush_read_lock_kill.result | 17 +- mysql-test/r/lock_multi.result | 8 +- mysql-test/r/mysqlbinlog.result | 16 +- mysql-test/r/read_only.result | 2 +- mysql-test/r/show_check.result | 6 +- mysql-test/r/skip_name_resolve.result | 6 +- mysql-test/r/sp-security.result | 16 +- mysql-test/r/view.result | 66 +- mysql-test/r/view_grant.result | 4 +- mysql-test/t/alter_table-big.test | 7 +- mysql-test/t/connect.test | 42 +- mysql-test/t/consistent_snapshot.test | 44 +- mysql-test/t/dirty_close.test | 21 +- mysql-test/t/flush_block_commit.test | 96 +- .../t/flush_block_commit_notembedded.test | 47 +- mysql-test/t/flush_read_lock_kill.test | 35 +- mysql-test/t/init_connect.test | 10 +- mysql-test/t/lock_multi.test | 201 +++-- mysql-test/t/mysqlbinlog.test | 41 +- mysql-test/t/mysqltest.test | 25 +- mysql-test/t/read_only.test | 28 +- mysql-test/t/show_check.test | 73 +- mysql-test/t/skip_name_resolve.test | 9 +- mysql-test/t/sp-security.test | 59 +- mysql-test/t/sp_notembedded.test | 40 +- mysql-test/t/ssl-big.test | 28 +- mysql-test/t/ssl.test | 8 + mysql-test/t/ssl_compress.test | 10 + mysql-test/t/status.test | 7 + mysql-test/t/user_limits.test | 41 +- mysql-test/t/view.test | 833 ++++++++++-------- mysql-test/t/view_grant.test | 196 +++-- mysql-test/t/wait_timeout.test | 5 +- mysql-test/t/xa.test | 28 +- 39 files changed, 1352 insertions(+), 902 deletions(-) diff --git a/mysql-test/include/wait_until_count_sessions.inc b/mysql-test/include/wait_until_count_sessions.inc index 41348bee129..6364ac95ada 100644 --- a/mysql-test/include/wait_until_count_sessions.inc +++ b/mysql-test/include/wait_until_count_sessions.inc @@ -2,14 +2,23 @@ # # SUMMARY # -# Waits until the passed number ($count_sessions) of concurrent sessions was -# observed via +# Waits until the passed number ($count_sessions) of concurrent sessions or +# a smaller number was observed via # SHOW STATUS LIKE 'Threads_connected' # or the operation times out. -# Note: Starting with 5.1 we could also use -# SELECT COUNT(*) FROM information_schema.processlist -# I stay with "SHOW STATUS LIKE 'Threads_connected'" because this -# runs in all versions 5.0+ +# Note: +# 1. We wait for $current_sessions <= $count_sessions because in the use case +# with count_sessions.inc before and wait_until_count_sessions.inc after +# the core of the test it could happen that the disconnects of sessions +# belonging to the preceeding test are not finished. +# sessions at test begin($count_sessions) = m + n +# sessions of the previous test which will be soon disconnected = n (n >= 0) +# sessions at test end ($current sessions, assuming the test disconnects +# all additional sessions) = m +# 2. Starting with 5.1 we could also use +# SELECT COUNT(*) FROM information_schema.processlist +# I stay with "SHOW STATUS LIKE 'Threads_connected'" because this +# runs in all versions 5.0+ # # # USAGE @@ -19,7 +28,7 @@ # # OR typical example of a test which uses more than one session # Such a test could harm successing tests if there is no server shutdown -# and start between.cw +# and start between. # # If the testing box is slow than the disconnect of sessions belonging to # the current test might happen when the successing test gets executed. @@ -79,7 +88,11 @@ # backup.test, grant3.test # # -# Created: 2009-01-14 mleich +# Created: +# 2009-01-14 mleich +# Modified: +# 2009-02-24 mleich Fix Bug#43114 wait_until_count_sessions too restrictive, +# random PB failures # let $wait_counter= 100; @@ -93,7 +106,7 @@ let $wait_timeout= 0; while ($wait_counter) { let $current_sessions= query_get_value(SHOW STATUS LIKE 'Threads_connected', Value, 1); - let $success= `SELECT $current_sessions = $count_sessions`; + let $success= `SELECT $current_sessions <= $count_sessions`; if ($success) { let $wait_counter= 0; @@ -107,7 +120,7 @@ while ($wait_counter) if (!$success) { --echo # Timeout in wait_until_count_sessions.inc - --echo # Number of sessions expected: $count_sessions found: $current_sessions + --echo # Number of sessions expected: < $count_sessions found: $current_sessions SHOW PROCESSLIST; } diff --git a/mysql-test/r/consistent_snapshot.result b/mysql-test/r/consistent_snapshot.result index 90606abbe4e..694c996a58e 100644 --- a/mysql-test/r/consistent_snapshot.result +++ b/mysql-test/r/consistent_snapshot.result @@ -1,15 +1,23 @@ -drop table if exists t1; -create table t1 (a int) engine=innodb; -start transaction with consistent snapshot; -insert into t1 values(1); -select * from t1; +DROP TABLE IF EXISTS t1; +# Establish connection con1 (user=root) +# Establish connection con2 (user=root) +# Switch to connection con1 +CREATE TABLE t1 (a INT) ENGINE=innodb; +START TRANSACTION WITH CONSISTENT SNAPSHOT; +# Switch to connection con2 +INSERT INTO t1 VALUES(1); +# Switch to connection con1 +SELECT * FROM t1; a -commit; -delete from t1; -start transaction; -insert into t1 values(1); -select * from t1; +COMMIT; +DELETE FROM t1; +START TRANSACTION; +# Switch to connection con2 +INSERT INTO t1 VALUES(1); +# Switch to connection con1 +SELECT * FROM t1; a 1 -commit; -drop table t1; +COMMIT; +# Switch to connection default + close connections con1 and con2 +DROP TABLE t1; diff --git a/mysql-test/r/dirty_close.result b/mysql-test/r/dirty_close.result index c4fc19a35f8..b49b72f1b95 100644 --- a/mysql-test/r/dirty_close.result +++ b/mysql-test/r/dirty_close.result @@ -1,9 +1,9 @@ -drop table if exists t1; -create table t1 (n int); -insert into t1 values (1),(2),(3); -select * from t1; +DROP TABLE IF EXISTS t1; +CREATE TABLE t1 (n INT); +INSERT INTO t1 VALUES (1),(2),(3); +SELECT * FROM t1; n 1 2 3 -drop table t1; +DROP TABLE t1; diff --git a/mysql-test/r/flush_block_commit.result b/mysql-test/r/flush_block_commit.result index d5b10868358..d2197beaaab 100644 --- a/mysql-test/r/flush_block_commit.result +++ b/mysql-test/r/flush_block_commit.result @@ -1,39 +1,57 @@ -drop table if exists t1; -create table t1 (a int) engine=innodb; -begin; -insert into t1 values(1); -flush tables with read lock; -select * from t1; +# Establish connection con1 (user=root) +# Establish connection con2 (user=root) +# Establish connection con3 (user=root) +# Switch to connection con1 +DROP TABLE IF EXISTS t1; +CREATE TABLE t1 (a INT) ENGINE=innodb; +BEGIN; +INSERT INTO t1 VALUES(1); +# Switch to connection con2 +FLUSH TABLES WITH READ LOCK; +SELECT * FROM t1; a -commit; -select * from t1; +# Switch to connection con1 +COMMIT; +# Switch to connection con2 +SELECT * FROM t1; a -unlock tables; -begin; -select * from t1 for update; +UNLOCK TABLES; +# Switch to connection con1 +# Switch to connection con1 +BEGIN; +SELECT * FROM t1 FOR UPDATE; a 1 -begin; -select * from t1 for update; -flush tables with read lock; -commit; +# Switch to connection con2 +BEGIN; +SELECT * FROM t1 FOR UPDATE; +# Switch to connection con3 +FLUSH TABLES WITH READ LOCK; +# Switch to connection con1 +COMMIT; +# Switch to connection con2 a 1 -unlock tables; -commit; -begin; -insert into t1 values(10); -flush tables with read lock; -commit; -unlock tables; -flush tables with read lock; -unlock tables; -begin; -select * from t1; +# Switch to connection con3 +UNLOCK TABLES; +# Switch to connection con2 +COMMIT; +# Switch to connection con1 +BEGIN; +INSERT INTO t1 VALUES(10); +FLUSH TABLES WITH READ LOCK; +COMMIT; +UNLOCK TABLES; +# Switch to connection con2 +FLUSH TABLES WITH READ LOCK; +UNLOCK TABLES; +BEGIN; +SELECT * FROM t1; a 1 10 -show create database test; +SHOW CREATE DATABASE test; Database Create Database test CREATE DATABASE `test` /*!40100 DEFAULT CHARACTER SET latin1 */ -drop table t1; +DROP TABLE t1; +# Switch to connection default and close connections con1, con2, con3 diff --git a/mysql-test/r/flush_block_commit_notembedded.result b/mysql-test/r/flush_block_commit_notembedded.result index 599efeb3e2d..76c55e948dd 100644 --- a/mysql-test/r/flush_block_commit_notembedded.result +++ b/mysql-test/r/flush_block_commit_notembedded.result @@ -1,15 +1,23 @@ -create table t1 (a int) engine=innodb; -reset master; -set autocommit=0; -insert t1 values (1); -flush tables with read lock; -show master status; +# Establish connection con1 (user=root) +# Establish connection con2 (user=root) +# Switch to connection con1 +CREATE TABLE t1 (a INT) ENGINE=innodb; +RESET MASTER; +SET AUTOCOMMIT=0; +INSERT t1 VALUES (1); +# Switch to connection con2 +FLUSH TABLES WITH READ LOCK; +SHOW MASTER STATUS; File Position Binlog_Do_DB Binlog_Ignore_DB master-bin.000001 98 -commit; -show master status; +# Switch to connection con1 +COMMIT; +# Switch to connection con2 +SHOW MASTER STATUS; File Position Binlog_Do_DB Binlog_Ignore_DB master-bin.000001 98 -unlock tables; -drop table t1; -set autocommit=1; +UNLOCK TABLES; +# Switch to connection con1 +DROP TABLE t1; +SET AUTOCOMMIT=1; +# Switch to connection default and close connections con1 and con2 diff --git a/mysql-test/r/flush_read_lock_kill.result b/mysql-test/r/flush_read_lock_kill.result index 6703b6bd533..b16a8b114b3 100644 --- a/mysql-test/r/flush_read_lock_kill.result +++ b/mysql-test/r/flush_read_lock_kill.result @@ -1,9 +1,12 @@ -drop table if exists t1; -create table t1 (kill_id int); -insert into t1 values(connection_id()); -flush tables with read lock; -select ((@id := kill_id) - kill_id) from t1; +SET @old_concurrent_insert= @@global.concurrent_insert; +SET @@global.concurrent_insert= 0; +DROP TABLE IF EXISTS t1; +CREATE TABLE t1 (kill_id INT); +INSERT INTO t1 VALUES(connection_id()); +FLUSH TABLES WITH READ LOCK; +SELECT ((@id := kill_id) - kill_id) FROM t1; ((@id := kill_id) - kill_id) 0 -kill connection @id; -drop table t1; +KILL CONNECTION @id; +DROP TABLE t1; +SET @@global.concurrent_insert= @old_concurrent_insert; diff --git a/mysql-test/r/lock_multi.result b/mysql-test/r/lock_multi.result index 0430d560a7a..d1b50a0080c 100644 --- a/mysql-test/r/lock_multi.result +++ b/mysql-test/r/lock_multi.result @@ -51,10 +51,10 @@ ERROR HY000: Can't execute the query because you have a conflicting read lock UNLOCK TABLES; DROP DATABASE mysqltest_1; ERROR HY000: Can't drop database 'mysqltest_1'; database doesn't exist -use mysql; +USE mysql; LOCK TABLES columns_priv WRITE, db WRITE, host WRITE, user WRITE; FLUSH TABLES; -use mysql; +USE mysql; SELECT user.Select_priv FROM user, db WHERE user.user = db.user LIMIT 1; OPTIMIZE TABLES columns_priv, db, host, user; Table Op Msg_type Msg_text @@ -65,7 +65,7 @@ mysql.user optimize status OK UNLOCK TABLES; Select_priv N -use test; +USE test; use test; CREATE TABLE t1 (c1 int); LOCK TABLE t1 WRITE; @@ -93,7 +93,7 @@ create table t1 (a int); connection: locker lock tables t1 read; connection: writer -create table t2 like t1;; +create table t2 like t1; connection: default kill query ERROR 70100: Query execution was interrupted diff --git a/mysql-test/r/mysqlbinlog.result b/mysql-test/r/mysqlbinlog.result index 4fd87861ded..83e1459b71a 100644 --- a/mysql-test/r/mysqlbinlog.result +++ b/mysql-test/r/mysqlbinlog.result @@ -349,17 +349,17 @@ DELIMITER ; ROLLBACK /* added by mysqlbinlog */; /*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/; CREATE TABLE t1 (c1 CHAR(10)); -flush logs; +FLUSH LOGS; INSERT INTO t1 VALUES ('0123456789'); -flush logs; +FLUSH LOGS; DROP TABLE t1; # Query thread_id=REMOVED exec_time=REMOVED error_code=REMOVED -flush logs; -create table t1(a int); -insert into t1 values(connection_id()); -flush logs; -drop table t1; +FLUSH LOGS; +CREATE TABLE t1(a INT); +INSERT INTO t1 VALUES(connection_id()); +FLUSH LOGS; +DROP TABLE t1; 1 -drop table t1; +DROP TABLE t1; shell> mysqlbinlog std_data/corrupt-relay-bin.000624 > var/tmp/bug31793.sql End of 5.0 tests diff --git a/mysql-test/r/read_only.result b/mysql-test/r/read_only.result index 1bf99a8ea07..4b405ddd71a 100644 --- a/mysql-test/r/read_only.result +++ b/mysql-test/r/read_only.result @@ -47,7 +47,7 @@ Note 1051 Unknown table 'ttt' drop table t1,t2; drop user test@localhost; # -# Bug #27440 read_only allows create and drop database +# Bug#27440 read_only allows create and drop database # drop database if exists mysqltest_db1; drop database if exists mysqltest_db2; diff --git a/mysql-test/r/show_check.result b/mysql-test/r/show_check.result index ad3138e80ea..70e7a95fc5b 100644 --- a/mysql-test/r/show_check.result +++ b/mysql-test/r/show_check.result @@ -507,9 +507,9 @@ ERROR 42000: Access denied for user 'mysqltest_3'@'localhost' to database 'mysql drop table mysqltest.t1; drop database mysqltest; set names binary; -delete from mysql.user +delete from mysql.user where user='mysqltest_1' || user='mysqltest_2' || user='mysqltest_3'; -delete from mysql.db +delete from mysql.db where user='mysqltest_1' || user='mysqltest_2' || user='mysqltest_3'; flush privileges; CREATE TABLE t1 (i int, KEY (i)) ENGINE=MEMORY; @@ -916,7 +916,7 @@ def TRIGGERS DEFINER Definer 252 589815 14 N 17 0 33 Trigger Event Table Statement Timing Created sql_mode Definer t1_bi INSERT t1 SET @a = 1 BEFORE NULL root@localhost ---------------------------------------------------------------- -SELECT +SELECT TRIGGER_CATALOG, TRIGGER_SCHEMA, TRIGGER_NAME, diff --git a/mysql-test/r/skip_name_resolve.result b/mysql-test/r/skip_name_resolve.result index 8ef52e75238..47741fed250 100644 --- a/mysql-test/r/skip_name_resolve.result +++ b/mysql-test/r/skip_name_resolve.result @@ -5,10 +5,10 @@ GRANT USAGE ON *.* TO 'mysqltest_1'@'127.0.0.1/255.255.255.255' GRANT ALL PRIVILEGES ON `test`.* TO 'mysqltest_1'@'127.0.0.1/255.255.255.255' REVOKE ALL ON test.* FROM mysqltest_1@'127.0.0.1/255.255.255.255'; DROP USER mysqltest_1@'127.0.0.1/255.255.255.255'; -select user(); -user() +SELECT USER(); +USER() # -show processlist; +SHOW PROCESSLIST; Id User Host db Command Time State Info root test