diff options
author | unknown <serg@janus.mylan> | 2007-10-22 20:05:06 +0200 |
---|---|---|
committer | unknown <serg@janus.mylan> | 2007-10-22 20:05:06 +0200 |
commit | e3bd02cfbfdaa467cc69c2183bb1b437006fb2b2 (patch) | |
tree | 33cce67b2e6cc3df13415b46772f315da6eeead0 | |
parent | bdab4dcefe7ba9ba44a7a8cbc9cd32d282cf3ee6 (diff) | |
parent | fc800ff76d0c1f47126645c7ec742ae07434056b (diff) | |
download | mariadb-git-e3bd02cfbfdaa467cc69c2183bb1b437006fb2b2.tar.gz |
Merge bk-internal.mysql.com:/home/bk/mysql-5.1
into janus.mylan:/usr/home/serg/Abk/mysql-5.1
mysql-test/r/innodb_mysql.result:
Auto merged
sql/sql_base.cc:
Auto merged
sql/sql_parse.cc:
Auto merged
sql/sql_plugin.cc:
Auto merged
sql/table.cc:
Auto merged
tests/mysql_client_test.c:
Auto merged
97 files changed, 4181 insertions, 1045 deletions
diff --git a/client/mysqlcheck.c b/client/mysqlcheck.c index 09940acd4f4..fb2071ce10f 100644 --- a/client/mysqlcheck.c +++ b/client/mysqlcheck.c @@ -545,13 +545,13 @@ static int process_all_tables_in_db(char *database) -static int fix_object_name(const char *obj, const char *name) +static int fix_table_storage_name(const char *name) { char qbuf[100 + NAME_LEN*4]; int rc= 0; if (strncmp(name, "#mysql50#", 9)) return 1; - sprintf(qbuf, "RENAME %s `%s` TO `%s`", obj, name, name + 9); + sprintf(qbuf, "RENAME TABLE `%s` TO `%s`", name, name + 9); if (mysql_query(sock, qbuf)) { fprintf(stderr, "Failed to %s\n", qbuf); @@ -563,6 +563,23 @@ static int fix_object_name(const char *obj, const char *name) return rc; } +static int fix_database_storage_name(const char *name) +{ + char qbuf[100 + NAME_LEN*4]; + int rc= 0; + if (strncmp(name, "#mysql50#", 9)) + return 1; + sprintf(qbuf, "ALTER DATABASE `%s` UPGRADE DATA DIRECTORY NAME", name); + if (mysql_query(sock, qbuf)) + { + fprintf(stderr, "Failed to %s\n", qbuf); + fprintf(stderr, "Error: %s\n", mysql_error(sock)); + rc= 1; + } + if (verbose) + printf("%-50s %s\n", name, rc ? "FAILED" : "OK"); + return rc; +} static int process_one_db(char *database) { @@ -571,7 +588,7 @@ static int process_one_db(char *database) int rc= 0; if (opt_fix_db_names && !strncmp(database,"#mysql50#", 9)) { - rc= fix_object_name("DATABASE", database); + rc= fix_database_storage_name(database); database+= 9; } if (rc || !opt_fix_table_names) @@ -626,7 +643,7 @@ static int handle_request_for_tables(char *tables, uint length) op= (opt_write_binlog) ? "OPTIMIZE" : "OPTIMIZE NO_WRITE_TO_BINLOG"; break; case DO_UPGRADE: - return fix_object_name("TABLE", tables); + return fix_table_storage_name(tables); } if (!(query =(char *) my_malloc((sizeof(char)*(length+110)), MYF(MY_WME)))) diff --git a/client/mysqltest.c b/client/mysqltest.c index 39fe05e4928..04226719888 100644 --- a/client/mysqltest.c +++ b/client/mysqltest.c @@ -263,7 +263,7 @@ enum enum_commands { Q_REPLACE_REGEX, Q_REMOVE_FILE, Q_FILE_EXIST, Q_WRITE_FILE, Q_COPY_FILE, Q_PERL, Q_DIE, Q_EXIT, Q_SKIP, Q_CHMOD_FILE, Q_APPEND_FILE, Q_CAT_FILE, Q_DIFF_FILES, - Q_SEND_QUIT, + Q_SEND_QUIT, Q_CHANGE_USER, Q_UNKNOWN, /* Unknown command. */ Q_COMMENT, /* Comments, ignored. */ @@ -352,6 +352,7 @@ const char *command_names[]= "cat_file", "diff_files", "send_quit", + "change_user", 0 }; @@ -1507,7 +1508,7 @@ int dyn_string_cmp(DYNAMIC_STRING* ds, const char *fname) die("Failed to create temporary file for ds"); /* Write ds to temporary file and set file pos to beginning*/ - if (my_write(fd, ds->str, ds->length, + if (my_write(fd, (uchar *) ds->str, ds->length, MYF(MY_FNABP | MY_WME)) || my_seek(fd, 0, SEEK_SET, MYF(0)) == MY_FILEPOS_ERROR) { @@ -1998,7 +1999,7 @@ void var_set_query_get_value(struct st_command *command, VAR *var) const struct command_arg query_get_value_args[] = { "query", ARG_STRING, TRUE, &ds_query, "Query to run", "column name", ARG_STRING, TRUE, &ds_col, "Name of column", - "row number", ARG_STRING, TRUE, &ds_row, "Number for row", + "row number", ARG_STRING, TRUE, &ds_row, "Number for row" }; DBUG_ENTER("var_set_query_get_value"); @@ -3042,6 +3043,69 @@ void do_send_quit(struct st_command *command) /* SYNOPSIS + do_change_user + command called command + + DESCRIPTION + change_user [<user>], [<passwd>], [<db>] + <user> - user to change to + <passwd> - user password + <db> - default database + + Changes the user and causes the database specified by db to become + the default (current) database for the the current connection. + +*/ + +void do_change_user(struct st_command *command) +{ + MYSQL *mysql = &cur_con->mysql; + /* static keyword to make the NetWare compiler happy. */ + static DYNAMIC_STRING ds_user, ds_passwd, ds_db; + const struct command_arg change_user_args[] = { + { "user", ARG_STRING, FALSE, &ds_user, "User to connect as" }, + { "password", ARG_STRING, FALSE, &ds_passwd, "Password used when connecting" }, + { "database", ARG_STRING, FALSE, &ds_db, "Database to select after connect" }, + }; + + DBUG_ENTER("do_change_user"); + + check_command_args(command, command->first_argument, + change_user_args, + sizeof(change_user_args)/sizeof(struct command_arg), + ','); + + if (cur_con->stmt) + { + mysql_stmt_close(cur_con->stmt); + cur_con->stmt= NULL; + } + + if (!ds_user.length) + dynstr_set(&ds_user, mysql->user); + + if (!ds_passwd.length) + dynstr_set(&ds_passwd, mysql->passwd); + + if (!ds_db.length) + dynstr_set(&ds_db, mysql->db); + + DBUG_PRINT("info",("connection: '%s' user: '%s' password: '%s' database: '%s'", + cur_con->name, ds_user.str, ds_passwd.str, ds_db.str)); + + if (mysql_change_user(mysql, ds_user.str, ds_passwd.str, ds_db.str)) + die("change user failed: %s", mysql_error(mysql)); + + dynstr_free(&ds_user); + dynstr_free(&ds_passwd); + dynstr_free(&ds_db); + + DBUG_VOID_RETURN; +} + + +/* + SYNOPSIS do_perl command command handle @@ -6854,6 +6918,7 @@ int main(int argc, char **argv) case Q_APPEND_FILE: do_append_file(command); break; case Q_DIFF_FILES: do_diff_files(command); break; case Q_SEND_QUIT: do_send_quit(command); break; + case Q_CHANGE_USER: do_change_user(command); break; case Q_CAT_FILE: do_cat_file(command); break; case Q_COPY_FILE: do_copy_file(command); break; case Q_CHMOD_FILE: do_chmod_file(command); break; diff --git a/include/config-win.h b/include/config-win.h index 2e64e165630..07b316dcbab 100644 --- a/include/config-win.h +++ b/include/config-win.h @@ -21,6 +21,9 @@ /* We have to do this define before including windows.h to get the AWE API functions */ #define _WIN32_WINNT 0x0500 +#else +/* Get NT 4.0 functions */ +#define _WIN32_WINNT 0x0400 #endif #if defined(_MSC_VER) && _MSC_VER >= 1400 diff --git a/include/my_getopt.h b/include/my_getopt.h index c74f3ed672e..30c2eb9531a 100644 --- a/include/my_getopt.h +++ b/include/my_getopt.h @@ -68,6 +68,7 @@ extern my_error_reporter my_getopt_error_reporter; extern int handle_options (int *argc, char ***argv, const struct my_option *longopts, my_get_one_option); +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, diff --git a/include/my_pthread.h b/include/my_pthread.h index eb390c2acc4..88abddc9e25 100644 --- a/include/my_pthread.h +++ b/include/my_pthread.h @@ -101,6 +101,7 @@ struct timespec { void win_pthread_init(void); int win_pthread_setspecific(void *A,void *B,uint length); +int win_pthread_mutex_trylock(pthread_mutex_t *mutex); int pthread_create(pthread_t *,pthread_attr_t *,pthread_handler,void *); int pthread_cond_init(pthread_cond_t *cond, const pthread_condattr_t *attr); int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex); @@ -156,7 +157,7 @@ void pthread_exit(void *a); /* was #define pthread_exit(A) ExitThread(A)*/ #define pthread_equal(A,B) ((A) == (B)) #define pthread_mutex_init(A,B) (InitializeCriticalSection(A),0) #define pthread_mutex_lock(A) (EnterCriticalSection(A),0) -#define pthread_mutex_trylock(A) (WaitForSingleObject((A), 0) == WAIT_TIMEOUT) +#define pthread_mutex_trylock(A) win_pthread_mutex_trylock((A)) #define pthread_mutex_unlock(A) LeaveCriticalSection(A) #define pthread_mutex_destroy(A) DeleteCriticalSection(A) #define my_pthread_setprio(A,B) SetThreadPriority(GetCurrentThread(), (B)) @@ -472,7 +473,7 @@ typedef struct st_safe_mutex_info_t int safe_mutex_init(safe_mutex_t *mp, const pthread_mutexattr_t *attr, const char *file, uint line); -int safe_mutex_lock(safe_mutex_t *mp,const char *file, uint line); +int safe_mutex_lock(safe_mutex_t *mp, my_bool try_lock, const char *file, uint line); int safe_mutex_unlock(safe_mutex_t *mp,const char *file, uint line); int safe_mutex_destroy(safe_mutex_t *mp,const char *file, uint line); int safe_cond_wait(pthread_cond_t *cond, safe_mutex_t *mp,const char *file, @@ -495,12 +496,12 @@ void safe_mutex_end(FILE *file); #undef pthread_cond_timedwait #undef pthread_mutex_trylock #define pthread_mutex_init(A,B) safe_mutex_init((A),(B),__FILE__,__LINE__) -#define pthread_mutex_lock(A) safe_mutex_lock((A),__FILE__,__LINE__) +#define pthread_mutex_lock(A) safe_mutex_lock((A), FALSE, __FILE__, __LINE__) #define pthread_mutex_unlock(A) safe_mutex_unlock((A),__FILE__,__LINE__) #define pthread_mutex_destroy(A) safe_mutex_destroy((A),__FILE__,__LINE__) #define pthread_cond_wait(A,B) safe_cond_wait((A),(B),__FILE__,__LINE__) #define pthread_cond_timedwait(A,B,C) safe_cond_timedwait((A),(B),(C),__FILE__,__LINE__) -#define pthread_mutex_trylock(A) pthread_mutex_lock(A) +#define pthread_mutex_trylock(A) safe_mutex_lock((A), TRUE, __FILE__, __LINE__) #define pthread_mutex_t safe_mutex_t #define safe_mutex_assert_owner(mp) \ DBUG_ASSERT((mp)->count > 0 && \ diff --git a/include/mysql_com.h b/include/mysql_com.h index 5850d48fbf5..f76486b9ec2 100644 --- a/include/mysql_com.h +++ b/include/mysql_com.h @@ -203,7 +203,7 @@ typedef struct st_net { unsigned char reading_or_writing; char save_char; my_bool no_send_ok; /* For SPs and other things that do multiple stmts */ - my_bool no_send_eof; /* For SPs' first version read-only cursors */ + my_bool unused; /* Please remove with the next incompatible ABI change */ my_bool compress; /* Set if OK packet is already sent, and we do not need to send error diff --git a/include/mysql_h.ic b/include/mysql_h.ic index 8b1c36fdaab..12e16df878a 100644 --- a/include/mysql_h.ic +++ b/include/mysql_h.ic @@ -538,7 +538,7 @@ struct __attribute__((aligned(__alignof__(void *)), aligned(__alignof__(unsigned unsigned char reading_or_writing; char save_char; my_bool no_send_ok; - my_bool no_send_eof; + my_bool unused; my_bool compress; my_bool no_send_error; unsigned char * query_cache_query; diff --git a/libmysql/client_settings.h b/libmysql/client_settings.h index a803ff8372f..f87e625771f 100644 --- a/libmysql/client_settings.h +++ b/libmysql/client_settings.h @@ -63,3 +63,7 @@ int cli_read_change_user_result(MYSQL *mysql, char *buff, const char *passwd); int init_embedded_server(int argc, char **argv, char **groups); void end_embedded_server(); #endif /*EMBEDDED_LIBRARY*/ + +C_MODE_START +extern int mysql_init_character_set(MYSQL *mysql); +C_MODE_END diff --git a/libmysql/libmysql.c b/libmysql/libmysql.c index f0f2d60dcad..7807982df1a 100644 --- a/libmysql/libmysql.c +++ b/libmysql/libmysql.c @@ -698,14 +698,25 @@ int cli_read_change_user_result(MYSQL *mysql, char *buff, const char *passwd) return 0; } - my_bool STDCALL mysql_change_user(MYSQL *mysql, const char *user, const char *passwd, const char *db) { char buff[512],*end=buff; int rc; + CHARSET_INFO *saved_cs= mysql->charset; + DBUG_ENTER("mysql_change_user"); + /* Get the connection-default character set. */ + + if (mysql_init_character_set(mysql)) + { + mysql->charset= saved_cs; + DBUG_RETURN(TRUE); + } + + /* Use an empty string instead of NULL. */ + if (!user) user=""; if (!passwd) @@ -734,6 +745,14 @@ my_bool STDCALL mysql_change_user(MYSQL *mysql, const char *user, /* Add database if needed */ end= strmov(end, db ? db : "") + 1; + /* Add character set number. */ + + if (mysql->server_capabilities & CLIENT_SECURE_CONNECTION) + { + int2store(end, (ushort) mysql->charset->number); + end+= 2; + } + /* Write authentication package */ simple_command(mysql,COM_CHANGE_USER, (uchar*) buff, (ulong) (end-buff), 1); @@ -756,6 +775,11 @@ my_bool STDCALL mysql_change_user(MYSQL *mysql, const char *user, mysql->passwd=my_strdup(passwd,MYF(MY_WME)); mysql->db= db ? my_strdup(db,MYF(MY_WME)) : 0; } + else + { + mysql->charset= saved_cs; + } + DBUG_RETURN(rc); } @@ -2515,7 +2539,7 @@ static my_bool execute(MYSQL_STMT *stmt, char *packet, ulong length) 5 /* execution flags */]; my_bool res; DBUG_ENTER("execute"); - DBUG_DUMP("packet", packet, length); + DBUG_DUMP("packet", (uchar *) packet, length); mysql->last_used_con= mysql; int4store(buff, stmt->stmt_id); /* Send stmt id to server */ diff --git a/libmysqld/lib_sql.cc b/libmysqld/lib_sql.cc index 9c26febe627..4e525f8447f 100644 --- a/libmysqld/lib_sql.cc +++ b/libmysqld/lib_sql.cc @@ -111,7 +111,7 @@ emb_advanced_command(MYSQL *mysql, enum enum_server_command command, } thd->net.no_send_error= 0; - result= dispatch_command(command, thd, (char *) arg, arg_length + 1); + result= dispatch_command(command, thd, (char *) arg, arg_length); thd->cur_data= 0; if (!skip_check) diff --git a/mysql-test/include/handler.inc b/mysql-test/include/handler.inc index 437dd6ced4d..71647112126 100644 --- a/mysql-test/include/handler.inc +++ b/mysql-test/include/handler.inc @@ -498,3 +498,71 @@ handler t1_alias read a next; handler t1_alias READ a next where inexistent > 0; handler t1_alias close; drop table t1; + +# +# Bug#21587 FLUSH TABLES causes server crash when used with HANDLER statements +# + +--disable_warnings +drop table if exists t1,t2; +--enable_warnings +create table t1 (c1 int); +create table t2 (c1 int); +insert into t1 values (1); +insert into t2 values (2); +--echo connection: default +handler t1 open; +handler t1 read first; +connect (flush,localhost,root,,); +connection flush; +--echo connection: flush +--send flush tables; +connection default; +--echo connection: default +let $wait_condition= + select count(*) = 1 from information_schema.processlist + where state = "Flushing tables"; +--source include/wait_condition.inc +handler t2 open; +handler t2 read first; +handler t1 read next; +handler t1 close; +handler t2 close; +connection flush; +reap; +connection default; +drop table t1,t2; +disconnect flush; + +# +# Bug#31409 RENAME TABLE causes server crash or deadlock when used with HANDLER statements +# + +--disable_warnings +drop table if exists t1,t2; +--enable_warnings +create table t1 (c1 int); +--echo connection: default +handler t1 open; +handler t1 read first; +connect (flush,localhost,root,,); +connection flush; +--echo connection: flush +--send rename table t1 to t2; +connection default; +--echo connection: default +let $wait_condition= + select count(*) = 1 from information_schema.processlist + where state = "Waiting for table" and info = "rename table t1 to t2"; +--source include/wait_condition.inc +handler t2 open; +handler t2 read first; +--error ER_NO_SUCH_TABLE +handler t1 read next; +handler t1 close; +handler t2 close; +connection flush; +reap; +connection default; +drop table t2; +disconnect flush; diff --git a/mysql-test/include/mix1.inc b/mysql-test/include/mix1.inc index e2a22303d9d..aee5613ff35 100644 --- a/mysql-test/include/mix1.inc +++ b/mysql-test/include/mix1.inc @@ -1146,4 +1146,38 @@ select @b:=f2 from t1; select if(@a=@b,"ok","wrong"); drop table t1; +# +# Bug#30747 Create table with identical constraint names behaves incorrectly +# + +if ($test_foreign_keys) +{ + CREATE TABLE t1 (a INT NOT NULL, b INT NOT NULL, PRIMARY KEY (a,b)) engine=innodb; + --error ER_WRONG_FK_DEF + CREATE TABLE t2 (c INT NOT NULL, d INT NOT NULL, PRIMARY KEY (c,d), + CONSTRAINT c2 FOREIGN KEY f2 (c) REFERENCES t1 (a,b) ON UPDATE NO ACTION) engine=innodb; + --error ER_WRONG_FK_DEF + CREATE TABLE t2 (c INT NOT NULL, d INT NOT NULL, PRIMARY KEY (c,d), + CONSTRAINT c2 FOREIGN KEY (c) REFERENCES t1 (a,b) ON UPDATE NO ACTION) engine=innodb; + CREATE TABLE t2 (c INT NOT NULL, d INT NOT NULL, PRIMARY KEY (c,d), + CONSTRAINT c1 FOREIGN KEY c2 (c) REFERENCES t1 (a) ON DELETE NO ACTION, + CONSTRAINT c2 FOREIGN KEY (c) REFERENCES t1 (a) ON UPDATE NO ACTION) engine=innodb; + ALTER TABLE t2 DROP FOREIGN KEY c2; + DROP TABLE t2; + --error ER_WRONG_FK_DEF + CREATE TABLE t2 (c INT NOT NULL, d INT NOT NULL, PRIMARY KEY (c,d), + FOREIGN KEY (c) REFERENCES t1 (a,k) ON UPDATE NO ACTION) engine=innodb; + --error ER_WRONG_FK_DEF + CREATE TABLE t2 (c INT NOT NULL, d INT NOT NULL, PRIMARY KEY (c,d), + FOREIGN KEY f1 (c) REFERENCES t1 (a,k) ON UPDATE NO ACTION) engine=innodb; + CREATE TABLE t2 (c INT NOT NULL, d INT NOT NULL, PRIMARY KEY (c,d), + CONSTRAINT c1 FOREIGN KEY f1 (c) REFERENCES t1 (a) ON DELETE NO ACTION, + CONSTRAINT c2 FOREIGN KEY (c) REFERENCES t1 (a) ON UPDATE NO ACTION, + FOREIGN KEY f3 (c) REFERENCES t1 (a) ON UPDATE NO ACTION, + FOREIGN KEY (c) REFERENCES t1 (a) ON UPDATE NO ACTION) engine=innodb; + SHOW CREATE TABLE t2; + DROP TABLE t2; + DROP TABLE t1; +} + --echo End of 5.1 tests diff --git a/mysql-test/r/change_user.result b/mysql-test/r/change_user.result new file mode 100644 index 00000000000..cb409621d56 --- /dev/null +++ b/mysql-test/r/change_user.result @@ -0,0 +1,46 @@ +Bug#20023 +SELECT @@session.sql_big_selects; +@@session.sql_big_selects +1 +SELECT @@global.max_join_size; +@@global.max_join_size +-1 +change_user +SELECT @@session.sql_big_selects; +@@session.sql_big_selects +1 +SELECT @@global.max_join_size; +@@global.max_join_size +-1 +SET @@global.max_join_size = 10000; +SET @@session.max_join_size = default; +change_user +SELECT @@session.sql_big_selects; +@@session.sql_big_selects +0 +SET @@global.max_join_size = -1; +SET @@session.max_join_size = default; +change_user +SELECT @@session.sql_big_selects; +@@session.sql_big_selects +1 +Bug#31418 +SELECT IS_FREE_LOCK('bug31418'); +IS_FREE_LOCK('bug31418') +1 +SELECT IS_USED_LOCK('bug31418'); +IS_USED_LOCK('bug31418') +NULL +SELECT GET_LOCK('bug31418', 1); +GET_LOCK('bug31418', 1) +1 +SELECT IS_USED_LOCK('bug31418') = CONNECTION_ID(); +IS_USED_LOCK('bug31418') = CONNECTION_ID() +1 +change_user +SELECT IS_FREE_LOCK('bug31418'); +IS_FREE_LOCK('bug31418') +1 +SELECT IS_USED_LOCK('bug31418'); +IS_USED_LOCK('bug31418') +NULL diff --git a/mysql-test/r/create.result b/mysql-test/r/create.result index b370fbf6fbe..e79a255967b 100644 --- a/mysql-test/r/create.result +++ b/mysql-test/r/create.result @@ -1588,14 +1588,6 @@ CREATE DATABASE aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa ERROR 42000: Incorrect database name 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' DROP DATABASE aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa; ERROR 42000: Incorrect database name 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' -RENAME DATABASE aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa TO a; -ERROR 42000: Unknown database 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' -RENAME DATABASE mysqltest TO aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa; -ERROR 42000: Incorrect database name 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' -create database mysqltest; -RENAME DATABASE mysqltest TO aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa; -ERROR 42000: Incorrect database name 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' -drop database mysqltest; USE aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa; ERROR 42000: Incorrect database name 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' SHOW CREATE DATABASE aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa; @@ -1699,4 +1691,18 @@ ERROR 42000: Identifier name 'очень_очень_очень_очень_оче drop view имÑ_вью_кодировке_утф8_длиной_больше_чем_42; drop table имÑ_таблицы_в_кодировке_утф8_длиной_больше_чем_48; set names default; +drop table if exists t1,t2,t3; +drop function if exists f1; +create function f1() returns int +begin +declare res int; +create temporary table t3 select 1 i; +set res:= (select count(*) from t1); +drop temporary table t3; +return res; +end| +create table t1 as select 1; +create table t2 as select f1() from t1; +drop table t1,t2; +drop function f1; End of 5.1 tests diff --git a/mysql-test/r/csv.result b/mysql-test/r/csv.result index 86ba5002af8..69f77dc3cd8 100644 --- a/mysql-test/r/csv.result +++ b/mysql-test/r/csv.result @@ -4929,7 +4929,7 @@ Note 1051 Unknown table 't2' Note 1051 Unknown table 't3' Note 1051 Unknown table 't4' DROP TABLE IF EXISTS bug13894; -CREATE TABLE bug13894 ( val integer ) ENGINE = CSV; +CREATE TABLE bug13894 ( val integer not null ) ENGINE = CSV; INSERT INTO bug13894 VALUES (5); INSERT INTO bug13894 VALUES (10); INSERT INTO bug13894 VALUES (11); @@ -4949,7 +4949,7 @@ val 11 DROP TABLE bug13894; DROP TABLE IF EXISTS bug14672; -CREATE TABLE bug14672 (c1 integer) engine = CSV; +CREATE TABLE bug14672 (c1 integer not null) engine = CSV; INSERT INTO bug14672 VALUES (1), (2), (3); SELECT * FROM bug14672; c1 @@ -4975,7 +4975,7 @@ c1 4 5 DROP TABLE bug14672; -CREATE TABLE test_concurrent_insert ( val integer ) ENGINE = CSV; +CREATE TABLE test_concurrent_insert ( val integer not null ) ENGINE = CSV; LOCK TABLES test_concurrent_insert READ LOCAL; INSERT INTO test_concurrent_insert VALUES (1); SELECT * FROM test_concurrent_insert; @@ -4992,7 +4992,7 @@ val 2 UNLOCK TABLES; DROP TABLE test_concurrent_insert; -CREATE TABLE test_repair_table ( val integer ) ENGINE = CSV; +CREATE TABLE test_repair_table ( val integer not null ) ENGINE = CSV; CHECK TABLE test_repair_table; Table Op Msg_type Msg_text test.test_repair_table check status OK @@ -5000,7 +5000,7 @@ REPAIR TABLE test_repair_table; Table Op Msg_type Msg_text test.test_repair_table repair status OK DROP TABLE test_repair_table; -CREATE TABLE test_repair_table2 ( val integer ) ENGINE = CSV; +CREATE TABLE test_repair_table2 ( val integer not null ) ENGINE = CSV; SELECT * from test_repair_table2; val Warnings: @@ -5011,7 +5011,7 @@ CHECK TABLE test_repair_table2; Table Op Msg_type Msg_text test.test_repair_table2 check status OK DROP TABLE test_repair_table2; -CREATE TABLE test_repair_table3 ( val integer ) ENGINE = CSV; +CREATE TABLE test_repair_table3 ( val integer not null ) ENGINE = CSV; CHECK TABLE test_repair_table3; Table Op Msg_type Msg_text test.test_repair_table3 check error Corrupt @@ -5114,7 +5114,7 @@ num magic_no company_name founded 1 0102 CORRECT 1876 1 0102 CORRECT2 1876 DROP TABLE test_repair_table5; -create table t1 (a int) engine=csv; +create table t1 (a int not null) engine=csv; insert t1 values (1); delete from t1; affected rows: 1 @@ -5138,7 +5138,7 @@ insert t1 values (1),(2),(3),(4),(5); truncate table t1; affected rows: 0 drop table t1; -create table t1 (v varchar(32)); +create table t1 (v varchar(32) not null); insert into t1 values ('def'),('abc'),('hij'),('3r4f'); select * from t1; v @@ -5193,8 +5193,8 @@ select * from t1 where i between 2 and 4 and v in ('def','3r4f','lmn'); i v 4 3r4f drop table t1; -create table bug15205 (val int(11) default null) engine=csv; -create table bug15205_2 (val int(11) default null) engine=csv; +create table bug15205 (val int(11) not null) engine=csv; +create table bug15205_2 (val int(11) not null) engine=csv; select * from bug15205; ERROR HY000: Can't get stat of './test/bug15205.CSV' (Errcode: 2) select * from bug15205_2; @@ -5205,8 +5205,8 @@ drop table bug15205; drop table bug15205_2; set names latin1; create table t1 ( -c varchar(1), -name varchar(64) +c varchar(1) not null, +name varchar(64) not null ) character set latin1 engine=csv; insert into t1 values (0xC0,'LATIN CAPITAL LETTER A WITH GRAVE'); insert into t1 values (0xE0,'LATIN SMALL LETTER A WITH GRAVE'); @@ -5224,9 +5224,9 @@ FE þ LATIN SMALL LETTER THORN FF ÿ LATIN SMALL LETTER Y WITH DIAERESIS drop table t1; End of 5.0 tests -create table bug22080_1 (id int,string varchar(64)) Engine=CSV; -create table bug22080_2 (id int,string varchar(64)) Engine=CSV; -create table bug22080_3 (id int,string varchar(64)) Engine=CSV; +create table bug22080_1 (id int not null,string varchar(64) not null) Engine=CSV; +create table bug22080_2 (id int not null,string varchar(64) not null) Engine=CSV; +create table bug22080_3 (id int not null,string varchar(64) not null) Engine=CSV; insert into bug22080_1 values(1,'string'); insert into bug22080_1 values(2,'string'); insert into bug22080_1 values(3,'string'); @@ -5237,7 +5237,7 @@ check table bug22080_3; Table Op Msg_type Msg_text test.bug22080_3 check error Corrupt drop tables bug22080_1,bug22080_2,bug22080_3; -create table float_test (id float,string varchar(64)) Engine=CSV; +create table float_test (id float not null,string varchar(64) not null) Engine=CSV; insert into float_test values(1.0,'string'); insert into float_test values(2.23,'serg.g'); insert into float_test values(0.03,'string'); @@ -5254,14 +5254,14 @@ id string 9.67 string drop table float_test; CREATE TABLE `bug21328` ( -`col1` int(11) DEFAULT NULL, -`col2` int(11) DEFAULT NULL, -`col3` int(11) DEFAULT NULL +`col1` int(11) NOT NULL, +`col2` int(11) NOT NULL, +`col3` int(11) NOT NULL ) ENGINE=CSV; -insert into bug21328 values (1,NULL,NULL); +insert into bug21328 values (1,0,0); alter table bug21328 engine=myisam; drop table bug21328; -create table t1(a blob, b int) engine=csv; +create table t1(a blob not null, b int not null) engine=csv; insert into t1 values('a', 1); flush tables; update t1 set b=2; @@ -5269,7 +5269,7 @@ select * from t1; a b a 2 drop table t1; -create table t1(a int) engine=csv; +create table t1(a int not null) engine=csv; insert into t1 values(-1), (-123.34), (2), (-23); select * from t1; a @@ -5281,7 +5281,7 @@ check table t1; Table Op Msg_type Msg_text test.t1 check status OK drop table t1; -create table t1(a int, b int) engine=csv; +create table t1(a int not null, b int not null) engine=csv; repair table t1; Table Op Msg_type Msg_text test.t1 repair Warning Data truncated for column 'a' at row 5 @@ -5299,7 +5299,7 @@ check table t1; Table Op Msg_type Msg_text test.t1 check status OK drop table t1; -create table t1(a int) engine=csv; +create table t1(a int not null) engine=csv; insert into t1 values (0), (1), (2); delete from t1 limit 2; check table t1; @@ -5315,4 +5315,62 @@ test.t1 check status OK select * from t1; a drop table t1; +create table t1(a datetime not null) engine=csv; +insert into t1 values(); +Warnings: +Warning 1364 Field 'a' doesn't have a default value +select * from t1; +a +0000-00-00 00:00:00 +drop table t1; +create table t1(a set('foo','bar') not null) engine=csv; +insert into t1 values(); +Warnings: +Warning 1364 Field 'a' doesn't have a default value +select * from t1; +a + +drop table t1; +create table t1(a varchar(32) not null) engine=csv; +insert into t1 values(); +Warnings: +Warning 1364 Field 'a' doesn't have a default value +select * from t1; +a + +drop table t1; +create table t1(a int not null) engine=csv; +insert into t1 values(); +Warnings: +Warning 1364 Field 'a' doesn't have a default value +select * from t1; +a +0 +drop table t1; +create table t1(a blob not null) engine=csv; +insert into t1 values(); +Warnings: +Warning 1364 Field 'a' doesn't have a default value +select * from t1; +a + +drop table t1; +create table t1(a bit(1) not null) engine=csv; +insert into t1 values(); +Warnings: +Warning 1364 Field 'a' doesn't have a default value +select BIN(a) from t1; +BIN(a) +0 +drop table t1; +create table t1(a enum('foo','bar') default null) engine=csv; +ERROR HY000: Can't create table 'test.t1' (errno: -1) +create table t1(a enum('foo','bar') default 'foo') engine=csv; +ERROR HY000: Can't create table 'test.t1' (errno: -1) +create table t1(a enum('foo','bar') default 'foo' not null) engine=csv; +insert into t1 values(); +select * from t1; +a +foo +drop table t1; End of 5.1 tests diff --git a/mysql-test/r/delayed.result b/mysql-test/r/delayed.result index fb8dc9af71a..c520ab52ab3 100644 --- a/mysql-test/r/delayed.result +++ b/mysql-test/r/delayed.result @@ -255,3 +255,32 @@ CREATE TABLE t2(c1 INT) ENGINE=MERGE UNION=(t1); INSERT DELAYED INTO t2 VALUES(1); ERROR HY000: Table storage engine for 't2' doesn't have this option DROP TABLE t1, t2; +DROP TABLE IF EXISTS t1,t2; +SET SQL_MODE='NO_AUTO_VALUE_ON_ZERO'; +CREATE TABLE `t1` ( +`id` int(11) PRIMARY KEY auto_increment, +`f1` varchar(10) NOT NULL UNIQUE +); +INSERT DELAYED INTO t1 VALUES(0,"test1"); +SELECT * FROM t1; +id f1 +0 test1 +SET SQL_MODE='PIPES_AS_CONCAT'; +INSERT DELAYED INTO t1 VALUES(0,'a' || 'b'); +SELECT * FROM t1; +id f1 +0 test1 +1 ab +SET SQL_MODE='ERROR_FOR_DIVISION_BY_ZERO,STRICT_ALL_TABLES'; +INSERT DELAYED INTO t1 VALUES(mod(1,0),"test3"); +ERROR 22012: Division by 0 +CREATE TABLE t2 ( +`id` int(11) PRIMARY KEY auto_increment, +`f1` date +); +SET SQL_MODE='NO_ZERO_DATE,STRICT_ALL_TABLES,NO_ZERO_IN_DATE'; +INSERT DELAYED INTO t2 VALUES (0,'0000-00-00'); +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; diff --git a/mysql-test/r/handler_innodb.result b/mysql-test/r/handler_innodb.result index 98b8922bc5f..e9e5c7dbdd5 100644 --- a/mysql-test/r/handler_innodb.result +++ b/mysql-test/r/handler_innodb.result @@ -535,3 +535,43 @@ handler t1_alias READ a next where inexistent > 0; ERROR 42S22: Unknown column 'inexistent' in 'field list' handler t1_alias close; drop table t1; +drop table if exists t1,t2; +create table t1 (c1 int); +create table t2 (c1 int); +insert into t1 values (1); +insert into t2 values (2); +connection: default +handler t1 open; +handler t1 read first; +c1 +1 +connection: flush +flush tables;; +connection: default +handler t2 open; +handler t2 read first; +c1 +2 +handler t1 read next; +c1 +1 +handler t1 close; +handler t2 close; +drop table t1,t2; +drop table if exists t1,t2; +create table t1 (c1 int); +connection: default +handler t1 open; +handler t1 read first; +c1 +connection: flush +rename table t1 to t2;; +connection: default +handler t2 open; +handler t2 read first; +c1 +handler t1 read next; +ERROR 42S02: Table 'test.t1' doesn't exist +handler t1 close; +handler t2 close; +drop table t2; diff --git a/mysql-test/r/handler_myisam.result b/mysql-test/r/handler_myisam.result index 464b775b795..715e5ab03d6 100644 --- a/mysql-test/r/handler_myisam.result +++ b/mysql-test/r/handler_myisam.result @@ -535,3 +535,43 @@ handler t1_alias READ a next where inexistent > 0; ERROR 42S22: Unknown column 'inexistent' in 'field list' handler t1_alias close; drop table t1; +drop table if exists t1,t2; +create table t1 (c1 int); +create table t2 (c1 int); +insert into t1 values (1); +insert into t2 values (2); +connection: default +handler t1 open; +handler t1 read first; +c1 +1 +connection: flush +flush tables;; +connection: default +handler t2 open; +handler t2 read first; +c1 +2 +handler t1 read next; +c1 +1 +handler t1 close; +handler t2 close; +drop table t1,t2; +drop table if exists t1,t2; +create table t1 (c1 int); +connection: default +handler t1 open; +handler t1 read first; +c1 +connection: flush +rename table t1 to t2;; +connection: default +handler t2 open; +handler t2 read first; +c1 +handler t1 read next; +ERROR 42S02: Table 'test.t1' doesn't exist +handler t1 close; +handler t2 close; +drop table t2; diff --git a/mysql-test/r/heap_btree.result b/mysql-test/r/heap_btree.result index 44241563dda..9db03855c01 100644 --- a/mysql-test/r/heap_btree.result +++ b/mysql-test/r/heap_btree.result @@ -307,6 +307,13 @@ UNIQUE USING BTREE(c1) ) ENGINE= MEMORY DEFAULT CHARSET= utf8; INSERT INTO t1 VALUES('1'), ('2'); DROP TABLE t1; +CREATE TABLE t1 (a INT, KEY USING BTREE(a)) ENGINE=MEMORY; +INSERT INTO t1 VALUES(1),(2),(2); +DELETE FROM t1 WHERE a=2; +SELECT * FROM t1; +a +1 +DROP TABLE t1; End of 4.1 tests CREATE TABLE t1(val INT, KEY USING BTREE(val)) ENGINE=memory; INSERT INTO t1 VALUES(0); diff --git a/mysql-test/r/information_schema.result b/mysql-test/r/information_schema.result index 885acf5c744..d1120d24884 100644 --- a/mysql-test/r/information_schema.result +++ b/mysql-test/r/information_schema.result @@ -578,7 +578,7 @@ proc sql_data_access enum('CONTAINS_SQL','NO_SQL','READS_SQL_DATA','MODIFIES_SQL proc is_deterministic enum('YES','NO') proc security_type enum('INVOKER','DEFINER') proc param_list blob -proc returns char(64) +proc returns longblob proc body longblob proc definer char(77) proc created timestamp diff --git a/mysql-test/r/innodb_mysql.result b/mysql-test/r/innodb_mysql.result index 73aaa23679f..a2f249ad4f5 100644 --- a/mysql-test/r/innodb_mysql.result +++ b/mysql-test/r/innodb_mysql.result @@ -1421,4 +1421,40 @@ select if(@a=@b,"ok","wrong"); if(@a=@b,"ok","wrong") ok drop table t1; +CREATE TABLE t1 (a INT NOT NULL, b INT NOT NULL, PRIMARY KEY (a,b)) engine=innodb; +CREATE TABLE t2 (c INT NOT NULL, d INT NOT NULL, PRIMARY KEY (c,d), +CONSTRAINT c2 FOREIGN KEY f2 (c) REFERENCES t1 (a,b) ON UPDATE NO ACTION) engine=innodb; +ERROR 42000: Incorrect foreign key definition for 'f2': Key reference and table reference don't match +CREATE TABLE t2 (c INT NOT NULL, d INT NOT NULL, PRIMARY KEY (c,d), +CONSTRAINT c2 FOREIGN KEY (c) REFERENCES t1 (a,b) ON UPDATE NO ACTION) engine=innodb; +ERROR 42000: Incorrect foreign key definition for 'c2': Key reference and table reference don't match +CREATE TABLE t2 (c INT NOT NULL, d INT NOT NULL, PRIMARY KEY (c,d), +CONSTRAINT c1 FOREIGN KEY c2 (c) REFERENCES t1 (a) ON DELETE NO ACTION, +CONSTRAINT c2 FOREIGN KEY (c) REFERENCES t1 (a) ON UPDATE NO ACTION) engine=innodb; +ALTER TABLE t2 DROP FOREIGN KEY c2; +DROP TABLE t2; +CREATE TABLE t2 (c INT NOT NULL, d INT NOT NULL, PRIMARY KEY (c,d), +FOREIGN KEY (c) REFERENCES t1 (a,k) ON UPDATE NO ACTION) engine=innodb; +ERROR 42000: Incorrect foreign key definition for 'foreign key without name': Key reference and table reference don't match +CREATE TABLE t2 (c INT NOT NULL, d INT NOT NULL, PRIMARY KEY (c,d), +FOREIGN KEY f1 (c) REFERENCES t1 (a,k) ON UPDATE NO ACTION) engine=innodb; +ERROR 42000: Incorrect foreign key definition for 'f1': Key reference and table reference don't match +CREATE TABLE t2 (c INT NOT NULL, d INT NOT NULL, PRIMARY KEY (c,d), +CONSTRAINT c1 FOREIGN KEY f1 (c) REFERENCES t1 (a) ON DELETE NO ACTION, +CONSTRAINT c2 FOREIGN KEY (c) REFERENCES t1 (a) ON UPDATE NO ACTION, +FOREIGN KEY f3 (c) REFERENCES t1 (a) ON UPDATE NO ACTION, +FOREIGN KEY (c) REFERENCES t1 (a) ON UPDATE NO ACTION) engine=innodb; +SHOW CREATE TABLE t2; +Table Create Table +t2 CREATE TABLE `t2` ( + `c` int(11) NOT NULL, + `d` int(11) NOT NULL, + PRIMARY KEY (`c`,`d`), + CONSTRAINT `c1` FOREIGN KEY (`c`) REFERENCES `t1` (`a`) ON DELETE NO ACTION, + CONSTRAINT `c2` FOREIGN KEY (`c`) REFERENCES `t1` (`a`) ON UPDATE NO ACTION, + CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`c`) REFERENCES `t1` (`a`) ON UPDATE NO ACTION, + CONSTRAINT `t2_ibfk_2` FOREIGN KEY (`c`) REFERENCES `t1` (`a`) ON UPDATE NO ACTION +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +DROP TABLE t2; +DROP TABLE t1; End of 5.1 tests diff --git a/mysql-test/r/log_tables.result b/mysql-test/r/log_tables.result index 5e18e1273c0..261e3292f4d 100644 --- a/mysql-test/r/log_tables.result +++ b/mysql-test/r/log_tables.result @@ -42,20 +42,20 @@ show create table mysql.general_log; Table Create Table general_log CREATE TABLE `general_log` ( `event_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - `user_host` mediumtext, - `thread_id` int(11) DEFAULT NULL, - `server_id` int(11) DEFAULT NULL, - `command_type` varchar(64) DEFAULT NULL, - `argument` mediumtext + `user_host` mediumtext NOT NULL, + `thread_id` int(11) NOT NULL, + `server_id` int(11) NOT NULL, + `command_type` varchar(64) NOT NULL, + `argument` mediumtext NOT NULL ) ENGINE=CSV DEFAULT CHARSET=utf8 COMMENT='General log' show fields from mysql.general_log; Field Type Null Key Default Extra event_time timestamp NO CURRENT_TIMESTAMP -user_host mediumtext YES NULL -thread_id int(11) YES NULL -server_id int(11) YES NULL -command_type varchar(64) YES NULL -argument mediumtext YES NULL +user_host mediumtext NO NULL +thread_id int(11) NO NULL +server_id int(11) NO NULL +command_type varchar(64) NO NULL +argument mediumtext NO NULL show create table mysql.slow_log; Table Create Table slow_log CREATE TABLE `slow_log` ( @@ -65,10 +65,10 @@ slow_log CREATE TABLE `slow_log` ( `lock_time` time NOT NULL, `rows_sent` int(11) NOT NULL, `rows_examined` int(11) NOT NULL, - `db` varchar(512) DEFAULT NULL, - `last_insert_id` int(11) DEFAULT NULL, - `insert_id` int(11) DEFAULT NULL, - `server_id` int(11) DEFAULT NULL, + `db` varchar(512) NOT NULL, + `last_insert_id` int(11) NOT NULL, + `insert_id` int(11) NOT NULL, + `server_id` int(11) NOT NULL, `sql_text` mediumtext NOT NULL ) ENGINE=CSV DEFAULT CHARSET=utf8 COMMENT='Slow log' show fields from mysql.slow_log; @@ -79,10 +79,10 @@ query_time time NO NULL lock_time time NO NULL rows_sent int(11) NO NULL rows_examined int(11) NO NULL -db varchar(512) YES NULL -last_insert_id int(11) YES NULL -insert_id int(11) YES NULL -server_id int(11) YES NULL +db varchar(512) NO NULL +last_insert_id int(11) NO NULL +insert_id int(11) NO NULL +server_id int(11) NO NULL sql_text mediumtext NO NULL flush logs; flush tables; @@ -141,11 +141,11 @@ show create table mysql.general_log; Table Create Table general_log CREATE TABLE `general_log` ( `event_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - `user_host` mediumtext, - `thread_id` int(11) DEFAULT NULL, - `server_id` int(11) DEFAULT NULL, - `command_type` varchar(64) DEFAULT NULL, - `argument` mediumtext + `user_host` mediumtext NOT NULL, + `thread_id` int(11) NOT NULL, + `server_id` int(11) NOT NULL, + `command_type` varchar(64) NOT NULL, + `argument` mediumtext NOT NULL ) ENGINE=CSV DEFAULT CHARSET=utf8 COMMENT='General log' show create table mysql.slow_log; Table Create Table @@ -156,10 +156,10 @@ slow_log CREATE TABLE `slow_log` ( `lock_time` time NOT NULL, `rows_sent` int(11) NOT NULL, `rows_examined` int(11) NOT NULL, - `db` varchar(512) DEFAULT NULL, - `last_insert_id` int(11) DEFAULT NULL, - `insert_id` int(11) DEFAULT NULL, - `server_id` int(11) DEFAULT NULL, + `db` varchar(512) NOT NULL, + `last_insert_id` int(11) NOT NULL, + `insert_id` int(11) NOT NULL, + `server_id` int(11) NOT NULL, `sql_text` mediumtext NOT NULL ) ENGINE=CSV DEFAULT CHARSET=utf8 COMMENT='Slow log' alter table mysql.general_log engine=myisam; @@ -168,11 +168,11 @@ show create table mysql.general_log; Table Create Table general_log CREATE TABLE `general_log` ( `event_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - `user_host` mediumtext, - `thread_id` int(11) DEFAULT NULL, - `server_id` int(11) DEFAULT NULL, - `command_type` varchar(64) DEFAULT NULL, - `argument` mediumtext + `user_host` mediumtext NOT NULL, + `thread_id` int(11) NOT NULL, + `server_id` int(11) NOT NULL, + `command_type` varchar(64) NOT NULL, + `argument` mediumtext NOT NULL ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT='General log' show create table mysql.slow_log; Table Create Table @@ -183,10 +183,10 @@ slow_log CREATE TABLE `slow_log` ( `lock_time` time NOT NULL, `rows_sent` int(11) NOT NULL, `rows_examined` int(11) NOT NULL, - `db` varchar(512) DEFAULT NULL, - `last_insert_id` int(11) DEFAULT NULL, - `insert_id` int(11) DEFAULT NULL, - `server_id` int(11) DEFAULT NULL, + `db` varchar(512) NOT NULL, + `last_insert_id` int(11) NOT NULL, + `insert_id` int(11) NOT NULL, + `server_id` int(11) NOT NULL, `sql_text` mediumtext NOT NULL ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT='Slow log' set global general_log='ON'; @@ -241,11 +241,11 @@ use mysql; CREATE TABLE `general_log` ( `event_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, -`user_host` mediumtext, -`thread_id` int(11) DEFAULT NULL, -`server_id` int(11) DEFAULT NULL, -`command_type` varchar(64) DEFAULT NULL, -`argument` mediumtext +`user_host` mediumtext NOT NULL, +`thread_id` int(11) NOT NULL, +`server_id` int(11) NOT NULL, +`command_type` varchar(64) NOT NULL, +`argument` mediumtext NOT NULL ) ENGINE=CSV DEFAULT CHARSET=utf8 COMMENT='General log'; CREATE TABLE `slow_log` ( `start_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP @@ -255,10 +255,10 @@ ON UPDATE CURRENT_TIMESTAMP, `lock_time` time NOT NULL, `rows_sent` int(11) NOT NULL, `rows_examined` int(11) NOT NULL, -`db` varchar(512) DEFAULT NULL, -`last_insert_id` int(11) DEFAULT NULL, -`insert_id` int(11) DEFAULT NULL, -`server_id` int(11) DEFAULT NULL, +`db` varchar(512) NOT NULL, +`last_insert_id` int(11) NOT NULL, +`insert_id` int(11) NOT NULL, +`server_id` int(11) NOT NULL, `sql_text` mediumtext NOT NULL ) ENGINE=CSV DEFAULT CHARSET=utf8 COMMENT='Slow log'; set global general_log='ON'; @@ -270,6 +270,10 @@ use mysql; lock tables general_log read local, help_category read local; ERROR HY000: You can't use locks with log tables. unlock tables; +drop table if exists mysql.renamed_general_log; +drop table if exists mysql.renamed_slow_log; +drop table if exists mysql.general_log_new; +drop table if exists mysql.slow_log_new; use mysql; RENAME TABLE general_log TO renamed_general_log; ERROR HY000: Cannot rename 'general_log'. When logging enabled, rename to/from log table must rename two tables: the log table to an archive table and another table back to 'general_log' @@ -399,9 +403,9 @@ My own slow query sleep(2) My own slow query 0 SELECT * FROM mysql.slow_log WHERE seq >= 2 LIMIT 3; start_time user_host query_time lock_time rows_sent rows_examined db last_insert_id insert_id server_id sql_text seq -START_TIME USER_HOST QUERY_TIME 00:00:00 1 0 test NULL NULL 1 SELECT "My own slow query", sleep(2) 2 -START_TIME USER_HOST QUERY_TIME 00:00:00 1 0 test NULL NULL 1 SELECT "My own slow query", sleep(2) 3 -START_TIME USER_HOST QUERY_TIME 00:00:00 1 0 test NULL NULL 1 SELECT "My own slow query", sleep(2) 4 +START_TIME USER_HOST QUERY_TIME 00:00:00 1 0 test 0 0 1 SELECT "My own slow query", sleep(2) 2 +START_TIME USER_HOST QUERY_TIME 00:00:00 1 0 test 0 0 1 SELECT "My own slow query", sleep(2) 3 +START_TIME USER_HOST QUERY_TIME 00:00:00 1 0 test 0 0 1 SELECT "My own slow query", sleep(2) 4 SET GLOBAL slow_query_log = 0; SET SESSION long_query_time =@old_long_query_time; FLUSH LOGS; @@ -601,3 +605,218 @@ DROP PROCEDURE IF EXISTS `db_17876.archiveGeneralLog`; DROP DATABASE IF EXISTS `db_17876`; SET GLOBAL general_log = @old_general_log_state; SET GLOBAL slow_query_log = @old_slow_log_state; +truncate table mysql.general_log; +set @old_general_log_state = @@global.general_log; +set global general_log = on; +set @lparam = "000 001 002 003 004 005 006 007 008 009" + "010 011 012 013 014 015 016 017 018 019" + "020 021 022 023 024 025 026 027 028 029" + "030 031 032 033 034 035 036 037 038 039" + "040 041 042 043 044 045 046 047 048 049" + "050 051 052 053 054 055 056 057 058 059" + "060 061 062 063 064 065 066 067 068 069" + "070 071 072 073 074 075 076 077 078 079" + "080 081 082 083 084 085 086 087 088 089" + "090 091 092 093 094 095 096 097 098 099" + "100 101 102 103 104 105 106 107 108 109" + "110 111 112 113 114 115 116 117 118 119" + "120 121 122 123 124 125 126 127 128 129" + "130 131 132 133 134 135 136 137 138 139" + "140 141 142 143 144 145 146 147 148 149" + "150 151 152 153 154 155 156 157 158 159" + "160 161 162 163 164 165 166 167 168 169" + "170 171 172 173 174 175 176 177 178 179" + "180 181 182 183 184 185 186 187 188 189" + "190 191 192 193 194 195 196 197 198 199" + "200 201 202 203 204 205 206 207 208 209" + "210 211 212 213 214 215 216 217 218 219" + "220 221 222 223 224 225 226 227 228 229" + "230 231 232 233 234 235 236 237 238 239" + "240 241 242 243 244 245 246 247 248 249" + "250 251 252 253 254 255 256 257 258 259" + "260 261 262 263 264 265 266 267 268 269" + "270 271 272 273 274 275 276 277 278 279" + "280 281 282 283 284 285 286 287 288 289" + "290 291 292 293 294 295 296 297 298 299" + "300 301 302 303 304 305 306 307 308 309" + "310 311 312 313 314 315 316 317 318 319" + "320 321 322 323 324 325 326 327 328 329" + "330 331 332 333 334 335 336 337 338 339" + "340 341 342 343 344 345 346 347 348 349" + "350 351 352 353 354 355 356 357 358 359" + "360 361 362 363 364 365 366 367 368 369" + "370 371 372 373 374 375 376 377 378 379" + "380 381 382 383 384 385 386 387 388 389" + "390 391 392 393 394 395 396 397 398 399" + "400 401 402 403 404 405 406 407 408 409" + "410 411 412 413 414 415 416 417 418 419" + "420 421 422 423 424 425 426 427 428 429" + "430 431 432 433 434 435 436 437 438 439" + "440 441 442 443 444 445 446 447 448 449" + "450 451 452 453 454 455 456 457 458 459" + "460 461 462 463 464 465 466 467 468 469" + "470 471 472 473 474 475 476 477 478 479" + "480 481 482 483 484 485 486 487 488 489" + "490 491 492 493 494 495 496 497 498 499" + "500 501 502 503 504 505 506 507 508 509" + "510 511 512 513 514 515 516 517 518 519" + "520 521 522 523 524 525 526 527 528 529" + "530 531 532 533 534 535 536 537 538 539" + "540 541 542 543 544 545 546 547 548 549" + "550 551 552 553 554 555 556 557 558 559" + "560 561 562 563 564 565 566 567 568 569" + "570 571 572 573 574 575 576 577 578 579" + "580 581 582 583 584 585 586 587 588 589" + "590 591 592 593 594 595 596 597 598 599" + "600 601 602 603 604 605 606 607 608 609" + "610 611 612 613 614 615 616 617 618 619" + "620 621 622 623 624 625 626 627 628 629" + "630 631 632 633 634 635 636 637 638 639" + "640 641 642 643 644 645 646 647 648 649" + "650 651 652 653 654 655 656 657 658 659" + "660 661 662 663 664 665 666 667 668 669" + "670 671 672 673 674 675 676 677 678 679" + "680 681 682 683 684 685 686 687 688 689" + "690 691 692 693 694 695 696 697 698 699" + "700 701 702 703 704 705 706 707 708 709" + "710 711 712 713 714 715 716 717 718 719" + "720 721 722 723 724 725 726 727 728 729" + "730 731 732 733 734 735 736 737 738 739" + "740 741 742 743 744 745 746 747 748 749" + "750 751 752 753 754 755 756 757 758 759" + "760 761 762 763 764 765 766 767 768 769" + "770 771 772 773 774 775 776 777 778 779" + "780 781 782 783 784 785 786 787 788 789" + "790 791 792 793 794 795 796 797 798 799" + "800 801 802 803 804 805 806 807 808 809" + "810 811 812 813 814 815 816 817 818 819" + "820 821 822 823 824 825 826 827 828 829" + "830 831 832 833 834 835 836 837 838 839" + "840 841 842 843 844 845 846 847 848 849" + "850 851 852 853 854 855 856 857 858 859" + "860 861 862 863 864 865 866 867 868 869" + "870 871 872 873 874 875 876 877 878 879" + "880 881 882 883 884 885 886 887 888 889" + "890 891 892 893 894 895 896 897 898 899" + "900 901 902 903 904 905 906 907 908 909" + "910 911 912 913 914 915 916 917 918 919" + "920 921 922 923 924 925 926 927 928 929" + "930 931 932 933 934 935 936 937 938 939" + "940 941 942 943 944 945 946 947 948 949" + "950 951 952 953 954 955 956 957 958 959" + "960 961 962 963 964 965 966 967 968 969" + "970 971 972 973 974 975 976 977 978 979" + "980 981 982 983 984 985 986 987 988 989" + "990 991 992 993 994 995 996 997 998 999"; +prepare long_query from "select ? as long_query"; +execute long_query using @lparam; +set global general_log = off; +select command_type, argument from mysql.general_log; +command_type argument +Query set @lparam = "000 001 002 003 004 005 006 007 008 009" + "010 011 012 013 014 015 016 017 018 019" + "020 021 022 023 024 025 026 027 028 029" + "030 031 032 033 034 035 036 037 038 039" + "040 041 042 043 044 045 046 047 048 049" + "050 051 052 053 054 055 056 057 058 059" + "060 061 062 063 064 065 066 067 068 069" + "070 071 072 073 074 075 076 077 078 079" + "080 081 082 083 084 085 086 087 088 089" + "090 091 092 093 094 095 096 097 098 099" + "100 101 102 103 104 105 106 107 108 109" + "110 111 112 113 114 115 116 117 118 119" + "120 121 122 123 124 125 126 127 128 129" + "130 131 132 133 134 135 136 137 138 139" + "140 141 142 143 144 145 146 147 148 149" + "150 151 152 153 154 155 156 157 158 159" + "160 161 162 163 164 165 166 167 168 169" + "170 171 172 173 174 175 176 177 178 179" + "180 181 182 183 184 185 186 187 188 189" + "190 191 192 193 194 195 196 197 198 199" + "200 201 202 203 204 205 206 207 208 209" + "210 211 212 213 214 215 216 217 218 219" + "220 221 222 223 224 225 226 227 228 229" + "230 231 232 233 234 235 236 237 238 239" + "240 241 242 243 244 245 246 247 248 249" + "250 251 252 253 254 255 256 257 258 259" + "260 261 262 263 264 265 266 267 268 269" + "270 271 272 273 274 275 276 277 278 279" + "280 281 282 283 284 285 286 287 288 289" + "290 291 292 293 294 295 296 297 298 299" + "300 301 302 303 304 305 306 307 308 309" + "310 311 312 313 314 315 316 317 318 319" + "320 321 322 323 324 325 326 327 328 329" + "330 331 332 333 334 335 336 337 338 339" + "340 341 342 343 344 345 346 347 348 349" + "350 351 352 353 354 355 356 357 358 359" + "360 361 362 363 364 365 366 367 368 369" + "370 371 372 373 374 375 376 377 378 379" + "380 381 382 383 384 385 386 387 388 389" + "390 391 392 393 394 395 396 397 398 399" + "400 401 402 403 404 405 406 407 408 409" + "410 411 412 413 414 415 416 417 418 419" + "420 421 422 423 424 425 426 427 428 429" + "430 431 432 433 434 435 436 437 438 439" + "440 441 442 443 444 445 446 447 448 449" + "450 451 452 453 454 455 456 457 458 459" + "460 461 462 463 464 465 466 467 468 469" + "470 471 472 473 474 475 476 477 478 479" + "480 481 482 483 484 485 486 487 488 489" + "490 491 492 493 494 495 496 497 498 499" + "500 501 502 503 504 505 506 507 508 509" + "510 511 512 513 514 515 516 517 518 519" + "520 521 522 523 524 525 526 527 528 529" + "530 531 532 533 534 535 536 537 538 539" + "540 541 542 543 544 545 546 547 548 549" + "550 551 552 553 554 555 556 557 558 559" + "560 561 562 563 564 565 566 567 568 569" + "570 571 572 573 574 575 576 577 578 579" + "580 581 582 583 584 585 586 587 588 589" + "590 591 592 593 594 595 596 597 598 599" + "600 601 602 603 604 605 606 607 608 609" + "610 611 612 613 614 615 616 617 618 619" + "620 621 622 623 624 625 626 627 628 629" + "630 631 632 633 634 635 636 637 638 639" + "640 641 642 643 644 645 646 647 648 649" + "650 651 652 653 654 655 656 657 658 659" + "660 661 662 663 664 665 666 667 668 669" + "670 671 672 673 674 675 676 677 678 679" + "680 681 682 683 684 685 686 687 688 689" + "690 691 692 693 694 695 696 697 698 699" + "700 701 702 703 704 705 706 707 708 709" + "710 711 712 713 714 715 716 717 718 719" + "720 721 722 723 724 725 726 727 728 729" + "730 731 732 733 734 735 736 737 738 739" + "740 741 742 743 744 745 746 747 748 749" + "750 751 752 753 754 755 756 757 758 759" + "760 761 762 763 764 765 766 767 768 769" + "770 771 772 773 774 775 776 777 778 779" + "780 781 782 783 784 785 786 787 788 789" + "790 791 792 793 794 795 796 797 798 799" + "800 801 802 803 804 805 806 807 808 809" + "810 811 812 813 814 815 816 817 818 819" + "820 821 822 823 824 825 826 827 828 829" + "830 831 832 833 834 835 836 837 838 839" + "840 841 842 843 844 845 846 847 848 849" + "850 851 852 853 854 855 856 857 858 859" + "860 861 862 863 864 865 866 867 868 869" + "870 871 872 873 874 875 876 877 878 879" + "880 881 882 883 884 885 886 887 888 889" + "890 891 892 893 894 895 896 897 898 899" + "900 901 902 903 904 905 906 907 908 909" + "910 911 912 913 914 915 916 917 918 919" + "920 921 922 923 924 925 926 927 928 929" + "930 931 932 933 934 935 936 937 938 939" + "940 941 942 943 944 945 946 947 948 949" + "950 951 952 953 954 955 956 957 958 959" + "960 961 962 963 964 965 966 967 968 969" + "970 971 972 973 974 975 976 977 978 979" + "980 981 982 983 984 985 986 987 988 989" + "990 991 992 993 994 995 996 997 998 999" +Query prepare long_query from "select ? as long_query" +Prepare select ? as long_query +Query execute long_query using @lparam +Execute select '000 001 002 003 004 005 006 007 008 009010 011 012 013 014 015 016 017 018 019020 021 022 023 024 025 026 027 028 029030 031 032 033 034 035 036 037 038 039040 041 042 043 044 045 046 047 048 049050 051 052 053 054 055 056 057 058 059060 061 062 063 064 065 066 067 068 069070 071 072 073 074 075 076 077 078 079080 081 082 083 084 085 086 087 088 089090 091 092 093 094 095 096 097 098 099100 101 102 103 104 105 106 107 108 109110 111 112 113 114 115 116 117 118 119120 121 122 123 124 125 126 127 128 129130 131 132 133 134 135 136 137 138 139140 141 142 143 144 145 146 147 148 149150 151 152 153 154 155 156 157 158 159160 161 162 163 164 165 166 167 168 169170 171 172 173 174 175 176 177 178 179180 181 182 183 184 185 186 187 188 189190 191 192 193 194 195 196 197 198 199200 201 202 203 204 205 206 207 208 209210 211 212 213 214 215 216 217 218 219220 221 222 223 224 225 226 227 228 229230 231 232 233 234 235 236 237 238 239240 241 242 243 244 245 246 247 248 249250 251 252 253 254 255 256 257 258 259260 261 262 263 264 265 266 267 268 269270 271 272 273 274 275 276 277 278 279280 281 282 283 284 285 286 287 288 289290 291 292 293 294 295 296 297 298 299300 301 302 303 304 305 306 307 308 309310 311 312 313 314 315 316 317 318 319320 321 322 323 324 325 326 327 328 329330 331 332 333 334 335 336 337 338 339340 341 342 343 344 345 346 347 348 349350 351 352 353 354 355 356 357 358 359360 361 362 363 364 365 366 367 368 369370 371 372 373 374 375 376 377 378 379380 381 382 383 384 385 386 387 388 389390 391 392 393 394 395 396 397 398 399400 401 402 403 404 405 406 407 408 409410 411 412 413 414 415 416 417 418 419420 421 422 423 424 425 426 427 428 429430 431 432 433 434 435 436 437 438 439440 441 442 443 444 445 446 447 448 449450 451 452 453 454 455 456 457 458 459460 461 462 463 464 465 466 467 468 469470 471 472 473 474 475 476 477 478 479480 481 482 483 484 485 486 487 488 489490 491 492 493 494 495 496 497 498 499500 501 502 503 504 505 506 507 508 509510 511 512 513 514 515 516 517 518 519520 521 522 523 524 525 526 527 528 529530 531 532 533 534 535 536 537 538 539540 541 542 543 544 545 546 547 548 549550 551 552 553 554 555 556 557 558 559560 561 562 563 564 565 566 567 568 569570 571 572 573 574 575 576 577 578 579580 581 582 583 584 585 586 587 588 589590 591 592 593 594 595 596 597 598 599600 601 602 603 604 605 606 607 608 609610 611 612 613 614 615 616 617 618 619620 621 622 623 624 625 626 627 628 629630 631 632 633 634 635 636 637 638 639640 641 642 643 644 645 646 647 648 649650 651 652 653 654 655 656 657 658 659660 661 662 663 664 665 666 667 668 669670 671 672 673 674 675 676 677 678 679680 681 682 683 684 685 686 687 688 689690 691 692 693 694 695 696 697 698 699700 701 702 703 704 705 706 707 708 709710 711 712 713 714 715 716 717 718 719720 721 722 723 724 725 726 727 728 729730 731 732 733 734 735 736 737 738 739740 741 742 743 744 745 746 747 748 749750 751 752 753 754 755 756 757 758 759760 761 762 763 764 765 766 767 768 769770 771 772 773 774 775 776 777 778 779780 781 782 783 784 785 786 787 788 789790 791 792 793 794 795 796 797 798 799800 801 802 803 804 805 806 807 808 809810 811 812 813 814 815 816 817 818 819820 821 822 823 824 825 826 827 828 829830 831 832 833 834 835 836 837 838 839840 841 842 843 844 845 846 847 848 849850 851 852 853 854 855 856 857 858 859860 861 862 863 864 865 866 867 868 869870 871 872 873 874 875 876 877 878 879880 881 882 883 884 885 886 887 888 889890 891 892 893 894 895 896 897 898 899900 901 902 903 904 905 906 907 908 909910 911 912 913 914 915 916 917 918 919920 921 922 923 924 925 926 927 928 929930 931 932 933 934 935 936 937 938 939940 941 942 943 944 945 946 947 948 949950 951 952 953 954 955 956 957 958 959960 961 962 963 964 965 966 967 968 969970 971 972 973 974 975 976 977 978 979980 981 982 983 984 985 986 987 988 989990 991 992 993 994 995 996 997 998 999' as long_query +Query set global general_log = off +deallocate prepare long_query; +set global general_log = @old_general_log_state; diff --git a/mysql-test/r/merge.result b/mysql-test/r/merge.result index 5aa4288500c..d6e19107ec4 100644 --- a/mysql-test/r/merge.result +++ b/mysql-test/r/merge.result @@ -879,4 +879,9 @@ CHECK TABLE tm1; Table Op Msg_type Msg_text test.tm1 check status OK DROP TABLE tm1, t1, t2; +CREATE TABLE t1(c1 INT); +CREATE TABLE t2 (c1 INT) ENGINE=MERGE UNION=(t1) INSERT_METHOD=FIRST; +CREATE TABLE IF NOT EXISTS t1 SELECT * FROM t2; +ERROR HY000: You can't specify target table 't1' for update in FROM clause +DROP TABLE t1, t2; End of 5.0 tests diff --git a/mysql-test/r/mysqltest.result b/mysql-test/r/mysqltest.result index d03e21b1bb0..a7df1a523cf 100644 --- a/mysql-test/r/mysqltest.result +++ b/mysql-test/r/mysqltest.result @@ -722,4 +722,7 @@ a int(11) YES NULL b varchar(255) YES NULL c datetime YES NULL drop table t1; +mysqltest: At line 1: change user failed: Unknown database 'inexistent' +mysqltest: At line 1: change user failed: Access denied for user 'inexistent'@'localhost' (using password: NO) +mysqltest: At line 1: change user failed: Access denied for user 'root'@'localhost' (using password: YES) End of tests diff --git a/mysql-test/r/partition.result b/mysql-test/r/partition.result index 7120e3ea9e6..4e4bd0bbc0a 100644 --- a/mysql-test/r/partition.result +++ b/mysql-test/r/partition.result @@ -1259,6 +1259,10 @@ INSERT INTO t1 SELECT a + 8, b FROM t1; ALTER TABLE t1 ADD PARTITION (PARTITION p1 VALUES LESS THAN (64)); ALTER TABLE t1 DROP PARTITION p1; DROP TABLE t1; +create table t (s1 int) engine=myisam partition by key (s1); +create trigger t_ad after delete on t for each row insert into t values (old.s1); +insert into t values (1); +drop table t; USE mysql; SET GLOBAL general_log = 0; ALTER TABLE general_log ENGINE = MyISAM; diff --git a/mysql-test/r/partition_innodb.result b/mysql-test/r/partition_innodb.result index 8282cfc212a..5b755b6bfd5 100644 --- a/mysql-test/r/partition_innodb.result +++ b/mysql-test/r/partition_innodb.result @@ -129,3 +129,10 @@ insert into t1 (time, first_name, last_name) values ('2007-02-07', 'Q', 'Robert' SELECT * FROM t1 WHERE first_name='Andy' OR last_name='Jake'; id time first_name last_name drop table t1; +CREATE TABLE t1 (a DOUBLE NOT NULL, KEY(a)) ENGINE=InnoDB +PARTITION BY KEY(a) PARTITIONS 10; +INSERT INTO t1 VALUES(1),(2); +SELECT COUNT(*) FROM t1; +COUNT(*) +2 +DROP TABLE t1; diff --git a/mysql-test/r/query_cache.result b/mysql-test/r/query_cache.result index 321b08628ee..73436dc392f 100644 --- a/mysql-test/r/query_cache.result +++ b/mysql-test/r/query_cache.result @@ -1650,86 +1650,8 @@ a (select count(*) from t2) 3 0 4 0 drop table t1,t2; -DROP DATABASE IF EXISTS bug30269; -FLUSH STATUS; -CREATE DATABASE bug30269; -USE bug30269; -CREATE TABLE test1 (id int, name varchar(23)); -CREATE VIEW view1 AS SELECT * FROM test1; -INSERT INTO test1 VALUES (5, 'testit'); -GRANT SELECT (id) ON TABLE bug30269.test1 TO 'bug30269'@'localhost'; -GRANT SELECT ON TABLE bug30269.view1 TO 'bug30269'@'localhost'; -set global query_cache_size= 81920; -USE bug30269; -show status like 'Qcache_queries_in_cache'; -Variable_name Value -Qcache_queries_in_cache 0 -# Select statement not stored in query cache because of column privileges. -SELECT id FROM test1 WHERE id>2; -id -5 -show status like 'Qcache_queries_in_cache'; -Variable_name Value -Qcache_queries_in_cache 0 -SELECT id FROM view1 WHERE id>2; -id -5 -show status like 'Qcache_queries_in_cache'; -Variable_name Value -Qcache_queries_in_cache 1 -DROP DATABASE bug30269; -DROP USER 'bug30269'@'localhost'; +End of 5.0 tests set GLOBAL query_cache_type=default; set GLOBAL query_cache_limit=default; set GLOBAL query_cache_min_res_unit=default; set GLOBAL query_cache_size=default; -End of 5.0 tests -drop database if exists db1; -drop database if exists db2; -set GLOBAL query_cache_size=15*1024*1024; -create database db1; -use db1; -create table t1(c1 int)engine=myisam; -insert into t1(c1) values (1); -select * from db1.t1 f; -c1 -1 -show status like 'Qcache_queries_in_cache'; -Variable_name Value -Qcache_queries_in_cache 1 -rename schema db1 to db2; -show status like 'Qcache_queries_in_cache'; -Variable_name Value -Qcache_queries_in_cache 0 -drop database db2; -set global query_cache_size=default; -drop database if exists db1; -drop database if exists db3; -set GLOBAL query_cache_size=15*1024*1024; -create database db1; -create database db3; -use db1; -create table t1(c1 int) engine=myisam; -use db3; -create table t1(c1 int) engine=myisam; -use db1; -insert into t1(c1) values (1); -use mysql; -select * from db1.t1; -c1 -1 -select c1+1 from db1.t1; -c1+1 -2 -select * from db3.t1; -c1 -show status like 'Qcache_queries_in_cache'; -Variable_name Value -Qcache_queries_in_cache 3 -rename schema db1 to db2; -show status like 'Qcache_queries_in_cache'; -Variable_name Value -Qcache_queries_in_cache 1 -drop database db2; -drop database db3; -End of 5.1 tests diff --git a/mysql-test/r/query_cache_notembedded.result b/mysql-test/r/query_cache_notembedded.result index 05ef28a3180..ec78c2267d2 100644 --- a/mysql-test/r/query_cache_notembedded.result +++ b/mysql-test/r/query_cache_notembedded.result @@ -347,3 +347,36 @@ drop table t1; drop function f1; set GLOBAL query_cache_size=0; SET GLOBAL log_bin_trust_function_creators = 0; +DROP DATABASE IF EXISTS bug30269; +FLUSH STATUS; +CREATE DATABASE bug30269; +USE bug30269; +CREATE TABLE test1 (id int, name varchar(23)); +CREATE VIEW view1 AS SELECT * FROM test1; +INSERT INTO test1 VALUES (5, 'testit'); +GRANT SELECT (id) ON TABLE bug30269.test1 TO 'bug30269'@'localhost'; +GRANT SELECT ON TABLE bug30269.view1 TO 'bug30269'@'localhost'; +set global query_cache_size= 81920; +USE bug30269; +show status like 'Qcache_queries_in_cache'; +Variable_name Value +Qcache_queries_in_cache 0 +# Select statement not stored in query cache because of column privileges. +SELECT id FROM test1 WHERE id>2; +id +5 +show status like 'Qcache_queries_in_cache'; +Variable_name Value +Qcache_queries_in_cache 0 +SELECT id FROM view1 WHERE id>2; +id +5 +show status like 'Qcache_queries_in_cache'; +Variable_name Value +Qcache_queries_in_cache 1 +DROP DATABASE bug30269; +DROP USER 'bug30269'@'localhost'; +set GLOBAL query_cache_type=default; +set GLOBAL query_cache_limit=default; +set GLOBAL query_cache_min_res_unit=default; +set GLOBAL query_cache_size=default; diff --git a/mysql-test/r/renamedb.result b/mysql-test/r/renamedb.result index b22322fbe8d..ff8f89592fc 100644 --- a/mysql-test/r/renamedb.result +++ b/mysql-test/r/renamedb.result @@ -1,33 +1,12 @@ -drop database if exists testdb1; -create database testdb1 default character set latin2; -use testdb1; -create table t1 (a int); -insert into t1 values (1),(2),(3); -show create database testdb1; -Database Create Database -testdb1 CREATE DATABASE `testdb1` /*!40100 DEFAULT CHARACTER SET latin2 */ -show tables; -Tables_in_testdb1 -t1 rename database testdb1 to testdb2; -show create database testdb1; -ERROR 42000: Unknown database 'testdb1' -show create database testdb2; -Database Create Database -testdb2 CREATE DATABASE `testdb2` /*!40100 DEFAULT CHARACTER SET latin2 */ -select database(); -database() -testdb2 -show tables; -Tables_in_testdb2 -t1 -select a from t1 order by a; -a -1 -2 -3 -drop database testdb2; -create database testdb1; -rename database testdb1 to testdb1; -ERROR HY000: Can't create database 'testdb1'; database exists -drop database testdb1; +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 'database testdb1 to testdb2' at line 1 +ALTER DATABASE wrong UPGRADE DATA DIRECTORY NAME; +ERROR HY000: Incorrect usage of ALTER DATABASE UPGRADE DATA DIRECTORY NAME and name +ALTER DATABASE `#mysql41#not-supported` UPGRADE DATA DIRECTORY NAME; +ERROR HY000: Incorrect usage of ALTER DATABASE UPGRADE DATA DIRECTORY NAME and name +ALTER DATABASE `#mysql51#not-yet` UPGRADE DATA DIRECTORY NAME; +ERROR HY000: Incorrect usage of ALTER DATABASE UPGRADE DATA DIRECTORY NAME and name +ALTER DATABASE `#mysql50#` UPGRADE DATA DIRECTORY NAME; +ERROR HY000: Incorrect usage of ALTER DATABASE UPGRADE DATA DIRECTORY NAME and name +ALTER DATABASE `#mysql50#upgrade-me` UPGRADE DATA DIRECTORY NAME; +ERROR 42000: Unknown database '#mysql50#upgrade-me' diff --git a/mysql-test/r/sp-code.result b/mysql-test/r/sp-code.result index b2bcfff0fdb..018173e723d 100644 --- a/mysql-test/r/sp-code.result +++ b/mysql-test/r/sp-code.result @@ -155,11 +155,11 @@ Pos Instruction 0 stmt 9 "drop temporary table if exists sudoku..." 1 stmt 1 "create temporary table sudoku_work ( ..." 2 stmt 1 "create temporary table sudoku_schedul..." -3 stmt 95 "call sudoku_init()" +3 stmt 94 "call sudoku_init()" 4 jump_if_not 7(8) p_naive@0 5 stmt 4 "update sudoku_work set cnt = 0 where ..." 6 jump 8 -7 stmt 95 "call sudoku_count()" +7 stmt 94 "call sudoku_count()" 8 stmt 6 "insert into sudoku_schedule (row,col)..." 9 set v_scounter@2 0 10 set v_i@3 1 diff --git a/mysql-test/r/sp-error.result b/mysql-test/r/sp-error.result index 2e0d437aeb6..1b14d75cd9c 100644 --- a/mysql-test/r/sp-error.result +++ b/mysql-test/r/sp-error.result @@ -142,7 +142,10 @@ declare c cursor for insert into test.t1 values ("foo", 42); open c; close c; end| -ERROR 42000: Cursor statement must be a SELECT +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 'insert into test.t1 values ("foo", 42); +open c; +close c; +end' at line 3 create procedure p() begin declare x int; @@ -1223,7 +1226,7 @@ ERROR 42S02: Unknown table 'c' in field list drop procedure bug15091; drop function if exists bug16896; create aggregate function bug16896() returns int return 1; -ERROR 42000: AGGREGATE is not supported for stored functions +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 '() returns int return 1' at line 1 DROP PROCEDURE IF EXISTS bug14702; CREATE IF NOT EXISTS PROCEDURE bug14702() BEGIN @@ -1478,3 +1481,45 @@ end until true end repeat retry; end// ERROR 42000: LEAVE with no matching label: retry +drop procedure if exists proc_28360; +drop function if exists func_28360; +CREATE PROCEDURE proc_28360() +BEGIN +ALTER DATABASE `#mysql50#upgrade-me` UPGRADE DATA DIRECTORY NAME; +END// +ERROR HY000: Can't drop or alter a DATABASE from within another stored routine +CREATE FUNCTION func_28360() RETURNS int +BEGIN +ALTER DATABASE `#mysql50#upgrade-me` UPGRADE DATA DIRECTORY NAME; +RETURN 0; +END// +ERROR HY000: Can't drop or alter a DATABASE from within another stored routine +DROP PROCEDURE IF EXISTS p1; +CREATE PROCEDURE p1() +BEGIN +DECLARE c char(100); +DECLARE cur1 CURSOR FOR SHOW TABLES; +OPEN cur1; +FETCH cur1 INTO c; +select c; +CLOSE cur1; +END| +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 'SHOW TABLES; +OPEN cur1; +FETCH cur1 INTO c; +select c; +CLOSE cur1; +END' at line 4 +DROP DATABASE IF EXISTS mysqltest; +CREATE DATABASE mysqltest; +USE mysqltest; +DROP DATABASE mysqltest; +SELECT inexistent(), 1 + ,; +ERROR 42000: FUNCTION inexistent does not exist +SELECT inexistent(); +ERROR 42000: FUNCTION inexistent does not exist +SELECT .inexistent(); +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 '()' at line 1 +SELECT ..inexistent(); +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 '.inexistent()' at line 1 +USE test; diff --git a/mysql-test/r/sp.result b/mysql-test/r/sp.result index 55b27b0a733..412f6b94fa2 100644 --- a/mysql-test/r/sp.result +++ b/mysql-test/r/sp.result @@ -4914,7 +4914,7 @@ create table t3 as select * from v1| show create table t3| Table Create Table t3 CREATE TABLE `t3` ( - `j` bigint(11) DEFAULT NULL + `j` int(11) DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 select * from t3| j @@ -6620,4 +6620,295 @@ DROP TABLE t1; DROP PROCEDURE p1; DROP PROCEDURE p2; + +# +# Bug#31035. +# + +# +# - Prepare. +# + +DROP TABLE IF EXISTS t1; +DROP FUNCTION IF EXISTS f1; +DROP FUNCTION IF EXISTS f2; +DROP FUNCTION IF EXISTS f3; +DROP FUNCTION IF EXISTS f4; + +# +# - Create required objects. +# + +CREATE TABLE t1(c1 INT); + +INSERT INTO t1 VALUES (1), (2), (3); + +CREATE FUNCTION f1() +RETURNS INT +NOT DETERMINISTIC +RETURN 1; + +CREATE FUNCTION f2(p INT) +RETURNS INT +NOT DETERMINISTIC +RETURN 1; + +CREATE FUNCTION f3() +RETURNS INT +DETERMINISTIC +RETURN 1; + +CREATE FUNCTION f4(p INT) +RETURNS INT +DETERMINISTIC +RETURN 1; + +# +# - Check. +# + +SELECT f1() AS a FROM t1 GROUP BY a; +a +1 + +SELECT f2(@a) AS a FROM t1 GROUP BY a; +a +1 + +SELECT f3() AS a FROM t1 GROUP BY a; +a +1 + +SELECT f4(0) AS a FROM t1 GROUP BY a; +a +1 + +SELECT f4(@a) AS a FROM t1 GROUP BY a; +a +1 + +# +# - Cleanup. +# + +DROP TABLE t1; +DROP FUNCTION f1; +DROP FUNCTION f2; +DROP FUNCTION f3; +DROP FUNCTION f4; + +# +# Bug#31191. +# + +# +# - Prepare. +# + +DROP TABLE IF EXISTS t1; +DROP TABLE IF EXISTS t2; +DROP FUNCTION IF EXISTS f1; + +# +# - Create required objects. +# + +CREATE TABLE t1 ( +id INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, +barcode INT(8) UNSIGNED ZEROFILL nOT NULL, +PRIMARY KEY (id), +UNIQUE KEY barcode (barcode) +); + +INSERT INTO t1 (id, barcode) VALUES (1, 12345678); +INSERT INTO t1 (id, barcode) VALUES (2, 12345679); + +CREATE TABLE test.t2 ( +id INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, +barcode BIGINT(11) UNSIGNED ZEROFILL NOT NULL, +PRIMARY KEY (id) +); + +INSERT INTO test.t2 (id, barcode) VALUES (1, 12345106708); +INSERT INTO test.t2 (id, barcode) VALUES (2, 12345106709); + +CREATE FUNCTION f1(p INT(8)) +RETURNS BIGINT(11) UNSIGNED +READS SQL DATA +RETURN FLOOR(p/1000)*1000000 + 100000 + FLOOR((p MOD 1000)/10)*100 + (p MOD 10); + +# +# - Check. +# + +SELECT DISTINCT t1.barcode, f1(t1.barcode) +FROM t1 +INNER JOIN t2 +ON f1(t1.barcode) = t2.barcode +WHERE t1.barcode=12345678; +barcode f1(t1.barcode) +12345678 12345106708 + +# +# - Cleanup. +# + +DROP TABLE t1; +DROP TABLE t2; +DROP FUNCTION f1; + +# +# Bug#31226. +# + +# +# - Prepare. +# + +DROP TABLE IF EXISTS t1; +DROP FUNCTION IF EXISTS f1; + +# +# - Create required objects. +# + +CREATE TABLE t1(id INT); + +INSERT INTO t1 VALUES (1), (2), (3); + +CREATE FUNCTION f1() +RETURNS DATETIME +NOT DETERMINISTIC NO SQL +RETURN NOW(); + +# +# - Check. +# + +SELECT f1() FROM t1 GROUP BY 1; +f1() +<timestamp> + +# +# - Cleanup. +# + +DROP TABLE t1; +DROP FUNCTION f1; + +DROP PROCEDURE IF EXISTS db28318_a.t1; +DROP PROCEDURE IF EXISTS db28318_b.t2; +DROP DATABASE IF EXISTS db28318_a; +DROP DATABASE IF EXISTS db28318_b; +CREATE DATABASE db28318_a; +CREATE DATABASE db28318_b; +CREATE PROCEDURE db28318_a.t1() SELECT "db28318_a.t1"; +CREATE PROCEDURE db28318_b.t2() CALL t1(); +use db28318_a; +CALL db28318_b.t2(); +ERROR 42000: PROCEDURE db28318_b.t1 does not exist +DROP PROCEDURE db28318_a.t1; +DROP PROCEDURE db28318_b.t2; +DROP DATABASE db28318_a; +DROP DATABASE db28318_b; +use test; End of 5.0 tests + +# +# Bug#20550. +# + +# +# - Prepare. +# + +DROP VIEW IF EXISTS v1; +DROP VIEW IF EXISTS v2; +DROP FUNCTION IF EXISTS f1; +DROP FUNCTION IF EXISTS f2; + +# +# - Create required objects. +# + +CREATE FUNCTION f1() RETURNS VARCHAR(65525) RETURN 'Hello'; + +CREATE FUNCTION f2() RETURNS TINYINT RETURN 1; + +CREATE VIEW v1 AS SELECT f1(); + +CREATE VIEW v2 AS SELECT f2(); + +# +# - Check. +# + +SELECT DATA_TYPE FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 'v1'; +DATA_TYPE +varchar + +SELECT DATA_TYPE FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 'v2'; +DATA_TYPE +tinyint + +# +# - Cleanup. +# + +DROP FUNCTION f1; +DROP FUNCTION f2; +DROP VIEW v1; +DROP VIEW v2; + +# +# - Bug#24923: prepare. +# + +DROP FUNCTION IF EXISTS f1; + +# +# - Bug#24923: create required objects. +# + +CREATE FUNCTION f1(p INT) +RETURNS ENUM ('Very_long_enum_element_identifier', +'Another_very_long_enum_element_identifier') +BEGIN +CASE p +WHEN 1 THEN +RETURN 'Very_long_enum_element_identifier'; +ELSE +RETURN 'Another_very_long_enum_element_identifier'; +END CASE; +END| + +# +# - Bug#24923: check. +# + +SELECT f1(1); +f1(1) +Very_long_enum_element_identifier + +SELECT f1(2); +f1(2) +Another_very_long_enum_element_identifier + +SHOW CREATE FUNCTION f1; +Function sql_mode Create Function character_set_client collation_connection Database Collation +f1 CREATE DEFINER=`root`@`localhost` FUNCTION `f1`(p INT) RETURNS enum('Very_long_enum_element_identifier','Another_very_long_enum_element_identifier') CHARSET latin1 +BEGIN +CASE p +WHEN 1 THEN +RETURN 'Very_long_enum_element_identifier'; +ELSE +RETURN 'Another_very_long_enum_element_identifier'; +END CASE; +END latin1 latin1_swedish_ci latin1_swedish_ci +# +# - Bug#24923: cleanup. +# + +DROP FUNCTION f1; + +End of 5.1 tests diff --git a/mysql-test/r/system_mysql_db.result b/mysql-test/r/system_mysql_db.result index 7696afdf06d..d1aff0fa657 100644 --- a/mysql-test/r/system_mysql_db.result +++ b/mysql-test/r/system_mysql_db.result @@ -196,7 +196,7 @@ proc CREATE TABLE `proc` ( `is_deterministic` enum('YES','NO') NOT NULL DEFAULT 'NO', `security_type` enum('INVOKER','DEFINER') NOT NULL DEFAULT 'DEFINER', `param_list` blob NOT NULL, - `returns` char(64) NOT NULL DEFAULT '', + `returns` longblob NOT NULL, `body` longblob NOT NULL, `definer` char(77) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL DEFAULT '', `created` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, @@ -240,11 +240,11 @@ show create table general_log; Table Create Table general_log CREATE TABLE `general_log` ( `event_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - `user_host` mediumtext, - `thread_id` int(11) DEFAULT NULL, - `server_id` int(11) DEFAULT NULL, - `command_type` varchar(64) DEFAULT NULL, - `argument` mediumtext + `user_host` mediumtext NOT NULL, + `thread_id` int(11) NOT NULL, + `server_id` int(11) NOT NULL, + `command_type` varchar(64) NOT NULL, + `argument` mediumtext NOT NULL ) ENGINE=CSV DEFAULT CHARSET=utf8 COMMENT='General log' show create table slow_log; Table Create Table @@ -255,10 +255,10 @@ slow_log CREATE TABLE `slow_log` ( `lock_time` time NOT NULL, `rows_sent` int(11) NOT NULL, `rows_examined` int(11) NOT NULL, - `db` varchar(512) DEFAULT NULL, - `last_insert_id` int(11) DEFAULT NULL, - `insert_id` int(11) DEFAULT NULL, - `server_id` int(11) DEFAULT NULL, + `db` varchar(512) NOT NULL, + `last_insert_id` int(11) NOT NULL, + `insert_id` int(11) NOT NULL, + `server_id` int(11) NOT NULL, `sql_text` mediumtext NOT NULL ) ENGINE=CSV DEFAULT CHARSET=utf8 COMMENT='Slow log' show tables; diff --git a/mysql-test/r/udf.result b/mysql-test/r/udf.result index f1e47905f5d..da27a71c1a1 100644 --- a/mysql-test/r/udf.result +++ b/mysql-test/r/udf.result @@ -95,10 +95,10 @@ FR DROP TABLE bug19904; CREATE DEFINER=CURRENT_USER() FUNCTION should_not_parse RETURNS STRING SONAME "should_not_parse.so"; -ERROR HY000: Incorrect usage of SONAME and DEFINER +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 'RETURNS STRING SONAME "should_not_parse.so"' at line 2 CREATE DEFINER=someone@somewhere FUNCTION should_not_parse RETURNS STRING SONAME "should_not_parse.so"; -ERROR HY000: Incorrect usage of SONAME and DEFINER +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 'RETURNS STRING SONAME "should_not_parse.so"' at line 2 create table t1(f1 int); insert into t1 values(1),(2); explain select myfunc_int(f1) from t1 order by 1; @@ -214,7 +214,7 @@ DROP FUNCTION IF EXISTS metaphon; CREATE FUNCTION metaphon(a int) RETURNS int return 0; CREATE FUNCTION metaphon RETURNS STRING SONAME "UDF_EXAMPLE_LIB"; -ERROR HY000: Function 'metaphon' already exists +DROP FUNCTION metaphon; DROP FUNCTION metaphon; CREATE FUNCTION metaphon RETURNS STRING SONAME "UDF_EXAMPLE_LIB"; CREATE FUNCTION metaphon(a int) RETURNS int @@ -334,6 +334,13 @@ Qcache_queries_in_cache 0 drop table t1; drop function metaphon; set GLOBAL query_cache_size=default; +DROP DATABASE IF EXISTS mysqltest; +CREATE DATABASE mysqltest; +USE mysqltest; +DROP DATABASE mysqltest; +CREATE FUNCTION metaphon RETURNS STRING SONAME "UDF_EXAMPLE_LIB"; +DROP FUNCTION metaphon; +USE test; CREATE TABLE const_len_bug ( str_const varchar(4000), result1 varchar(4000), diff --git a/mysql-test/r/upgrade.result b/mysql-test/r/upgrade.result index 76e0359c405..adf81efe8e3 100644 --- a/mysql-test/r/upgrade.result +++ b/mysql-test/r/upgrade.result @@ -59,3 +59,28 @@ drop table `txu@0023p@0023p1`; drop table `txu#p#p1`; truncate t1; drop table t1; +drop database if exists `tabc`; +drop database if exists `a-b-c`; +create database `tabc` default character set latin2; +create table tabc.t1 (a int); +FLUSH TABLES; +show databases like '%a-b-c%'; +Database (%a-b-c%) +#mysql50#a-b-c +ALTER DATABASE `#mysql50#a-b-c` UPGRADE DATA DIRECTORY NAME; +show databases like '%a-b-c%'; +Database (%a-b-c%) +a-b-c +show create database `a-b-c`; +Database Create Database +a-b-c CREATE DATABASE `a-b-c` /*!40100 DEFAULT CHARACTER SET latin2 */ +show tables in `a-b-c`; +Tables_in_a-b-c +t1 +show create table `a-b-c`.`t1`; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` int(11) DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin2 +drop database `a-b-c`; +drop database `tabc`; diff --git a/mysql-test/t/change_user.test b/mysql-test/t/change_user.test new file mode 100644 index 00000000000..d0cdfc8a741 --- /dev/null +++ b/mysql-test/t/change_user.test @@ -0,0 +1,35 @@ +# +# Bug#20023 mysql_change_user() resets the value of SQL_BIG_SELECTS +# + +--echo Bug#20023 +SELECT @@session.sql_big_selects; +SELECT @@global.max_join_size; +--echo change_user +--change_user +SELECT @@session.sql_big_selects; +SELECT @@global.max_join_size; +SET @@global.max_join_size = 10000; +SET @@session.max_join_size = default; +--echo change_user +--change_user +SELECT @@session.sql_big_selects; +SET @@global.max_join_size = -1; +SET @@session.max_join_size = default; +--echo change_user +--change_user +SELECT @@session.sql_big_selects; + +# +# Bug#31418 User locks misfunctioning after mysql_change_user() +# + +--echo Bug#31418 +SELECT IS_FREE_LOCK('bug31418'); +SELECT IS_USED_LOCK('bug31418'); +SELECT GET_LOCK('bug31418', 1); +SELECT IS_USED_LOCK('bug31418') = CONNECTION_ID(); +--echo change_user +--change_user +SELECT IS_FREE_LOCK('bug31418'); +SELECT IS_USED_LOCK('bug31418'); diff --git a/mysql-test/t/create.test b/mysql-test/t/create.test index 341c019af6e..023e55ea418 100644 --- a/mysql-test/t/create.test +++ b/mysql-test/t/create.test @@ -1197,14 +1197,17 @@ drop table t1,t2; CREATE DATABASE aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa; --error 1102 DROP DATABASE aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa; ---error 1049 -RENAME DATABASE aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa TO a; ---error 1102 -RENAME DATABASE mysqltest TO aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa; -create database mysqltest; ---error 1102 -RENAME DATABASE mysqltest TO aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa; -drop database mysqltest; + +# TODO: enable these tests when RENAME DATABASE is implemented. +# --error 1049 +# RENAME DATABASE aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa TO a; +# --error 1102 +# RENAME DATABASE mysqltest TO aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa; +# create database mysqltest; +# --error 1102 +# RENAME DATABASE mysqltest TO aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa; +# drop database mysqltest; + --error 1102 USE aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa; --error 1102 @@ -1300,4 +1303,29 @@ return 0; drop view имÑ_вью_кодировке_утф8_длиной_больше_чем_42; drop table имÑ_таблицы_в_кодировке_утф8_длиной_больше_чем_48; set names default; + +# +# Bug#21136 CREATE TABLE SELECT within CREATE TABLE SELECT causes server crash +# + +--disable_warnings +drop table if exists t1,t2,t3; +drop function if exists f1; +--enable_warnings + +--delimiter | +create function f1() returns int +begin + declare res int; + create temporary table t3 select 1 i; + set res:= (select count(*) from t1); + drop temporary table t3; + return res; +end| +--delimiter ; +create table t1 as select 1; +create table t2 as select f1() from t1; +drop table t1,t2; +drop function f1; + --echo End of 5.1 tests diff --git a/mysql-test/t/csv.test b/mysql-test/t/csv.test index 5c877557dfc..6c83fbfdc9c 100644 --- a/mysql-test/t/csv.test +++ b/mysql-test/t/csv.test @@ -1322,7 +1322,7 @@ drop table if exists t1,t2,t3,t4; DROP TABLE IF EXISTS bug13894; --enable_warnings -CREATE TABLE bug13894 ( val integer ) ENGINE = CSV; +CREATE TABLE bug13894 ( val integer not null ) ENGINE = CSV; INSERT INTO bug13894 VALUES (5); INSERT INTO bug13894 VALUES (10); INSERT INTO bug13894 VALUES (11); @@ -1340,7 +1340,7 @@ DROP TABLE bug13894; DROP TABLE IF EXISTS bug14672; --enable_warnings -CREATE TABLE bug14672 (c1 integer) engine = CSV; +CREATE TABLE bug14672 (c1 integer not null) engine = CSV; INSERT INTO bug14672 VALUES (1), (2), (3); SELECT * FROM bug14672; DELETE FROM bug14672 WHERE c1 = 2; @@ -1357,7 +1357,7 @@ DROP TABLE bug14672; # Test CONCURRENT INSERT (5.1) # -CREATE TABLE test_concurrent_insert ( val integer ) ENGINE = CSV; +CREATE TABLE test_concurrent_insert ( val integer not null ) ENGINE = CSV; connect (con1,localhost,root,,); connect (con2,localhost,root,,); @@ -1393,7 +1393,7 @@ DROP TABLE test_concurrent_insert; # Check that repair on the newly created table works fine -CREATE TABLE test_repair_table ( val integer ) ENGINE = CSV; +CREATE TABLE test_repair_table ( val integer not null ) ENGINE = CSV; CHECK TABLE test_repair_table; REPAIR TABLE test_repair_table; @@ -1405,7 +1405,7 @@ DROP TABLE test_repair_table; # restore the meta-file # -CREATE TABLE test_repair_table2 ( val integer ) ENGINE = CSV; +CREATE TABLE test_repair_table2 ( val integer not null ) ENGINE = CSV; --remove_file $MYSQLTEST_VARDIR/master-data/test/test_repair_table2.CSM # Should give a warning and perform autorepair. We also disable ps-protocol @@ -1423,7 +1423,7 @@ DROP TABLE test_repair_table2; # Corrupt csv file and see if we can repair it -CREATE TABLE test_repair_table3 ( val integer ) ENGINE = CSV; +CREATE TABLE test_repair_table3 ( val integer not null ) ENGINE = CSV; --remove_file $MYSQLTEST_VARDIR/master-data/test/test_repair_table3.CSV --write_file $MYSQLTEST_VARDIR/master-data/test/test_repair_table3.CSV "1" @@ -1517,7 +1517,7 @@ DROP TABLE test_repair_table5; # BUG#13406 - incorrect amount of "records deleted" # -create table t1 (a int) engine=csv; +create table t1 (a int not null) engine=csv; insert t1 values (1); --enable_info delete from t1; # delete_row @@ -1549,7 +1549,7 @@ drop table t1; # whole alter table code is being tested all around the test suite already. # -create table t1 (v varchar(32)); +create table t1 (v varchar(32) not null); insert into t1 values ('def'),('abc'),('hij'),('3r4f'); select * from t1; # Fast alter, no copy performed @@ -1583,8 +1583,8 @@ drop table t1; # resulted in scanning through deleted memory and we were geting a crash. # that's why we need two tables in the bugtest -create table bug15205 (val int(11) default null) engine=csv; -create table bug15205_2 (val int(11) default null) engine=csv; +create table bug15205 (val int(11) not null) engine=csv; +create table bug15205_2 (val int(11) not null) engine=csv; --remove_file $MYSQLTEST_VARDIR/master-data/test/bug15205.CSV # system error (can't open the datafile) --replace_result $MYSQLTEST_VARDIR . master-data/ '' @@ -1604,8 +1604,8 @@ drop table bug15205_2; # set names latin1; create table t1 ( - c varchar(1), - name varchar(64) + c varchar(1) not null, + name varchar(64) not null ) character set latin1 engine=csv; insert into t1 values (0xC0,'LATIN CAPITAL LETTER A WITH GRAVE'); insert into t1 values (0xE0,'LATIN SMALL LETTER A WITH GRAVE'); @@ -1623,9 +1623,9 @@ drop table t1; # Bug#22080 "CHECK fails to identify some corruption" # -create table bug22080_1 (id int,string varchar(64)) Engine=CSV; -create table bug22080_2 (id int,string varchar(64)) Engine=CSV; -create table bug22080_3 (id int,string varchar(64)) Engine=CSV; +create table bug22080_1 (id int not null,string varchar(64) not null) Engine=CSV; +create table bug22080_2 (id int not null,string varchar(64) not null) Engine=CSV; +create table bug22080_3 (id int not null,string varchar(64) not null) Engine=CSV; insert into bug22080_1 values(1,'string'); insert into bug22080_1 values(2,'string'); insert into bug22080_1 values(3,'string'); @@ -1655,7 +1655,7 @@ drop tables bug22080_1,bug22080_2,bug22080_3; # # Testing float type # -create table float_test (id float,string varchar(64)) Engine=CSV; +create table float_test (id float not null,string varchar(64) not null) Engine=CSV; insert into float_test values(1.0,'string'); insert into float_test values(2.23,'serg.g'); insert into float_test values(0.03,'string'); @@ -1670,12 +1670,12 @@ drop table float_test; # CREATE TABLE `bug21328` ( - `col1` int(11) DEFAULT NULL, - `col2` int(11) DEFAULT NULL, - `col3` int(11) DEFAULT NULL + `col1` int(11) NOT NULL, + `col2` int(11) NOT NULL, + `col3` int(11) NOT NULL ) ENGINE=CSV; -insert into bug21328 values (1,NULL,NULL); +insert into bug21328 values (1,0,0); alter table bug21328 engine=myisam; drop table bug21328; @@ -1683,7 +1683,7 @@ drop table bug21328; # BUG#28971 - ALTER TABLE followed by UPDATE for a CSV table make server # crash # -create table t1(a blob, b int) engine=csv; +create table t1(a blob not null, b int not null) engine=csv; insert into t1 values('a', 1); flush tables; update t1 set b=2; @@ -1693,13 +1693,13 @@ drop table t1; # # Bug #29353: negative values # -create table t1(a int) engine=csv; +create table t1(a int not null) engine=csv; insert into t1 values(-1), (-123.34), (2), (-23); select * from t1; check table t1; drop table t1; -create table t1(a int, b int) engine=csv; +create table t1(a int not null, b int not null) engine=csv; --remove_file $MYSQLTEST_VARDIR/master-data/test/t1.CSV --write_file $MYSQLTEST_VARDIR/master-data/test/t1.CSV 1, 1E-2 @@ -1717,7 +1717,7 @@ drop table t1; # # Bug #29411: deleting from a csv table leads to the table corruption # -create table t1(a int) engine=csv; +create table t1(a int not null) engine=csv; insert into t1 values (0), (1), (2); delete from t1 limit 2; check table t1; @@ -1727,4 +1727,43 @@ check table t1; select * from t1; drop table t1; +# +# Bug #31473: does not work with NULL value in datetime field +# +create table t1(a datetime not null) engine=csv; +insert into t1 values(); +select * from t1; +drop table t1; +create table t1(a set('foo','bar') not null) engine=csv; +insert into t1 values(); +select * from t1; +drop table t1; +create table t1(a varchar(32) not null) engine=csv; +insert into t1 values(); +select * from t1; +drop table t1; +create table t1(a int not null) engine=csv; +insert into t1 values(); +select * from t1; +drop table t1; +create table t1(a blob not null) engine=csv; +insert into t1 values(); +select * from t1; +drop table t1; +create table t1(a bit(1) not null) engine=csv; +insert into t1 values(); +select BIN(a) from t1; +drop table t1; +# We prevent creation of table with nullable ENUM +--error ER_CANT_CREATE_TABLE +create table t1(a enum('foo','bar') default null) engine=csv; +--error ER_CANT_CREATE_TABLE +create table t1(a enum('foo','bar') default 'foo') engine=csv; +# Enum columns must be specified as NOT NULL +create table t1(a enum('foo','bar') default 'foo' not null) engine=csv; +insert into t1 values(); +select * from t1; +drop table t1; + + --echo End of 5.1 tests diff --git a/mysql-test/t/delayed.test b/mysql-test/t/delayed.test index 396c06f43e7..03b4f8b3013 100644 --- a/mysql-test/t/delayed.test +++ b/mysql-test/t/delayed.test @@ -251,4 +251,35 @@ CREATE TABLE t2(c1 INT) ENGINE=MERGE UNION=(t1); --error 1031 INSERT DELAYED INTO t2 VALUES(1); DROP TABLE t1, t2; +# +# Bug#27358 INSERT DELAYED does not honour SQL_MODE of the client +# +--disable_warnings +DROP TABLE IF EXISTS t1,t2; +--enable_warnings +SET SQL_MODE='NO_AUTO_VALUE_ON_ZERO'; +CREATE TABLE `t1` ( + `id` int(11) PRIMARY KEY auto_increment, + `f1` varchar(10) NOT NULL UNIQUE +); +INSERT DELAYED INTO t1 VALUES(0,"test1"); +sleep 1; +SELECT * FROM t1; +SET SQL_MODE='PIPES_AS_CONCAT'; +INSERT DELAYED INTO t1 VALUES(0,'a' || 'b'); +sleep 1; +SELECT * FROM t1; +SET SQL_MODE='ERROR_FOR_DIVISION_BY_ZERO,STRICT_ALL_TABLES'; +--error 1365 +INSERT DELAYED INTO t1 VALUES(mod(1,0),"test3"); +CREATE TABLE t2 ( + `id` int(11) PRIMARY KEY auto_increment, + `f1` date +); +SET SQL_MODE='NO_ZERO_DATE,STRICT_ALL_TABLES,NO_ZERO_IN_DATE'; +--error ER_TRUNCATED_WRONG_VALUE +INSERT DELAYED INTO t2 VALUES (0,'0000-00-00'); +--error ER_TRUNCATED_WRONG_VALUE +INSERT DELAYED INTO t2 VALUES (0,'2007-00-00'); +DROP TABLE t1,t2; diff --git a/mysql-test/t/heap_btree.test b/mysql-test/t/heap_btree.test index 204b820970c..b51eeb27331 100644 --- a/mysql-test/t/heap_btree.test +++ b/mysql-test/t/heap_btree.test @@ -213,6 +213,15 @@ CREATE TABLE t1 ( INSERT INTO t1 VALUES('1'), ('2'); DROP TABLE t1; +# +# BUG#30590 - delete from memory table with composite btree primary key +# +CREATE TABLE t1 (a INT, KEY USING BTREE(a)) ENGINE=MEMORY; +INSERT INTO t1 VALUES(1),(2),(2); +DELETE FROM t1 WHERE a=2; +SELECT * FROM t1; +DROP TABLE t1; + --echo End of 4.1 tests # diff --git a/mysql-test/t/information_schema.test b/mysql-test/t/information_schema.test index 6bcc14d4e49..9ad658645bd 100644 --- a/mysql-test/t/information_schema.test +++ b/mysql-test/t/information_schema.test @@ -953,7 +953,7 @@ BEGIN DECLARE col1, col2, col3, col4, col6 CHAR(255); DECLARE default_val VARCHAR(65532); DECLARE done INT DEFAULT 0; - DECLARE cur1 CURSOR FOR SHOW COLUMNS FROM bug23037; + DECLARE cur1 CURSOR FOR SELECT COLUMN_NAME, COLUMN_TYPE, IS_NULLABLE, COLUMN_KEY, COLUMN_DEFAULT, EXTRA FROM INFORMATION_SCHEMA.COLUMNS where TABLE_NAME='bug23037'; DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' SET done = 1; OPEN cur1; FETCH cur1 INTO col1, col2, col3, col4, default_val, col6; diff --git a/mysql-test/t/log_tables.test b/mysql-test/t/log_tables.test index 89c7c255554..12098b4543b 100644 --- a/mysql-test/t/log_tables.test +++ b/mysql-test/t/log_tables.test @@ -253,11 +253,11 @@ use mysql; CREATE TABLE `general_log` ( `event_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - `user_host` mediumtext, - `thread_id` int(11) DEFAULT NULL, - `server_id` int(11) DEFAULT NULL, - `command_type` varchar(64) DEFAULT NULL, - `argument` mediumtext + `user_host` mediumtext NOT NULL, + `thread_id` int(11) NOT NULL, + `server_id` int(11) NOT NULL, + `command_type` varchar(64) NOT NULL, + `argument` mediumtext NOT NULL ) ENGINE=CSV DEFAULT CHARSET=utf8 COMMENT='General log'; CREATE TABLE `slow_log` ( @@ -268,10 +268,10 @@ CREATE TABLE `slow_log` ( `lock_time` time NOT NULL, `rows_sent` int(11) NOT NULL, `rows_examined` int(11) NOT NULL, - `db` varchar(512) DEFAULT NULL, - `last_insert_id` int(11) DEFAULT NULL, - `insert_id` int(11) DEFAULT NULL, - `server_id` int(11) DEFAULT NULL, + `db` varchar(512) NOT NULL, + `last_insert_id` int(11) NOT NULL, + `insert_id` int(11) NOT NULL, + `server_id` int(11) NOT NULL, `sql_text` mediumtext NOT NULL ) ENGINE=CSV DEFAULT CHARSET=utf8 COMMENT='Slow log'; @@ -295,6 +295,13 @@ unlock tables; # Bug #21785 Server crashes after rename of the log table # +--disable_warnings +drop table if exists mysql.renamed_general_log; +drop table if exists mysql.renamed_slow_log; +drop table if exists mysql.general_log_new; +drop table if exists mysql.slow_log_new; +--enable_warnings + use mysql; # Should result in error --error ER_CANT_RENAME_LOG_TABLE @@ -359,6 +366,55 @@ drop table renamed_general_log, renamed_slow_log; use test; # +# Bug#27858 (Failing to log to a log table doesn't log anything to error log) +# +# This test works as expected, it's a negative test. +# The message "[ERROR] Failed to write to mysql.general_log" +# is printed to master.err when writing to the table mysql.general_log +# failed. +# However, this message is picked up by mysql-test-run.pl, +# and reported as a test failure, which is a false negative. +# There is no current way to *selectively* filter out these expected error conditions +# (see mysql-test/lib/mtr_report.pl, mtr_report_stats()). +# Instead of filtering all occurences of "Failed to write to +# mysql.general_log", which could hide bugs when the error is not expected, +# this test case is commented instead. +# TODO: improve filtering of expected errors in master.err in +# mysql-test-run.pl (based on the test name ?), and uncomment this test. + +# --disable_warnings +# drop table if exists mysql.bad_general_log; +# drop table if exists mysql.bad_slow_log; +# drop table if exists mysql.general_log_hide; +# drop table if exists mysql.slow_log_hide; +# --enable_warnings +# +# create table mysql.bad_general_log (a int) engine= CSV; +# create table mysql.bad_slow_log (a int) engine= CSV; +# +# # Rename does not perform checks on the table structure, +# # exploiting this to force a failure to log +# rename table mysql.general_log to mysql.general_log_hide, mysql.bad_general_log TO mysql.general_log; +# rename table mysql.slow_log to mysql.slow_log_hide, mysql.bad_slow_log TO mysql.slow_log; +# +# # The following message should be printed in master.log: +# # [ERROR] Failed to write to mysql.general_log +# # TODO: See how verifying this could be automated +# +# flush tables; +# select "logging this should fail"; +# +# # Restore the log tables +# +# rename table mysql.general_log to mysql.bad_general_log, mysql.general_log_hide TO mysql.general_log; +# rename table mysql.slow_log to mysql.bad_slow_log, mysql.slow_log_hide TO mysql.slow_log; +# +# flush tables; +# +# drop table mysql.bad_general_log; +# drop table mysql.bad_slow_log; + +# # Bug #21966 Strange warnings on repair of the log tables # @@ -751,3 +807,120 @@ DROP DATABASE IF EXISTS `db_17876`; SET GLOBAL general_log = @old_general_log_state; SET GLOBAL slow_query_log = @old_slow_log_state; +# +# Bug#21557 entries in the general query log truncated at 1000 characters. +# + +truncate table mysql.general_log; +set @old_general_log_state = @@global.general_log; +set global general_log = on; +--disable_result_log +set @lparam = "000 001 002 003 004 005 006 007 008 009" + "010 011 012 013 014 015 016 017 018 019" + "020 021 022 023 024 025 026 027 028 029" + "030 031 032 033 034 035 036 037 038 039" + "040 041 042 043 044 045 046 047 048 049" + "050 051 052 053 054 055 056 057 058 059" + "060 061 062 063 064 065 066 067 068 069" + "070 071 072 073 074 075 076 077 078 079" + "080 081 082 083 084 085 086 087 088 089" + "090 091 092 093 094 095 096 097 098 099" + "100 101 102 103 104 105 106 107 108 109" + "110 111 112 113 114 115 116 117 118 119" + "120 121 122 123 124 125 126 127 128 129" + "130 131 132 133 134 135 136 137 138 139" + "140 141 142 143 144 145 146 147 148 149" + "150 151 152 153 154 155 156 157 158 159" + "160 161 162 163 164 165 166 167 168 169" + "170 171 172 173 174 175 176 177 178 179" + "180 181 182 183 184 185 186 187 188 189" + "190 191 192 193 194 195 196 197 198 199" + "200 201 202 203 204 205 206 207 208 209" + "210 211 212 213 214 215 216 217 218 219" + "220 221 222 223 224 225 226 227 228 229" + "230 231 232 233 234 235 236 237 238 239" + "240 241 242 243 244 245 246 247 248 249" + "250 251 252 253 254 255 256 257 258 259" + "260 261 262 263 264 265 266 267 268 269" + "270 271 272 273 274 275 276 277 278 279" + "280 281 282 283 284 285 286 287 288 289" + "290 291 292 293 294 295 296 297 298 299" + "300 301 302 303 304 305 306 307 308 309" + "310 311 312 313 314 315 316 317 318 319" + "320 321 322 323 324 325 326 327 328 329" + "330 331 332 333 334 335 336 337 338 339" + "340 341 342 343 344 345 346 347 348 349" + "350 351 352 353 354 355 356 357 358 359" + "360 361 362 363 364 365 366 367 368 369" + "370 371 372 373 374 375 376 377 378 379" + "380 381 382 383 384 385 386 387 388 389" + "390 391 392 393 394 395 396 397 398 399" + "400 401 402 403 404 405 406 407 408 409" + "410 411 412 413 414 415 416 417 418 419" + "420 421 422 423 424 425 426 427 428 429" + "430 431 432 433 434 435 436 437 438 439" + "440 441 442 443 444 445 446 447 448 449" + "450 451 452 453 454 455 456 457 458 459" + "460 461 462 463 464 465 466 467 468 469" + "470 471 472 473 474 475 476 477 478 479" + "480 481 482 483 484 485 486 487 488 489" + "490 491 492 493 494 495 496 497 498 499" + "500 501 502 503 504 505 506 507 508 509" + "510 511 512 513 514 515 516 517 518 519" + "520 521 522 523 524 525 526 527 528 529" + "530 531 532 533 534 535 536 537 538 539" + "540 541 542 543 544 545 546 547 548 549" + "550 551 552 553 554 555 556 557 558 559" + "560 561 562 563 564 565 566 567 568 569" + "570 571 572 573 574 575 576 577 578 579" + "580 581 582 583 584 585 586 587 588 589" + "590 591 592 593 594 595 596 597 598 599" + "600 601 602 603 604 605 606 607 608 609" + "610 611 612 613 614 615 616 617 618 619" + "620 621 622 623 624 625 626 627 628 629" + "630 631 632 633 634 635 636 637 638 639" + "640 641 642 643 644 645 646 647 648 649" + "650 651 652 653 654 655 656 657 658 659" + "660 661 662 663 664 665 666 667 668 669" + "670 671 672 673 674 675 676 677 678 679" + "680 681 682 683 684 685 686 687 688 689" + "690 691 692 693 694 695 696 697 698 699" + "700 701 702 703 704 705 706 707 708 709" + "710 711 712 713 714 715 716 717 718 719" + "720 721 722 723 724 725 726 727 728 729" + "730 731 732 733 734 735 736 737 738 739" + "740 741 742 743 744 745 746 747 748 749" + "750 751 752 753 754 755 756 757 758 759" + "760 761 762 763 764 765 766 767 768 769" + "770 771 772 773 774 775 776 777 778 779" + "780 781 782 783 784 785 786 787 788 789" + "790 791 792 793 794 795 796 797 798 799" + "800 801 802 803 804 805 806 807 808 809" + "810 811 812 813 814 815 816 817 818 819" + "820 821 822 823 824 825 826 827 828 829" + "830 831 832 833 834 835 836 837 838 839" + "840 841 842 843 844 845 846 847 848 849" + "850 851 852 853 854 855 856 857 858 859" + "860 861 862 863 864 865 866 867 868 869" + "870 871 872 873 874 875 876 877 878 879" + "880 881 882 883 884 885 886 887 888 889" + "890 891 892 893 894 895 896 897 898 899" + "900 901 902 903 904 905 906 907 908 909" + "910 911 912 913 914 915 916 917 918 919" + "920 921 922 923 924 925 926 927 928 929" + "930 931 932 933 934 935 936 937 938 939" + "940 941 942 943 944 945 946 947 948 949" + "950 951 952 953 954 955 956 957 958 959" + "960 961 962 963 964 965 966 967 968 969" + "970 971 972 973 974 975 976 977 978 979" + "980 981 982 983 984 985 986 987 988 989" + "990 991 992 993 994 995 996 997 998 999"; +--enable_result_log +prepare long_query from "select ? as long_query"; +--disable_result_log +execute long_query using @lparam; +--enable_result_log +set global general_log = off; +select command_type, argument from mysql.general_log; +deallocate prepare long_query; +set global general_log = @old_general_log_state; diff --git a/mysql-test/t/merge.test b/mysql-test/t/merge.test index fd479276b3b..a50588b1e78 100644 --- a/mysql-test/t/merge.test +++ b/mysql-test/t/merge.test @@ -511,4 +511,18 @@ SELECT * FROM tm1; CHECK TABLE tm1; DROP TABLE tm1, t1, t2; +# +# Bug#15522 - create ... select and with merge tables +# +# This was fixed together with Bug#20662 (Infinite loop in CREATE TABLE +# IF NOT EXISTS ... SELECT with locked tables). +# The new behavior for MERGE tables is consistent with the +# CREATE TABLE SELECT behavior for ordinary tables. +# +CREATE TABLE t1(c1 INT); +CREATE TABLE t2 (c1 INT) ENGINE=MERGE UNION=(t1) INSERT_METHOD=FIRST; +--error ER_UPDATE_TABLE_USED +CREATE TABLE IF NOT EXISTS t1 SELECT * FROM t2; +DROP TABLE t1, t2; + --echo End of 5.0 tests diff --git a/mysql-test/t/mysql_client_test.test b/mysql-test/t/mysql_client_test.test index 66a27abd61a..7667522feaf 100644 --- a/mysql-test/t/mysql_client_test.test +++ b/mysql-test/t/mysql_client_test.test @@ -8,8 +8,8 @@ # server or run mysql-test-run --debug mysql_client_test and check # var/log/mysql_client_test.trace ---exec echo "$MYSQL_CLIENT_TEST" > $MYSQLTEST_VARDIR/log/mysql_client_test.log 2>&1 ---exec $MYSQL_CLIENT_TEST --getopt-ll-test=25600M >> $MYSQLTEST_VARDIR/log/mysql_client_test.log 2>&1 +--exec echo "$MYSQL_CLIENT_TEST" > $MYSQLTEST_VARDIR/log/mysql_client_test.out.log 2>&1 +--exec $MYSQL_CLIENT_TEST --getopt-ll-test=25600M >> $MYSQLTEST_VARDIR/log/mysql_client_test.out.log 2>&1 # End of 4.1 tests echo ok; diff --git a/mysql-test/t/mysqltest.test b/mysql-test/t/mysqltest.test index ec188af0244..d0c8c0b4e38 100644 --- a/mysql-test/t/mysqltest.test +++ b/mysql-test/t/mysqltest.test @@ -2083,5 +2083,23 @@ eval $show_statement; drop table t1; +# ---------------------------------------------------------------------------- +# Test change_user command +# ---------------------------------------------------------------------------- + +--error 1 +--exec echo "--change_user root,,inexistent" | $MYSQL_TEST 2>&1 + +--error 1 +--exec echo "--change_user inexistent,,test" | $MYSQL_TEST 2>&1 + +--error 1 +--exec echo "--change_user root,inexistent,test" | $MYSQL_TEST 2>&1 + +--change_user +--change_user root +--change_user root,, +--change_user root,,test + --echo End of tests diff --git a/mysql-test/t/partition.test b/mysql-test/t/partition.test index 2be2ab83c88..2906b4640cd 100644 --- a/mysql-test/t/partition.test +++ b/mysql-test/t/partition.test @@ -1481,6 +1481,15 @@ ALTER TABLE t1 DROP PARTITION p1; DROP TABLE t1; # +# Bug #30484: Partitions: crash with self-referencing trigger +# + +create table t (s1 int) engine=myisam partition by key (s1); +create trigger t_ad after delete on t for each row insert into t values (old.s1); +insert into t values (1); +drop table t; + +# # Bug #27816: Log tables ran with partitions crashes the server when logging # is enabled. # diff --git a/mysql-test/t/partition_innodb.test b/mysql-test/t/partition_innodb.test index f4320c5c56a..4a50332b3df 100644 --- a/mysql-test/t/partition_innodb.test +++ b/mysql-test/t/partition_innodb.test @@ -134,3 +134,11 @@ SELECT * FROM t1 WHERE first_name='Andy' OR last_name='Jake'; drop table t1; +# +# BUG#30583 - Partition on DOUBLE key + INNODB + count(*) == crash +# +CREATE TABLE t1 (a DOUBLE NOT NULL, KEY(a)) ENGINE=InnoDB +PARTITION BY KEY(a) PARTITIONS 10; +INSERT INTO t1 VALUES(1),(2); +SELECT COUNT(*) FROM t1; +DROP TABLE t1; diff --git a/mysql-test/t/query_cache.test b/mysql-test/t/query_cache.test index d06698cdb17..7571e60859f 100644 --- a/mysql-test/t/query_cache.test +++ b/mysql-test/t/query_cache.test @@ -1,10 +1,5 @@ -- source include/have_query_cache.inc -# Disabled on embedded due to bug #30710, "query_cache.test fails on -# embedded w/ per-column privs test". Please re-enable when that bug -# is resolved. --- source include/not_embedded.inc - # # Tests with query cache # @@ -1255,82 +1250,52 @@ disconnect user1; disconnect user2; disconnect user3; -# -# Bug #30269 Query cache eats memory -# ---disable_warnings -DROP DATABASE IF EXISTS bug30269; ---enable_warnings -FLUSH STATUS; -CREATE DATABASE bug30269; -USE bug30269; -CREATE TABLE test1 (id int, name varchar(23)); -CREATE VIEW view1 AS SELECT * FROM test1; -INSERT INTO test1 VALUES (5, 'testit'); -GRANT SELECT (id) ON TABLE bug30269.test1 TO 'bug30269'@'localhost'; -GRANT SELECT ON TABLE bug30269.view1 TO 'bug30269'@'localhost'; -set global query_cache_size= 81920; -connect (bug30269, localhost, bug30269,,); -connection bug30269; -USE bug30269; -show status like 'Qcache_queries_in_cache'; ---echo # Select statement not stored in query cache because of column privileges. -SELECT id FROM test1 WHERE id>2; -show status like 'Qcache_queries_in_cache'; -SELECT id FROM view1 WHERE id>2; -show status like 'Qcache_queries_in_cache'; +--echo End of 5.0 tests -connection default; -DROP DATABASE bug30269; -disconnect bug30269; -DROP USER 'bug30269'@'localhost'; +# +# Bug #28211 RENAME DATABASE and query cache don't play nicely together +# TODO: enable these tests when RENAME DATABASE is implemented. +# --disable_warnings +# drop database if exists db1; +# drop database if exists db2; +# --enable_warnings +# set GLOBAL query_cache_size=15*1024*1024; +# create database db1; +# use db1; +# create table t1(c1 int)engine=myisam; +# insert into t1(c1) values (1); +# select * from db1.t1 f; +# show status like 'Qcache_queries_in_cache'; +# rename schema db1 to db2; +# show status like 'Qcache_queries_in_cache'; +# drop database db2; +# set global query_cache_size=default; +# +# --disable_warnings +# drop database if exists db1; +# drop database if exists db3; +# --enable_warnings +# set GLOBAL query_cache_size=15*1024*1024; +# create database db1; +# create database db3; +# use db1; +# create table t1(c1 int) engine=myisam; +# use db3; +# create table t1(c1 int) engine=myisam; +# use db1; +# insert into t1(c1) values (1); +# use mysql; +# select * from db1.t1; +# select c1+1 from db1.t1; +# select * from db3.t1; +# show status like 'Qcache_queries_in_cache'; +# rename schema db1 to db2; +# show status like 'Qcache_queries_in_cache'; +# drop database db2; +# drop database db3; set GLOBAL query_cache_type=default; set GLOBAL query_cache_limit=default; set GLOBAL query_cache_min_res_unit=default; set GLOBAL query_cache_size=default; ---echo End of 5.0 tests - -# -# Bug #28211 RENAME DATABASE and query cache don't play nicely together -# ---disable_warnings -drop database if exists db1; -drop database if exists db2; ---enable_warnings -set GLOBAL query_cache_size=15*1024*1024; -create database db1; -use db1; -create table t1(c1 int)engine=myisam; -insert into t1(c1) values (1); -select * from db1.t1 f; -show status like 'Qcache_queries_in_cache'; -rename schema db1 to db2; -show status like 'Qcache_queries_in_cache'; -drop database db2; -set global query_cache_size=default; ---disable_warnings -drop database if exists db1; -drop database if exists db3; ---enable_warnings -set GLOBAL query_cache_size=15*1024*1024; -create database db1; -create database db3; -use db1; -create table t1(c1 int) engine=myisam; -use db3; -create table t1(c1 int) engine=myisam; -use db1; -insert into t1(c1) values (1); -use mysql; -select * from db1.t1; -select c1+1 from db1.t1; -select * from db3.t1; -show status like 'Qcache_queries_in_cache'; -rename schema db1 to db2; -show status like 'Qcache_queries_in_cache'; -drop database db2; -drop database db3; - ---echo End of 5.1 tests diff --git a/mysql-test/t/query_cache_notembedded.test b/mysql-test/t/query_cache_notembedded.test index a0085c0ba31..929b93e10d5 100644 --- a/mysql-test/t/query_cache_notembedded.test +++ b/mysql-test/t/query_cache_notembedded.test @@ -225,3 +225,39 @@ connection default; set GLOBAL query_cache_size=0; SET GLOBAL log_bin_trust_function_creators = 0; + +# +# Bug #30269 Query cache eats memory +# +--disable_warnings +DROP DATABASE IF EXISTS bug30269; +--enable_warnings +FLUSH STATUS; +CREATE DATABASE bug30269; +USE bug30269; +CREATE TABLE test1 (id int, name varchar(23)); +CREATE VIEW view1 AS SELECT * FROM test1; +INSERT INTO test1 VALUES (5, 'testit'); +GRANT SELECT (id) ON TABLE bug30269.test1 TO 'bug30269'@'localhost'; +GRANT SELECT ON TABLE bug30269.view1 TO 'bug30269'@'localhost'; +set global query_cache_size= 81920; +connect (bug30269, localhost, bug30269,,); +connection bug30269; +USE bug30269; +show status like 'Qcache_queries_in_cache'; +--echo # Select statement not stored in query cache because of column privileges. +SELECT id FROM test1 WHERE id>2; +show status like 'Qcache_queries_in_cache'; +SELECT id FROM view1 WHERE id>2; +show status like 'Qcache_queries_in_cache'; + +connection default; +DROP DATABASE bug30269; +disconnect bug30269; +DROP USER 'bug30269'@'localhost'; + +set GLOBAL query_cache_type=default; +set GLOBAL query_cache_limit=default; +set GLOBAL query_cache_min_res_unit=default; +set GLOBAL query_cache_size=default; + diff --git a/mysql-test/t/renamedb.test b/mysql-test/t/renamedb.test index 1e71adb3bf3..84315090b7a 100644 --- a/mysql-test/t/renamedb.test +++ b/mysql-test/t/renamedb.test @@ -1,26 +1,53 @@ ---disable_warnings -drop database if exists testdb1; ---enable_warnings - -create database testdb1 default character set latin2; -use testdb1; -create table t1 (a int); -insert into t1 values (1),(2),(3); -show create database testdb1; -show tables; -rename database testdb1 to testdb2; ---error 1049 -show create database testdb1; -show create database testdb2; -select database(); -show tables; -select a from t1 order by a; -drop database testdb2; +# TODO: enable these tests when RENAME DATABASE is implemented. +# +# --disable_warnings +# drop database if exists testdb1; +# --enable_warnings +# +# create database testdb1 default character set latin2; +# use testdb1; +# create table t1 (a int); +# insert into t1 values (1),(2),(3); +# show create database testdb1; +# show tables; +# rename database testdb1 to testdb2; +# --error 1049 +# show create database testdb1; +# show create database testdb2; +# select database(); +# show tables; +# select a from t1 order by a; +# drop database testdb2; +# # # Bug#19392 Rename Database: Crash if case change # -create database testdb1; ---error 1007 -rename database testdb1 to testdb1; -drop database testdb1; +# create database testdb1; +# --error 1007 +# rename database testdb1 to testdb1; +# drop database testdb1; + +# +# WL#4030 (Deprecate RENAME DATABASE: replace with ALTER DATABASE <name> UPGRADE) +# + +--error ER_PARSE_ERROR +rename database testdb1 to testdb2; + +--error ER_WRONG_USAGE +ALTER DATABASE wrong UPGRADE DATA DIRECTORY NAME; + +--error ER_WRONG_USAGE +ALTER DATABASE `#mysql41#not-supported` UPGRADE DATA DIRECTORY NAME; + +--error ER_WRONG_USAGE +ALTER DATABASE `#mysql51#not-yet` UPGRADE DATA DIRECTORY NAME; + +--error ER_WRONG_USAGE +ALTER DATABASE `#mysql50#` UPGRADE DATA DIRECTORY NAME; + +--error ER_BAD_DB_ERROR +ALTER DATABASE `#mysql50#upgrade-me` UPGRADE DATA DIRECTORY NAME; + + diff --git a/mysql-test/t/sp-error.test b/mysql-test/t/sp-error.test index 012f2b33225..a956a246770 100644 --- a/mysql-test/t/sp-error.test +++ b/mysql-test/t/sp-error.test @@ -196,7 +196,7 @@ select f(10)| drop function f| ---error 1322 +--error ER_PARSE_ERROR create procedure p() begin declare c cursor for insert into test.t1 values ("foo", 42); @@ -1763,7 +1763,7 @@ drop procedure bug15091; drop function if exists bug16896; --enable_warnings ---error ER_SP_NO_AGGREGATE +--error ER_PARSE_ERROR create aggregate function bug16896() returns int return 1; # @@ -2150,6 +2150,78 @@ end// delimiter ;// + +# +# Bug#28360 (RENAME DATABASE destroys routines) +# + +--disable_warnings +drop procedure if exists proc_28360; +drop function if exists func_28360; +--enable_warnings + +delimiter //; + +--error ER_SP_NO_DROP_SP +CREATE PROCEDURE proc_28360() +BEGIN + ALTER DATABASE `#mysql50#upgrade-me` UPGRADE DATA DIRECTORY NAME; +END// + +--error ER_SP_NO_DROP_SP +CREATE FUNCTION func_28360() RETURNS int +BEGIN + ALTER DATABASE `#mysql50#upgrade-me` UPGRADE DATA DIRECTORY NAME; + RETURN 0; +END// + +delimiter ;// + + +# +# Bug#29223 declare cursor c for SHOW ..... +# + +--disable_warnings +DROP PROCEDURE IF EXISTS p1; +--enable_warnings +--delimiter | +--error ER_PARSE_ERROR +CREATE PROCEDURE p1() +BEGIN + DECLARE c char(100); + DECLARE cur1 CURSOR FOR SHOW TABLES; + + OPEN cur1; + FETCH cur1 INTO c; + select c; + CLOSE cur1; +END| +--delimiter ; + +# +# Bug#29816 Syntactically wrong query fails with misleading error message +# + +--disable_warnings +DROP DATABASE IF EXISTS mysqltest; +--enable_warnings +CREATE DATABASE mysqltest; +USE mysqltest; +DROP DATABASE mysqltest; +# Both ER_SP_DOES_NOT_EXIST and ER_PARSE_ERROR are valid here, +# the result is implementation dependent: +# See Bug#29816 for details +--error ER_SP_DOES_NOT_EXIST +SELECT inexistent(), 1 + ,; +--error ER_SP_DOES_NOT_EXIST +SELECT inexistent(); +--error ER_PARSE_ERROR +SELECT .inexistent(); +--error ER_PARSE_ERROR +SELECT ..inexistent(); +USE test; + # # BUG#NNNN: New bug synopsis # diff --git a/mysql-test/t/sp.test b/mysql-test/t/sp.test index 4e4102dd1ef..004e1c4ddd2 100644 --- a/mysql-test/t/sp.test +++ b/mysql-test/t/sp.test @@ -7581,4 +7581,479 @@ DROP TABLE t1; DROP PROCEDURE p1; DROP PROCEDURE p2; +########################################################################### + +# +# Bug#31035: select from function, group by result crasher. +# + +########################################################################### + +--echo + +--echo # +--echo # Bug#31035. +--echo # + +--echo + +--echo # +--echo # - Prepare. +--echo # + +--echo + +--disable_warnings +DROP TABLE IF EXISTS t1; +DROP FUNCTION IF EXISTS f1; +DROP FUNCTION IF EXISTS f2; +DROP FUNCTION IF EXISTS f3; +DROP FUNCTION IF EXISTS f4; +--enable_warnings + +--echo + +--echo # +--echo # - Create required objects. +--echo # + +--echo + +CREATE TABLE t1(c1 INT); + +--echo + +INSERT INTO t1 VALUES (1), (2), (3); + +--echo + +CREATE FUNCTION f1() + RETURNS INT + NOT DETERMINISTIC + RETURN 1; + +--echo + +CREATE FUNCTION f2(p INT) + RETURNS INT + NOT DETERMINISTIC + RETURN 1; + +--echo + +CREATE FUNCTION f3() + RETURNS INT + DETERMINISTIC + RETURN 1; + +--echo + +CREATE FUNCTION f4(p INT) + RETURNS INT + DETERMINISTIC + RETURN 1; + +--echo + +--echo # +--echo # - Check. +--echo # + +--echo + +# Not deterministic function, no arguments. + +SELECT f1() AS a FROM t1 GROUP BY a; + +--echo + +# Not deterministic function, non-constant argument. + +SELECT f2(@a) AS a FROM t1 GROUP BY a; + +--echo + +# Deterministic function, no arguments. + +SELECT f3() AS a FROM t1 GROUP BY a; + +--echo + +# Deterministic function, constant argument. + +SELECT f4(0) AS a FROM t1 GROUP BY a; + +--echo + +# Deterministic function, non-constant argument. + +SELECT f4(@a) AS a FROM t1 GROUP BY a; + +--echo + +--echo # +--echo # - Cleanup. +--echo # + +--echo + +DROP TABLE t1; +DROP FUNCTION f1; +DROP FUNCTION f2; +DROP FUNCTION f3; +DROP FUNCTION f4; + +--echo + +########################################################################### + +# +# Bug#31191: JOIN in combination with stored function crashes the server. +# + +########################################################################### + +--echo # +--echo # Bug#31191. +--echo # + +--echo + +--echo # +--echo # - Prepare. +--echo # + +--echo + +--disable_warnings +DROP TABLE IF EXISTS t1; +DROP TABLE IF EXISTS t2; +DROP FUNCTION IF EXISTS f1; +--enable_warnings + +--echo + +--echo # +--echo # - Create required objects. +--echo # + +--echo + +CREATE TABLE t1 ( + id INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, + barcode INT(8) UNSIGNED ZEROFILL nOT NULL, + PRIMARY KEY (id), + UNIQUE KEY barcode (barcode) +); + +--echo + +INSERT INTO t1 (id, barcode) VALUES (1, 12345678); +INSERT INTO t1 (id, barcode) VALUES (2, 12345679); + +--echo + +CREATE TABLE test.t2 ( + id INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, + barcode BIGINT(11) UNSIGNED ZEROFILL NOT NULL, + PRIMARY KEY (id) +); + +--echo + +INSERT INTO test.t2 (id, barcode) VALUES (1, 12345106708); +INSERT INTO test.t2 (id, barcode) VALUES (2, 12345106709); + +--echo + +CREATE FUNCTION f1(p INT(8)) + RETURNS BIGINT(11) UNSIGNED + READS SQL DATA + RETURN FLOOR(p/1000)*1000000 + 100000 + FLOOR((p MOD 1000)/10)*100 + (p MOD 10); + +--echo + +--echo # +--echo # - Check. +--echo # + +--echo + +SELECT DISTINCT t1.barcode, f1(t1.barcode) +FROM t1 +INNER JOIN t2 +ON f1(t1.barcode) = t2.barcode +WHERE t1.barcode=12345678; + +--echo + +--echo # +--echo # - Cleanup. +--echo # + +--echo + +DROP TABLE t1; +DROP TABLE t2; +DROP FUNCTION f1; + +--echo + +########################################################################### + +# +# Bug#31226: Group by function crashes mysql. +# + +########################################################################### + +--echo # +--echo # Bug#31226. +--echo # + +--echo + +--echo # +--echo # - Prepare. +--echo # + +--echo + +--disable_warnings +DROP TABLE IF EXISTS t1; +DROP FUNCTION IF EXISTS f1; +--enable_warnings + +--echo + +--echo # +--echo # - Create required objects. +--echo # + +--echo + +CREATE TABLE t1(id INT); + +--echo + +INSERT INTO t1 VALUES (1), (2), (3); + +--echo + +CREATE FUNCTION f1() + RETURNS DATETIME + NOT DETERMINISTIC NO SQL + RETURN NOW(); + +--echo + +--echo # +--echo # - Check. +--echo # + +--echo + +--replace_column 1 <timestamp> +SELECT f1() FROM t1 GROUP BY 1; + +--echo + +--echo # +--echo # - Cleanup. +--echo # + +--echo + +DROP TABLE t1; +DROP FUNCTION f1; + +--echo + +########################################################################### + +# +# Bug#28318 (CREATE FUNCTION (UDF) requires a schema) +# + +--disable_warnings +DROP PROCEDURE IF EXISTS db28318_a.t1; +DROP PROCEDURE IF EXISTS db28318_b.t2; +DROP DATABASE IF EXISTS db28318_a; +DROP DATABASE IF EXISTS db28318_b; +--enable_warnings + +CREATE DATABASE db28318_a; +CREATE DATABASE db28318_b; + +CREATE PROCEDURE db28318_a.t1() SELECT "db28318_a.t1"; +CREATE PROCEDURE db28318_b.t2() CALL t1(); + +use db28318_a; + +# In db28318_b.t2, t1 refers to db28318_b.t1 +--error ER_SP_DOES_NOT_EXIST +CALL db28318_b.t2(); + +DROP PROCEDURE db28318_a.t1; +DROP PROCEDURE db28318_b.t2; +DROP DATABASE db28318_a; +DROP DATABASE db28318_b; +use test; + +########################################################################### + --echo End of 5.0 tests + +########################################################################### + +# +# Bug#20550: Stored function: wrong RETURN type metadata when used in a VIEW. +# + +########################################################################### + +--echo + +--echo # +--echo # Bug#20550. +--echo # + +--echo + +--echo # +--echo # - Prepare. +--echo # + +--echo + +--disable_warnings +DROP VIEW IF EXISTS v1; +DROP VIEW IF EXISTS v2; +DROP FUNCTION IF EXISTS f1; +DROP FUNCTION IF EXISTS f2; +--enable_warnings + +--echo + +--echo # +--echo # - Create required objects. +--echo # + +--echo + +CREATE FUNCTION f1() RETURNS VARCHAR(65525) RETURN 'Hello'; + +--echo + +CREATE FUNCTION f2() RETURNS TINYINT RETURN 1; + +--echo + +CREATE VIEW v1 AS SELECT f1(); + +--echo + +CREATE VIEW v2 AS SELECT f2(); + +--echo + +--echo # +--echo # - Check. +--echo # + +--echo + +SELECT DATA_TYPE FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 'v1'; + +--echo + +SELECT DATA_TYPE FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 'v2'; + +--echo + +--echo # +--echo # - Cleanup. +--echo # + +--echo + +DROP FUNCTION f1; +DROP FUNCTION f2; +DROP VIEW v1; +DROP VIEW v2; + +--echo + +########################################################################### + +# +# Bug#24923: Functions with ENUM issues. +# + +########################################################################### + +--echo # +--echo # - Bug#24923: prepare. +--echo # + +--echo + +--disable_warnings +DROP FUNCTION IF EXISTS f1; +--enable_warnings + +--echo + +--echo # +--echo # - Bug#24923: create required objects. +--echo # + +--echo + +delimiter |; + +CREATE FUNCTION f1(p INT) + RETURNS ENUM ('Very_long_enum_element_identifier', + 'Another_very_long_enum_element_identifier') + BEGIN + CASE p + WHEN 1 THEN + RETURN 'Very_long_enum_element_identifier'; + ELSE + RETURN 'Another_very_long_enum_element_identifier'; + END CASE; + END| + +delimiter ;| + +--echo + +--echo # +--echo # - Bug#24923: check. +--echo # + +--echo + +SELECT f1(1); + +--echo + +SELECT f1(2); + +--echo + +SHOW CREATE FUNCTION f1; + +--echo # +--echo # - Bug#24923: cleanup. +--echo # + +--echo + +DROP FUNCTION f1; + +--echo + +########################################################################### + +--echo End of 5.1 tests diff --git a/mysql-test/t/udf.test b/mysql-test/t/udf.test index 2f1d197cb9e..663dc08d72e 100644 --- a/mysql-test/t/udf.test +++ b/mysql-test/t/udf.test @@ -113,11 +113,11 @@ DROP TABLE bug19904; # Bug#21269: DEFINER-clause is allowed for UDF-functions # ---error ER_WRONG_USAGE +--error ER_PARSE_ERROR CREATE DEFINER=CURRENT_USER() FUNCTION should_not_parse RETURNS STRING SONAME "should_not_parse.so"; ---error ER_WRONG_USAGE +--error ER_PARSE_ERROR CREATE DEFINER=someone@somewhere FUNCTION should_not_parse RETURNS STRING SONAME "should_not_parse.so"; # @@ -206,11 +206,12 @@ DROP FUNCTION IF EXISTS metaphon; CREATE FUNCTION metaphon(a int) RETURNS int return 0; +# this currently passes, and eclipse the stored function --replace_result $UDF_EXAMPLE_LIB UDF_EXAMPLE_LIB ---error ER_UDF_EXISTS eval CREATE FUNCTION metaphon RETURNS STRING SONAME "$UDF_EXAMPLE_LIB"; DROP FUNCTION metaphon; +DROP FUNCTION metaphon; --replace_result $UDF_EXAMPLE_LIB UDF_EXAMPLE_LIB eval CREATE FUNCTION metaphon RETURNS STRING SONAME "$UDF_EXAMPLE_LIB"; @@ -363,6 +364,20 @@ drop table t1; drop function metaphon; set GLOBAL query_cache_size=default; +# +# Bug#28318 CREATE FUNCTION (UDF) requires a schema +# + +--disable_warnings +DROP DATABASE IF EXISTS mysqltest; +--enable_warnings +CREATE DATABASE mysqltest; +USE mysqltest; +DROP DATABASE mysqltest; +--replace_result $UDF_EXAMPLE_LIB UDF_EXAMPLE_LIB +eval CREATE FUNCTION metaphon RETURNS STRING SONAME "$UDF_EXAMPLE_LIB"; +DROP FUNCTION metaphon; +USE test; # # Bug #29804 UDF parameters don't contain correct string length diff --git a/mysql-test/t/upgrade.test b/mysql-test/t/upgrade.test index f517c7787f8..05f430b087b 100644 --- a/mysql-test/t/upgrade.test +++ b/mysql-test/t/upgrade.test @@ -1,5 +1,10 @@ -- source include/not_embedded.inc +# Temporary disabled on windows, +# because of --exec mkdir +# TODO: implement Bug#31004 and remove this limitation +--source include/not_windows.inc + --disable_warnings drop database if exists `mysqltest1`; drop database if exists `mysqltest-1`; @@ -56,3 +61,33 @@ system cp $MYSQL_TEST_DIR/std_data/old_table-323.frm $MYSQLTEST_VARDIR/master-da truncate t1; drop table t1; +# +# Bug#28360 (RENAME DATABASE destroys routines) +# + +--disable_warnings +drop database if exists `tabc`; +drop database if exists `a-b-c`; +--enable_warnings + +create database `tabc` default character set latin2; +create table tabc.t1 (a int); +FLUSH TABLES; + +# Manually make a 5.0 database from the template +--exec mkdir $MYSQLTEST_VARDIR/master-data/a-b-c +--copy_file $MYSQLTEST_VARDIR/master-data/tabc/db.opt $MYSQLTEST_VARDIR/master-data/a-b-c/db.opt +--copy_file $MYSQLTEST_VARDIR/master-data/tabc/t1.frm $MYSQLTEST_VARDIR/master-data/a-b-c/t1.frm +--copy_file $MYSQLTEST_VARDIR/master-data/tabc/t1.MYD $MYSQLTEST_VARDIR/master-data/a-b-c/t1.MYD +--copy_file $MYSQLTEST_VARDIR/master-data/tabc/t1.MYI $MYSQLTEST_VARDIR/master-data/a-b-c/t1.MYI + +show databases like '%a-b-c%'; +ALTER DATABASE `#mysql50#a-b-c` UPGRADE DATA DIRECTORY NAME; +# The physical directory name is now a@002db@002dc, the logical name still a-b-c +show databases like '%a-b-c%'; +show create database `a-b-c`; +show tables in `a-b-c`; +show create table `a-b-c`.`t1`; +drop database `a-b-c`; +drop database `tabc`; + diff --git a/mysys/my_getopt.c b/mysys/my_getopt.c index 5b5c0881314..3aad6152dfd 100644 --- a/mysys/my_getopt.c +++ b/mysys/my_getopt.c @@ -21,6 +21,9 @@ #include <my_getopt.h> #include <errno.h> +typedef void (*init_func_p)(const struct my_option *option, uchar* *variable, + longlong value); + static void default_reporter(enum loglevel level, const char *format, ...); my_error_reporter my_getopt_error_reporter= &default_reporter; @@ -34,7 +37,12 @@ static longlong getopt_ll(char *arg, const struct my_option *optp, int *err); static ulonglong getopt_ull(char *arg, const struct my_option *optp, int *err); static double getopt_double(char *arg, const struct my_option *optp, int *err); -static void init_variables(const struct my_option *options); +static void init_variables(const struct my_option *options, + init_func_p init_one_value); +static void init_one_value(const struct my_option *option, uchar* *variable, + longlong value); +static void fini_one_value(const struct my_option *option, uchar* *variable, + longlong value); static int setval(const struct my_option *opts, uchar* *value, char *argument, my_bool set_maximum_value); static char *check_struct_option(char *cur_arg, char *key_name); @@ -118,7 +126,7 @@ int handle_options(int *argc, char ***argv, DBUG_ASSERT(argv && *argv); (*argc)--; /* Skip the program name */ (*argv)++; /* --- || ---- */ - init_variables(longopts); + init_variables(longopts, init_one_value); for (pos= *argv, pos_end=pos+ *argc; pos != pos_end ; pos++) { @@ -922,6 +930,37 @@ static void init_one_value(const struct my_option *option, uchar* *variable, } +/* + Init one value to it's default values + + SYNOPSIS + init_one_value() + option Option to initialize + value Pointer to variable +*/ + +static void fini_one_value(const struct my_option *option, uchar* *variable, + longlong value __attribute__ ((unused))) +{ + DBUG_ENTER("fini_one_value"); + switch ((option->var_type & GET_TYPE_MASK)) { + case GET_STR_ALLOC: + my_free((*(char**) variable), MYF(MY_ALLOW_ZERO_PTR)); + *((char**) variable)= NULL; + break; + default: /* dummy default to avoid compiler warnings */ + break; + } + DBUG_VOID_RETURN; +} + + +void my_cleanup_options(const struct my_option *options) +{ + init_variables(options, fini_one_value); +} + + /* initialize all variables to their default values @@ -935,7 +974,8 @@ static void init_one_value(const struct my_option *option, uchar* *variable, for a value and initialize. */ -static void init_variables(const struct my_option *options) +static void init_variables(const struct my_option *options, + init_func_p init_one_value) { DBUG_ENTER("init_variables"); for (; options->name; options++) diff --git a/mysys/my_winthread.c b/mysys/my_winthread.c index 27ccaef4f23..e94369bec32 100644 --- a/mysys/my_winthread.c +++ b/mysys/my_winthread.c @@ -40,6 +40,29 @@ void win_pthread_init(void) pthread_mutex_init(&THR_LOCK_thread,MY_MUTEX_INIT_FAST); } + +/** + Adapter to @c pthread_mutex_trylock() + + @retval 0 Mutex was acquired + @retval EBUSY Mutex was already locked by a thread + */ +int +win_pthread_mutex_trylock(pthread_mutex_t *mutex) +{ + if (TryEnterCriticalSection(mutex)) + { + /* Don't allow recursive lock */ + if (mutex->RecursionCount > 1){ + LeaveCriticalSection(mutex); + return EBUSY; + } + return 0; + } + return EBUSY; +} + + /* ** We have tried to use '_beginthreadex' instead of '_beginthread' here ** but in this case the program leaks about 512 characters for each diff --git a/mysys/thr_mutex.c b/mysys/thr_mutex.c index e7a927e562a..49003553f0b 100644 --- a/mysys/thr_mutex.c +++ b/mysys/thr_mutex.c @@ -91,7 +91,7 @@ int safe_mutex_init(safe_mutex_t *mp, } -int safe_mutex_lock(safe_mutex_t *mp,const char *file, uint line) +int safe_mutex_lock(safe_mutex_t *mp, my_bool try_lock, const char *file, uint line) { int error; if (!mp->file) @@ -104,15 +104,50 @@ int safe_mutex_lock(safe_mutex_t *mp,const char *file, uint line) } pthread_mutex_lock(&mp->global); - if (mp->count > 0 && pthread_equal(pthread_self(),mp->thread)) + if (mp->count > 0) { - fprintf(stderr,"safe_mutex: Trying to lock mutex at %s, line %d, when the mutex was already locked at %s, line %d in thread %s\n", - file,line,mp->file, mp->line, my_thread_name()); - fflush(stderr); - abort(); + if (try_lock) + { + pthread_mutex_unlock(&mp->global); + return EBUSY; + } + else if (pthread_equal(pthread_self(),mp->thread)) + { + fprintf(stderr, + "safe_mutex: Trying to lock mutex at %s, line %d, when the" + " mutex was already locked at %s, line %d in thread %s\n", + file,line,mp->file, mp->line, my_thread_name()); + fflush(stderr); + abort(); + } } pthread_mutex_unlock(&mp->global); - error=pthread_mutex_lock(&mp->mutex); + + /* + If we are imitating trylock(), we need to take special + precautions. + + - We cannot use pthread_mutex_lock() only since another thread can + overtake this thread and take the lock before this thread + causing pthread_mutex_trylock() to hang. In this case, we should + just return EBUSY. Hence, we use pthread_mutex_trylock() to be + able to return immediately. + + - We cannot just use trylock() and continue execution below, since + this would generate an error and abort execution if the thread + was overtaken and trylock() returned EBUSY . In this case, we + instead just return EBUSY, since this is the expected behaviour + of trylock(). + */ + if (try_lock) + { + error= pthread_mutex_trylock(&mp->mutex); + if (error == EBUSY) + return error; + } + else + error= pthread_mutex_lock(&mp->mutex); + if (error || (error=pthread_mutex_lock(&mp->global))) { fprintf(stderr,"Got error %d when trying to lock mutex at %s, line %d\n", diff --git a/scripts/mysql_system_tables.sql b/scripts/mysql_system_tables.sql index f7b23e4e7ae..7ca35ae0752 100644 --- a/scripts/mysql_system_tables.sql +++ b/scripts/mysql_system_tables.sql @@ -60,13 +60,13 @@ CREATE TABLE IF NOT EXISTS time_zone_transition_type ( Time_zone_id int unsign CREATE TABLE IF NOT EXISTS time_zone_leap_second ( Transition_time bigint signed NOT NULL, Correction int signed NOT NULL, PRIMARY KEY TranTime (Transition_time) ) engine=MyISAM CHARACTER SET utf8 comment='Leap seconds information for time zones'; -CREATE TABLE IF NOT EXISTS proc (db char(64) collate utf8_bin DEFAULT '' NOT NULL, name char(64) DEFAULT '' NOT NULL, type enum('FUNCTION','PROCEDURE') NOT NULL, specific_name char(64) DEFAULT '' NOT NULL, language enum('SQL') DEFAULT 'SQL' NOT NULL, sql_data_access enum( 'CONTAINS_SQL', 'NO_SQL', 'READS_SQL_DATA', 'MODIFIES_SQL_DATA') DEFAULT 'CONTAINS_SQL' NOT NULL, is_deterministic enum('YES','NO') DEFAULT 'NO' NOT NULL, security_type enum('INVOKER','DEFINER') DEFAULT 'DEFINER' NOT NULL, param_list blob NOT NULL, returns char(64) DEFAULT '' NOT NULL, body longblob NOT NULL, definer char(77) collate utf8_bin DEFAULT '' NOT NULL, created timestamp, modified timestamp, sql_mode set( 'REAL_AS_FLOAT', 'PIPES_AS_CONCAT', 'ANSI_QUOTES', 'IGNORE_SPACE', 'NOT_USED', 'ONLY_FULL_GROUP_BY', 'NO_UNSIGNED_SUBTRACTION', 'NO_DIR_IN_CREATE', 'POSTGRESQL', 'ORACLE', 'MSSQL', 'DB2', 'MAXDB', 'NO_KEY_OPTIONS', 'NO_TABLE_OPTIONS', 'NO_FIELD_OPTIONS', 'MYSQL323', 'MYSQL40', 'ANSI', 'NO_AUTO_VALUE_ON_ZERO', 'NO_BACKSLASH_ESCAPES', 'STRICT_TRANS_TABLES', 'STRICT_ALL_TABLES', 'NO_ZERO_IN_DATE', 'NO_ZERO_DATE', 'INVALID_DATES', 'ERROR_FOR_DIVISION_BY_ZERO', 'TRADITIONAL', 'NO_AUTO_CREATE_USER', 'HIGH_NOT_PRECEDENCE') DEFAULT '' NOT NULL, comment char(64) collate utf8_bin DEFAULT '' NOT NULL, character_set_client char(32) collate utf8_bin, collation_connection char(32) collate utf8_bin, db_collation char(32) collate utf8_bin, body_utf8 longblob, PRIMARY KEY (db,name,type)) engine=MyISAM character set utf8 comment='Stored Procedures'; +CREATE TABLE IF NOT EXISTS proc (db char(64) collate utf8_bin DEFAULT '' NOT NULL, name char(64) DEFAULT '' NOT NULL, type enum('FUNCTION','PROCEDURE') NOT NULL, specific_name char(64) DEFAULT '' NOT NULL, language enum('SQL') DEFAULT 'SQL' NOT NULL, sql_data_access enum( 'CONTAINS_SQL', 'NO_SQL', 'READS_SQL_DATA', 'MODIFIES_SQL_DATA') DEFAULT 'CONTAINS_SQL' NOT NULL, is_deterministic enum('YES','NO') DEFAULT 'NO' NOT NULL, security_type enum('INVOKER','DEFINER') DEFAULT 'DEFINER' NOT NULL, param_list blob NOT NULL, returns longblob DEFAULT '' NOT NULL, body longblob NOT NULL, definer char(77) collate utf8_bin DEFAULT '' NOT NULL, created timestamp, modified timestamp, sql_mode set( 'REAL_AS_FLOAT', 'PIPES_AS_CONCAT', 'ANSI_QUOTES', 'IGNORE_SPACE', 'NOT_USED', 'ONLY_FULL_GROUP_BY', 'NO_UNSIGNED_SUBTRACTION', 'NO_DIR_IN_CREATE', 'POSTGRESQL', 'ORACLE', 'MSSQL', 'DB2', 'MAXDB', 'NO_KEY_OPTIONS', 'NO_TABLE_OPTIONS', 'NO_FIELD_OPTIONS', 'MYSQL323', 'MYSQL40', 'ANSI', 'NO_AUTO_VALUE_ON_ZERO', 'NO_BACKSLASH_ESCAPES', 'STRICT_TRANS_TABLES', 'STRICT_ALL_TABLES', 'NO_ZERO_IN_DATE', 'NO_ZERO_DATE', 'INVALID_DATES', 'ERROR_FOR_DIVISION_BY_ZERO', 'TRADITIONAL', 'NO_AUTO_CREATE_USER', 'HIGH_NOT_PRECEDENCE') DEFAULT '' NOT NULL, comment char(64) collate utf8_bin DEFAULT '' NOT NULL, character_set_client char(32) collate utf8_bin, collation_connection char(32) collate utf8_bin, db_collation char(32) collate utf8_bin, body_utf8 longblob, PRIMARY KEY (db,name,type)) engine=MyISAM character set utf8 comment='Stored Procedures'; CREATE TABLE IF NOT EXISTS procs_priv ( Host char(60) binary DEFAULT '' NOT NULL, Db char(64) binary DEFAULT '' NOT NULL, User char(16) binary DEFAULT '' NOT NULL, Routine_name char(64) binary DEFAULT '' NOT NULL, Routine_type enum('FUNCTION','PROCEDURE') NOT NULL, Grantor char(77) DEFAULT '' NOT NULL, Proc_priv set('Execute','Alter Routine','Grant') COLLATE utf8_general_ci DEFAULT '' NOT NULL, Timestamp timestamp(14), PRIMARY KEY (Host,Db,User,Routine_name,Routine_type), KEY Grantor (Grantor) ) engine=MyISAM CHARACTER SET utf8 COLLATE utf8_bin comment='Procedure privileges'; -- Create general_log if CSV is enabled. -SET @str = IF (@@have_csv = 'YES', 'CREATE TABLE IF NOT EXISTS general_log (event_time TIMESTAMP NOT NULL, user_host MEDIUMTEXT, thread_id INTEGER, server_id INTEGER, command_type VARCHAR(64), argument MEDIUMTEXT) engine=CSV CHARACTER SET utf8 comment="General log"', 'SET @dummy = 0'); +SET @str = IF (@@have_csv = 'YES', 'CREATE TABLE IF NOT EXISTS general_log (event_time TIMESTAMP NOT NULL, user_host MEDIUMTEXT NOT NULL, thread_id INTEGER NOT NULL, server_id INTEGER NOT NULL, command_type VARCHAR(64) NOT NULL, argument MEDIUMTEXT NOT NULL) engine=CSV CHARACTER SET utf8 comment="General log"', 'SET @dummy = 0'); PREPARE stmt FROM @str; EXECUTE stmt; @@ -74,7 +74,7 @@ DROP PREPARE stmt; -- Create slow_log if CSV is enabled. -SET @str = IF (@@have_csv = 'YES', 'CREATE TABLE IF NOT EXISTS slow_log (start_time TIMESTAMP NOT NULL, user_host MEDIUMTEXT NOT NULL, query_time TIME NOT NULL, lock_time TIME NOT NULL, rows_sent INTEGER NOT NULL, rows_examined INTEGER NOT NULL, db VARCHAR(512), last_insert_id INTEGER, insert_id INTEGER, server_id INTEGER, sql_text MEDIUMTEXT NOT NULL) engine=CSV CHARACTER SET utf8 comment="Slow log"', 'SET @dummy = 0'); +SET @str = IF (@@have_csv = 'YES', 'CREATE TABLE IF NOT EXISTS slow_log (start_time TIMESTAMP NOT NULL, user_host MEDIUMTEXT NOT NULL, query_time TIME NOT NULL, lock_time TIME NOT NULL, rows_sent INTEGER NOT NULL, rows_examined INTEGER NOT NULL, db VARCHAR(512) NOT NULL, last_insert_id INTEGER NOT NULL, insert_id INTEGER NOT NULL, server_id INTEGER NOT NULL, sql_text MEDIUMTEXT NOT NULL) engine=CSV CHARACTER SET utf8 comment="Slow log"', 'SET @dummy = 0'); PREPARE stmt FROM @str; EXECUTE stmt; diff --git a/scripts/mysql_system_tables_fix.sql b/scripts/mysql_system_tables_fix.sql index 78e6a0ceb57..a43964bf09a 100644 --- a/scripts/mysql_system_tables_fix.sql +++ b/scripts/mysql_system_tables_fix.sql @@ -344,6 +344,7 @@ ALTER TABLE proc MODIFY name char(64) DEFAULT '' NOT NULL, 'MODIFIES_SQL_DATA' ) DEFAULT 'CONTAINS_SQL' NOT NULL, MODIFY body longblob NOT NULL, + MODIFY returns longblob NOT NULL, MODIFY sql_mode set('REAL_AS_FLOAT', 'PIPES_AS_CONCAT', diff --git a/sql/ha_partition.cc b/sql/ha_partition.cc index 200e8a97c67..1150cf41417 100644 --- a/sql/ha_partition.cc +++ b/sql/ha_partition.cc @@ -3391,6 +3391,22 @@ int ha_partition::index_init(uint inx, bool sorted) */ if (m_lock_type == F_WRLCK) bitmap_union(table->read_set, &m_part_info->full_part_field_set); + else if (sorted && m_table_flags & HA_PARTIAL_COLUMN_READ) + { + /* + An ordered scan is requested and necessary fields aren't in read_set. + This may happen e.g. with SELECT COUNT(*) FROM t1. We must ensure + that all fields of current key are included into read_set, as + partitioning requires them for sorting + (see ha_partition::handle_ordered_index_scan). + + TODO: handle COUNT(*) queries via unordered scan. + */ + uint i; + for (i= 0; i < m_curr_key_info->key_parts; i++) + bitmap_set_bit(table->read_set, + m_curr_key_info->key_part[i].field->field_index); + } file= m_file; do { @@ -4540,6 +4556,8 @@ void ha_partition::get_dynamic_partition_info(PARTITION_INFO *stat_info, 4) Parameters only used by temporary tables for query processing 5) Parameters only used by MyISAM internally 6) Parameters not used at all + 7) Parameters only used by federated tables for query processing + 8) Parameters only used by NDB The partition handler need to handle category 1), 2) and 3). @@ -4806,6 +4824,15 @@ void ha_partition::get_dynamic_partition_info(PARTITION_INFO *stat_info, HA_EXTRA_INSERT_WITH_UPDATE: Inform handler that an "INSERT...ON DUPLICATE KEY UPDATE" will be executed. This condition is unset by HA_EXTRA_NO_IGNORE_DUP_KEY. + + 8) Parameters only used by NDB + ------------------------------ + HA_EXTRA_DELETE_CANNOT_BATCH: + HA_EXTRA_UPDATE_CANNOT_BATCH: + Inform handler that delete_row()/update_row() cannot batch deletes/updates + and should perform them immediately. This may be needed when table has + AFTER DELETE/UPDATE triggers which access to subject table. + These flags are reset by the handler::extra(HA_EXTRA_RESET) call. */ int ha_partition::extra(enum ha_extra_function operation) @@ -4890,6 +4917,13 @@ int ha_partition::extra(enum ha_extra_function operation) /* Category 7), used by federated handlers */ case HA_EXTRA_INSERT_WITH_UPDATE: DBUG_RETURN(loop_extra(operation)); + /* Category 8) Parameters only used by NDB */ + case HA_EXTRA_DELETE_CANNOT_BATCH: + case HA_EXTRA_UPDATE_CANNOT_BATCH: + { + /* Currently only NDB use the *_CANNOT_BATCH */ + break; + } default: { /* Temporary crash to discover what is wrong */ diff --git a/sql/item.cc b/sql/item.cc index 3b592633ad0..18b48280754 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -4459,12 +4459,14 @@ Field *Item::tmp_table_field_from_field_type(TABLE *table, bool fixed_length) else field= new Field_blob(max_length, maybe_null, name, collation.collation); break; // Blob handled outside of case +#ifdef HAVE_SPATIAL case MYSQL_TYPE_GEOMETRY: field= new Field_geom(max_length, maybe_null, name, table->s, (Field::geometry_type) ((type() == Item::TYPE_HOLDER) ? ((Item_type_holder *)this)->get_geometry_type() : ((Item_geometry_func *)this)->get_geometry_type())); +#endif /* HAVE_SPATIAL */ } if (field) field->init(table); @@ -6588,10 +6590,12 @@ Item_type_holder::Item_type_holder(THD *thd, Item *item) if (Field::result_merge_type(fld_type) == INT_RESULT) decimals= 0; prev_decimal_int_part= item->decimal_int_part(); +#ifdef HAVE_SPATIAL if (item->field_type() == MYSQL_TYPE_GEOMETRY) geometry_type= (item->type() == Item::FIELD_ITEM) ? ((Item_field *)item)->get_geometry_type() : (Field::geometry_type)((Item_geometry_func *)item)->get_geometry_type(); +#endif /* HAVE_SPATIAL */ } diff --git a/sql/item_create.cc b/sql/item_create.cc index 12b795e79a1..dc9f6e92884 100644 --- a/sql/item_create.cc +++ b/sql/item_create.cc @@ -2326,6 +2326,25 @@ Item* Create_qfunc::create(THD *thd, LEX_STRING name, List<Item> *item_list) { LEX_STRING db; + + if (! thd->db && ! thd->lex->sphead) + { + /* + The proper error message should be in the lines of: + Can't resolve <name>() to a function call, + because this function: + - is not a native function, + - is not a user defined function, + - can not match a qualified (read: stored) function + since no database is selected. + Reusing ER_SP_DOES_NOT_EXIST have a message consistent with + the case when a default database exist, see Create_sp_func::create(). + */ + my_error(ER_SP_DOES_NOT_EXIST, MYF(0), + "FUNCTION", name.str); + return NULL; + } + if (thd->lex->copy_db_to(&db.str, &db.length)) return NULL; diff --git a/sql/item_func.cc b/sql/item_func.cc index efc42c1b73f..fded5fa1391 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -5592,8 +5592,13 @@ Item_func_sp::fix_fields(THD *thd, Item **ref) #endif /* ! NO_EMBEDDED_ACCESS_CHECKS */ } + if (!m_sp->m_chistics->detistic) - used_tables_cache |= RAND_TABLE_BIT; + { + used_tables_cache |= RAND_TABLE_BIT; + const_item_cache= FALSE; + } + DBUG_RETURN(res); } @@ -5601,8 +5606,12 @@ Item_func_sp::fix_fields(THD *thd, Item **ref) void Item_func_sp::update_used_tables() { Item_func::update_used_tables(); + if (!m_sp->m_chistics->detistic) - used_tables_cache |= RAND_TABLE_BIT; + { + used_tables_cache |= RAND_TABLE_BIT; + const_item_cache= FALSE; + } } diff --git a/sql/item_func.h b/sql/item_func.h index ea22e35773d..66a417f31fa 100644 --- a/sql/item_func.h +++ b/sql/item_func.h @@ -1535,6 +1535,11 @@ public: bool fix_fields(THD *thd, Item **ref); void fix_length_and_dec(void); bool is_expensive() { return 1; } + + inline Field *get_sp_result_field() + { + return sp_result_field; + } }; diff --git a/sql/log.cc b/sql/log.cc index 95204e89d0e..e923418b23a 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -387,10 +387,15 @@ bool Log_to_csv_event_handler:: if (table->field[1]->store(user_host, user_host_len, client_cs) || table->field[2]->store((longlong) thread_id, TRUE) || table->field[3]->store((longlong) server_id, TRUE) || - table->field[4]->store(command_type, command_type_len, client_cs) || - table->field[5]->store(sql_text, sql_text_len, client_cs)) + table->field[4]->store(command_type, command_type_len, client_cs)) goto err; + /* + A positive return value in store() means truncation. + Still logging a message in the log in this case. + */ + if (table->field[5]->store(sql_text, sql_text_len, client_cs) < 0) + goto err; /* mark all fields as not null */ table->field[1]->set_notnull(); @@ -407,19 +412,14 @@ bool Log_to_csv_event_handler:: /* log table entries are not replicated */ if (table->file->ha_write_row(table->record[0])) - { - struct tm start; - localtime_r(&event_time, &start); - - sql_print_error("%02d%02d%02d %2d:%02d:%02d - Failed to write to mysql.general_log", - start.tm_year % 100, start.tm_mon + 1, - start.tm_mday, start.tm_hour, - start.tm_min, start.tm_sec); - } + goto err; result= FALSE; err: + if (result) + sql_print_error("Failed to write to mysql.general_log"); + if (need_rnd_end) { table->file->ha_rnd_end(); @@ -595,25 +595,24 @@ bool Log_to_csv_event_handler:: goto err; table->field[9]->set_notnull(); - /* sql_text */ - if (table->field[10]->store(sql_text,sql_text_len, client_cs)) + /* + Column sql_text. + A positive return value in store() means truncation. + Still logging a message in the log in this case. + */ + if (table->field[10]->store(sql_text, sql_text_len, client_cs) < 0) goto err; /* log table entries are not replicated */ if (table->file->ha_write_row(table->record[0])) - { - struct tm start; - localtime_r(¤t_time, &start); - - sql_print_error("%02d%02d%02d %2d:%02d:%02d - Failed to write to mysql.slow_log", - start.tm_year % 100, start.tm_mon + 1, - start.tm_mday, start.tm_hour, - start.tm_min, start.tm_sec); - } + goto err; result= FALSE; err: + if (result) + sql_print_error("Failed to write to mysql.slow_log"); + if (need_rnd_end) { table->file->ha_rnd_end(); @@ -945,73 +944,65 @@ bool LOGGER::slow_log_print(THD *thd, const char *query, uint query_length, return error; } -bool LOGGER::general_log_print(THD *thd, enum enum_server_command command, - const char *format, va_list args) +bool LOGGER::general_log_write(THD *thd, enum enum_server_command command, + const char *query, uint query_length) { bool error= FALSE; Log_event_handler **current_handler= general_log_handler_list; + char user_host_buff[MAX_USER_HOST_SIZE]; + Security_context *sctx= thd->security_ctx; + ulong id; + uint user_host_len= 0; + time_t current_time; - /* - Print the message to the buffer if we have at least one log event handler - enabled and want to log this king of commands - */ - if (*general_log_handler_list && (what_to_log & (1L << (uint) command))) - { - char message_buff[MAX_LOG_BUFFER_SIZE]; - char user_host_buff[MAX_USER_HOST_SIZE]; - Security_context *sctx= thd->security_ctx; - ulong id; - uint message_buff_len= 0, user_host_len= 0; - time_t current_time; - if (thd) - { /* Normal thread */ - if ((thd->options & OPTION_LOG_OFF) -#ifndef NO_EMBEDDED_ACCESS_CHECKS - && (sctx->master_access & SUPER_ACL) -#endif - ) - { - return 0; /* No logging */ - } - id= thd->thread_id; - } - else - id=0; /* Log from connect handler */ + if (thd) + id= thd->thread_id; /* Normal thread */ + else + id= 0; /* Log from connect handler */ - lock_shared(); - if (!opt_log) - { - unlock(); - return 0; - } - user_host_len= strxnmov(user_host_buff, MAX_USER_HOST_SIZE, - sctx->priv_user ? sctx->priv_user : "", "[", - sctx->user ? sctx->user : "", "] @ ", - sctx->host ? sctx->host : "", " [", - sctx->ip ? sctx->ip : "", "]", NullS) - - user_host_buff; - - /* prepare message */ - if (format) - message_buff_len= my_vsnprintf(message_buff, - sizeof(message_buff), format, args); - else - message_buff[0]= '\0'; - - current_time= my_time(0); - while (*current_handler) - error+= (*current_handler++)-> - log_general(thd, current_time, user_host_buff, - user_host_len, id, - command_name[(uint) command].str, - command_name[(uint) command].length, - message_buff, message_buff_len, - thd->variables.character_set_client) || error; + lock_shared(); + if (!opt_log) + { unlock(); + return 0; } + user_host_len= strxnmov(user_host_buff, MAX_USER_HOST_SIZE, + sctx->priv_user ? sctx->priv_user : "", "[", + sctx->user ? sctx->user : "", "] @ ", + sctx->host ? sctx->host : "", " [", + sctx->ip ? sctx->ip : "", "]", NullS) - + user_host_buff; + + current_time= my_time(0); + while (*current_handler) + error+= (*current_handler++)-> + log_general(thd, current_time, user_host_buff, + user_host_len, id, + command_name[(uint) command].str, + command_name[(uint) command].length, + query, query_length, + thd->variables.character_set_client) || error; + unlock(); + return error; } +bool LOGGER::general_log_print(THD *thd, enum enum_server_command command, + const char *format, va_list args) +{ + uint message_buff_len= 0; + char message_buff[MAX_LOG_BUFFER_SIZE]; + + /* prepare message */ + if (format) + message_buff_len= my_vsnprintf(message_buff, sizeof(message_buff), + format, args); + else + message_buff[0]= '\0'; + + return general_log_write(thd, command, message_buff, message_buff_len); +} + void LOGGER::init_error_log(uint error_log_printer) { if (error_log_printer & LOG_NONE) @@ -2076,10 +2067,10 @@ bool MYSQL_QUERY_LOG::write(THD *thd, time_t current_time, if (my_b_write(&log_file, (uchar*) buff, buff_len)) tmp_errno= errno; } - if (my_b_printf(&log_file, "# User@Host: ", sizeof("# User@Host: ") - 1) - != sizeof("# User@Host: ") - 1) + const uchar uh[]= "# User@Host: "; + if (my_b_write(&log_file, uh, sizeof(uh) - 1)) tmp_errno= errno; - if (my_b_printf(&log_file, user_host, user_host_len) != user_host_len) + if (my_b_write(&log_file, (uchar*) user_host, user_host_len)) tmp_errno= errno; if (my_b_write(&log_file, (uchar*) "\n", 1)) tmp_errno= errno; @@ -3737,12 +3728,44 @@ bool slow_log_print(THD *thd, const char *query, uint query_length, } +bool LOGGER::log_command(THD *thd, enum enum_server_command command) +{ +#ifndef NO_EMBEDDED_ACCESS_CHECKS + Security_context *sctx= thd->security_ctx; +#endif + /* + Log command if we have at least one log event handler enabled and want + to log this king of commands + */ + if (*general_log_handler_list && (what_to_log & (1L << (uint) command))) + { + if ((thd->options & OPTION_LOG_OFF) +#ifndef NO_EMBEDDED_ACCESS_CHECKS + && (sctx->master_access & SUPER_ACL) +#endif + ) + { + /* No logging */ + return FALSE; + } + + return TRUE; + } + + return FALSE; +} + + bool general_log_print(THD *thd, enum enum_server_command command, const char *format, ...) { va_list args; uint error= 0; + /* Print the message to the buffer if we want to log this king of commands */ + if (! logger.log_command(thd, command)) + return FALSE; + va_start(args, format); error= logger.general_log_print(thd, command, format, args); va_end(args); @@ -3750,6 +3773,16 @@ bool general_log_print(THD *thd, enum enum_server_command command, return error; } +bool general_log_write(THD *thd, enum enum_server_command command, + const char *query, uint query_length) +{ + /* Write the message to the log if we want to log this king of commands */ + if (logger.log_command(thd, command)) + return logger.general_log_write(thd, command, query, query_length); + + return FALSE; +} + void MYSQL_BIN_LOG::rotate_and_purge(uint flags) { if (!(flags & RP_LOCK_LOG_IS_ALREADY_LOCKED)) diff --git a/sql/log.h b/sql/log.h index e597c986794..bef0101c8b5 100644 --- a/sql/log.h +++ b/sql/log.h @@ -499,6 +499,8 @@ public: void lock_exclusive() { rw_wrlock(&LOCK_logger); } void unlock() { rw_unlock(&LOCK_logger); } bool is_log_table_enabled(uint log_table_type); + bool log_command(THD *thd, enum enum_server_command command); + /* We want to initialize all log mutexes as soon as possible, but we cannot do it in constructor, as safe_mutex relies on @@ -518,6 +520,8 @@ public: ulonglong current_utime); bool general_log_print(THD *thd,enum enum_server_command command, const char *format, va_list args); + bool general_log_write(THD *thd, enum enum_server_command command, + const char *query, uint query_length); /* we use this function to setup all enabled log event handlers */ int set_handlers(uint error_log_printer, diff --git a/sql/log_event.cc b/sql/log_event.cc index d8e22953fc2..a435894382b 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -2113,7 +2113,7 @@ START SLAVE; . Query: '%s'", expected_error, thd->query); /* If the query was not ignored, it is printed to the general log */ if (thd->net.last_errno != ER_SLAVE_IGNORED_TABLE) - general_log_print(thd, COM_QUERY, "%s", thd->query); + general_log_write(thd, COM_QUERY, thd->query, thd->query_length); compare_errors: diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index dfea3060cee..49eb2ba0e36 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -745,6 +745,9 @@ bool slow_log_print(THD *thd, const char *query, uint query_length, bool general_log_print(THD *thd, enum enum_server_command command, const char *format,...); +bool general_log_write(THD *thd, enum enum_server_command command, + const char *query, uint query_length); + #include "sql_class.h" #include "sql_acl.h" #include "tztime.h" @@ -922,13 +925,12 @@ void decrease_user_connections(USER_CONN *uc); void thd_init_client_charset(THD *thd, uint cs_number); bool setup_connection_thread_globals(THD *thd); bool login_connection(THD *thd); -void prepare_new_connection_state(THD* thd); void end_connection(THD *thd); bool mysql_create_db(THD *thd, char *db, HA_CREATE_INFO *create, bool silent); bool mysql_alter_db(THD *thd, const char *db, HA_CREATE_INFO *create); bool mysql_rm_db(THD *thd,char *db,bool if_exists, bool silent); -bool mysql_rename_db(THD *thd, LEX_STRING *old_db, LEX_STRING *new_db); +bool mysql_upgrade_db(THD *thd, LEX_STRING *old_db); void mysql_binlog_send(THD* thd, char* log_ident, my_off_t pos, ushort flags); void mysql_client_binlog_statement(THD *thd); bool mysql_rm_table(THD *thd,TABLE_LIST *tables, my_bool if_exists, diff --git a/sql/net_serv.cc b/sql/net_serv.cc index 1f75d7ab1d7..18cf1ebae5b 100644 --- a/sql/net_serv.cc +++ b/sql/net_serv.cc @@ -123,7 +123,7 @@ my_bool my_net_init(NET *net, Vio* vio) MYF(MY_WME)))) DBUG_RETURN(1); net->buff_end=net->buff+net->max_packet; - net->no_send_ok= net->no_send_eof= net->no_send_error= 0; + net->no_send_ok= net->no_send_error= 0; net->error=0; net->return_errno=0; net->return_status=0; net->pkt_nr=net->compress_pkt_nr=0; net->write_pos=net->read_pos = net->buff; diff --git a/sql/protocol.cc b/sql/protocol.cc index 2ed241c4c98..9d473912ba3 100644 --- a/sql/protocol.cc +++ b/sql/protocol.cc @@ -346,7 +346,7 @@ send_eof(THD *thd) { NET *net= &thd->net; DBUG_ENTER("send_eof"); - if (net->vio != 0 && !net->no_send_eof) + if (net->vio != 0) { write_eof_packet(thd, net); VOID(net_flush(net)); diff --git a/sql/share/errmsg.txt b/sql/share/errmsg.txt index 30cf85f3181..8fad09eb221 100644 --- a/sql/share/errmsg.txt +++ b/sql/share/errmsg.txt @@ -6109,3 +6109,6 @@ ER_EVENT_INVALID_CREATION_CTX ER_TRG_CANT_OPEN_TABLE eng "Cannot open table for trigger `%-.64s`.`%-.64s`" + +ER_CANT_CREATE_SROUTINE + eng "Cannot create stored routine `%-.64s`. Check warnings" diff --git a/sql/sp.cc b/sql/sp.cc index 6032688f7f1..1b5d8ca87b8 100644 --- a/sql/sp.cc +++ b/sql/sp.cc @@ -682,6 +682,10 @@ sp_create_routine(THD *thd, int type, sp_head *sp) CHARSET_INFO *db_cs= get_default_db_collation(thd, sp->m_db.str); + enum_check_fields saved_count_cuted_fields; + + bool store_failed= FALSE; + DBUG_ENTER("sp_create_routine"); DBUG_PRINT("enter", ("type: %d name: %.*s",type, (int) sp->m_name.length, sp->m_name.str)); @@ -696,6 +700,9 @@ sp_create_routine(THD *thd, int type, sp_head *sp) */ thd->clear_current_stmt_binlog_row_based(); + saved_count_cuted_fields= thd->count_cuted_fields; + thd->count_cuted_fields= CHECK_FIELD_WARN; + if (!(table= open_proc_table_for_update(thd))) ret= SP_OPEN_TABLE_FAILED; else @@ -725,43 +732,77 @@ sp_create_routine(THD *thd, int type, sp_head *sp) ret= SP_BODY_TOO_LONG; goto done; } - table->field[MYSQL_PROC_FIELD_DB]-> - store(sp->m_db.str, sp->m_db.length, system_charset_info); - table->field[MYSQL_PROC_FIELD_NAME]-> - store(sp->m_name.str, sp->m_name.length, system_charset_info); - table->field[MYSQL_PROC_MYSQL_TYPE]-> - store((longlong)type, TRUE); - table->field[MYSQL_PROC_FIELD_SPECIFIC_NAME]-> - store(sp->m_name.str, sp->m_name.length, system_charset_info); + + store_failed= + table->field[MYSQL_PROC_FIELD_DB]-> + store(sp->m_db.str, sp->m_db.length, system_charset_info); + + store_failed= store_failed || + table->field[MYSQL_PROC_FIELD_NAME]-> + store(sp->m_name.str, sp->m_name.length, system_charset_info); + + store_failed= store_failed || + table->field[MYSQL_PROC_MYSQL_TYPE]-> + store((longlong)type, TRUE); + + store_failed= store_failed || + table->field[MYSQL_PROC_FIELD_SPECIFIC_NAME]-> + store(sp->m_name.str, sp->m_name.length, system_charset_info); + if (sp->m_chistics->daccess != SP_DEFAULT_ACCESS) - table->field[MYSQL_PROC_FIELD_ACCESS]-> - store((longlong)sp->m_chistics->daccess, TRUE); - table->field[MYSQL_PROC_FIELD_DETERMINISTIC]-> - store((longlong)(sp->m_chistics->detistic ? 1 : 2), TRUE); + { + store_failed= store_failed || + table->field[MYSQL_PROC_FIELD_ACCESS]-> + store((longlong)sp->m_chistics->daccess, TRUE); + } + + store_failed= store_failed || + table->field[MYSQL_PROC_FIELD_DETERMINISTIC]-> + store((longlong)(sp->m_chistics->detistic ? 1 : 2), TRUE); + if (sp->m_chistics->suid != SP_IS_DEFAULT_SUID) - table->field[MYSQL_PROC_FIELD_SECURITY_TYPE]-> - store((longlong)sp->m_chistics->suid, TRUE); - table->field[MYSQL_PROC_FIELD_PARAM_LIST]-> - store(sp->m_params.str, sp->m_params.length, system_charset_info); + { + store_failed= store_failed || + table->field[MYSQL_PROC_FIELD_SECURITY_TYPE]-> + store((longlong)sp->m_chistics->suid, TRUE); + } + + store_failed= store_failed || + table->field[MYSQL_PROC_FIELD_PARAM_LIST]-> + store(sp->m_params.str, sp->m_params.length, system_charset_info); + if (sp->m_type == TYPE_ENUM_FUNCTION) { String retstr(64); sp_returns_type(thd, retstr, sp); - table->field[MYSQL_PROC_FIELD_RETURNS]-> - store(retstr.ptr(), retstr.length(), system_charset_info); + + store_failed= store_failed || + table->field[MYSQL_PROC_FIELD_RETURNS]-> + store(retstr.ptr(), retstr.length(), system_charset_info); } - table->field[MYSQL_PROC_FIELD_BODY]-> - store(sp->m_body.str, sp->m_body.length, system_charset_info); - table->field[MYSQL_PROC_FIELD_DEFINER]-> - store(definer, (uint)strlen(definer), system_charset_info); + + store_failed= store_failed || + table->field[MYSQL_PROC_FIELD_BODY]-> + store(sp->m_body.str, sp->m_body.length, system_charset_info); + + store_failed= store_failed || + table->field[MYSQL_PROC_FIELD_DEFINER]-> + store(definer, (uint)strlen(definer), system_charset_info); + ((Field_timestamp *)table->field[MYSQL_PROC_FIELD_CREATED])->set_time(); ((Field_timestamp *)table->field[MYSQL_PROC_FIELD_MODIFIED])->set_time(); - table->field[MYSQL_PROC_FIELD_SQL_MODE]-> - store((longlong)thd->variables.sql_mode, TRUE); + + store_failed= store_failed || + table->field[MYSQL_PROC_FIELD_SQL_MODE]-> + store((longlong)thd->variables.sql_mode, TRUE); + if (sp->m_chistics->comment.str) - table->field[MYSQL_PROC_FIELD_COMMENT]-> - store(sp->m_chistics->comment.str, sp->m_chistics->comment.length, - system_charset_info); + { + store_failed= store_failed || + table->field[MYSQL_PROC_FIELD_COMMENT]-> + store(sp->m_chistics->comment.str, sp->m_chistics->comment.length, + system_charset_info); + } if ((sp->m_type == TYPE_ENUM_FUNCTION) && !trust_function_creators && mysql_bin_log.is_open()) @@ -794,24 +835,34 @@ sp_create_routine(THD *thd, int type, sp_head *sp) } table->field[MYSQL_PROC_FIELD_CHARACTER_SET_CLIENT]->set_notnull(); - table->field[MYSQL_PROC_FIELD_CHARACTER_SET_CLIENT]->store( - thd->charset()->csname, - strlen(thd->charset()->csname), - system_charset_info); + store_failed= store_failed || + table->field[MYSQL_PROC_FIELD_CHARACTER_SET_CLIENT]->store( + thd->charset()->csname, + strlen(thd->charset()->csname), + system_charset_info); table->field[MYSQL_PROC_FIELD_COLLATION_CONNECTION]->set_notnull(); - table->field[MYSQL_PROC_FIELD_COLLATION_CONNECTION]->store( - thd->variables.collation_connection->name, - strlen(thd->variables.collation_connection->name), - system_charset_info); + store_failed= store_failed || + table->field[MYSQL_PROC_FIELD_COLLATION_CONNECTION]->store( + thd->variables.collation_connection->name, + strlen(thd->variables.collation_connection->name), + system_charset_info); table->field[MYSQL_PROC_FIELD_DB_COLLATION]->set_notnull(); - table->field[MYSQL_PROC_FIELD_DB_COLLATION]->store( - db_cs->name, strlen(db_cs->name), system_charset_info); + store_failed= store_failed || + table->field[MYSQL_PROC_FIELD_DB_COLLATION]->store( + db_cs->name, strlen(db_cs->name), system_charset_info); table->field[MYSQL_PROC_FIELD_BODY_UTF8]->set_notnull(); - table->field[MYSQL_PROC_FIELD_BODY_UTF8]->store( - sp->m_body_utf8.str, sp->m_body_utf8.length, system_charset_info); + store_failed= store_failed || + table->field[MYSQL_PROC_FIELD_BODY_UTF8]->store( + sp->m_body_utf8.str, sp->m_body_utf8.length, system_charset_info); + + if (store_failed) + { + ret= SP_FLD_STORE_FAILED; + goto done; + } ret= SP_OK; if (table->file->ha_write_row(table->record[0])) @@ -842,6 +893,8 @@ sp_create_routine(THD *thd, int type, sp_head *sp) } done: + thd->count_cuted_fields= saved_count_cuted_fields; + close_thread_tables(thd); DBUG_RETURN(ret); } @@ -1591,12 +1644,12 @@ static bool add_used_routine(LEX *lex, Query_arena *arena, { Sroutine_hash_entry *rn= (Sroutine_hash_entry *)arena->alloc(sizeof(Sroutine_hash_entry) + - key->length); + key->length + 1); if (!rn) // OOM. Error will be reported using fatal_error(). return FALSE; rn->key.length= key->length; rn->key.str= (char *)rn + sizeof(Sroutine_hash_entry); - memcpy(rn->key.str, key->str, key->length); + memcpy(rn->key.str, key->str, key->length + 1); my_hash_insert(&lex->sroutines, (uchar *)rn); lex->sroutines_list.link_in_list((uchar *)rn, (uchar **)&rn->next); rn->belong_to_view= belong_to_view; @@ -1779,7 +1832,7 @@ sp_cache_routines_and_add_tables_aux(THD *thd, LEX *lex, for (Sroutine_hash_entry *rt= start; rt; rt= rt->next) { - sp_name name(rt->key.str, rt->key.length); + sp_name name(thd, rt->key.str, rt->key.length); int type= rt->key.str[0]; sp_head *sp; @@ -1787,13 +1840,6 @@ sp_cache_routines_and_add_tables_aux(THD *thd, LEX *lex, &thd->sp_func_cache : &thd->sp_proc_cache), &name))) { - name.m_name.str= strchr(name.m_qname.str, '.'); - name.m_db.length= name.m_name.str - name.m_qname.str; - name.m_db.str= strmake_root(thd->mem_root, name.m_qname.str, - name.m_db.length); - name.m_name.str+= 1; - name.m_name.length= name.m_qname.length - name.m_db.length - 1; - switch ((ret= db_find_routine(thd, type, &name, &sp))) { case SP_OK: @@ -29,6 +29,7 @@ #define SP_NO_DB_ERROR -8 #define SP_BAD_IDENTIFIER -9 #define SP_BODY_TOO_LONG -10 +#define SP_FLD_STORE_FAILED -11 /* Drop all routines in database 'db' */ int diff --git a/sql/sp_head.cc b/sql/sp_head.cc index 828517011d5..093544cdd0a 100644 --- a/sql/sp_head.cc +++ b/sql/sp_head.cc @@ -386,17 +386,43 @@ sp_eval_expr(THD *thd, Field *result_field, Item **expr_item_ptr) * */ +sp_name::sp_name(THD *thd, char *key, uint key_len) +{ + m_sroutines_key.str= key; + m_sroutines_key.length= key_len; + m_qname.str= ++key; + m_qname.length= key_len - 1; + if ((m_name.str= strchr(m_qname.str, '.'))) + { + m_db.length= m_name.str - key; + m_db.str= strmake_root(thd->mem_root, key, m_db.length); + m_name.str++; + m_name.length= m_qname.length - m_db.length - 1; + } + else + { + m_name.str= m_qname.str; + m_name.length= m_qname.length; + m_db.str= 0; + m_db.length= 0; + } + m_explicit_name= false; +} + void sp_name::init_qname(THD *thd) { - m_sroutines_key.length= m_db.length + m_name.length + 2; + const uint dot= !!m_db.length; + /* m_sroutines format: m_type + [database + dot] + name + nul */ + m_sroutines_key.length= 1 + m_db.length + dot + m_name.length; if (!(m_sroutines_key.str= (char*) thd->alloc(m_sroutines_key.length + 1))) return; m_qname.length= m_sroutines_key.length - 1; m_qname.str= m_sroutines_key.str + 1; - sprintf(m_qname.str, "%.*s.%.*s", - (int) m_db.length, (m_db.length ? m_db.str : ""), - (int) m_name.length, m_name.str); + sprintf(m_qname.str, "%.*s%.*s%.*s", + (int) m_db.length, (m_db.length ? m_db.str : ""), + dot, ".", + (int) m_name.length, m_name.str); } @@ -2699,7 +2725,7 @@ sp_instr_stmt::execute(THD *thd, uint *nextp) query= thd->query; query_length= thd->query_length; - if (!(res= alloc_query(thd, m_query.str, m_query.length+1)) && + if (!(res= alloc_query(thd, m_query.str, m_query.length)) && !(res=subst_spvars(thd, this, &m_query))) { /* @@ -2707,7 +2733,7 @@ sp_instr_stmt::execute(THD *thd, uint *nextp) queries with SP vars can't be cached) */ if (unlikely((thd->options & OPTION_LOG_OFF)==0)) - general_log_print(thd, COM_QUERY, "%s", thd->query); + general_log_write(thd, COM_QUERY, thd->query, thd->query_length); if (query_cache_send_result_to_client(thd, thd->query, thd->query_length) <= 0) diff --git a/sql/sp_head.h b/sql/sp_head.h index 3a8b41acd4c..d74170534bd 100644 --- a/sql/sp_head.h +++ b/sql/sp_head.h @@ -129,16 +129,7 @@ public: Creates temporary sp_name object from key, used mainly for SP-cache lookups. */ - sp_name(char *key, uint key_len) - { - m_sroutines_key.str= key; - m_sroutines_key.length= key_len; - m_name.str= m_qname.str= key + 1; - m_name.length= m_qname.length= key_len - 1; - m_db.str= 0; - m_db.length= 0; - m_explicit_name= false; - } + sp_name(THD *thd, char *key, uint key_len); // Init. the qualified name from the db and name. void init_qname(THD *thd); // thd for memroot allocation diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 337fde53dac..3a959d30a5d 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -2466,7 +2466,13 @@ TABLE *open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root, DBUG_RETURN(0); } - /* close handler tables which are marked for flush */ + /* + In order for the back off and re-start process to work properly, + handler tables having old versions (due to FLUSH TABLES or pending + name-lock) MUST be closed. This is specially important if a name-lock + is pending for any table of the handler_tables list, otherwise a + deadlock may occur. + */ if (thd->handler_tables) mysql_ha_flush(thd, (TABLE_LIST*) NULL, MYSQL_HA_REOPEN_ON_USAGE, TRUE); @@ -2533,6 +2539,10 @@ TABLE *open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root, table->db_stat == 0 signals wait_for_locked_table_names that the tables in question are not used any more. See table_is_used call for details. + + Notice that HANDLER tables were already taken care of by + the earlier call to mysql_ha_flush() in this same critical + section. */ close_old_data_files(thd,thd->open_tables,0,0); /* @@ -7748,7 +7758,17 @@ open_performance_schema_table(THD *thd, TABLE_LIST *one_table, table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET; } else + { + /* + If error in mysql_lock_tables(), open_ltable doesn't close the + table. Thread kill during mysql_lock_tables() is such error. But + open tables cannot be accepted when restoring the open tables + state. + */ + if (thd->killed) + close_thread_tables(thd); thd->restore_backup_open_tables_state(backup); + } thd->utime_after_lock= save_utime_after_lock; DBUG_RETURN(table); diff --git a/sql/sql_cache.cc b/sql/sql_cache.cc index ada927fa467..56b048a4f9d 100644 --- a/sql/sql_cache.cc +++ b/sql/sql_cache.cc @@ -3240,7 +3240,7 @@ Query_cache::process_and_count_tables(THD *thd, TABLE_LIST *tables_used, for (; tables_used; tables_used= tables_used->next_global) { table_count++; -#ifdef HAVE_QUERY_CACHE +#ifndef NO_EMBEDDED_ACCESS_CHECKS /* Disable any attempt to store this statement if there are column level grants on any referenced tables. diff --git a/sql/sql_class.cc b/sql/sql_class.cc index 5e8a8ab658a..ffbf0649961 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -585,6 +585,12 @@ void THD::init(void) if (variables.sql_mode & MODE_NO_BACKSLASH_ESCAPES) server_status|= SERVER_STATUS_NO_BACKSLASH_ESCAPES; options= thd_startup_options; + + if (variables.max_join_size == HA_POS_ERROR) + options |= OPTION_BIG_SELECTS; + else + options &= ~OPTION_BIG_SELECTS; + transaction.all.modified_non_trans_table= transaction.stmt.modified_non_trans_table= FALSE; open_options=ha_open_options; update_lock_default= (variables.low_priority_updates ? @@ -692,6 +698,7 @@ void THD::cleanup(void) pthread_mutex_lock(&LOCK_user_locks); item_user_lock_release(ull); pthread_mutex_unlock(&LOCK_user_locks); + ull= NULL; } cleanup_done=1; @@ -1416,7 +1423,14 @@ bool select_to_file::send_eof() if (my_close(file,MYF(MY_WME))) error= 1; if (!error) + { + /* + In order to remember the value of affected rows for ROW_COUNT() + function, SELECT INTO has to have an own SQLCOM. + TODO: split from SQLCOM_SELECT + */ ::send_ok(thd,row_count); + } file= -1; return error; } @@ -2331,6 +2345,11 @@ bool select_dumpvar::send_eof() if (! row_count) push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, ER_SP_FETCH_NO_DATA, ER(ER_SP_FETCH_NO_DATA)); + /* + In order to remember the value of affected rows for ROW_COUNT() + function, SELECT INTO has to have an own SQLCOM. + TODO: split from SQLCOM_SELECT + */ ::send_ok(thd,row_count); return 0; } diff --git a/sql/sql_class.h b/sql/sql_class.h index 7875870bd1a..97a63ed9448 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -2133,6 +2133,10 @@ class select_create: public select_insert { TABLE_LIST *select_tables; Alter_info *alter_info; Field **field; + /* lock data for tmp table */ + MYSQL_LOCK *m_lock; + /* m_lock or thd->extra_lock */ + MYSQL_LOCK **m_plock; public: select_create (TABLE_LIST *table_arg, HA_CREATE_INFO *create_info_par, @@ -2143,7 +2147,8 @@ public: create_table(table_arg), create_info(create_info_par), select_tables(select_tables_arg), - alter_info(alter_info_arg) + alter_info(alter_info_arg), + m_plock(NULL) {} int prepare(List<Item> &list, SELECT_LEX_UNIT *u); diff --git a/sql/sql_connect.cc b/sql/sql_connect.cc index 6bb0f62d843..094bef9324e 100644 --- a/sql/sql_connect.cc +++ b/sql/sql_connect.cc @@ -933,7 +933,7 @@ bool login_connection(THD *thd) NET *net= &thd->net; Security_context *sctx= thd->security_ctx; DBUG_ENTER("login_connection"); - DBUG_PRINT("info", ("handle_one_connection called by thread %lu", + DBUG_PRINT("info", ("login_connection called by thread %lu", thd->thread_id)); net->no_send_error= 0; @@ -973,21 +973,29 @@ void end_connection(THD *thd) plugin_thdvar_cleanup(thd); if (thd->user_connect) decrease_user_connections(thd->user_connect); + + if (thd->killed || + net->error && net->vio != 0 && net->report_error) + { + statistic_increment(aborted_threads,&LOCK_status); + } + if (net->error && net->vio != 0 && net->report_error) { - Security_context *sctx= thd->security_ctx; if (!thd->killed && thd->variables.log_warnings > 1) + { + Security_context *sctx= thd->security_ctx; + sql_print_warning(ER(ER_NEW_ABORTING_CONNECTION), thd->thread_id,(thd->db ? thd->db : "unconnected"), sctx->user ? sctx->user : "unauthenticated", sctx->host_or_ip, (net->last_errno ? ER(net->last_errno) : ER(ER_UNKNOWN_ERROR))); + } + net_send_error(thd, net->last_errno, NullS); - statistic_increment(aborted_threads,&LOCK_status); } - else if (thd->killed) - statistic_increment(aborted_threads,&LOCK_status); } @@ -995,7 +1003,7 @@ void end_connection(THD *thd) Initialize THD to handle queries */ -void prepare_new_connection_state(THD* thd) +static void prepare_new_connection_state(THD* thd) { Security_context *sctx= thd->security_ctx; diff --git a/sql/sql_db.cc b/sql/sql_db.cc index cd7ad048802..abbf2131957 100644 --- a/sql/sql_db.cc +++ b/sql/sql_db.cc @@ -1727,41 +1727,21 @@ lock_databases(THD *thd, const char *db1, uint length1, } -/* - Rename database. - - SYNOPSIS - mysql_rename_db() - thd Thread handler - olddb Old database name - newdb New database name - - DESCRIPTION - This function is invoked whenever a RENAME DATABASE query is executed: - - RENAME DATABASE 'olddb' TO 'newdb'. - - NOTES - - If we have managed to rename (move) tables to the new database - but something failed on a later step, then we store the - RENAME DATABASE event in the log. mysql_rename_db() is atomic in - the sense that it will rename all or none of the tables. - - TODO: - - Better trigger, stored procedure, event, grant handling, - see the comments below. - NOTE: It's probably a good idea to call wait_if_global_read_lock() - once in mysql_rename_db(), instead of locking inside all - the required functions for renaming triggerts, SP, events, grants, etc. - - RETURN VALUES - 0 ok - 1 error +/** + Upgrade a 5.0 database. + This function is invoked whenever an ALTER DATABASE UPGRADE query is executed: + ALTER DATABASE 'olddb' UPGRADE DATA DIRECTORY NAME. + + If we have managed to rename (move) tables to the new database + but something failed on a later step, then we store the + RENAME DATABASE event in the log. mysql_rename_db() is atomic in + the sense that it will rename all or none of the tables. + + @param thd Current thread + @param old_db 5.0 database name, in #mysql50#name format + @return 0 on success, 1 on error */ - - -bool mysql_rename_db(THD *thd, LEX_STRING *old_db, LEX_STRING *new_db) +bool mysql_upgrade_db(THD *thd, LEX_STRING *old_db) { int error= 0, change_to_newdb= 0; char path[FN_REFLEN+16]; @@ -1770,11 +1750,27 @@ bool mysql_rename_db(THD *thd, LEX_STRING *old_db, LEX_STRING *new_db) MY_DIR *dirp; TABLE_LIST *table_list; SELECT_LEX *sl= thd->lex->current_select; - DBUG_ENTER("mysql_rename_db"); + LEX_STRING new_db; + DBUG_ENTER("mysql_upgrade_db"); + + if ((old_db->length <= MYSQL50_TABLE_NAME_PREFIX_LENGTH) || + (strncmp(old_db->str, + MYSQL50_TABLE_NAME_PREFIX, + MYSQL50_TABLE_NAME_PREFIX_LENGTH) != 0)) + { + my_error(ER_WRONG_USAGE, MYF(0), + "ALTER DATABASE UPGRADE DATA DIRECTORY NAME", + "name"); + DBUG_RETURN(1); + } + + /* `#mysql50#<name>` converted to encoded `<name>` */ + new_db.str= old_db->str + MYSQL50_TABLE_NAME_PREFIX_LENGTH; + new_db.length= old_db->length - MYSQL50_TABLE_NAME_PREFIX_LENGTH; if (lock_databases(thd, old_db->str, old_db->length, - new_db->str, new_db->length)) - return 1; + new_db.str, new_db.length)) + DBUG_RETURN(1); /* Let's remember if we should do "USE newdb" afterwards. @@ -1798,7 +1794,7 @@ bool mysql_rename_db(THD *thd, LEX_STRING *old_db, LEX_STRING *new_db) } /* Step1: Create the new database */ - if ((error= mysql_create_db(thd, new_db->str, &create_info, 1))) + if ((error= mysql_create_db(thd, new_db.str, &create_info, 1))) goto exit; /* Step2: Move tables to the new database */ @@ -1819,12 +1815,12 @@ bool mysql_rename_db(THD *thd, LEX_STRING *old_db, LEX_STRING *new_db) /* A frm file found, add the table info rename list */ *extension= '\0'; - + table_str.length= filename_to_tablename(file->name, tname, sizeof(tname)-1); table_str.str= (char*) sql_memdup(tname, table_str.length + 1); Table_ident *old_ident= new Table_ident(thd, *old_db, table_str, 0); - Table_ident *new_ident= new Table_ident(thd, *new_db, table_str, 0); + Table_ident *new_ident= new Table_ident(thd, new_db, table_str, 0); if (!old_ident || !new_ident || !sl->add_table_to_list(thd, old_ident, NULL, TL_OPTION_UPDATING, TL_IGNORE) || @@ -1854,9 +1850,9 @@ bool mysql_rename_db(THD *thd, LEX_STRING *old_db, LEX_STRING *new_db) It garantees we never loose any tables. */ build_table_filename(path, sizeof(path)-1, - new_db->str,"",MY_DB_OPT_FILE, 0); + new_db.str,"",MY_DB_OPT_FILE, 0); my_delete(path, MYF(MY_WME)); - length= build_table_filename(path, sizeof(path)-1, new_db->str, "", "", 0); + length= build_table_filename(path, sizeof(path)-1, new_db.str, "", "", 0); if (length && path[length-1] == FN_LIBCHAR) path[length-1]=0; // remove ending '\' rmdir(path); @@ -1910,47 +1906,13 @@ bool mysql_rename_db(THD *thd, LEX_STRING *old_db, LEX_STRING *new_db) build_table_filename(oldname, sizeof(oldname)-1, old_db->str, "", file->name, 0); build_table_filename(newname, sizeof(newname)-1, - new_db->str, "", file->name, 0); + new_db.str, "", file->name, 0); my_rename(oldname, newname, MYF(MY_WME)); } - my_dirend(dirp); + my_dirend(dirp); } /* - Step4: TODO: moving stored procedures in the 'proc' system table - We need a new function: sp_move_db_routines(thd, olddb, newdb) - Which will basically have the same effect with: - UPDATE proc SET db='newdb' WHERE db='olddb' - Note, for 5.0 to 5.1 upgrade purposes we don't really need it. - - The biggest problem here is that we can't have a lock on LOCK_open() while - calling open_table() for 'proc'. - - Two solutions: - - Start by opening the 'event' and 'proc' (and other) tables for write - even before creating the 'to' database. (This will have the nice - effect of blocking another 'rename database' while the lock is active). - - Use the solution "Disable create of new tables during lock table" - - For an example of how to read through all rows, see: - sql_help.cc::search_topics() - */ - - /* - Step5: TODO: moving events in the 'event' system table - We need a new function evex_move_db_events(thd, olddb, newdb) - Which will have the same effect with: - UPDATE event SET db='newdb' WHERE db='olddb' - Note, for 5.0 to 5.1 upgrade purposes we don't really need it. - */ - - /* - Step6: TODO: moving grants in the 'db', 'tables_priv', 'columns_priv'. - Update each grant table, doing the same with: - UPDATE system_table SET db='newdb' WHERE db='olddb' - */ - - /* Step7: drop the old database. remove_db_from_cache(olddb) and query_cache_invalidate(olddb) are done inside mysql_rm_db(), no needs to execute them again. @@ -1968,13 +1930,13 @@ bool mysql_rename_db(THD *thd, LEX_STRING *old_db, LEX_STRING *new_db) /* Step9: Let's do "use newdb" if we renamed the current database */ if (change_to_newdb) - error|= mysql_change_db(thd, new_db, FALSE); + error|= mysql_change_db(thd, & new_db, FALSE); exit: pthread_mutex_lock(&LOCK_lock_db); /* Remove the databases from db lock cache */ lock_db_delete(old_db->str, old_db->length); - lock_db_delete(new_db->str, new_db->length); + lock_db_delete(new_db.str, new_db.length); creating_database--; /* Signal waiting CREATE TABLE's to continue */ pthread_cond_signal(&COND_refresh); diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc index 303918f42a2..4c57fad8d87 100644 --- a/sql/sql_delete.cc +++ b/sql/sql_delete.cc @@ -142,7 +142,7 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, { free_underlaid_joins(thd, select_lex); thd->row_count_func= 0; - send_ok(thd); // No matching records + send_ok(thd, (ha_rows) thd->row_count_func); // No matching records DBUG_RETURN(0); } #endif @@ -159,7 +159,7 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, delete select; free_underlaid_joins(thd, select_lex); thd->row_count_func= 0; - send_ok(thd,0L); + send_ok(thd, (ha_rows) thd->row_count_func); /* We don't need to call reset_auto_increment in this case, because mysql_truncate always gives a NULL conds argument, hence we never @@ -386,7 +386,7 @@ cleanup: if (error < 0 || (thd->lex->ignore && !thd->is_fatal_error)) { thd->row_count_func= deleted; - send_ok(thd,deleted); + send_ok(thd, (ha_rows) thd->row_count_func); DBUG_PRINT("info",("%ld records deleted",(long) deleted)); } DBUG_RETURN(error >= 0 || thd->net.report_error); @@ -889,7 +889,7 @@ bool multi_delete::send_eof() if (!local_error) { thd->row_count_func= deleted; - ::send_ok(thd, deleted); + ::send_ok(thd, (ha_rows) thd->row_count_func); } return 0; } diff --git a/sql/sql_handler.cc b/sql/sql_handler.cc index 1adce48c539..ed7e30c1fef 100644 --- a/sql/sql_handler.cc +++ b/sql/sql_handler.cc @@ -65,11 +65,6 @@ static enum enum_ha_read_modes rkey_to_rnext[]= { RNEXT_SAME, RNEXT, RPREV, RNEXT, RPREV, RNEXT, RPREV, RPREV }; -#define HANDLER_TABLES_HACK(thd) { \ - TABLE *tmp=thd->open_tables; \ - thd->open_tables=thd->handler_tables; \ - thd->handler_tables=tmp; } - static int mysql_ha_flush_table(THD *thd, TABLE **table_ptr, uint mode_flags); @@ -187,6 +182,7 @@ bool mysql_ha_open(THD *thd, TABLE_LIST *tables, bool reopen) char *db, *name, *alias; uint dblen, namelen, aliaslen, counter; int error; + TABLE *backup_open_tables; DBUG_ENTER("mysql_ha_open"); DBUG_PRINT("enter",("'%s'.'%s' as '%s' reopen: %d", tables->db, tables->table_name, tables->alias, @@ -216,16 +212,37 @@ bool mysql_ha_open(THD *thd, TABLE_LIST *tables, bool reopen) } /* + Save and reset the open_tables list so that open_tables() won't + be able to access (or know about) the previous list. And on return + from open_tables(), thd->open_tables will contain only the opened + table. + + The thd->handler_tables list is kept as-is to avoid deadlocks if + open_table(), called by open_tables(), needs to back-off because + of a pending name-lock on the table being opened. + + See open_table() back-off comments for more details. + */ + backup_open_tables= thd->open_tables; + thd->open_tables= NULL; + + /* open_tables() will set 'tables->table' if successful. It must be NULL for a real open when calling open_tables(). */ DBUG_ASSERT(! tables->table); - HANDLER_TABLES_HACK(thd); /* for now HANDLER can be used only for real TABLES */ tables->required_type= FRMTYPE_TABLE; error= open_tables(thd, &tables, &counter, 0); - HANDLER_TABLES_HACK(thd); + /* restore the state and merge the opened table into handler_tables list */ + if (thd->open_tables) + { + thd->open_tables->next= thd->handler_tables; + thd->handler_tables= thd->open_tables; + } + + thd->open_tables= backup_open_tables; if (error) goto err; @@ -351,7 +368,7 @@ bool mysql_ha_read(THD *thd, TABLE_LIST *tables, ha_rows select_limit_cnt, ha_rows offset_limit_cnt) { TABLE_LIST *hash_tables; - TABLE *table; + TABLE *table, *backup_open_tables; MYSQL_LOCK *lock; List<Item> list; Protocol *protocol= thd->protocol; @@ -361,7 +378,7 @@ bool mysql_ha_read(THD *thd, TABLE_LIST *tables, uint num_rows; uchar *key; uint key_len; - bool not_used; + bool need_reopen; DBUG_ENTER("mysql_ha_read"); DBUG_PRINT("enter",("'%s'.'%s' as '%s'", tables->db, tables->table_name, tables->alias)); @@ -375,6 +392,7 @@ bool mysql_ha_read(THD *thd, TABLE_LIST *tables, List_iterator<Item> it(list); it++; +retry: if ((hash_tables= (TABLE_LIST*) hash_search(&thd->handler_tables_hash, (uchar*) tables->alias, strlen(tables->alias) + 1))) @@ -428,9 +446,34 @@ bool mysql_ha_read(THD *thd, TABLE_LIST *tables, } tables->table=table; - HANDLER_TABLES_HACK(thd); - lock= mysql_lock_tables(thd, &tables->table, 1, 0, ¬_used); - HANDLER_TABLES_HACK(thd); + /* save open_tables state */ + backup_open_tables= thd->open_tables; + /* + mysql_lock_tables() needs thd->open_tables to be set correctly to + be able to handle aborts properly. When the abort happens, it's + safe to not protect thd->handler_tables because it won't close any + tables. + */ + thd->open_tables= thd->handler_tables; + + lock= mysql_lock_tables(thd, &tables->table, 1, + MYSQL_LOCK_NOTIFY_IF_NEED_REOPEN, &need_reopen); + + /* restore previous context */ + thd->open_tables= backup_open_tables; + + if (need_reopen) + { + mysql_ha_close_table(thd, tables); + hash_tables->table= NULL; + /* + The lock might have been aborted, we need to manually reset + thd->some_tables_deleted because handler's tables are closed + in a non-standard way. Otherwise we might loop indefinitely. + */ + thd->some_tables_deleted= 0; + goto retry; + } if (!lock) goto err0; // mysql_lock_tables() printed error message already diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index ebbf4cafb19..b4f2d8c65f2 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -1639,6 +1639,8 @@ public: char *record; enum_duplicates dup; time_t start_time; + ulong sql_mode; + bool auto_increment_field_not_null; bool query_start_used, ignore, log_query; bool stmt_depends_on_first_successful_insert_id_in_prev_stmt; ulonglong first_successful_insert_id_in_prev_stmt; @@ -2141,6 +2143,9 @@ int write_delayed(THD *thd, TABLE *table, enum_duplicates duplic, /* Copy session variables. */ row->auto_increment_increment= thd->variables.auto_increment_increment; row->auto_increment_offset= thd->variables.auto_increment_offset; + row->sql_mode= thd->variables.sql_mode; + row->auto_increment_field_not_null= table->auto_increment_field_not_null; + /* Copy the next forced auto increment value, if any. */ if ((forced_auto_inc= thd->auto_inc_intervals_forced.get_next())) { @@ -2555,10 +2560,13 @@ bool Delayed_insert::handle_inserts(void) thd.stmt_depends_on_first_successful_insert_id_in_prev_stmt= row->stmt_depends_on_first_successful_insert_id_in_prev_stmt; table->timestamp_field_type= row->timestamp_field_type; + table->auto_increment_field_not_null= row->auto_increment_field_not_null; /* Copy the session variables. */ thd.variables.auto_increment_increment= row->auto_increment_increment; thd.variables.auto_increment_offset= row->auto_increment_offset; + thd.variables.sql_mode= row->sql_mode; + /* Copy a forced insert_id, if any. */ if (row->forced_insert_id) { @@ -3419,6 +3427,7 @@ static TABLE *create_table_from_items(THD *thd, HA_CREATE_INFO *create_info, int select_create::prepare(List<Item> &values, SELECT_LEX_UNIT *u) { + MYSQL_LOCK *extra_lock= NULL; DBUG_ENTER("select_create::prepare"); TABLEOP_HOOKS *hook_ptr= NULL; @@ -3488,9 +3497,21 @@ select_create::prepare(List<Item> &values, SELECT_LEX_UNIT *u) if (!(table= create_table_from_items(thd, create_info, create_table, alter_info, &values, - &thd->extra_lock, hook_ptr))) + &extra_lock, hook_ptr))) DBUG_RETURN(-1); // abort() deletes table + if (extra_lock) + { + DBUG_ASSERT(m_plock == NULL); + + if (create_info->options & HA_LEX_CREATE_TMP_TABLE) + m_plock= &m_lock; + else + m_plock= &thd->extra_lock; + + *m_plock= extra_lock; + } + if (table->s->fields < values.elements) { my_error(ER_WRONG_VALUE_COUNT_ON_ROW, MYF(0), 1); @@ -3629,10 +3650,11 @@ bool select_create::send_eof() table->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY); table->file->extra(HA_EXTRA_WRITE_CANNOT_REPLACE); - if (thd->extra_lock) + if (m_plock) { - mysql_unlock_tables(thd, thd->extra_lock); - thd->extra_lock=0; + mysql_unlock_tables(thd, *m_plock); + *m_plock= NULL; + m_plock= NULL; } } return tmp; @@ -3667,10 +3689,11 @@ void select_create::abort() if (thd->current_stmt_binlog_row_based) ha_rollback_stmt(thd); - if (thd->extra_lock) + if (m_plock) { - mysql_unlock_tables(thd, thd->extra_lock); - thd->extra_lock=0; + mysql_unlock_tables(thd, *m_plock); + *m_plock= NULL; + m_plock= NULL; } if (table) diff --git a/sql/sql_lex.h b/sql/sql_lex.h index 50211f6b3f9..4b3228390c7 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -78,7 +78,6 @@ enum enum_sql_command { SQLCOM_LOAD,SQLCOM_SET_OPTION,SQLCOM_LOCK_TABLES,SQLCOM_UNLOCK_TABLES, SQLCOM_GRANT, SQLCOM_CHANGE_DB, SQLCOM_CREATE_DB, SQLCOM_DROP_DB, SQLCOM_ALTER_DB, - SQLCOM_RENAME_DB, SQLCOM_REPAIR, SQLCOM_REPLACE, SQLCOM_REPLACE_SELECT, SQLCOM_CREATE_FUNCTION, SQLCOM_DROP_FUNCTION, SQLCOM_REVOKE,SQLCOM_OPTIMIZE, SQLCOM_CHECK, @@ -117,6 +116,7 @@ enum enum_sql_command { SQLCOM_CREATE_EVENT, SQLCOM_ALTER_EVENT, SQLCOM_DROP_EVENT, SQLCOM_SHOW_CREATE_EVENT, SQLCOM_SHOW_EVENTS, SQLCOM_SHOW_CREATE_TRIGGER, + SQLCOM_ALTER_DB_UPGRADE, /* This should be the last !!! */ @@ -1550,7 +1550,6 @@ typedef struct st_lex : public Query_tables_list required a local context, the parser pops the top-most context. */ List<Name_resolution_context> context_stack; - List<LEX_STRING> db_list; SQL_LIST proc_list, auxiliary_table_list, save_list; Create_field *last_field; diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index ae347bebb47..4d8beb6f67d 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -86,7 +86,6 @@ const char *xa_state_names[]={ "NON-EXISTING", "ACTIVE", "IDLE", "PREPARED" }; - static void unlock_locked_tables(THD *thd) { if (thd->locked_tables) @@ -321,8 +320,6 @@ void execute_init_command(THD *thd, sys_var_str *init_command_var, values of init_command_var can't be changed */ rw_rdlock(var_mutex); - thd->query= init_command_var->value; - thd->query_length= init_command_var->value_length; save_client_capabilities= thd->client_capabilities; thd->client_capabilities|= CLIENT_MULTI_QUERIES; /* @@ -332,7 +329,9 @@ void execute_init_command(THD *thd, sys_var_str *init_command_var, save_vio= thd->net.vio; thd->net.vio= 0; thd->net.no_send_error= 0; - dispatch_command(COM_QUERY, thd, thd->query, thd->query_length+1); + dispatch_command(COM_QUERY, thd, + init_command_var->value, + init_command_var->value_length); rw_unlock(var_mutex); thd->client_capabilities= save_client_capabilities; thd->net.vio= save_vio; @@ -681,40 +680,49 @@ bool do_command(THD *thd) DBUG_PRINT("info",("Got error %d reading command from socket %s", net->error, vio_description(net->vio))); + /* Check if we can continue without closing the connection */ + if (net->error != 3) - { - statistic_increment(aborted_threads,&LOCK_status); DBUG_RETURN(TRUE); // We have to close it. - } + net_send_error(thd, net->last_errno, NullS); net->error= 0; DBUG_RETURN(FALSE); } - else + + packet= (char*) net->read_pos; + /* + 'packet_length' contains length of data, as it was stored in packet + header. In case of malformed header, my_net_read returns zero. + If packet_length is not zero, my_net_read ensures that the returned + number of bytes was actually read from network. + There is also an extra safety measure in my_net_read: + it sets packet[packet_length]= 0, but only for non-zero packets. + */ + if (packet_length == 0) /* safety */ { - packet=(char*) net->read_pos; - command = (enum enum_server_command) (uchar) packet[0]; - if (command >= COM_END) - command= COM_END; // Wrong command - DBUG_PRINT("info",("Command on %s = %d (%s)", - vio_description(net->vio), command, - command_name[command].str)); + /* Initialize with COM_SLEEP packet */ + packet[0]= (uchar) COM_SLEEP; + packet_length= 1; } + /* Do not rely on my_net_read, extra safety against programming errors. */ + packet[packet_length]= '\0'; /* safety */ + + command= (enum enum_server_command) (uchar) packet[0]; + + if (command >= COM_END) + command= COM_END; // Wrong command + + DBUG_PRINT("info",("Command on %s = %d (%s)", + vio_description(net->vio), command, + command_name[command].str)); /* Restore read timeout value */ my_net_set_read_timeout(net, thd->variables.net_read_timeout); - /* - packet_length contains length of data, as it was stored in packet - header. In case of malformed header, packet_length can be zero. - If packet_length is not zero, my_net_read ensures that this number - of bytes was actually read from network. Additionally my_net_read - sets packet[packet_length]= 0 (thus if packet_length == 0, - command == packet[0] == COM_SLEEP). - In dispatch_command packet[packet_length] points beyond the end of packet. - */ - DBUG_RETURN(dispatch_command(command,thd, packet+1, (uint) packet_length)); + DBUG_ASSERT(packet_length); + DBUG_RETURN(dispatch_command(command, thd, packet+1, (uint) (packet_length-1))); } #endif /* EMBEDDED_LIBRARY */ @@ -727,9 +735,7 @@ bool do_command(THD *thd) thd connection handle command type of command to perform packet data for the command, packet is always null-terminated - packet_length length of packet + 1 (to show that data is - null-terminated) except for COM_SLEEP, where it - can be zero. + packet_length length of packet. Can be zero, e.g. in case of COM_SLEEP. RETURN VALUE 0 ok 1 request of thread shutdown, i. e. if command is @@ -773,10 +779,10 @@ bool dispatch_command(enum enum_server_command command, THD *thd, LEX_STRING tmp; status_var_increment(thd->status_var.com_stat[SQLCOM_CHANGE_DB]); thd->convert_string(&tmp, system_charset_info, - packet, packet_length-1, thd->charset()); + packet, packet_length, thd->charset()); if (!mysql_change_db(thd, &tmp, FALSE)) { - general_log_print(thd, command, "%s",thd->db); + general_log_write(thd, command, thd->db, thd->db_length); send_ok(thd); } break; @@ -793,14 +799,16 @@ bool dispatch_command(enum enum_server_command command, THD *thd, { char *tbl_name; LEX_STRING db; + /* Safe because there is always a trailing \0 at the end of the packet */ uint db_len= *(uchar*) packet; - if (db_len >= packet_length || db_len > NAME_LEN) + if (db_len + 1 > packet_length || db_len > NAME_LEN) { my_message(ER_UNKNOWN_COM_ERROR, ER(ER_UNKNOWN_COM_ERROR), MYF(0)); break; } + /* Safe because there is always a trailing \0 at the end of the packet */ uint tbl_len= *(uchar*) (packet + db_len + 1); - if (db_len+tbl_len+2 > packet_length || tbl_len > NAME_LEN) + if (db_len + tbl_len + 2 > packet_length || tbl_len > NAME_LEN) { my_message(ER_UNKNOWN_COM_ERROR, ER(ER_UNKNOWN_COM_ERROR), MYF(0)); break; @@ -823,7 +831,8 @@ bool dispatch_command(enum enum_server_command command, THD *thd, case COM_CHANGE_USER: { status_var_increment(thd->status_var.com_other); - char *user= (char*) packet, *packet_end= packet+ packet_length; + char *user= (char*) packet, *packet_end= packet + packet_length; + /* Safe because there is always a trailing \0 at the end of the packet */ char *passwd= strend(user)+1; thd->change_user(); @@ -840,6 +849,15 @@ bool dispatch_command(enum enum_server_command command, THD *thd, char db_buff[NAME_LEN+1]; // buffer to store db in utf8 char *db= passwd; char *save_db; + /* + If there is no password supplied, the packet must contain '\0', + in any type of handshake (4.1 or pre-4.1). + */ + if (passwd >= packet_end) + { + my_message(ER_UNKNOWN_COM_ERROR, ER(ER_UNKNOWN_COM_ERROR), MYF(0)); + break; + } uint passwd_len= (thd->client_capabilities & CLIENT_SECURE_CONNECTION ? (uchar)(*passwd++) : strlen(passwd)); uint dummy_errors, save_db_length, db_length; @@ -848,22 +866,32 @@ bool dispatch_command(enum enum_server_command command, THD *thd, USER_CONN *save_user_connect; db+= passwd_len + 1; -#ifndef EMBEDDED_LIBRARY - /* Small check for incoming packet */ - if ((uint) ((uchar*) db - net->read_pos) > packet_length) + /* + Database name is always NUL-terminated, so in case of empty database + the packet must contain at least the trailing '\0'. + */ + if (db >= packet_end) { my_message(ER_UNKNOWN_COM_ERROR, ER(ER_UNKNOWN_COM_ERROR), MYF(0)); break; } -#endif + db_length= strlen(db); + + char *ptr= db + db_length + 1; + uint cs_number= 0; + + if (ptr < packet_end) + { + if (ptr + 2 > packet_end) + { + my_message(ER_UNKNOWN_COM_ERROR, ER(ER_UNKNOWN_COM_ERROR), MYF(0)); + break; + } + + cs_number= uint2korr(ptr); + } + /* Convert database name to utf8 */ - /* - Handle problem with old bug in client protocol where db had an extra - \0 - */ - db_length= (packet_end - db); - if (db_length > 0 && db[db_length-1] == 0) - db_length--; db_buff[copy_and_convert(db_buff, sizeof(db_buff)-1, system_charset_info, db, db_length, thd->charset(), &dummy_errors)]= 0; @@ -907,6 +935,12 @@ bool dispatch_command(enum enum_server_command command, THD *thd, #endif /* NO_EMBEDDED_ACCESS_CHECKS */ x_free((uchar*) save_db); x_free((uchar*) save_security_ctx.user); + + if (cs_number) + { + thd_init_client_charset(thd, cs_number); + thd->update_charset(); + } } break; } @@ -946,10 +980,9 @@ bool dispatch_command(enum enum_server_command command, THD *thd, break; // fatal error is set char *packet_end= thd->query + thd->query_length; /* 'b' stands for 'buffer' parameter', special for 'my_snprintf' */ - const char *format= "%.*b"; const char* found_semicolon= NULL; - general_log_print(thd, command, format, thd->query_length, thd->query); + general_log_write(thd, command, thd->query, thd->query_length); DBUG_PRINT("query",("%-.4096s",thd->query)); if (!(specialflag & SPECIAL_NO_PRIOR)) @@ -999,7 +1032,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd, break; #else { - char *fields, *packet_end= packet + packet_length - 1, *arg_end; + char *fields, *packet_end= packet + packet_length, *arg_end; /* Locked closure of all tables */ TABLE_LIST table_list; LEX_STRING conv_name; @@ -1073,7 +1106,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd, HA_CREATE_INFO create_info; status_var_increment(thd->status_var.com_stat[SQLCOM_CREATE_DB]); - if (thd->make_lex_string(&db, packet, packet_length - 1, FALSE) || + if (thd->make_lex_string(&db, packet, packet_length, FALSE) || thd->make_lex_string(&alias, db.str, db.length, FALSE) || check_db_name(&db)) { @@ -1094,7 +1127,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd, status_var_increment(thd->status_var.com_stat[SQLCOM_DROP_DB]); LEX_STRING db; - if (thd->make_lex_string(&db, packet, packet_length - 1, FALSE) || + if (thd->make_lex_string(&db, packet, packet_length, FALSE) || check_db_name(&db)) { my_error(ER_WRONG_DB_NAME, MYF(0), db.str ? db.str : "NULL"); @@ -1108,7 +1141,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd, ER(ER_LOCK_OR_ACTIVE_TRANSACTION), MYF(0)); break; } - general_log_print(thd, command, db.str); + general_log_write(thd, command, db.str, db.length); mysql_rm_db(thd, db.str, 0, 0); break; } @@ -1163,7 +1196,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd, break; /* purecov: inspected */ /* If the client is < 4.1.3, it is going to send us no argument; then - packet_length is 1, packet[0] is the end 0 of the packet. Note that + packet_length is 0, packet[0] is the end 0 of the packet. Note that SHUTDOWN_DEFAULT is 0. If client is >= 4.1.3, the shutdown level is in packet[0]. */ @@ -1521,9 +1554,8 @@ int prepare_schema_table(THD *thd, LEX *lex, Table_ident *table_ident, bool alloc_query(THD *thd, const char *packet, uint packet_length) { - packet_length--; // Remove end null /* Remove garbage at start and end of query */ - while (my_isspace(thd->charset(),packet[0]) && packet_length > 0) + while (packet_length > 0 && my_isspace(thd->charset(), packet[0])) { packet++; packet_length--; @@ -3173,12 +3205,9 @@ end_with_restore_list: res= mysql_rm_db(thd, lex->name.str, lex->drop_if_exists, 0); break; } - case SQLCOM_RENAME_DB: + case SQLCOM_ALTER_DB_UPGRADE: { - LEX_STRING *olddb, *newdb; - List_iterator <LEX_STRING> db_list(lex->db_list); - olddb= db_list++; - newdb= db_list++; + LEX_STRING *db= & lex->name; if (end_active_trans(thd)) { res= 1; @@ -3186,24 +3215,22 @@ end_with_restore_list: } #ifdef HAVE_REPLICATION if (thd->slave_thread && - (!rpl_filter->db_ok(olddb->str) || - !rpl_filter->db_ok(newdb->str) || - !rpl_filter->db_ok_with_wild_table(olddb->str) || - !rpl_filter->db_ok_with_wild_table(newdb->str))) + (!rpl_filter->db_ok(db->str) || + !rpl_filter->db_ok_with_wild_table(db->str))) { res= 1; my_message(ER_SLAVE_IGNORED_TABLE, ER(ER_SLAVE_IGNORED_TABLE), MYF(0)); break; } #endif - if (check_db_name(newdb)) + if (check_db_name(db)) { - my_error(ER_WRONG_DB_NAME, MYF(0), newdb->str); + my_error(ER_WRONG_DB_NAME, MYF(0), db->str); break; } - if (check_access(thd,ALTER_ACL,olddb->str,0,1,0,is_schema_db(olddb->str)) || - check_access(thd,DROP_ACL,olddb->str,0,1,0,is_schema_db(olddb->str)) || - check_access(thd,CREATE_ACL,newdb->str,0,1,0,is_schema_db(newdb->str))) + if (check_access(thd, ALTER_ACL, db->str, 0, 1, 0, is_schema_db(db->str)) || + check_access(thd, DROP_ACL, db->str, 0, 1, 0, is_schema_db(db->str)) || + check_access(thd, CREATE_ACL, db->str, 0, 1, 0, is_schema_db(db->str))) { res= 1; break; @@ -3215,7 +3242,8 @@ end_with_restore_list: ER(ER_LOCK_OR_ACTIVE_TRANSACTION), MYF(0)); goto error; } - res= mysql_rename_db(thd, olddb, newdb); + + res= mysql_upgrade_db(thd, db); if (!res) send_ok(thd); break; @@ -3328,12 +3356,6 @@ end_with_restore_list: if (check_access(thd,INSERT_ACL,"mysql",0,1,0,0)) break; #ifdef HAVE_DLOPEN - if (sp_find_routine(thd, TYPE_ENUM_FUNCTION, lex->spname, - &thd->sp_func_cache, FALSE)) - { - my_error(ER_UDF_EXISTS, MYF(0), lex->spname->m_name.str); - goto error; - } if (!(res = mysql_create_function(thd, &lex->udf))) send_ok(thd); #else @@ -3789,6 +3811,9 @@ end_with_restore_list: case SP_BODY_TOO_LONG: my_error(ER_TOO_LONG_BODY, MYF(0), name); break; + case SP_FLD_STORE_FAILED: + my_error(ER_CANT_CREATE_SROUTINE, MYF(0), name); + break; default: my_error(ER_SP_STORE_FAILED, MYF(0), SP_TYPE_STRING(lex), name); break; @@ -7242,7 +7267,12 @@ bool parse_sql(THD *thd, /* Parse the query. */ - bool err_status= MYSQLparse(thd) != 0 || thd->is_fatal_error; + bool mysql_parse_status= MYSQLparse(thd) != 0; + + /* Check that if MYSQLparse() failed, thd->net.report_error is set. */ + + DBUG_ASSERT(!mysql_parse_status || + mysql_parse_status && thd->net.report_error); /* Reset Lex_input_stream. */ @@ -7255,7 +7285,7 @@ bool parse_sql(THD *thd, /* That's it. */ - return err_status; + return mysql_parse_status || thd->is_fatal_error; } /** diff --git a/sql/sql_plugin.cc b/sql/sql_plugin.cc index 1ec56e0caea..ca28d89f280 100644 --- a/sql/sql_plugin.cc +++ b/sql/sql_plugin.cc @@ -3059,7 +3059,7 @@ static int test_plugin_options(MEM_ROOT *tmp_root, struct st_plugin_int *tmp, MEM_ROOT *mem_root= alloc_root_inited(&tmp->mem_root) ? &tmp->mem_root : &plugin_mem_root; st_mysql_sys_var **opt; - my_option *opts; + my_option *opts= NULL; char *p, *varname; int error; st_mysql_sys_var *o; @@ -3098,7 +3098,7 @@ static int test_plugin_options(MEM_ROOT *tmp_root, struct st_plugin_int *tmp, { sql_print_error("Parsing options for plugin '%s' failed.", tmp->name.str); - DBUG_RETURN(error); + goto err; } } @@ -3108,6 +3108,8 @@ static int test_plugin_options(MEM_ROOT *tmp_root, struct st_plugin_int *tmp, *enabled= TRUE; } + error= 1; + if (*enabled) { for (opt= tmp->plugin->system_vars; opt && *opt; opt++) @@ -3146,7 +3148,7 @@ static int test_plugin_options(MEM_ROOT *tmp_root, struct st_plugin_int *tmp, { sql_print_error("Plugin '%s' has conflicting system variables", tmp->name.str); - DBUG_RETURN(1); + goto err; } tmp->system_vars= chain.first; } @@ -3156,7 +3158,10 @@ static int test_plugin_options(MEM_ROOT *tmp_root, struct st_plugin_int *tmp, if (enabled_saved && global_system_variables.log_warnings) sql_print_information("Plugin '%s' disabled by command line option", tmp->name.str); - DBUG_RETURN(1); +err: + if (opts) + my_cleanup_options(opts); + DBUG_RETURN(error); } diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc index 9337a2aa329..a6cdcf14881 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -1799,7 +1799,7 @@ static bool check_prepared_statement(Prepared_statement *stmt, case SQLCOM_UNINSTALL_PLUGIN: case SQLCOM_CREATE_DB: case SQLCOM_DROP_DB: - case SQLCOM_RENAME_DB: + case SQLCOM_ALTER_DB_UPGRADE: case SQLCOM_CHECKSUM: case SQLCOM_CREATE_USER: case SQLCOM_RENAME_USER: @@ -2107,7 +2107,7 @@ void mysql_sql_stmt_prepare(THD *thd) DBUG_VOID_RETURN; } - if (stmt->prepare(query, query_len+1)) + if (stmt->prepare(query, query_len)) { /* Statement map deletes the statement on erase */ thd->stmt_map.erase(stmt); @@ -2270,7 +2270,7 @@ void mysql_stmt_execute(THD *thd, char *packet_arg, uint packet_length) /* Query text for binary, general or slow log, if any of them is open */ String expanded_query; #ifndef EMBEDDED_LIBRARY - uchar *packet_end= packet + packet_length - 1; + uchar *packet_end= packet + packet_length; #endif Prepared_statement *stmt; bool error; @@ -2585,14 +2585,14 @@ void mysql_stmt_get_longdata(THD *thd, char *packet, ulong packet_length) Prepared_statement *stmt; Item_param *param; #ifndef EMBEDDED_LIBRARY - char *packet_end= packet + packet_length - 1; + char *packet_end= packet + packet_length; #endif DBUG_ENTER("mysql_stmt_get_longdata"); status_var_increment(thd->status_var.com_stmt_send_long_data); #ifndef EMBEDDED_LIBRARY /* Minimal size of long data packet is 6 bytes */ - if (packet_length <= MYSQL_LONG_DATA_HEADER) + if (packet_length < MYSQL_LONG_DATA_HEADER) { my_error(ER_WRONG_ARGUMENTS, MYF(0), "mysql_stmt_send_long_data"); DBUG_VOID_RETURN; @@ -2866,6 +2866,7 @@ bool Prepared_statement::prepare(const char *packet, uint packet_len) error= parse_sql(thd, &lip, NULL) || thd->net.report_error || init_param_array(this); + lex->set_trg_event_type_for_tables(); /* Remember the current database. */ @@ -2946,12 +2947,7 @@ bool Prepared_statement::prepare(const char *packet, uint packet_len) the general log. */ if (thd->spcont == NULL) - { - const char *format= "[%lu] %.*b"; - general_log_print(thd, COM_STMT_PREPARE, format, id, - query_length, query); - - } + general_log_write(thd, COM_STMT_PREPARE, query, query_length); } DBUG_RETURN(error); } @@ -3059,7 +3055,7 @@ bool Prepared_statement::execute(String *expanded_query, bool open_cursor) if (expanded_query->length() && alloc_query(thd, (char*) expanded_query->ptr(), - expanded_query->length()+1)) + expanded_query->length())) { my_error(ER_OUTOFMEMORY, 0, expanded_query->length()); goto error; @@ -3149,11 +3145,7 @@ bool Prepared_statement::execute(String *expanded_query, bool open_cursor) the general log. */ if (error == 0 && thd->spcont == NULL) - { - const char *format= "[%lu] %.*b"; - general_log_print(thd, COM_STMT_EXECUTE, format, id, - thd->query_length, thd->query); - } + general_log_write(thd, COM_STMT_EXECUTE, thd->query, thd->query_length); error: flags&= ~ (uint) IS_IN_USE; diff --git a/sql/sql_select.cc b/sql/sql_select.cc index ba06c93e6b0..eb2731205ec 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -9343,6 +9343,36 @@ Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type, } /* Fall through */ case Item::FUNC_ITEM: + if (((Item_func *) item)->functype() == Item_func::FUNC_SP) + { + Item_func_sp *item_func_sp= (Item_func_sp *) item; + Field *sp_result_field= item_func_sp->get_sp_result_field(); + + if (make_copy_field) + { + DBUG_ASSERT(item_func_sp->result_field); + *from_field= item_func_sp->result_field; + } + else + { + *((*copy_func)++)= item; + } + + Field *result_field= + create_tmp_field_from_field(thd, + sp_result_field, + item_func_sp->name, + table, + NULL, + convert_blob_length); + + if (modify_item) + item->set_result_field(result_field); + + return result_field; + } + + /* Fall through */ case Item::COND_ITEM: case Item::FIELD_AVG_ITEM: case Item::FIELD_STD_ITEM: diff --git a/sql/sql_udf.cc b/sql/sql_udf.cc index 19582af38f4..1076772d598 100644 --- a/sql/sql_udf.cc +++ b/sql/sql_udf.cc @@ -415,7 +415,7 @@ int mysql_create_function(THD *thd,udf_func *udf) if (check_string_char_length(&udf->name, "", NAME_CHAR_LEN, system_charset_info, 1)) { - my_error(ER_TOO_LONG_IDENT, MYF(0), udf->name); + my_error(ER_TOO_LONG_IDENT, MYF(0), udf->name.str); DBUG_RETURN(1); } @@ -429,7 +429,7 @@ int mysql_create_function(THD *thd,udf_func *udf) rw_wrlock(&THR_LOCK_udf); if ((hash_search(&udf_hash,(uchar*) udf->name.str, udf->name.length))) { - my_error(ER_UDF_EXISTS, MYF(0), udf->name); + my_error(ER_UDF_EXISTS, MYF(0), udf->name.str); goto err; } if (!(dl = find_udf_dl(udf->dl))) diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 68680addc58..30e62c5d7b5 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -1211,8 +1211,6 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); %type <cast_type> cast_type -%type <udf_type> udf_func_type - %type <symbol> keyword keyword_sp %type <lex_user> user grant_user @@ -1254,14 +1252,14 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); ref_list opt_on_delete opt_on_delete_list opt_on_delete_item use opt_delete_options opt_delete_option varchar nchar nvarchar opt_outer table_list table_name table_alias_ref_list table_alias_ref - opt_option opt_place + opt_option opt_place opt_attribute opt_attribute_list attribute column_list column_list_id opt_column_list grant_privileges grant_ident grant_list grant_option object_privilege object_privilege_list user_list rename_list clear_privileges flush_options flush_option equal optional_braces opt_mi_check_type opt_to mi_check_types normal_join - db_to_db table_to_table_list table_to_table opt_table_list opt_as + table_to_table_list table_to_table opt_table_list opt_as handler_rkey_function handler_read_or_scan single_multi table_wild_list table_wild_one opt_wild union_clause union_list @@ -1272,14 +1270,15 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); statement sp_suid sp_c_chistics sp_a_chistics sp_chistic sp_c_chistic xa load_data opt_field_or_var_spec fields_or_vars opt_load_data_set_spec - definer view_replace_or_algorithm view_replace + view_replace_or_algorithm view_replace view_algorithm view_or_trigger_or_sp_or_event - view_or_trigger_or_sp_or_event_tail + definer_tail no_definer_tail view_suid view_tail view_list_opt view_list view_select - view_check_option trigger_tail sp_tail + view_check_option trigger_tail sp_tail sf_tail udf_tail event_tail install uninstall partition_entry binlog_base64_event init_key_options key_options key_opts key_opt key_using_alg server_def server_options_list server_option + definer_opt no_definer definer END_OF_INPUT %type <NONE> call sp_proc_stmts sp_proc_stmts1 sp_proc_stmt @@ -2002,181 +2001,6 @@ sp_name: } ; -create_function_tail: - RETURNS_SYM udf_type SONAME_SYM TEXT_STRING_sys - { - THD *thd= YYTHD; - LEX *lex= thd->lex; - if (lex->definer != NULL) - { - /* - DEFINER is a concept meaningful when interpreting SQL code. - UDF functions are compiled. - Using DEFINER with UDF has therefore no semantic, - and is considered a parsing error. - */ - my_error(ER_WRONG_USAGE, MYF(0), "SONAME", "DEFINER"); - MYSQL_YYABORT; - } - if (is_native_function(thd, & lex->spname->m_name)) - { - my_error(ER_NATIVE_FCT_NAME_COLLISION, MYF(0), - lex->spname->m_name.str); - MYSQL_YYABORT; - } - lex->sql_command = SQLCOM_CREATE_FUNCTION; - lex->udf.name = lex->spname->m_name; - lex->udf.returns=(Item_result) $2; - lex->udf.dl=$4.str; - } - | '(' - { - THD *thd= YYTHD; - LEX *lex= thd->lex; - Lex_input_stream *lip= thd->m_lip; - sp_head *sp; - const char* tmp_param_begin; - - /* - First check if AGGREGATE was used, in that case it's a - syntax error. - */ - if (lex->udf.type == UDFTYPE_AGGREGATE) - { - my_error(ER_SP_NO_AGGREGATE, MYF(0)); - MYSQL_YYABORT; - } - - if (lex->sphead) - { - my_error(ER_SP_NO_RECURSIVE_CREATE, MYF(0), "FUNCTION"); - MYSQL_YYABORT; - } - /* Order is important here: new - reset - init */ - sp= new sp_head(); - sp->reset_thd_mem_root(thd); - sp->init(lex); - sp->init_sp_name(thd, lex->spname); - - sp->m_type= TYPE_ENUM_FUNCTION; - lex->sphead= sp; - /* - We have to turn off CLIENT_MULTI_QUERIES while parsing a - stored procedure, otherwise yylex will chop it into pieces - at each ';'. - */ - $<ulong_num>$= thd->client_capabilities & CLIENT_MULTI_QUERIES; - thd->client_capabilities &= ~CLIENT_MULTI_QUERIES; - - tmp_param_begin= lip->get_cpp_tok_start(); - tmp_param_begin++; - lex->sphead->m_param_begin= tmp_param_begin; - } - sp_fdparam_list ')' - { - THD *thd= YYTHD; - LEX *lex= thd->lex; - Lex_input_stream *lip= thd->m_lip; - - lex->sphead->m_param_end= lip->get_cpp_tok_start(); - } - RETURNS_SYM - { - LEX *lex= Lex; - lex->charset= NULL; - lex->length= lex->dec= NULL; - lex->interval_list.empty(); - lex->type= 0; - } - type - { - LEX *lex= Lex; - sp_head *sp= lex->sphead; - /* - This was disabled in 5.1.12. See bug #20701 - When collation support in SP is implemented, then this test - should be removed. - */ - if (($8 == MYSQL_TYPE_STRING || $8 == MYSQL_TYPE_VARCHAR) - && (lex->type & BINCMP_FLAG)) - { - my_error(ER_NOT_SUPPORTED_YET, MYF(0), "return value collation"); - MYSQL_YYABORT; - } - - if (sp->fill_field_definition(YYTHD, lex, - (enum enum_field_types) $8, - &sp->m_return_field_def)) - MYSQL_YYABORT; - - bzero((char *)&lex->sp_chistics, sizeof(st_sp_chistics)); - } - sp_c_chistics - { - THD *thd= YYTHD; - LEX *lex= thd->lex; - Lex_input_stream *lip= thd->m_lip; - - lex->sphead->m_chistics= &lex->sp_chistics; - lex->sphead->set_body_start(thd, lip->get_cpp_tok_start()); - } - sp_proc_stmt - { - THD *thd= YYTHD; - LEX *lex= thd->lex; - sp_head *sp= lex->sphead; - - if (sp->is_not_allowed_in_function("function")) - MYSQL_YYABORT; - - lex->sql_command= SQLCOM_CREATE_SPFUNCTION; - sp->set_stmt_end(thd); - if (!(sp->m_flags & sp_head::HAS_RETURN)) - { - my_error(ER_SP_NORETURN, MYF(0), sp->m_qname.str); - MYSQL_YYABORT; - } - if (is_native_function(thd, & sp->m_name)) - { - /* - This warning will be printed when - [1] A client query is parsed, - [2] A stored function is loaded by db_load_routine. - Printing the warning for [2] is intentional, to cover the - following scenario: - - A user define a SF 'foo' using MySQL 5.N - - An application uses select foo(), and works. - - MySQL 5.{N+1} defines a new native function 'foo', as - part of a new feature. - - MySQL 5.{N+1} documentation is updated, and should mention - that there is a potential incompatible change in case of - existing stored function named 'foo'. - - The user deploys 5.{N+1}. At this point, 'select foo()' - means something different, and the user code is most likely - broken (it's only safe if the code is 'select db.foo()'). - With a warning printed when the SF is loaded (which has to occur - before the call), the warning will provide a hint explaining - the root cause of a later failure of 'select foo()'. - With no warning printed, the user code will fail with no - apparent reason. - Printing a warning each time db_load_routine is executed for - an ambiguous function is annoying, since that can happen a lot, - but in practice should not happen unless there *are* name - collisions. - If a collision exists, it should not be silenced but fixed. - */ - push_warning_printf(thd, - MYSQL_ERROR::WARN_LEVEL_NOTE, - ER_NATIVE_FCT_NAME_COLLISION, - ER(ER_NATIVE_FCT_NAME_COLLISION), - sp->m_name.str); - } - /* Restore flag if it was cleared above */ - thd->client_capabilities |= $<ulong_num>2; - sp->restore_thd_mem_root(thd); - } - ; - sp_a_chistics: /* Empty */ {} | sp_a_chistics sp_chistic {} @@ -2540,25 +2364,13 @@ sp_decl: sp_cursor_stmt: { Lex->sphead->reset_lex(YYTHD); - - /* - We use statement here just be able to get a better - error message. Using 'select' works too, but will then - result in a generic "syntax error" if a non-select - statement is given. - */ } - statement + select { LEX *lex= Lex; - if (lex->sql_command != SQLCOM_SELECT && - !(sql_command_flags[lex->sql_command] & CF_STATUS_COMMAND)) - { - my_message(ER_SP_BAD_CURSOR_QUERY, ER(ER_SP_BAD_CURSOR_QUERY), - MYF(0)); - MYSQL_YYABORT; - } + DBUG_ASSERT(lex->sql_command == SQLCOM_SELECT); + if (lex->result) { my_message(ER_SP_BAD_CURSOR_SELECT, ER(ER_SP_BAD_CURSOR_SELECT), @@ -3362,7 +3174,6 @@ change_ts_option: ; tablespace_option_list: - /* empty */ {} tablespace_options ; @@ -3384,7 +3195,6 @@ tablespace_option: ; alter_tablespace_option_list: - /* empty */ {} alter_tablespace_options ; @@ -3403,7 +3213,6 @@ alter_tablespace_option: ; logfile_group_option_list: - /* empty */ {} logfile_group_options ; @@ -3424,7 +3233,6 @@ logfile_group_option: ; alter_logfile_group_option_list: - /* empty */ {} alter_logfile_group_options ; @@ -3669,7 +3477,7 @@ size_number: create2: '(' create2a {} | opt_create_table_options - opt_partitioning {} + opt_partitioning create3 {} | LIKE table_ident { @@ -3693,19 +3501,22 @@ create2: create2a: field_list ')' opt_create_table_options - opt_partitioning {} + opt_partitioning create3 {} - | opt_partitioning {} + | opt_partitioning create_select ')' - { Select->set_braces(1);} union_opt {} + { Select->set_braces(1);} + union_opt {} ; create3: /* empty */ {} | opt_duplicate opt_as create_select - { Select->set_braces(0);} union_clause {} + { Select->set_braces(0);} + union_clause {} | opt_duplicate opt_as '(' create_select ')' - { Select->set_braces(1);} union_opt {} + { Select->set_braces(1);} + union_opt {} ; /* @@ -3787,7 +3598,7 @@ partition_entry: ; partition: - BY part_type_def opt_no_parts {} opt_sub_part {} part_defs + BY part_type_def opt_no_parts opt_sub_part part_defs ; part_type_def: @@ -3988,10 +3799,11 @@ part_definition: part_info->use_default_partitions= FALSE; part_info->use_default_no_partitions= FALSE; } - part_name {} - opt_part_values {} - opt_part_options {} - opt_sub_partition {} + part_name + opt_part_values + opt_part_options + opt_sub_partition + {} ; part_name: @@ -4501,11 +4313,10 @@ create_table_option: } | TRANSACTIONAL_SYM opt_equal ulong_num { - Lex->create_info.used_fields|= HA_CREATE_USED_TRANSACTIONAL; + Lex->create_info.used_fields|= HA_CREATE_USED_TRANSACTIONAL; Lex->create_info.transactional= ($3 != 0 ? HA_CHOICE_YES : - HA_CHOICE_NO); + HA_CHOICE_NO); } - ; default_charset: @@ -4587,7 +4398,7 @@ row_types: | COMPRESSED_SYM { $$= ROW_TYPE_COMPRESSED; } | REDUNDANT_SYM { $$= ROW_TYPE_REDUNDANT; } | COMPACT_SYM { $$= ROW_TYPE_COMPACT; } - | PAGE_SYM { $$= ROW_TYPE_PAGE; } + | PAGE_SYM { $$= ROW_TYPE_PAGE; } ; merge_insert_types: @@ -4601,10 +4412,6 @@ opt_select_from: | select_from select_lock_type ; -udf_func_type: - /* empty */ { $$ = UDFTYPE_FUNCTION; } - | AGGREGATE_SYM { $$ = UDFTYPE_AGGREGATE; }; - udf_type: STRING_SYM {$$ = (int) STRING_RESULT; } | REAL {$$ = (int) REAL_RESULT; } @@ -4657,8 +4464,9 @@ key_def: | opt_constraint FOREIGN KEY_SYM opt_ident '(' key_list ')' references { LEX *lex=Lex; - const char *key_name= $4 ? $4 : $1; - Key *key= new Foreign_key(key_name, lex->col_list, + const char *key_name= $1 ? $1 : $4; + const char *fkey_name = $4 ? $4 : key_name; + Key *key= new Foreign_key(fkey_name, lex->col_list, $8, lex->ref_list, lex->fk_delete_opt, @@ -5401,6 +5209,17 @@ alter: lex->copy_db_to(&lex->name.str, &lex->name.length)) MYSQL_YYABORT; } + | ALTER DATABASE ident UPGRADE_SYM DATA_SYM DIRECTORY_SYM NAME_SYM + { + LEX *lex= Lex; + if (lex->sphead) + { + my_error(ER_SP_NO_DROP_SP, MYF(0), "DATABASE"); + MYSQL_YYABORT; + } + lex->sql_command= SQLCOM_ALTER_DB_UPGRADE; + lex->name= $3; + } | ALTER PROCEDURE sp_name { LEX *lex= Lex; @@ -5437,7 +5256,7 @@ alter: lex->sql_command= SQLCOM_ALTER_FUNCTION; lex->spname= $3; } - | ALTER view_algorithm definer + | ALTER view_algorithm definer_opt { LEX *lex= Lex; @@ -5450,7 +5269,7 @@ alter: } view_tail {} - | ALTER definer + | ALTER definer_opt /* We have two separate rules for ALTER VIEW rather that optional view_algorithm above, to resolve the ambiguity @@ -5469,7 +5288,7 @@ alter: } view_tail {} - | ALTER definer EVENT_SYM sp_name + | ALTER definer_opt EVENT_SYM sp_name /* BE CAREFUL when you add a new rule to update the block where YYTHD->client_capabilities is set back to original value @@ -5505,7 +5324,7 @@ alter: { /* $1 - ALTER - $2 - definer + $2 - definer_opt $3 - EVENT_SYM $4 - sp_name $5 - the block above @@ -6185,13 +6004,6 @@ rename: } table_to_table_list {} - | RENAME DATABASE - { - Lex->db_list.empty(); - Lex->sql_command= SQLCOM_RENAME_DB; - } - db_to_db - {} | RENAME USER clear_privileges rename_list { Lex->sql_command = SQLCOM_RENAME_USER; @@ -6229,18 +6041,6 @@ table_to_table: } ; -db_to_db: - ident TO_SYM ident - { - LEX *lex=Lex; - if (lex->db_list.push_back((LEX_STRING*) - sql_memdup(&$1, sizeof(LEX_STRING))) || - lex->db_list.push_back((LEX_STRING*) - sql_memdup(&$3, sizeof(LEX_STRING)))) - MYSQL_YYABORT; - } - ; - keycache: CACHE_SYM INDEX_SYM keycache_list IN_SYM key_cache_name { @@ -8578,9 +8378,11 @@ drop: lex->drop_if_exists=$3; lex->name= $4; } - | 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 (lex->sphead) { my_error(ER_SP_NO_DROP_SP, MYF(0), "FUNCTION"); @@ -8588,7 +8390,28 @@ drop: } lex->sql_command = SQLCOM_DROP_FUNCTION; lex->drop_if_exists= $3; - lex->spname= $4; + spname= new sp_name($4, $6, true); + 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); + spname->init_qname(thd); + lex->spname= spname; } | DROP PROCEDURE if_exists sp_name { @@ -8658,18 +8481,19 @@ table_name: ; table_alias_ref_list: - table_alias_ref - | table_alias_ref_list ',' table_alias_ref; + table_alias_ref + | table_alias_ref_list ',' table_alias_ref + ; table_alias_ref: - table_ident - { - if (!Select->add_table_to_list(YYTHD, $1, NULL, - TL_OPTION_UPDATING | TL_OPTION_ALIAS, - Lex->lock_option )) - MYSQL_YYABORT; - } - ; + table_ident + { + if (!Select->add_table_to_list(YYTHD, $1, NULL, + TL_OPTION_UPDATING | TL_OPTION_ALIAS, + Lex->lock_option )) + MYSQL_YYABORT; + } + ; if_exists: /* empty */ { $$= 0; } @@ -10644,7 +10468,7 @@ keyword_sp: | TEXT_SYM {} | THAN_SYM {} | TRANSACTION_SYM {} - | TRANSACTIONAL_SYM {} + | TRANSACTIONAL_SYM {} | TRIGGERS_SYM {} | TIMESTAMP {} | TIMESTAMP_ADD {} @@ -11874,21 +11698,29 @@ subselect_end: **************************************************************************/ view_or_trigger_or_sp_or_event: - definer view_or_trigger_or_sp_or_event_tail + definer definer_tail + {} + | no_definer no_definer_tail {} - | view_replace_or_algorithm definer view_tail + | view_replace_or_algorithm definer_opt view_tail {} ; -view_or_trigger_or_sp_or_event_tail: +definer_tail: view_tail - {} | trigger_tail - {} | sp_tail - {} + | sf_tail + | event_tail + ; + +no_definer_tail: + view_tail + | trigger_tail + | sp_tail + | sf_tail + | udf_tail | event_tail - {} ; /************************************************************************** @@ -11897,7 +11729,12 @@ view_or_trigger_or_sp_or_event_tail: **************************************************************************/ -definer: +definer_opt: + no_definer + | definer + ; + +no_definer: /* empty */ { /* @@ -11909,7 +11746,10 @@ definer: */ YYTHD->lex->definer= 0; } - | DEFINER_SYM EQ user + ; + +definer: + DEFINER_SYM EQ user { YYTHD->lex->definer= get_current_user(YYTHD, $3); } @@ -12146,17 +11986,193 @@ trigger_tail: **************************************************************************/ -sp_tail: - udf_func_type remember_name FUNCTION_SYM sp_name +udf_tail: + AGGREGATE_SYM remember_name FUNCTION_SYM ident + RETURNS_SYM udf_type SONAME_SYM TEXT_STRING_sys { - LEX *lex=Lex; - lex->udf.type= $1; + THD *thd= YYTHD; + LEX *lex= thd->lex; + if (is_native_function(thd, & $4)) + { + my_error(ER_NATIVE_FCT_NAME_COLLISION, MYF(0), + $4.str); + MYSQL_YYABORT; + } + lex->sql_command = SQLCOM_CREATE_FUNCTION; + lex->udf.type= UDFTYPE_AGGREGATE; lex->stmt_definition_begin= $2; - lex->spname= $4; + lex->udf.name = $4; + lex->udf.returns=(Item_result) $6; + lex->udf.dl=$8.str; } - create_function_tail - {} - | PROCEDURE remember_name sp_name + | remember_name FUNCTION_SYM ident + RETURNS_SYM udf_type SONAME_SYM TEXT_STRING_sys + { + THD *thd= YYTHD; + LEX *lex= thd->lex; + if (is_native_function(thd, & $3)) + { + my_error(ER_NATIVE_FCT_NAME_COLLISION, MYF(0), + $3.str); + MYSQL_YYABORT; + } + lex->sql_command = SQLCOM_CREATE_FUNCTION; + lex->udf.type= UDFTYPE_FUNCTION; + lex->stmt_definition_begin= $1; + lex->udf.name = $3; + lex->udf.returns=(Item_result) $5; + lex->udf.dl=$7.str; + } + ; + +sf_tail: + remember_name /* $1 */ + FUNCTION_SYM /* $2 */ + sp_name /* $3 */ + '(' /* $4 */ + { /* $5 */ + THD *thd= YYTHD; + LEX *lex= thd->lex; + Lex_input_stream *lip= thd->m_lip; + sp_head *sp; + const char* tmp_param_begin; + + lex->stmt_definition_begin= $1; + lex->spname= $3; + + if (lex->sphead) + { + my_error(ER_SP_NO_RECURSIVE_CREATE, MYF(0), "FUNCTION"); + MYSQL_YYABORT; + } + /* Order is important here: new - reset - init */ + sp= new sp_head(); + sp->reset_thd_mem_root(thd); + sp->init(lex); + sp->init_sp_name(thd, lex->spname); + + sp->m_type= TYPE_ENUM_FUNCTION; + lex->sphead= sp; + /* + We have to turn off CLIENT_MULTI_QUERIES while parsing a + stored procedure, otherwise yylex will chop it into pieces + at each ';'. + */ + $<ulong_num>$= thd->client_capabilities & CLIENT_MULTI_QUERIES; + thd->client_capabilities &= ~CLIENT_MULTI_QUERIES; + + tmp_param_begin= lip->get_cpp_tok_start(); + tmp_param_begin++; + lex->sphead->m_param_begin= tmp_param_begin; + } + sp_fdparam_list /* $6 */ + ')' /* $7 */ + { /* $8 */ + THD *thd= YYTHD; + LEX *lex= thd->lex; + Lex_input_stream *lip= thd->m_lip; + + lex->sphead->m_param_end= lip->get_cpp_tok_start(); + } + RETURNS_SYM /* $9 */ + { /* $10 */ + LEX *lex= Lex; + lex->charset= NULL; + lex->length= lex->dec= NULL; + lex->interval_list.empty(); + lex->type= 0; + } + type /* $11 */ + { /* $12 */ + LEX *lex= Lex; + sp_head *sp= lex->sphead; + /* + This was disabled in 5.1.12. See bug #20701 + When collation support in SP is implemented, then this test + should be removed. + */ + if (($11 == MYSQL_TYPE_STRING || $11 == MYSQL_TYPE_VARCHAR) + && (lex->type & BINCMP_FLAG)) + { + my_error(ER_NOT_SUPPORTED_YET, MYF(0), "return value collation"); + MYSQL_YYABORT; + } + + if (sp->fill_field_definition(YYTHD, lex, + (enum enum_field_types) $11, + &sp->m_return_field_def)) + MYSQL_YYABORT; + + bzero((char *)&lex->sp_chistics, sizeof(st_sp_chistics)); + } + sp_c_chistics /* $13 */ + { /* $14 */ + THD *thd= YYTHD; + LEX *lex= thd->lex; + Lex_input_stream *lip= thd->m_lip; + + lex->sphead->m_chistics= &lex->sp_chistics; + lex->sphead->set_body_start(thd, lip->get_cpp_tok_start()); + } + sp_proc_stmt /* $15 */ + { + THD *thd= YYTHD; + LEX *lex= thd->lex; + sp_head *sp= lex->sphead; + + if (sp->is_not_allowed_in_function("function")) + MYSQL_YYABORT; + + lex->sql_command= SQLCOM_CREATE_SPFUNCTION; + sp->set_stmt_end(thd); + if (!(sp->m_flags & sp_head::HAS_RETURN)) + { + my_error(ER_SP_NORETURN, MYF(0), sp->m_qname.str); + MYSQL_YYABORT; + } + if (is_native_function(thd, & sp->m_name)) + { + /* + This warning will be printed when + [1] A client query is parsed, + [2] A stored function is loaded by db_load_routine. + Printing the warning for [2] is intentional, to cover the + following scenario: + - A user define a SF 'foo' using MySQL 5.N + - An application uses select foo(), and works. + - MySQL 5.{N+1} defines a new native function 'foo', as + part of a new feature. + - MySQL 5.{N+1} documentation is updated, and should mention + that there is a potential incompatible change in case of + existing stored function named 'foo'. + - The user deploys 5.{N+1}. At this point, 'select foo()' + means something different, and the user code is most likely + broken (it's only safe if the code is 'select db.foo()'). + With a warning printed when the SF is loaded (which has to occur + before the call), the warning will provide a hint explaining + the root cause of a later failure of 'select foo()'. + With no warning printed, the user code will fail with no + apparent reason. + Printing a warning each time db_load_routine is executed for + an ambiguous function is annoying, since that can happen a lot, + but in practice should not happen unless there *are* name + collisions. + If a collision exists, it should not be silenced but fixed. + */ + push_warning_printf(thd, + MYSQL_ERROR::WARN_LEVEL_NOTE, + ER_NATIVE_FCT_NAME_COLLISION, + ER(ER_NATIVE_FCT_NAME_COLLISION), + sp->m_name.str); + } + /* Restore flag if it was cleared above */ + thd->client_capabilities |= $<ulong_num>5; + sp->restore_thd_mem_root(thd); + } + ; + +sp_tail: + PROCEDURE remember_name sp_name { LEX *lex= Lex; sp_head *sp; diff --git a/sql/table.cc b/sql/table.cc index c1d8e3abe94..ccddbf8134b 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -969,6 +969,7 @@ static int open_binary_frm(THD *thd, TABLE_SHARE *share, uchar *head, } parser_name.str= (char*) next_chunk; parser_name.length= strlen((char*) next_chunk); + next_chunk+= parser_name.length + 1; keyinfo->parser= my_plugin_lock_by_name(NULL, &parser_name, MYSQL_FTPARSER_PLUGIN); if (! keyinfo->parser) diff --git a/storage/csv/ha_tina.cc b/storage/csv/ha_tina.cc index 9a7781e017d..6a87b8ecc72 100644 --- a/storage/csv/ha_tina.cc +++ b/storage/csv/ha_tina.cc @@ -471,22 +471,30 @@ int ha_tina::encode_quote(uchar *buf) { const char *ptr; const char *end_ptr; + const bool was_null= (*field)->is_null(); /* - CSV does not support nulls. Write quoted 0 to the buffer. In fact, - (*field)->val_str(&attribute,&attribute) would usually return 0 - in this case but we write it explicitly here. - Basically this is a safety check, as no one ensures that the - field content is cleaned up every time we use Field::set_null() - in the code. + CSV does not support nulls. ::create() prevents creation of a table + with nullable columns so if we encounter them here, there is a bug. + This may only occur if the frm was created by an older version of + mysqld which permitted table creation with nullable columns. */ - if ((*field)->is_null()) + DBUG_ASSERT(!(*field)->maybe_null()); + + /* + assistance for backwards compatibility in production builds. + note: this will not work for ENUM columns. + */ + if (was_null) { - buffer.append(STRING_WITH_LEN("\"0\",")); - continue; + (*field)->set_default(); + (*field)->set_notnull(); } (*field)->val_str(&attribute,&attribute); + + if (was_null) + (*field)->set_null(); if ((*field)->str_needs_quotes()) { @@ -1480,6 +1488,16 @@ int ha_tina::create(const char *name, TABLE *table_arg, File create_file; DBUG_ENTER("ha_tina::create"); + /* + check columns + */ + for (Field **field= table_arg->s->field; *field; field++) + { + if ((*field)->real_maybe_null()) + DBUG_RETURN(-1); + } + + if ((create_file= my_create(fn_format(name_buff, name, "", CSM_EXT, MY_REPLACE_EXT|MY_UNPACK_FILENAME), 0, O_RDWR | O_TRUNC,MYF(MY_WME))) < 0) diff --git a/storage/heap/hp_delete.c b/storage/heap/hp_delete.c index 1dd79a42e0b..9e9e28da335 100644 --- a/storage/heap/hp_delete.c +++ b/storage/heap/hp_delete.c @@ -72,10 +72,7 @@ int hp_rb_delete_key(HP_INFO *info, register HP_KEYDEF *keyinfo, int res; if (flag) - { info->last_pos= NULL; /* For heap_rnext/heap_rprev */ - info->lastkey_len= 0; - } custom_arg.keyseg= keyinfo->seg; custom_arg.key_length= hp_rb_make_key(keyinfo, info->recbuf, record, recpos); diff --git a/storage/heap/hp_rfirst.c b/storage/heap/hp_rfirst.c index 48c1e625bd8..d0d2ec9b506 100644 --- a/storage/heap/hp_rfirst.c +++ b/storage/heap/hp_rfirst.c @@ -35,6 +35,17 @@ int heap_rfirst(HP_INFO *info, uchar *record, int inx) sizeof(uchar*)); info->current_ptr = pos; memcpy(record, pos, (size_t)share->reclength); + /* + If we're performing index_first on a table that was taken from + table cache, info->lastkey_len is initialized to previous query. + Thus we set info->lastkey_len to proper value for subsequent + heap_rnext() calls. + This is needed for DELETE queries only, otherwise this variable is + not used. + Note that the same workaround may be needed for heap_rlast(), but + for now heap_rlast() is never used for DELETE queries. + */ + info->lastkey_len= 0; info->update = HA_STATE_AKTIV; } else diff --git a/storage/heap/hp_rnext.c b/storage/heap/hp_rnext.c index 262754e9e64..3d715f4e6d3 100644 --- a/storage/heap/hp_rnext.c +++ b/storage/heap/hp_rnext.c @@ -33,11 +33,40 @@ int heap_rnext(HP_INFO *info, uchar *record) heap_rb_param custom_arg; if (info->last_pos) + { + /* + We enter this branch for non-DELETE queries after heap_rkey() + or heap_rfirst(). As last key position (info->last_pos) is available, + we only need to climb the tree using tree_search_next(). + */ pos = tree_search_next(&keyinfo->rb_tree, &info->last_pos, offsetof(TREE_ELEMENT, left), offsetof(TREE_ELEMENT, right)); + } + else if (!info->lastkey_len) + { + /* + We enter this branch only for DELETE queries after heap_rfirst(). E.g. + DELETE FROM t1 WHERE a<10. As last key position is not available + (last key is removed by heap_delete()), we must restart search as it + is done in heap_rfirst(). + + It should be safe to handle this situation without this branch. That is + branch below should find smallest element in a tree as lastkey_len is + zero. tree_search_edge() is a kind of optimisation here as it should be + faster than tree_search_key(). + */ + pos= tree_search_edge(&keyinfo->rb_tree, info->parents, + &info->last_pos, offsetof(TREE_ELEMENT, left)); + } else { + /* + We enter this branch only for DELETE queries after heap_rkey(). E.g. + DELETE FROM t1 WHERE a=10. As last key position is not available + (last key is removed by heap_delete()), we must restart search as it + is done in heap_rkey(). + */ custom_arg.keyseg = keyinfo->seg; custom_arg.key_length = info->lastkey_len; custom_arg.search_flag = SEARCH_SAME | SEARCH_FIND; diff --git a/tests/mysql_client_test.c b/tests/mysql_client_test.c index 93dfbee89fc..37927dbbd63 100644 --- a/tests/mysql_client_test.c +++ b/tests/mysql_client_test.c @@ -119,6 +119,8 @@ static void client_disconnect(void); #define DIE_UNLESS(expr) \ ((void) ((expr) ? 0 : (die(__FILE__, __LINE__, #expr), 0))) +#define DIE_IF(expr) \ + ((void) ((expr) ? (die(__FILE__, __LINE__, #expr), 0) : 0)) #define DIE(expr) \ die(__FILE__, __LINE__, #expr) @@ -177,8 +179,8 @@ if (stmt == 0) \ DIE_UNLESS(stmt == 0);\ } -#define mytest(x) if (!x) {myerror(NULL);DIE_UNLESS(FALSE);} -#define mytest_r(x) if (x) {myerror(NULL);DIE_UNLESS(FALSE);} +#define mytest(x) if (!(x)) {myerror(NULL);DIE_UNLESS(FALSE);} +#define mytest_r(x) if ((x)) {myerror(NULL);DIE_UNLESS(FALSE);} /* A workaround for Sun Forte 5.6 on Solaris x86 */ @@ -13534,7 +13536,7 @@ static void test_bug9478() { char buff[8]; - /* Fill in the fethc packet */ + /* Fill in the fetch packet */ int4store(buff, stmt->stmt_id); buff[4]= 1; /* prefetch rows */ rc= ((*mysql->methods->advanced_command)(mysql, COM_STMT_FETCH, @@ -16214,6 +16216,204 @@ static void test_bug28934() myquery(mysql_query(mysql, "drop table t1")); } +/* + Test mysql_change_user() C API and COM_CHANGE_USER +*/ + +static void test_change_user() +{ + char buff[256]; + const char *user_pw= "mysqltest_pw"; + const char *user_no_pw= "mysqltest_no_pw"; + const char *pw= "password"; + const char *db= "mysqltest_user_test_database"; + int rc; + + DBUG_ENTER("test_change_user"); + myheader("test_change_user"); + + /* Prepare environment */ + sprintf(buff, "drop database if exists %s", db); + rc= mysql_query(mysql, buff); + myquery(rc); + + sprintf(buff, "create database %s", db); + rc= mysql_query(mysql, buff); + myquery(rc); + + sprintf(buff, + "grant select on %s.* to %s@'%%' identified by '%s'", + db, + user_pw, + pw); + rc= mysql_query(mysql, buff); + myquery(rc); + + sprintf(buff, + "grant select on %s.* to %s@'%%'", + db, + user_no_pw); + rc= mysql_query(mysql, buff); + myquery(rc); + + + /* Try some combinations */ + rc= mysql_change_user(mysql, NULL, NULL, NULL); + DIE_UNLESS(rc); + if (! opt_silent) + printf("Got error (as expected): %s\n", mysql_error(mysql)); + + + rc= mysql_change_user(mysql, "", NULL, NULL); + DIE_UNLESS(rc); + if (! opt_silent) + printf("Got error (as expected): %s\n", mysql_error(mysql)); + + rc= mysql_change_user(mysql, "", "", NULL); + DIE_UNLESS(rc); + if (! opt_silent) + printf("Got error (as expected): %s\n", mysql_error(mysql)); + + rc= mysql_change_user(mysql, "", "", ""); + DIE_UNLESS(rc); + if (! opt_silent) + printf("Got error (as expected): %s\n", mysql_error(mysql)); + + rc= mysql_change_user(mysql, NULL, "", ""); + DIE_UNLESS(rc); + if (! opt_silent) + printf("Got error (as expected): %s\n", mysql_error(mysql)); + + + rc= mysql_change_user(mysql, NULL, NULL, ""); + DIE_UNLESS(rc); + if (! opt_silent) + printf("Got error (as expected): %s\n", mysql_error(mysql)); + + rc= mysql_change_user(mysql, "", NULL, ""); + DIE_UNLESS(rc); + if (! opt_silent) + printf("Got error (as expected): %s\n", mysql_error(mysql)); + + rc= mysql_change_user(mysql, user_pw, NULL, ""); + DIE_UNLESS(rc); + if (! opt_silent) + printf("Got error (as expected): %s\n", mysql_error(mysql)); + + rc= mysql_change_user(mysql, user_pw, "", ""); + DIE_UNLESS(rc); + if (! opt_silent) + printf("Got error (as expected): %s\n", mysql_error(mysql)); + + rc= mysql_change_user(mysql, user_pw, "", NULL); + DIE_UNLESS(rc); + if (! opt_silent) + printf("Got error (as expected): %s\n", mysql_error(mysql)); + + rc= mysql_change_user(mysql, user_pw, NULL, NULL); + DIE_UNLESS(rc); + if (! opt_silent) + printf("Got error (as expected): %s\n", mysql_error(mysql)); + + rc= mysql_change_user(mysql, user_pw, "", db); + DIE_UNLESS(rc); + if (! opt_silent) + printf("Got error (as expected): %s\n", mysql_error(mysql)); + + rc= mysql_change_user(mysql, user_pw, NULL, db); + DIE_UNLESS(rc); + if (! opt_silent) + printf("Got error (as expected): %s\n", mysql_error(mysql)); + + rc= mysql_change_user(mysql, user_pw, pw, db); + myquery(rc); + + rc= mysql_change_user(mysql, user_pw, pw, NULL); + myquery(rc); + + rc= mysql_change_user(mysql, user_pw, pw, ""); + myquery(rc); + + rc= mysql_change_user(mysql, user_no_pw, pw, db); + DIE_UNLESS(rc); + if (! opt_silent) + printf("Got error (as expected): %s\n", mysql_error(mysql)); + + rc= mysql_change_user(mysql, user_no_pw, pw, ""); + DIE_UNLESS(rc); + if (! opt_silent) + printf("Got error (as expected): %s\n", mysql_error(mysql)); + + rc= mysql_change_user(mysql, user_no_pw, pw, NULL); + DIE_UNLESS(rc); + if (! opt_silent) + printf("Got error (as expected): %s\n", mysql_error(mysql)); + + rc= mysql_change_user(mysql, user_no_pw, "", NULL); + myquery(rc); + + rc= mysql_change_user(mysql, user_no_pw, "", ""); + myquery(rc); + + rc= mysql_change_user(mysql, user_no_pw, "", db); + myquery(rc); + + rc= mysql_change_user(mysql, user_no_pw, NULL, db); + myquery(rc); + + rc= mysql_change_user(mysql, "", pw, db); + DIE_UNLESS(rc); + if (! opt_silent) + printf("Got error (as expected): %s\n", mysql_error(mysql)); + + rc= mysql_change_user(mysql, "", pw, ""); + DIE_UNLESS(rc); + if (! opt_silent) + printf("Got error (as expected): %s\n", mysql_error(mysql)); + + rc= mysql_change_user(mysql, "", pw, NULL); + DIE_UNLESS(rc); + if (! opt_silent) + printf("Got error (as expected): %s\n", mysql_error(mysql)); + + rc= mysql_change_user(mysql, NULL, pw, NULL); + DIE_UNLESS(rc); + if (! opt_silent) + printf("Got error (as expected): %s\n", mysql_error(mysql)); + + rc= mysql_change_user(mysql, NULL, NULL, db); + DIE_UNLESS(rc); + if (! opt_silent) + printf("Got error (as expected): %s\n", mysql_error(mysql)); + + rc= mysql_change_user(mysql, NULL, "", db); + DIE_UNLESS(rc); + if (! opt_silent) + printf("Got error (as expected): %s\n", mysql_error(mysql)); + + rc= mysql_change_user(mysql, "", "", db); + DIE_UNLESS(rc); + if (! opt_silent) + printf("Got error (as expected): %s\n", mysql_error(mysql)); + + /* Cleanup the environment */ + + mysql_change_user(mysql, opt_user, opt_password, current_db); + + sprintf(buff, "drop database %s", db); + rc= mysql_query(mysql, buff); + myquery(rc); + + sprintf(buff, "drop user %s@'%%'", user_pw); + rc= mysql_query(mysql, buff); + myquery(rc); + + sprintf(buff, "drop user %s@'%%'", user_no_pw); + rc= mysql_query(mysql, buff); + myquery(rc); + + DBUG_VOID_RETURN; +} /* Bug#27592 (stack overrun when storing datetime value using prepared statements) @@ -16452,6 +16652,446 @@ static void test_bug29306() DBUG_VOID_RETURN; } /* + Bug#30472: libmysql doesn't reset charset, insert_id after succ. + mysql_change_user() call row insertions. +*/ + +static void bug30472_retrieve_charset_info(MYSQL *con, + char *character_set_name, + char *character_set_client, + char *character_set_results, + char *collation_connection) +{ + MYSQL_RES *rs; + MYSQL_ROW row; + + /* Get the cached client character set name. */ + + strcpy(character_set_name, mysql_character_set_name(con)); + + /* Retrieve server character set information. */ + + DIE_IF(mysql_query(con, "SHOW VARIABLES LIKE 'character_set_client'")); + DIE_UNLESS(rs= mysql_store_result(con)); + DIE_UNLESS(row= mysql_fetch_row(rs)); + strcpy(character_set_client, row[1]); + mysql_free_result(rs); + + DIE_IF(mysql_query(con, "SHOW VARIABLES LIKE 'character_set_results'")); + DIE_UNLESS(rs= mysql_store_result(con)); + DIE_UNLESS(row= mysql_fetch_row(rs)); + strcpy(character_set_results, row[1]); + mysql_free_result(rs); + + DIE_IF(mysql_query(con, "SHOW VARIABLES LIKE 'collation_connection'")); + DIE_UNLESS(rs= mysql_store_result(con)); + DIE_UNLESS(row= mysql_fetch_row(rs)); + strcpy(collation_connection, row[1]); + mysql_free_result(rs); +} + +static void test_bug30472() +{ + MYSQL con; + + char character_set_name_1[MY_CS_NAME_SIZE]; + char character_set_client_1[MY_CS_NAME_SIZE]; + char character_set_results_1[MY_CS_NAME_SIZE]; + char collation_connnection_1[MY_CS_NAME_SIZE]; + + char character_set_name_2[MY_CS_NAME_SIZE]; + char character_set_client_2[MY_CS_NAME_SIZE]; + char character_set_results_2[MY_CS_NAME_SIZE]; + char collation_connnection_2[MY_CS_NAME_SIZE]; + + char character_set_name_3[MY_CS_NAME_SIZE]; + char character_set_client_3[MY_CS_NAME_SIZE]; + char character_set_results_3[MY_CS_NAME_SIZE]; + char collation_connnection_3[MY_CS_NAME_SIZE]; + + char character_set_name_4[MY_CS_NAME_SIZE]; + char character_set_client_4[MY_CS_NAME_SIZE]; + char character_set_results_4[MY_CS_NAME_SIZE]; + char collation_connnection_4[MY_CS_NAME_SIZE]; + + /* Create a new connection. */ + + DIE_UNLESS(mysql_init(&con)); + + DIE_UNLESS(mysql_real_connect(&con, + opt_host, + opt_user, + opt_password, + opt_db ? opt_db : "test", + opt_port, + opt_unix_socket, + CLIENT_FOUND_ROWS)); + + /* Retrieve character set information. */ + + bug30472_retrieve_charset_info(&con, + character_set_name_1, + character_set_client_1, + character_set_results_1, + collation_connnection_1); + + /* Switch client character set. */ + + DIE_IF(mysql_set_character_set(&con, "utf8")); + + /* Retrieve character set information. */ + + bug30472_retrieve_charset_info(&con, + character_set_name_2, + character_set_client_2, + character_set_results_2, + collation_connnection_2); + + /* + Check that + 1) character set has been switched and + 2) new character set is different from the original one. + */ + + DIE_UNLESS(strcmp(character_set_name_2, "utf8") == 0); + DIE_UNLESS(strcmp(character_set_client_2, "utf8") == 0); + DIE_UNLESS(strcmp(character_set_results_2, "utf8") == 0); + DIE_UNLESS(strcmp(collation_connnection_2, "utf8_general_ci") == 0); + + DIE_UNLESS(strcmp(character_set_name_1, character_set_name_2) != 0); + DIE_UNLESS(strcmp(character_set_client_1, character_set_client_2) != 0); + DIE_UNLESS(strcmp(character_set_results_1, character_set_results_2) != 0); + DIE_UNLESS(strcmp(collation_connnection_1, collation_connnection_2) != 0); + + /* Call mysql_change_user() with the same username, password, database. */ + + DIE_IF(mysql_change_user(&con, + opt_user, + opt_password, + opt_db ? opt_db : "test")); + + /* Retrieve character set information. */ + + bug30472_retrieve_charset_info(&con, + character_set_name_3, + character_set_client_3, + character_set_results_3, + collation_connnection_3); + + /* Check that character set information has been reset. */ + + DIE_UNLESS(strcmp(character_set_name_1, character_set_name_3) == 0); + DIE_UNLESS(strcmp(character_set_client_1, character_set_client_3) == 0); + DIE_UNLESS(strcmp(character_set_results_1, character_set_results_3) == 0); + DIE_UNLESS(strcmp(collation_connnection_1, collation_connnection_3) == 0); + + /* Change connection-default character set in the client. */ + + con.options.charset_name= my_strdup("utf8", MYF(MY_FAE)); + + /* + Call mysql_change_user() in order to check that new connection will + have UTF8 character set on the client and on the server. + */ + + DIE_IF(mysql_change_user(&con, + opt_user, + opt_password, + opt_db ? opt_db : "test")); + + /* Retrieve character set information. */ + + bug30472_retrieve_charset_info(&con, + character_set_name_4, + character_set_client_4, + character_set_results_4, + collation_connnection_4); + + /* Check that we have UTF8 on the server and on the client. */ + + DIE_UNLESS(strcmp(character_set_name_4, "utf8") == 0); + DIE_UNLESS(strcmp(character_set_client_4, "utf8") == 0); + DIE_UNLESS(strcmp(character_set_results_4, "utf8") == 0); + DIE_UNLESS(strcmp(collation_connnection_4, "utf8_general_ci") == 0); + + /* That's it. Cleanup. */ + + mysql_close(&con); +} + +static void bug20023_change_user(MYSQL *con) +{ + DIE_IF(mysql_change_user(con, + opt_user, + opt_password, + opt_db ? opt_db : "test")); +} + +static bool query_int_variable(MYSQL *con, + const char *var_name, + int *var_value) +{ + MYSQL_RES *rs; + MYSQL_ROW row; + + char query_buffer[MAX_TEST_QUERY_LENGTH]; + + bool is_null; + + my_snprintf(query_buffer, + sizeof (query_buffer), + "SELECT %s", + (const char *) var_name); + + DIE_IF(mysql_query(con, query_buffer)); + DIE_UNLESS(rs= mysql_store_result(con)); + DIE_UNLESS(row= mysql_fetch_row(rs)); + + is_null= row[0] == NULL; + + if (!is_null) + *var_value= atoi(row[0]); + + mysql_free_result(rs); + + return is_null; +} + +static void test_bug20023() +{ + MYSQL con; + + int sql_big_selects_orig; + int max_join_size_orig; + + int sql_big_selects_2; + int sql_big_selects_3; + int sql_big_selects_4; + int sql_big_selects_5; + + char query_buffer[MAX_TEST_QUERY_LENGTH]; + + /* Create a new connection. */ + + DIE_UNLESS(mysql_init(&con)); + + DIE_UNLESS(mysql_real_connect(&con, + opt_host, + opt_user, + opt_password, + opt_db ? opt_db : "test", + opt_port, + opt_unix_socket, + CLIENT_FOUND_ROWS)); + + /*********************************************************************** + Remember original SQL_BIG_SELECTS, MAX_JOIN_SIZE values. + ***********************************************************************/ + + query_int_variable(&con, + "@@session.sql_big_selects", + &sql_big_selects_orig); + + query_int_variable(&con, + "@@global.max_join_size", + &max_join_size_orig); + + /*********************************************************************** + Test that COM_CHANGE_USER resets the SQL_BIG_SELECTS to the initial value. + ***********************************************************************/ + + /* Issue COM_CHANGE_USER. */ + + bug20023_change_user(&con); + + /* Query SQL_BIG_SELECTS. */ + + query_int_variable(&con, + "@@session.sql_big_selects", + &sql_big_selects_2); + + /* Check that SQL_BIG_SELECTS is reset properly. */ + + DIE_UNLESS(sql_big_selects_orig == sql_big_selects_2); + + /*********************************************************************** + Test that if MAX_JOIN_SIZE set to non-default value, + SQL_BIG_SELECTS will be 0. + ***********************************************************************/ + + /* Set MAX_JOIN_SIZE to some non-default value. */ + + DIE_IF(mysql_query(&con, "SET @@global.max_join_size = 10000")); + DIE_IF(mysql_query(&con, "SET @@session.max_join_size = default")); + + /* Issue COM_CHANGE_USER. */ + + bug20023_change_user(&con); + + /* Query SQL_BIG_SELECTS. */ + + query_int_variable(&con, + "@@session.sql_big_selects", + &sql_big_selects_3); + + /* Check that SQL_BIG_SELECTS is 0. */ + + DIE_UNLESS(sql_big_selects_3 == 0); + + /*********************************************************************** + Test that if MAX_JOIN_SIZE set to default value, + SQL_BIG_SELECTS will be 1. + ***********************************************************************/ + + /* Set MAX_JOIN_SIZE to the default value (-1). */ + + DIE_IF(mysql_query(&con, "SET @@global.max_join_size = -1")); + DIE_IF(mysql_query(&con, "SET @@session.max_join_size = default")); + + /* Issue COM_CHANGE_USER. */ + + bug20023_change_user(&con); + + /* Query SQL_BIG_SELECTS. */ + + query_int_variable(&con, + "@@session.sql_big_selects", + &sql_big_selects_4); + + /* Check that SQL_BIG_SELECTS is 1. */ + + DIE_UNLESS(sql_big_selects_4 == 1); + + /*********************************************************************** + Restore MAX_JOIN_SIZE. + Check that SQL_BIG_SELECTS will be the original one. + ***********************************************************************/ + + /* Restore MAX_JOIN_SIZE. */ + + my_snprintf(query_buffer, + sizeof (query_buffer), + "SET @@global.max_join_size = %d", + (int) max_join_size_orig); + + DIE_IF(mysql_query(&con, query_buffer)); + DIE_IF(mysql_query(&con, "SET @@session.max_join_size = default")); + + /* Issue COM_CHANGE_USER. */ + + bug20023_change_user(&con); + + /* Query SQL_BIG_SELECTS. */ + + query_int_variable(&con, + "@@session.sql_big_selects", + &sql_big_selects_5); + + /* Check that SQL_BIG_SELECTS is 1. */ + + DIE_UNLESS(sql_big_selects_5 == sql_big_selects_orig); + + /*********************************************************************** + That's it. Cleanup. + ***********************************************************************/ + + mysql_close(&con); +} + +static void bug31418_impl() +{ + MYSQL con; + + bool is_null; + int rc; + + /* Create a new connection. */ + + DIE_UNLESS(mysql_init(&con)); + + DIE_UNLESS(mysql_real_connect(&con, + opt_host, + opt_user, + opt_password, + opt_db ? opt_db : "test", + opt_port, + opt_unix_socket, + CLIENT_FOUND_ROWS)); + + /*********************************************************************** + Check that lock is free: + - IS_FREE_LOCK() should return 1; + - IS_USED_LOCK() should return NULL; + ***********************************************************************/ + + is_null= query_int_variable(&con, + "IS_FREE_LOCK('bug31418')", + &rc); + DIE_UNLESS(!is_null && rc); + + is_null= query_int_variable(&con, + "IS_USED_LOCK('bug31418')", + &rc); + DIE_UNLESS(is_null); + + /*********************************************************************** + Acquire lock and check the lock status (the lock must be in use): + - IS_FREE_LOCK() should return 0; + - IS_USED_LOCK() should return non-zero thread id; + ***********************************************************************/ + + query_int_variable(&con, "GET_LOCK('bug31418', 1)", &rc); + DIE_UNLESS(rc); + + is_null= query_int_variable(&con, + "IS_FREE_LOCK('bug31418')", + &rc); + DIE_UNLESS(!is_null && !rc); + + is_null= query_int_variable(&con, + "IS_USED_LOCK('bug31418')", + &rc); + DIE_UNLESS(!is_null && rc); + + /*********************************************************************** + Issue COM_CHANGE_USER command and check the lock status + (the lock must be free): + - IS_FREE_LOCK() should return 1; + - IS_USED_LOCK() should return NULL; + **********************************************************************/ + + bug20023_change_user(&con); + + is_null= query_int_variable(&con, + "IS_FREE_LOCK('bug31418')", + &rc); + DIE_UNLESS(!is_null && rc); + + is_null= query_int_variable(&con, + "IS_USED_LOCK('bug31418')", + &rc); + DIE_UNLESS(is_null); + + /*********************************************************************** + That's it. Cleanup. + ***********************************************************************/ + + mysql_close(&con); +} + +static void test_bug31418() +{ + /* Run test case for BUG#31418 for three different connections. */ + + bug31418_impl(); + + bug31418_impl(); + + bug31418_impl(); +} + + +/* Read and parse arguments and MySQL options from my.cnf */ @@ -16750,6 +17390,10 @@ static struct my_tests_st my_tests[]= { { "test_bug29687", test_bug29687 }, { "test_bug29692", test_bug29692 }, { "test_bug29306", test_bug29306 }, + { "test_change_user", test_change_user }, + { "test_bug30472", test_bug30472 }, + { "test_bug20023", test_bug20023 }, + { "test_bug31418", test_bug31418 }, { 0, 0 } }; |