diff options
147 files changed, 2377 insertions, 415 deletions
diff --git a/BUILD/Makefile.am b/BUILD/Makefile.am index 45c1aaa1a76..a5f3623c25e 100644 --- a/BUILD/Makefile.am +++ b/BUILD/Makefile.am @@ -21,27 +21,46 @@ EXTRA_DIST = FINISH.sh \ SETUP.sh \ autorun.sh \ check-cpu \ + cleanup \ compile-alpha \ compile-alpha-ccc \ compile-alpha-cxx \ compile-alpha-debug \ + compile-amd64-debug-max \ + compile-amd64-max \ + compile-darwin-mwcc \ + compile-dist \ + compile-hpux11-parisc2-aCC \ compile-ia64-debug-max \ + compile-irix-mips64-mipspro \ compile-pentium \ compile-pentium-debug \ compile-pentium-debug-max \ + compile-pentium-debug-max-no-embedded \ + compile-pentium-debug-max-no-ndb \ compile-pentium-debug-no-bdb \ compile-pentium-debug-openssl \ compile-pentium-debug-yassl \ compile-pentium-gcov \ compile-pentium-gprof \ + compile-pentium-icc \ + compile-pentium-icc-valgrind-max \ + compile-pentium-icc-yassl \ compile-pentium-max \ compile-pentium-myodbc \ compile-pentium-mysqlfs-debug \ compile-pentium-pgcc \ + compile-pentium-valgrind-max \ + compile-pentium64-debug \ + compile-pentium64-debug-max \ + compile-pentium64-valgrind-max \ + compile-ppc \ + compile-ppc-debug \ + compile-ppc-debug-max \ + compile-ppc-debug-max-no-ndb \ + compile-ppc-max \ compile-solaris-sparc \ compile-solaris-sparc-debug \ - compile-irix-mips64-mipspro \ - compile-hpux11-parisc2-aCC \ compile-solaris-sparc-forte \ compile-solaris-sparc-purify diff --git a/bdb/dist/gen_rec.awk b/bdb/dist/gen_rec.awk index 75f2e86ca9e..e1b75699027 100644 --- a/bdb/dist/gen_rec.awk +++ b/bdb/dist/gen_rec.awk @@ -180,7 +180,7 @@ BEGIN { t = types[i]; if (modes[i] == "POINTER") { ndx = index(t, "*"); - t = substr(types[i], 0, ndx - 2); + t = substr(types[i], 1, ndx - 2); } printf("\t%s\t%s;\n", t, vars[i]) >> HFILE } diff --git a/client/mysqltest.c b/client/mysqltest.c index ba1b92b31a3..3a4ce5ce7cf 100644 --- a/client/mysqltest.c +++ b/client/mysqltest.c @@ -2731,10 +2731,8 @@ end: static struct my_option my_long_options[] = { - {"debug", '#', "Output debug log. Often this is 'd:t:o,filename'.", - 0, 0, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0}, - {"database", 'D', "Database to use.", (gptr*) &db, (gptr*) &db, 0, - GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, + {"help", '?', "Display this help and exit.", 0, 0, 0, GET_NO_ARG, NO_ARG, + 0, 0, 0, 0, 0, 0}, {"basedir", 'b', "Basedir for tests.", (gptr*) &opt_basedir, (gptr*) &opt_basedir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"big-test", 'B', "Define BIG_TEST to 1.", (gptr*) &opt_big_test, @@ -2742,13 +2740,17 @@ static struct my_option my_long_options[] = {"compress", 'C', "Use the compressed server/client protocol.", (gptr*) &opt_compress, (gptr*) &opt_compress, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, - {"help", '?', "Display this help and exit.", 0, 0, 0, GET_NO_ARG, NO_ARG, - 0, 0, 0, 0, 0, 0}, + {"database", 'D', "Database to use.", (gptr*) &db, (gptr*) &db, 0, + GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, +#ifdef DBUG_OFF + {"debug", '#', "This is a non-debug version. Catch this and exit", + 0,0, 0, GET_DISABLED, OPT_ARG, 0, 0, 0, 0, 0, 0}, +#else + {"debug", '#', "Output debug log. Often this is 'd:t:o,filename'.", + 0, 0, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0}, +#endif {"host", 'h', "Connect to host.", (gptr*) &host, (gptr*) &host, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, - {"manager-user", OPT_MANAGER_USER, "Undocumented: Used for debugging.", - (gptr*) &manager_user, (gptr*) &manager_user, 0, GET_STR, REQUIRED_ARG, 0, - 0, 0, 0, 0, 0}, {"manager-host", OPT_MANAGER_HOST, "Undocumented: Used for debugging.", (gptr*) &manager_host, (gptr*) &manager_host, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, @@ -2757,6 +2759,9 @@ static struct my_option my_long_options[] = {"manager-port", OPT_MANAGER_PORT, "Undocumented: Used for debugging.", (gptr*) &manager_port, (gptr*) &manager_port, 0, GET_INT, REQUIRED_ARG, MYSQL_MANAGER_PORT, 0, 0, 0, 0, 0}, + {"manager-user", OPT_MANAGER_USER, "Undocumented: Used for debugging.", + (gptr*) &manager_user, (gptr*) &manager_user, 0, GET_STR, REQUIRED_ARG, 0, + 0, 0, 0, 0, 0}, {"manager-wait-timeout", OPT_MANAGER_WAIT_TIMEOUT, "Undocumented: Used for debugging.", (gptr*) &manager_wait_timeout, (gptr*) &manager_wait_timeout, 0, GET_INT, REQUIRED_ARG, 3, 0, 0, 0, 0, 0}, diff --git a/config/ac-macros/misc.m4 b/config/ac-macros/misc.m4 index 6f93f38f119..5346b81fb03 100644 --- a/config/ac-macros/misc.m4 +++ b/config/ac-macros/misc.m4 @@ -693,6 +693,27 @@ dnl --------------------------------------------------------------------------- dnl END OF MYSQL_CHECK_BIG_TABLES SECTION dnl --------------------------------------------------------------------------- + +dnl --------------------------------------------------------------------------- +dnl Macro: MYSQL_CHECK_MAX_INDEXES +dnl Sets MAX_INDEXES +dnl --------------------------------------------------------------------------- +AC_DEFUN([MYSQL_CHECK_MAX_INDEXES], [ + AC_ARG_WITH([max-indexes], + [ + --with-max-indexes=\# Sets the maximum number of indexes per table, default 64], + [max_indexes="$withval"], + [max_indexes=64]) + AC_MSG_CHECKING([max indexes per table]) + AC_DEFINE_UNQUOTED([MAX_INDEXES], [$max_indexes], + [Maximum number of indexes per table]) + AC_MSG_RESULT([$max_indexes]) +]) +dnl --------------------------------------------------------------------------- +dnl END OF MYSQL_CHECK_MAX_INDEXES SECTION +dnl --------------------------------------------------------------------------- + + dnl MYSQL_NEEDS_MYSYS_NEW AC_DEFUN([MYSQL_NEEDS_MYSYS_NEW], [AC_CACHE_CHECK([needs mysys_new helpers], mysql_use_mysys_new, diff --git a/configure.in b/configure.in index 501757e3df1..b5c31361b26 100644 --- a/configure.in +++ b/configure.in @@ -7,7 +7,7 @@ AC_INIT(sql/mysqld.cc) AC_CANONICAL_SYSTEM # The Docs Makefile.am parses this line! # remember to also change ndb version below and update version.c in ndb -AM_INIT_AUTOMAKE(mysql, 5.0.18) +AM_INIT_AUTOMAKE(mysql, 5.0.19) AM_CONFIG_HEADER(config.h) PROTOCOL_VERSION=10 @@ -18,7 +18,7 @@ SHARED_LIB_VERSION=15:0:0 # ndb version NDB_VERSION_MAJOR=5 NDB_VERSION_MINOR=0 -NDB_VERSION_BUILD=17 +NDB_VERSION_BUILD=19 NDB_VERSION_STATUS="" # Set all version vars based on $VERSION. How do we do this more elegant ? @@ -2413,6 +2413,7 @@ AC_SUBST(readline_link) AC_SUBST(readline_h_ln_cmd) MYSQL_CHECK_BIG_TABLES +MYSQL_CHECK_MAX_INDEXES MYSQL_CHECK_BDB MYSQL_CHECK_INNODB MYSQL_CHECK_EXAMPLEDB diff --git a/extra/Makefile.am b/extra/Makefile.am index a60656cb5c6..c0ad75059df 100644 --- a/extra/Makefile.am +++ b/extra/Makefile.am @@ -29,8 +29,8 @@ SUBDIRS= DIST_SUBDIRS= yassl # This will build mysqld_error.h and sql_state.h -$(top_builddir)/include/mysqld_error.h: comp_err - $(top_builddir)/extra/comp_err \ +$(top_builddir)/include/mysqld_error.h: comp_err$(EXEEXT) + $(top_builddir)/extra/comp_err$(EXEEXT) \ --charset=$(top_srcdir)/sql/share/charsets \ --out-dir=$(top_builddir)/sql/share/ \ --header_file=$(top_builddir)/include/mysqld_error.h \ diff --git a/extra/innochecksum.c b/extra/innochecksum.c index bae5f3e8821..eda5cef4647 100644 --- a/extra/innochecksum.c +++ b/extra/innochecksum.c @@ -28,7 +28,7 @@ #define _LARGEFILE_SOURCE #define _LARGEFILE64_SOURCE -#define _XOPEN_SOURCE /* needed to include getopt.h on some platforms. */ +#define _XOPEN_SOURCE 500 /* needed to include getopt.h on some platforms. */ #include <stdio.h> #include <stdlib.h> diff --git a/extra/yassl/src/handshake.cpp b/extra/yassl/src/handshake.cpp index 45dfb6fa032..d7df438b8df 100644 --- a/extra/yassl/src/handshake.cpp +++ b/extra/yassl/src/handshake.cpp @@ -656,7 +656,11 @@ DoProcessReply(SSL& ssl, mySTL::auto_ptr<input_buffer> buffered) { ssl.getSocket().wait(); // wait for input if blocking uint ready = ssl.getSocket().get_ready(); - if (!ready) return buffered; + if (!ready) { + // Nothing to receive after blocking wait => error + ssl.SetError(receive_error); + return buffered= null_buffer; + } // add buffered data if its there uint buffSz = buffered.get() ? buffered.get()->get_size() : 0; diff --git a/include/config-win.h b/include/config-win.h index edfb4ecc5c7..528bc8a8cdd 100644 --- a/include/config-win.h +++ b/include/config-win.h @@ -325,6 +325,11 @@ inline double ulonglong2double(ulonglong value) #define HAVE_SETFILEPOINTER #define HAVE_VIO_READ_BUFF +#ifndef __NT__ +#undef FILE_SHARE_DELETE +#define FILE_SHARE_DELETE 0 /* Not implemented on Win 98/ME */ +#endif + #ifdef NOT_USED #define HAVE_SNPRINTF /* Gave link error */ #define _snprintf snprintf diff --git a/include/my_pthread.h b/include/my_pthread.h index 6f60a6df2c1..202e047dc4e 100644 --- a/include/my_pthread.h +++ b/include/my_pthread.h @@ -643,10 +643,10 @@ extern int pthread_dummy(int); #define THREAD_NAME_SIZE 10 #ifndef DEFAULT_THREAD_STACK -#if defined(__ia64__) +#if SIZEOF_CHARP > 4 /* MySQL can survive with 32K, but some glibc libraries require > 128K stack - To resolve hostnames + To resolve hostnames. Also recursive stored procedures needs stack. */ #define DEFAULT_THREAD_STACK (256*1024L) #else diff --git a/include/myisam.h b/include/myisam.h index 56717524bb2..96c1e7e192e 100644 --- a/include/myisam.h +++ b/include/myisam.h @@ -33,8 +33,6 @@ extern "C" { #endif #include "my_handler.h" - /* defines used by myisam-funktions */ - /* There is a hard limit for the maximum number of keys as there are only 8 bits in the index file header for the number of keys in a table. @@ -45,14 +43,19 @@ extern "C" { running myisamchk compiled for 128 keys on a table with 255 keys. */ #define MI_MAX_POSSIBLE_KEY 255 /* For myisam_chk */ +#if MAX_INDEXES > MI_MAX_POSSIBLE_KEY +#define MI_MAX_KEY MI_MAX_POSSIBLE_KEY /* Max allowed keys */ +#else +#define MI_MAX_KEY MAX_INDEXES /* Max allowed keys */ +#endif + #define MI_MAX_POSSIBLE_KEY_BUFF (1024+6+6) /* For myisam_chk */ /* The following defines can be increased if necessary. - BUT: MI_MAX_KEY must be <= MI_MAX_POSSIBLE_KEY. + But beware the dependency of MI_MAX_POSSIBLE_KEY_BUFF and MI_MAX_KEY_LENGTH. */ -#define MI_MAX_KEY 64 /* Max allowed keys */ +#define MI_MAX_KEY_LENGTH 1000 /* Max length in bytes */ #define MI_MAX_KEY_SEG 16 /* Max segments for key */ -#define MI_MAX_KEY_LENGTH 1000 #define MI_MAX_KEY_BUFF (MI_MAX_KEY_LENGTH+MI_MAX_KEY_SEG*6+8+8) #define MI_MAX_MSG_BUF 1024 /* used in CHECK TABLE, REPAIR TABLE */ diff --git a/innobase/btr/btr0sea.c b/innobase/btr/btr0sea.c index 9b1e93fe700..81f23cfa99c 100644 --- a/innobase/btr/btr0sea.c +++ b/innobase/btr/btr0sea.c @@ -889,7 +889,8 @@ Drops a page hash index. */ void btr_search_drop_page_hash_index( /*============================*/ - page_t* page) /* in: index page, s- or x-latched */ + page_t* page) /* in: index page, s- or x-latched, or an index page + for which we know that block->buf_fix_count == 0 */ { hash_table_t* table; buf_block_t* block; diff --git a/innobase/include/buf0buf.h b/innobase/include/buf0buf.h index 24e7a71c02d..fc1d9a64c7f 100644 --- a/innobase/include/buf0buf.h +++ b/innobase/include/buf0buf.h @@ -831,7 +831,13 @@ struct buf_block_struct{ records with the same prefix should be indexed in the hash index */ - /* The following 6 fields are protected by btr_search_latch: */ + /* These 6 fields may only be modified when we have + an x-latch on btr_search_latch AND + a) we are holding an s-latch or x-latch on block->lock or + b) we know that block->buf_fix_count == 0. + + An exception to this is when we init or create a page + in the buffer pool in buf0buf.c. */ ibool is_hashed; /* TRUE if hash index has already been built on this page; note that it does @@ -849,11 +855,7 @@ struct buf_block_struct{ BTR_SEARCH_RIGHT_SIDE in hash indexing */ dict_index_t* index; /* Index for which the adaptive - hash index has been created. - This field may only be modified - while holding an s-latch or x-latch - on block->lock and an x-latch on - btr_search_latch. */ + hash index has been created. */ /* 6. Debug fields */ #ifdef UNIV_SYNC_DEBUG rw_lock_t debug_latch; /* in the debug version, each thread diff --git a/innobase/include/os0file.h b/innobase/include/os0file.h index 224fd59a76b..02a38dd49ef 100644 --- a/innobase/include/os0file.h +++ b/innobase/include/os0file.h @@ -187,7 +187,7 @@ Creates a temporary file. */ FILE* os_file_create_tmpfile(void); /*========================*/ - /* out: temporary file handle (never NULL) */ + /* out: temporary file handle, or NULL on error */ /*************************************************************************** The os_file_opendir() function opens a directory stream corresponding to the directory named by the dirname argument. The directory stream is positioned diff --git a/innobase/include/srv0srv.h b/innobase/include/srv0srv.h index 11347f430d4..99ea4f2de27 100644 --- a/innobase/include/srv0srv.h +++ b/innobase/include/srv0srv.h @@ -34,6 +34,18 @@ extern ibool srv_lower_case_table_names; extern mutex_t srv_monitor_file_mutex; /* Temporary file for innodb monitor output */ extern FILE* srv_monitor_file; +/* Mutex for locking srv_dict_tmpfile. +This mutex has a very high rank; threads reserving it should not +be holding any InnoDB latches. */ +extern mutex_t srv_dict_tmpfile_mutex; +/* Temporary file for output from the data dictionary */ +extern FILE* srv_dict_tmpfile; +/* Mutex for locking srv_misc_tmpfile. +This mutex has a very low rank; threads reserving it should not +acquire any further latches or sleep before releasing this one. */ +extern mutex_t srv_misc_tmpfile_mutex; +/* Temporary file for miscellanous diagnostic output */ +extern FILE* srv_misc_tmpfile; /* Server parameters which are read from the initfile */ diff --git a/innobase/row/row0ins.c b/innobase/row/row0ins.c index 5e833372299..32aa0385596 100644 --- a/innobase/row/row0ins.c +++ b/innobase/row/row0ins.c @@ -588,20 +588,21 @@ row_ins_set_detailed( trx_t* trx, /* in: transaction */ dict_foreign_t* foreign) /* in: foreign key constraint */ { - - FILE* tf = os_file_create_tmpfile(); - - if (tf) { - ut_print_name(tf, trx, foreign->foreign_table_name); - dict_print_info_on_foreign_key_in_create_format(tf, trx, - foreign, FALSE); - - trx_set_detailed_error_from_file(trx, tf); - - fclose(tf); + mutex_enter(&srv_misc_tmpfile_mutex); + rewind(srv_misc_tmpfile); + + if (os_file_set_eof(srv_misc_tmpfile)) { + ut_print_name(srv_misc_tmpfile, trx, + foreign->foreign_table_name); + dict_print_info_on_foreign_key_in_create_format( + srv_misc_tmpfile, + trx, foreign, FALSE); + trx_set_detailed_error_from_file(trx, srv_misc_tmpfile); } else { - trx_set_detailed_error(trx, "temp file creation failed"); + trx_set_detailed_error(trx, "temp file operation failed"); } + + mutex_exit(&srv_misc_tmpfile_mutex); } /************************************************************************* @@ -709,7 +710,7 @@ row_ins_foreign_report_add_err( } if (rec) { - rec_print(ef, rec, foreign->foreign_index); + rec_print(ef, rec, foreign->referenced_index); } putc('\n', ef); diff --git a/innobase/srv/srv0srv.c b/innobase/srv/srv0srv.c index c585536baee..6e0b9b23266 100644 --- a/innobase/srv/srv0srv.c +++ b/innobase/srv/srv0srv.c @@ -397,6 +397,18 @@ mutex_t srv_innodb_monitor_mutex; mutex_t srv_monitor_file_mutex; /* Temporary file for innodb monitor output */ FILE* srv_monitor_file; +/* Mutex for locking srv_dict_tmpfile. +This mutex has a very high rank; threads reserving it should not +be holding any InnoDB latches. */ +mutex_t srv_dict_tmpfile_mutex; +/* Temporary file for output from the data dictionary */ +FILE* srv_dict_tmpfile; +/* Mutex for locking srv_misc_tmpfile. +This mutex has a very low rank; threads reserving it should not +acquire any further latches or sleep before releasing this one. */ +mutex_t srv_misc_tmpfile_mutex; +/* Temporary file for miscellanous diagnostic output */ +FILE* srv_misc_tmpfile; ulint srv_main_thread_process_no = 0; ulint srv_main_thread_id = 0; diff --git a/innobase/srv/srv0start.c b/innobase/srv/srv0start.c index e5151ebf631..4f99f340e1c 100644 --- a/innobase/srv/srv0start.c +++ b/innobase/srv/srv0start.c @@ -1180,6 +1180,20 @@ NetWare. */ } } + mutex_create(&srv_dict_tmpfile_mutex); + mutex_set_level(&srv_dict_tmpfile_mutex, SYNC_DICT_OPERATION); + srv_dict_tmpfile = os_file_create_tmpfile(); + if (!srv_dict_tmpfile) { + return(DB_ERROR); + } + + mutex_create(&srv_misc_tmpfile_mutex); + mutex_set_level(&srv_misc_tmpfile_mutex, SYNC_ANY_LATCH); + srv_misc_tmpfile = os_file_create_tmpfile(); + if (!srv_misc_tmpfile) { + return(DB_ERROR); + } + /* Restrict the maximum number of file i/o threads */ if (srv_n_file_io_threads > SRV_MAX_N_IO_THREADS) { @@ -1822,8 +1836,19 @@ innobase_shutdown_for_mysql(void) mem_free(srv_monitor_file_name); } } - + if (srv_dict_tmpfile) { + fclose(srv_dict_tmpfile); + srv_dict_tmpfile = 0; + } + + if (srv_misc_tmpfile) { + fclose(srv_misc_tmpfile); + srv_misc_tmpfile = 0; + } + mutex_free(&srv_monitor_file_mutex); + mutex_free(&srv_dict_tmpfile_mutex); + mutex_free(&srv_misc_tmpfile_mutex); /* 3. Free all InnoDB's own mutexes and the os_fast_mutexes inside them */ diff --git a/mysql-test/lib/mtr_stress.pl b/mysql-test/lib/mtr_stress.pl index a57d94e8043..d3ed24db545 100644 --- a/mysql-test/lib/mtr_stress.pl +++ b/mysql-test/lib/mtr_stress.pl @@ -145,6 +145,14 @@ sub run_stress_test () mtr_add_arg($args, "--stress-init-file=%", $::opt_stress_init_file); } + if ( !$::opt_stress_loop_count && !$::opt_stress_test_count && + !$::opt_stress_test_duration ) + { + #Limit stress testing with 20 loops in case when any limit parameter + #was specified + $::opt_stress_test_count=20; + } + if ( $::opt_stress_loop_count ) { mtr_add_arg($args, "--loop-count=%s", $::opt_stress_loop_count); diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl index 8ccd87fc7a8..d64a487758d 100755 --- a/mysql-test/mysql-test-run.pl +++ b/mysql-test/mysql-test-run.pl @@ -276,9 +276,9 @@ our $opt_stress= ""; our $opt_stress_suite= "main"; our $opt_stress_mode= "random"; our $opt_stress_threads= 5; -our $opt_stress_test_count= 20; -our $opt_stress_loop_count= ""; -our $opt_stress_test_duration= ""; +our $opt_stress_test_count= 0; +our $opt_stress_loop_count= 0; +our $opt_stress_test_duration= 0; our $opt_stress_init_file= ""; our $opt_stress_test_file= ""; @@ -964,7 +964,7 @@ sub executable_setup () { $exe_mysql_fix_system_tables= mtr_script_exists("$glob_basedir/scripts/mysql_fix_privilege_tables"); $exe_my_print_defaults= - mtr_script_exists("$glob_basedir/extra/my_print_defaults"); + mtr_exe_exists("$glob_basedir/extra/my_print_defaults"); $path_ndb_tools_dir= mtr_path_exists("$glob_basedir/ndb/tools"); $exe_ndb_mgm= "$glob_basedir/ndb/src/mgmclient/ndb_mgm"; } @@ -982,7 +982,7 @@ sub executable_setup () { mtr_script_exists("$path_client_bindir/mysql_fix_privilege_tables", "$glob_basedir/scripts/mysql_fix_privilege_tables"); $exe_my_print_defaults= - mtr_script_exists("$path_client_bindir/my_print_defaults"); + mtr_exe_exists("$path_client_bindir/my_print_defaults"); $path_language= mtr_path_exists("$glob_basedir/share/mysql/english/", "$glob_basedir/share/english/"); diff --git a/mysql-test/mysql-test-run.sh b/mysql-test/mysql-test-run.sh index c84763713e1..a115a82a6a4 100644 --- a/mysql-test/mysql-test-run.sh +++ b/mysql-test/mysql-test-run.sh @@ -279,7 +279,7 @@ DO_STRESS="" STRESS_SUITE="main" STRESS_MODE="random" STRESS_THREADS=5 -STRESS_TEST_COUNT=20 +STRESS_TEST_COUNT="" STRESS_LOOP_COUNT="" STRESS_TEST_DURATION="" STRESS_INIT_FILE="" @@ -1906,7 +1906,7 @@ run_stress_test() --stress-basedir=$STRESS_BASEDIR \ --server-logs-dir=$STRESS_BASEDIR \ --stress-mode=$STRESS_MODE \ - --mysqltest=$BASEDIR/client/mysqltest \ + --mysqltest=$CLIENT_BINDIR/mysqltest \ --threads=$STRESS_THREADS \ --verbose \ --cleanup \ @@ -1917,6 +1917,14 @@ run_stress_test() STRESS_TEST_ARGS="$STRESS_TEST_ARGS --stress-init-file=$STRESS_INIT_FILE" fi + if [ -z "$STRESS_LOOP_COUNT" -a -z "$STRESS_TEST_COUNT" -a + -z "$STRESS_TEST_DURATION" ] ; then + + #Limit stress testing with 20 loops in case when any limit parameter + #was specified + STRESS_TEST_COUNT=20 + fi + if [ -n "$STRESS_LOOP_COUNT" ] ; then STRESS_TEST_ARGS="$STRESS_TEST_ARGS --loop-count=$STRESS_LOOP_COUNT" fi diff --git a/mysql-test/r/bdb.result b/mysql-test/r/bdb.result index ac14f891622..a564fd1045c 100644 --- a/mysql-test/r/bdb.result +++ b/mysql-test/r/bdb.result @@ -1289,6 +1289,25 @@ SELECT id FROM t1 WHERE (list_id = 1) AND (term = "letterd"); id 4 DROP TABLE t1; +create table t1 (a int, key(a)) engine=bdb; +create table t2 (b int, key(b)) engine=bdb; +insert into t1 values (1),(1),(2),(3),(4); +insert into t2 values (1),(5),(6),(7); +delete from t1 where (a in (select b from t2)); +select count(*) from t1; +count(*) +3 +insert into t1 set a=(select b from t2); +ERROR 21000: Subquery returns more than 1 row +select count(*) from t1; +count(*) +3 +update t1 set a = a + 1 where (a in (select b from t2)); +select count(*) from t1; +count(*) +3 +drop table t1, t2; +End of 4.1 tests create temporary table t1 (a int, primary key(a)) engine=bdb; select * from t1; a diff --git a/mysql-test/r/ctype_uca.result b/mysql-test/r/ctype_uca.result index 4b245c69d2a..3e286c77c00 100644 --- a/mysql-test/r/ctype_uca.result +++ b/mysql-test/r/ctype_uca.result @@ -2015,6 +2015,112 @@ Z,z,Ź,ź,Å»,ż,Ž,ž Ç Ç‚ ǃ +select group_concat(c1 order by c1) from t1 group by c1 collate utf8_hungarian_ci; +group_concat(c1 order by c1) +÷ +× +A,a,À,Ã,Â,Ã,Ä,Ã…,à ,á,â,ã,ä,Ã¥,Ä€,Ä,Ä‚,ă,Ä„,Ä…,Ç,ÇŽ,Çž,ÇŸ,Ç ,Ç¡,Ǻ,Ç» +AA,Aa,aA,aa +Æ,æ,Ç¢,Ç£,Ǽ,ǽ +B,b +Æ€ +Æ +Æ‚,ƃ +C,c,Ç,ç,Ć,ć,Ĉ,ĉ,ÄŠ,Ä‹,ÄŒ,Ä +CH,Ch,cH,ch +Ƈ,ƈ +D,d,ÄŽ,Ä +DZ,Dz,dZ,dz,Ç„,Ç…,dž,DZ,Dz,dz +Ä,Ä‘ +Ɖ +ÆŠ +Æ‹,ÆŒ +Ã,ð +E,e,È,É,Ê,Ë,è,é,ê,ë,Ä’,Ä“,Ä”,Ä•,Ä–,Ä—,Ę,Ä™,Äš,Ä› +ÆŽ,Ç +Æ +Æ +F,f +Æ‘,Æ’ +G,g,Äœ,Ä,Äž,ÄŸ,Ä ,Ä¡,Ä¢,Ä£,Ǧ,ǧ,Ç´,ǵ +Ǥ,Ç¥ +Æ“ +Æ” +Æ¢,Æ£ +H,h,Ĥ,Ä¥ +Æ•,Ƕ +Ħ,ħ +I,i,ÃŒ,Ã,ÃŽ,Ã,ì,Ã,î,ï,Ĩ,Ä©,Ī,Ä«,Ĭ,Ä,Ä®,į,Ä°,Ç,Ç +IJ,Ij,iJ,ij,IJ,ij +ı +Æ— +Æ– +J,j,Ä´,ĵ,Ç° +K,k,Ķ,Ä·,Ǩ,Ç© +Ƙ,Æ™ +L,l,Ĺ,ĺ,Ä»,ļ,Ľ,ľ +Ä¿,Å€ +LJ,Lj,lJ,lj,LJ,Lj,lj +LL,Ll,lL,ll +Å,Å‚ +Æš +Æ› +M,m +N,n,Ñ,ñ,Ń,Å„,Å…,ņ,Ň,ň,Ǹ,ǹ +NJ,Nj,nJ,nj,ÇŠ,Ç‹,ÇŒ +Æ +Æž +ÅŠ,Å‹ +O,o,Ã’,Ó,Ô,Õ,ò,ó,ô,õ,ÅŒ,Å,ÅŽ,Å,Æ ,Æ¡,Ç‘,Ç’,Ǫ,Ç«,Ǭ,Ç +OE,Oe,oE,oe,Å’,Å“ +Ö,ö,Å,Å‘ +Ø,ø,Ǿ,Ç¿ +Ɔ +ÆŸ +P,p +Ƥ,Æ¥ +Q,q +ĸ +R,r,Å”,Å•,Å–,Å—,Ř,Å™ +RR,Rr,rR,rr +Ʀ +S,s,Åš,Å›,Åœ,Å,Åž,ÅŸ,Å ,Å¡,Å¿ +SS,Ss,sS,ss,ß +Æ© +ƪ +T,t,Å¢,Å£,Ť,Å¥ +ƾ +Ŧ,ŧ +Æ« +Ƭ,Æ +Æ® +U,u,Ù,Ú,Û,ù,ú,û,Ũ,Å©,Ū,Å«,Ŭ,Å,Å®,ů,Ų,ų,Ư,Æ°,Ç“,Ç”,Ç•,Ç–,Ç—,ǘ,Ç™,Çš,Ç›,Çœ +Ãœ,ü,Å°,ű +Æœ +Ʊ +V,v +Ʋ +W,w,Å´,ŵ +X,x +Y,y,Ã,ý,ÿ,Ŷ,Å·,Ÿ +Ƴ,Æ´ +Z,z,Ź,ź,Å»,ż,Ž,ž +Æ +Ƶ,ƶ +Æ·,Ç®,ǯ +Ƹ,ƹ +ƺ +Þ,þ +Æ¿,Ç· +Æ» +Ƨ,ƨ +Ƽ,ƽ +Æ„,Æ… +ʼn +Ç€ +Ç +Ç‚ +ǃ drop table t1; SET NAMES utf8; CREATE TABLE t1 (c varchar(255) NOT NULL COLLATE utf8_general_ci, INDEX (c)); diff --git a/mysql-test/r/func_gconcat.result b/mysql-test/r/func_gconcat.result index 7987ceca712..2a36e6fe17b 100644 --- a/mysql-test/r/func_gconcat.result +++ b/mysql-test/r/func_gconcat.result @@ -163,7 +163,7 @@ show warnings; Level Code Message Warning 1260 1 line(s) were cut by GROUP_CONCAT() set group_concat_max_len = 1024; -select group_concat(sum(a)) from t1 group by grp; +select group_concat(sum(c)) from t1 group by grp; ERROR HY000: Invalid use of group function select grp,group_concat(c order by 2) from t1 group by grp; ERROR 42S22: Unknown column '2' in 'order clause' diff --git a/mysql-test/r/information_schema.result b/mysql-test/r/information_schema.result index 6224b30b70e..e8d343ad711 100644 --- a/mysql-test/r/information_schema.result +++ b/mysql-test/r/information_schema.result @@ -1056,3 +1056,21 @@ where table_name="v1"; table_type VIEW drop view v1; +create temporary table t1(f1 int, index(f1)); +show columns from t1; +Field Type Null Key Default Extra +f1 int(11) YES MUL NULL +describe t1; +Field Type Null Key Default Extra +f1 int(11) YES MUL NULL +show indexes from t1; +Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment +t1 1 f1 1 f1 A NULL NULL NULL YES BTREE +drop table t1; +create table t1(f1 binary(32), f2 varbinary(64)); +select character_maximum_length, character_octet_length +from information_schema.columns where table_name='t1'; +character_maximum_length character_octet_length +32 32 +64 64 +drop table t1; diff --git a/mysql-test/r/innodb.result b/mysql-test/r/innodb.result index 0e0e6a20770..dcff72ba7c0 100644 --- a/mysql-test/r/innodb.result +++ b/mysql-test/r/innodb.result @@ -2846,4 +2846,33 @@ d varchar(255) character set utf8, e varchar(255) character set utf8, key (a,b,c,d,e)) engine=innodb; ERROR 42000: Specified key was too long; max key length is 3072 bytes +create table t1(a int primary key) row_format=redundant engine=innodb; +create table t2(a int primary key,constraint foreign key(a)references t1(a)) row_format=compact engine=innodb; +create table t3(a int primary key) row_format=compact engine=innodb; +create table t4(a int primary key,constraint foreign key(a)references t3(a)) row_format=redundant engine=innodb; +insert into t1 values(1); +insert into t3 values(1); +insert into t2 values(2); +ERROR 23000: Cannot add or update a child row: a foreign key constraint fails (`test/t2`, CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`a`) REFERENCES `t1` (`a`)) +insert into t4 values(2); +ERROR 23000: Cannot add or update a child row: a foreign key constraint fails (`test/t4`, CONSTRAINT `t4_ibfk_1` FOREIGN KEY (`a`) REFERENCES `t3` (`a`)) +insert into t2 values(1); +insert into t4 values(1); +update t1 set a=2; +ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test/t2`, CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`a`) REFERENCES `t1` (`a`)) +update t2 set a=2; +ERROR 23000: Cannot add or update a child row: a foreign key constraint fails (`test/t2`, CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`a`) REFERENCES `t1` (`a`)) +update t3 set a=2; +ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test/t4`, CONSTRAINT `t4_ibfk_1` FOREIGN KEY (`a`) REFERENCES `t3` (`a`)) +update t4 set a=2; +ERROR 23000: Cannot add or update a child row: a foreign key constraint fails (`test/t4`, CONSTRAINT `t4_ibfk_1` FOREIGN KEY (`a`) REFERENCES `t3` (`a`)) +truncate t1; +ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test/t2`, CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`a`) REFERENCES `t1` (`a`)) +truncate t3; +ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test/t4`, CONSTRAINT `t4_ibfk_1` FOREIGN KEY (`a`) REFERENCES `t3` (`a`)) +truncate t2; +truncate t4; +truncate t1; +truncate t3; +drop table t4,t3,t2,t1; End of 5.0 tests diff --git a/mysql-test/r/ndb_basic.result b/mysql-test/r/ndb_basic.result index 55cbbd89b3c..9dd75f1390c 100644 --- a/mysql-test/r/ndb_basic.result +++ b/mysql-test/r/ndb_basic.result @@ -677,3 +677,19 @@ select * from atablewithareallylongandirritatingname; a 2 drop table atablewithareallylongandirritatingname; +create table t1 (f1 varchar(50), f2 text,f3 int, primary key(f1)) engine=NDB; +insert into t1 (f1,f2,f3)VALUES("111111","aaaaaa",1); +insert into t1 (f1,f2,f3)VALUES("222222","bbbbbb",2); +select * from t1 order by f1; +f1 f2 f3 +111111 aaaaaa 1 +222222 bbbbbb 2 +select * from t1 order by f2; +f1 f2 f3 +111111 aaaaaa 1 +222222 bbbbbb 2 +select * from t1 order by f3; +f1 f2 f3 +111111 aaaaaa 1 +222222 bbbbbb 2 +drop table t1; diff --git a/mysql-test/r/ndb_multi.result b/mysql-test/r/ndb_multi.result index 2080be241e8..bd3af223a65 100644 --- a/mysql-test/r/ndb_multi.result +++ b/mysql-test/r/ndb_multi.result @@ -30,6 +30,7 @@ create table t1 (a int) engine=ndbcluster; insert into t1 value (2); select * from t1; ERROR HY000: Got error 241 'Invalid schema object version' from ndbcluster +flush table t1; select * from t1; a 2 diff --git a/mysql-test/r/ndb_read_multi_range.result b/mysql-test/r/ndb_read_multi_range.result index f42ac394b6c..bb9398054ff 100644 --- a/mysql-test/r/ndb_read_multi_range.result +++ b/mysql-test/r/ndb_read_multi_range.result @@ -1,4 +1,4 @@ -DROP TABLE IF EXISTS t1, r1; +DROP TABLE IF EXISTS t1, t2, r1; create table t1 ( a int primary key, b int not null, diff --git a/mysql-test/r/rpl000001.result b/mysql-test/r/rpl000001.result index 450e728090e..de9f6f16b2a 100644 --- a/mysql-test/r/rpl000001.result +++ b/mysql-test/r/rpl000001.result @@ -50,7 +50,7 @@ select (@id := id) - id from t2; 0 kill @id; drop table t2; -ERROR 08S01: Server shutdown in progress +Got one of the listed errors set global sql_slave_skip_counter=1; start slave; select count(*) from t1; diff --git a/mysql-test/r/rpl_relayrotate.result b/mysql-test/r/rpl_relayrotate.result index b038e7b6a3e..20f19973d83 100644 --- a/mysql-test/r/rpl_relayrotate.result +++ b/mysql-test/r/rpl_relayrotate.result @@ -10,9 +10,6 @@ reset slave; start slave; stop slave; start slave; -select master_pos_wait('master-bin.001',3000)>=0; -master_pos_wait('master-bin.001',3000)>=0 -1 select max(a) from t1; max(a) 8000 diff --git a/mysql-test/r/rpl_trigger.result b/mysql-test/r/rpl_trigger.result index 999af131b8b..7613f2547f0 100644 --- a/mysql-test/r/rpl_trigger.result +++ b/mysql-test/r/rpl_trigger.result @@ -122,3 +122,15 @@ a=b && a=c 1 drop function bug12480; drop table t1; +create table t1 (i int); +create table t2 (i int); +create trigger tr1 before insert on t1 for each row +begin +insert into t2 values (1); +end| +create database other; +use other; +insert into test.t1 values (1); +use test; +drop table t1,t2; +drop database other; diff --git a/mysql-test/r/rpl_until.result b/mysql-test/r/rpl_until.result index 4a4dcdbb1c0..b584e04ed57 100644 --- a/mysql-test/r/rpl_until.result +++ b/mysql-test/r/rpl_until.result @@ -31,7 +31,7 @@ n 4 show slave status; Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master -# 127.0.0.1 root MASTER_MYPORT 1 master-bin.000001 776 slave-relay-bin.000004 # master-bin.000001 Yes No 0 0 319 # Master master-bin.000001 319 No # +# 127.0.0.1 root MASTER_MYPORT 1 master-bin.000001 776 slave-relay-bin.000004 # master-bin.000001 # No 0 0 319 # Master master-bin.000001 319 No # start slave until master_log_file='master-no-such-bin.000001', master_log_pos=291; select * from t1; n @@ -41,7 +41,7 @@ n 4 show slave status; Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master -# 127.0.0.1 root MASTER_MYPORT 1 master-bin.000001 776 slave-relay-bin.000004 # master-bin.000001 Yes No 0 0 319 # Master master-no-such-bin.000001 291 No # +# 127.0.0.1 root MASTER_MYPORT 1 master-bin.000001 776 slave-relay-bin.000004 # master-bin.000001 # No 0 0 319 # Master master-no-such-bin.000001 291 No # start slave until relay_log_file='slave-relay-bin.000004', relay_log_pos=746; select * from t2; n diff --git a/mysql-test/r/select.result b/mysql-test/r/select.result index 598ea2b10d1..e2c4609d902 100644 --- a/mysql-test/r/select.result +++ b/mysql-test/r/select.result @@ -3337,3 +3337,11 @@ id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t2 const PRIMARY PRIMARY 4 const 1 Using index 1 SIMPLE t3 const PRIMARY PRIMARY 8 const,const 1 DROP TABLE t1,t2,t3; +create table t1(f1 char, f2 char not null); +insert into t1 values(null,'a'); +create table t2 (f2 char not null); +insert into t2 values('b'); +select * from t1 left join t2 on f1=t2.f2 where t1.f2='a'; +f1 f2 f2 +NULL a NULL +drop table t1,t2; diff --git a/mysql-test/r/sp-error.result b/mysql-test/r/sp-error.result index b384a1c1649..d7bed7e88a7 100644 --- a/mysql-test/r/sp-error.result +++ b/mysql-test/r/sp-error.result @@ -1088,3 +1088,43 @@ ERROR 0A000: Not allowed to return a result set from a function drop table t1| drop procedure bug13012_1| drop function bug13012_2| +drop function if exists bug11555_1; +drop function if exists bug11555_2; +drop view if exists v1, v2, v3, v4; +create function bug11555_1() returns int return (select max(i) from t1); +create function bug11555_2() returns int return bug11555_1(); +create view v1 as select bug11555_1(); +ERROR 42S02: Table 'test.t1' doesn't exist +create view v2 as select bug11555_2(); +ERROR 42S02: Table 'test.t1' doesn't exist +create table t1 (i int); +create view v1 as select bug11555_1(); +create view v2 as select bug11555_2(); +create view v3 as select * from v1; +drop table t1; +select * from v1; +ERROR HY000: View 'test.v1' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them +select * from v2; +ERROR HY000: View 'test.v2' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them +select * from v3; +ERROR HY000: View 'test.v3' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them +create view v4 as select * from v1; +ERROR HY000: View 'test.v1' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them +drop view v1, v2, v3; +drop function bug11555_1; +drop function bug11555_2; +create table t1 (i int); +create table t2 (i int); +create trigger t1_ai after insert on t1 for each row insert into t2 values (new.i); +create view v1 as select * from t1; +drop table t2; +insert into v1 values (1); +ERROR HY000: View 'test.v1' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them +drop trigger t1_ai; +create function bug11555_1() returns int return (select max(i) from t2); +create trigger t1_ai after insert on t1 for each row set @a:=bug11555_1(); +insert into v1 values (2); +ERROR HY000: View 'test.v1' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them +drop function bug11555_1; +drop table t1; +drop view v1; diff --git a/mysql-test/r/sp.result b/mysql-test/r/sp.result index 2725c42ccbe..ded9754f172 100644 --- a/mysql-test/r/sp.result +++ b/mysql-test/r/sp.result @@ -4110,23 +4110,23 @@ call bug14376(4711)| x 4711 drop procedure bug14376| -drop procedure if exists p1| -drop table if exists t1| -create table t1 (a varchar(255))| -insert into t1 (a) values ("a - table column")| -create procedure p1(a varchar(255)) +drop procedure if exists bug5967| +drop table if exists t3| +create table t3 (a varchar(255))| +insert into t3 (a) values ("a - table column")| +create procedure bug5967(a varchar(255)) begin declare i varchar(255); -declare c cursor for select a from t1; +declare c cursor for select a from t3; select a; -select a from t1 into i; +select a from t3 into i; select i as 'Parameter takes precedence over table column'; open c; fetch c into i; close c; select i as 'Parameter takes precedence over table column in cursors'; begin declare a varchar(255) default 'a - local variable'; -declare c1 cursor for select a from t1; +declare c1 cursor for select a from t3; select a as 'A local variable takes precedence over parameter'; open c1; fetch c1 into i; @@ -4134,9 +4134,9 @@ close c1; select i as 'A local variable takes precedence over parameter in cursors'; begin declare a varchar(255) default 'a - local variable in a nested compound statement'; -declare c2 cursor for select a from t1; +declare c2 cursor for select a from t3; select a as 'A local variable in a nested compound statement takes precedence over a local variable in the outer statement'; -select a from t1 into i; +select a from t3 into i; select i as 'A local variable in a nested compound statement takes precedence over table column'; open c2; fetch c2 into i; @@ -4145,7 +4145,7 @@ select i as 'A local variable in a nested compound statement takes precedence o end; end; end| -call p1("a - stored procedure parameter")| +call bug5967("a - stored procedure parameter")| a a - stored procedure parameter Parameter takes precedence over table column @@ -4162,7 +4162,7 @@ A local variable in a nested compound statement takes precedence over table colu a - local variable in a nested compound statement A local variable in a nested compound statement takes precedence over table column in cursors a - local variable in a nested compound statement -drop procedure p1| +drop procedure bug5967| drop procedure if exists bug13012| create procedure bug13012() BEGIN @@ -4190,17 +4190,17 @@ call bug13012()| Table Op Msg_type Msg_text test.t1 repair status OK test.t2 repair status OK -test.t3 repair error Table 'test.t3' doesn't exist +test.t3 repair status OK test.v1 repair error 'test.v1' is not BASE TABLE Table Op Msg_type Msg_text test.t1 optimize status OK test.t2 optimize status OK -test.t3 optimize error Table 'test.t3' doesn't exist +test.t3 optimize status OK test.v1 optimize error 'test.v1' is not BASE TABLE Table Op Msg_type Msg_text test.t1 analyze status Table is already up to date test.t2 analyze status Table is already up to date -test.t3 analyze error Table 'test.t3' doesn't exist +test.t3 analyze status Table is already up to date test.v1 analyze error 'test.v1' is not BASE TABLE Warnings: Error 1347 'test.v1' is not BASE TABLE @@ -4208,17 +4208,17 @@ call bug13012()| Table Op Msg_type Msg_text test.t1 repair status OK test.t2 repair status OK -test.t3 repair error Table 'test.t3' doesn't exist +test.t3 repair status OK test.v1 repair error 'test.v1' is not BASE TABLE Table Op Msg_type Msg_text test.t1 optimize status OK test.t2 optimize status OK -test.t3 optimize error Table 'test.t3' doesn't exist +test.t3 optimize status OK test.v1 optimize error 'test.v1' is not BASE TABLE Table Op Msg_type Msg_text test.t1 analyze status Table is already up to date test.t2 analyze status Table is already up to date -test.t3 analyze error Table 'test.t3' doesn't exist +test.t3 analyze status Table is already up to date test.v1 analyze error 'test.v1' is not BASE TABLE Warnings: Error 1347 'test.v1' is not BASE TABLE @@ -4226,25 +4226,34 @@ call bug13012()| Table Op Msg_type Msg_text test.t1 repair status OK test.t2 repair status OK -test.t3 repair error Table 'test.t3' doesn't exist +test.t3 repair status OK test.v1 repair error 'test.v1' is not BASE TABLE Table Op Msg_type Msg_text test.t1 optimize status OK test.t2 optimize status OK -test.t3 optimize error Table 'test.t3' doesn't exist +test.t3 optimize status OK test.v1 optimize error 'test.v1' is not BASE TABLE Table Op Msg_type Msg_text test.t1 analyze status Table is already up to date test.t2 analyze status Table is already up to date -test.t3 analyze error Table 'test.t3' doesn't exist +test.t3 analyze status Table is already up to date test.v1 analyze error 'test.v1' is not BASE TABLE Warnings: Error 1347 'test.v1' is not BASE TABLE drop procedure bug13012| drop view v1; select * from t1| -a -a - table column +id data +aa 0 +aa 1 +aa 2 +aa 3 +aa 4 +aa 5 +aa 6 +aa 7 +aa 8 +aa 9 drop schema if exists mysqltest1| Warnings: Note 1008 Can't drop database 'mysqltest1'; database doesn't exist @@ -4284,4 +4293,31 @@ drop schema if exists mysqltest1| drop schema if exists mysqltest2| drop schema if exists mysqltest3| use test| +drop table if exists t3| +drop procedure if exists bug15441| +create table t3 (id int not null primary key, county varchar(25))| +insert into t3 (id, county) values (1, 'York')| +create procedure bug15441(c varchar(25)) +begin +update t3 set id=2, county=values(c); +end| +call bug15441('county')| +ERROR 42S22: Unknown column 'c' in 'field list' +drop procedure bug15441| +create procedure bug15441(county varchar(25)) +begin +declare c varchar(25) default "hello"; +insert into t3 (id, county) values (1, county) +on duplicate key update county= values(county); +select * from t3; +update t3 set id=2, county=values(id); +select * from t3; +end| +call bug15441('Yale')| +id county +1 Yale +id county +2 NULL +drop table t3| +drop procedure bug15441| drop table t1,t2; diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result index d42e439f4de..6094d23b0d0 100644 --- a/mysql-test/r/subselect.result +++ b/mysql-test/r/subselect.result @@ -2988,3 +2988,146 @@ max(fld) 1 drop table t1; purge master logs before (select adddate(current_timestamp(), interval -4 day)); +CREATE TABLE t1 (a int, b int); +CREATE TABLE t2 (c int, d int); +CREATE TABLE t3 (e int); +INSERT INTO t1 VALUES +(1,10), (2,10), (1,20), (2,20), (3,20), (2,30), (4,40); +INSERT INTO t2 VALUES +(2,10), (2,20), (4,10), (5,10), (3,20), (2,40); +INSERT INTO t3 VALUES (10), (30), (10), (20) ; +SELECT a, MAX(b), MIN(b) FROM t1 GROUP BY a; +a MAX(b) MIN(b) +1 20 10 +2 30 10 +3 20 20 +4 40 40 +SELECT * FROM t2; +c d +2 10 +2 20 +4 10 +5 10 +3 20 +2 40 +SELECT * FROM t3; +e +10 +30 +10 +20 +SELECT a FROM t1 GROUP BY a +HAVING a IN (SELECT c FROM t2 WHERE MAX(b)>20); +a +2 +4 +SELECT a FROM t1 GROUP BY a +HAVING a IN (SELECT c FROM t2 WHERE MAX(b)<d); +a +2 +SELECT a FROM t1 GROUP BY a +HAVING a IN (SELECT c FROM t2 WHERE MAX(b)>d); +a +2 +4 +SELECT a FROM t1 GROUP BY a +HAVING a IN (SELECT c FROM t2 +WHERE d >= SOME(SELECT e FROM t3 WHERE MAX(b)=e)); +a +2 +3 +SELECT a FROM t1 GROUP BY a +HAVING a IN (SELECT c FROM t2 +WHERE EXISTS(SELECT e FROM t3 WHERE MAX(b)=e AND e <= d)); +a +2 +3 +SELECT a FROM t1 GROUP BY a +HAVING a IN (SELECT c FROM t2 +WHERE d > SOME(SELECT e FROM t3 WHERE MAX(b)=e)); +a +2 +SELECT a FROM t1 GROUP BY a +HAVING a IN (SELECT c FROM t2 +WHERE EXISTS(SELECT e FROM t3 WHERE MAX(b)=e AND e < d)); +a +2 +SELECT a FROM t1 GROUP BY a +HAVING a IN (SELECT c FROM t2 +WHERE MIN(b) < d AND +EXISTS(SELECT e FROM t3 WHERE MAX(b)=e AND e <= d)); +a +2 +SELECT a, SUM(a) FROM t1 GROUP BY a; +a SUM(a) +1 2 +2 6 +3 3 +4 4 +SELECT a FROM t1 +WHERE EXISTS(SELECT c FROM t2 GROUP BY c HAVING SUM(a) = c) GROUP BY a; +a +3 +4 +SELECT a FROM t1 GROUP BY a +HAVING EXISTS(SELECT c FROM t2 GROUP BY c HAVING SUM(a) = c); +a +1 +3 +4 +SELECT a FROM t1 +WHERE a < 3 AND +EXISTS(SELECT c FROM t2 GROUP BY c HAVING SUM(a) != c) GROUP BY a; +a +1 +2 +SELECT a FROM t1 +WHERE a < 3 AND +EXISTS(SELECT c FROM t2 GROUP BY c HAVING SUM(a) != c); +a +1 +2 +1 +2 +2 +SELECT t1.a FROM t1 GROUP BY t1.a +HAVING t1.a < ALL(SELECT t2.c FROM t2 GROUP BY t2.c +HAVING EXISTS(SELECT t3.e FROM t3 GROUP BY t3.e +HAVING SUM(t1.a+t2.c) < t3.e/4)); +a +1 +2 +SELECT t1.a FROM t1 GROUP BY t1.a +HAVING t1.a > ALL(SELECT t2.c FROM t2 +WHERE EXISTS(SELECT t3.e FROM t3 GROUP BY t3.e +HAVING SUM(t1.a+t2.c) < t3.e/4)); +a +4 +SELECT t1.a FROM t1 GROUP BY t1.a +HAVING t1.a > ALL(SELECT t2.c FROM t2 +WHERE EXISTS(SELECT t3.e FROM t3 +WHERE SUM(t1.a+t2.c) < t3.e/4)); +ERROR HY000: Invalid use of group function +SELECT t1.a from t1 GROUP BY t1.a HAVING AVG(SUM(t1.b)) > 20; +ERROR HY000: Invalid use of group function +SELECT t1.a FROM t1 GROUP BY t1.a +HAVING t1.a IN (SELECT t2.c FROM t2 GROUP BY t2.c +HAVING AVG(t2.c+SUM(t1.b)) > 20); +a +2 +3 +4 +SELECT t1.a FROM t1 GROUP BY t1.a +HAVING t1.a IN (SELECT t2.c FROM t2 GROUP BY t2.c +HAVING AVG(SUM(t1.b)) > 20); +a +2 +4 +SELECT t1.a, SUM(b) AS sum FROM t1 GROUP BY t1.a +HAVING t1.a IN (SELECT t2.c FROM t2 GROUP BY t2.c +HAVING t2.c+sum > 20); +a sum +2 60 +3 20 +4 40 +DROP TABLE t1,t2,t3; diff --git a/mysql-test/r/trigger.result b/mysql-test/r/trigger.result index ff92fc543d4..e0048515fed 100644 --- a/mysql-test/r/trigger.result +++ b/mysql-test/r/trigger.result @@ -780,3 +780,9 @@ end// CALL p2(); drop procedure p2; drop table t1; +create trigger t1_bi before insert on test.t1 for each row set @a:=0; +ERROR 3D000: No database selected +create trigger test.t1_bi before insert on t1 for each row set @a:=0; +ERROR 3D000: No database selected +drop trigger t1_bi; +ERROR 3D000: No database selected diff --git a/mysql-test/r/type_time.result b/mysql-test/r/type_time.result index 442435b0459..deb60a95f21 100644 --- a/mysql-test/r/type_time.result +++ b/mysql-test/r/type_time.result @@ -85,3 +85,27 @@ sec_to_time(time_to_sec(t)) 13:00:00 09:00:00 drop table t1; +SELECT CAST(235959.123456 AS TIME); +CAST(235959.123456 AS TIME) +23:59:59.123456 +SELECT CAST(0.235959123456e+6 AS TIME); +CAST(0.235959123456e+6 AS TIME) +23:59:59.123456 +SELECT CAST(235959123456e-6 AS TIME); +CAST(235959123456e-6 AS TIME) +23:59:59.123456 +SELECT CAST(235959.1234567 AS TIME); +CAST(235959.1234567 AS TIME) +23:59:59.123456 +Warnings: +Warning 1292 Truncated incorrect time value: '235959.1234567' +SELECT CAST(0.2359591234567e6 AS TIME); +CAST(0.2359591234567e6 AS TIME) +23:59:59.123456 +Warnings: +Warning 1292 Truncated incorrect time value: '235959.1234567' +SELECT CAST(0.2359591234567e+30 AS TIME); +CAST(0.2359591234567e+30 AS TIME) +NULL +Warnings: +Warning 1292 Truncated incorrect time value: '2.359591234567e+29' diff --git a/mysql-test/r/view.result b/mysql-test/r/view.result index f651169d71d..7e7d0617b51 100644 --- a/mysql-test/r/view.result +++ b/mysql-test/r/view.result @@ -1933,11 +1933,11 @@ create function f1 () returns int return (select max(col1) from t1); DROP TABLE t1; CHECK TABLE v1, v2, v3, v4, v5, v6; Table Op Msg_type Msg_text -test.v1 check error Table 'test.t1' doesn't exist +test.v1 check error View 'test.v1' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them test.v2 check status OK -test.v3 check error Table 'test.t1' doesn't exist +test.v3 check error View 'test.v3' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them test.v4 check status OK -test.v5 check error Table 'test.t1' doesn't exist +test.v5 check error View 'test.v5' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them test.v6 check status OK drop function f1; drop function f2; @@ -2456,3 +2456,19 @@ f1() 42 drop view v2,v1; drop function f1; +create table t1 (id numeric, warehouse_id numeric); +create view v1 as select id from t1; +create view v2 as +select t1.warehouse_id, v1.id as receipt_id +from t1, v1 where t1.id = v1.id; +insert into t1 (id, warehouse_id) values(3, 2); +insert into t1 (id, warehouse_id) values(4, 2); +insert into t1 (id, warehouse_id) values(5, 1); +select v2.receipt_id as alias1, v2.receipt_id as alias2 from v2 +order by v2.receipt_id; +alias1 alias2 +3 3 +4 4 +5 5 +drop view v2, v1; +drop table t1; diff --git a/mysql-test/t/bdb.test b/mysql-test/t/bdb.test index 72b3ee89ed5..d3068b29e28 100644 --- a/mysql-test/t/bdb.test +++ b/mysql-test/t/bdb.test @@ -938,7 +938,25 @@ SELECT id FROM t1 WHERE (list_id = 1) AND (term = "lettera"); SELECT id FROM t1 WHERE (list_id = 1) AND (term = "letterd"); DROP TABLE t1; -# End of 4.1 tests +# +# Bug #15536: Crash when DELETE with subquery using BDB tables +# +create table t1 (a int, key(a)) engine=bdb; +create table t2 (b int, key(b)) engine=bdb; +insert into t1 values (1),(1),(2),(3),(4); +insert into t2 values (1),(5),(6),(7); +delete from t1 where (a in (select b from t2)); +select count(*) from t1; +# INSERT also blows up +--error 1242 +insert into t1 set a=(select b from t2); +select count(*) from t1; +# UPDATE also blows up +update t1 set a = a + 1 where (a in (select b from t2)); +select count(*) from t1; +drop table t1, t2; + +--echo End of 4.1 tests # # alter temp table diff --git a/mysql-test/t/ctype_uca.test b/mysql-test/t/ctype_uca.test index 6d8713f4910..3e49b9de883 100644 --- a/mysql-test/t/ctype_uca.test +++ b/mysql-test/t/ctype_uca.test @@ -212,6 +212,7 @@ select group_concat(c1 order by c1) from t1 group by c1 collate utf8_slovak_ci; select group_concat(c1 order by c1) from t1 group by c1 collate utf8_spanish2_ci; select group_concat(c1 order by c1) from t1 group by c1 collate utf8_roman_ci; select group_concat(c1 order by c1) from t1 group by c1 collate utf8_esperanto_ci; +select group_concat(c1 order by c1) from t1 group by c1 collate utf8_hungarian_ci; drop table t1; diff --git a/mysql-test/t/disabled.def b/mysql-test/t/disabled.def index 4f5e11e7fbd..0e7eabbed6d 100644 --- a/mysql-test/t/disabled.def +++ b/mysql-test/t/disabled.def @@ -12,3 +12,5 @@ sp-goto : GOTO is currently is disabled - will be fixed in the future kill : Unstable test case, bug#9712 +subselect : Bug#15706 +type_time : Bug#15805 diff --git a/mysql-test/t/flush_read_lock_kill.test b/mysql-test/t/flush_read_lock_kill.test index de2576300dc..19a47b2893a 100644 --- a/mysql-test/t/flush_read_lock_kill.test +++ b/mysql-test/t/flush_read_lock_kill.test @@ -42,7 +42,7 @@ connection con1; # debug build running without our --debug=make_global..., will be # error 0 (no error). The only important thing to test is that on # debug builds with our --debug=make_global... we don't hang forever. ---error 0,1053 +--error 0,1053,2013 reap; connection con2; diff --git a/mysql-test/t/func_gconcat.test b/mysql-test/t/func_gconcat.test index cd686585dd8..058df9af56b 100644 --- a/mysql-test/t/func_gconcat.test +++ b/mysql-test/t/func_gconcat.test @@ -69,7 +69,7 @@ set group_concat_max_len = 1024; # Test errors --error 1111 -select group_concat(sum(a)) from t1 group by grp; +select group_concat(sum(c)) from t1 group by grp; --error 1054 select grp,group_concat(c order by 2) from t1 group by grp; diff --git a/mysql-test/t/information_schema.test b/mysql-test/t/information_schema.test index acbc62f1364..b05798b781f 100644 --- a/mysql-test/t/information_schema.test +++ b/mysql-test/t/information_schema.test @@ -748,3 +748,22 @@ drop table t1; select table_type from information_schema.tables where table_name="v1"; drop view v1; + +# +# Bug #14387 SHOW COLUMNS doesn't work on temporary tables +# Bug #15224 SHOW INDEX from temporary table doesn't work +# Bug #12770 DESC cannot display the info. about temporary table +# +create temporary table t1(f1 int, index(f1)); +show columns from t1; +describe t1; +show indexes from t1; +drop table t1; + +# +# Bug#14271 I_S: columns has no size for (var)binary columns +# +create table t1(f1 binary(32), f2 varbinary(64)); +select character_maximum_length, character_octet_length +from information_schema.columns where table_name='t1'; +drop table t1; diff --git a/mysql-test/t/innodb.test b/mysql-test/t/innodb.test index 735deba2b05..887d8193157 100644 --- a/mysql-test/t/innodb.test +++ b/mysql-test/t/innodb.test @@ -1833,4 +1833,38 @@ create table t1 (a varchar(255) character set utf8, e varchar(255) character set utf8, key (a,b,c,d,e)) engine=innodb; +# test that foreign key errors are reported correctly (Bug #15550) + +create table t1(a int primary key) row_format=redundant engine=innodb; +create table t2(a int primary key,constraint foreign key(a)references t1(a)) row_format=compact engine=innodb; +create table t3(a int primary key) row_format=compact engine=innodb; +create table t4(a int primary key,constraint foreign key(a)references t3(a)) row_format=redundant engine=innodb; + +insert into t1 values(1); +insert into t3 values(1); +-- error 1452 +insert into t2 values(2); +-- error 1452 +insert into t4 values(2); +insert into t2 values(1); +insert into t4 values(1); +-- error 1451 +update t1 set a=2; +-- error 1452 +update t2 set a=2; +-- error 1451 +update t3 set a=2; +-- error 1452 +update t4 set a=2; +-- error 1451 +truncate t1; +-- error 1451 +truncate t3; +truncate t2; +truncate t4; +truncate t1; +truncate t3; + +drop table t4,t3,t2,t1; + --echo End of 5.0 tests diff --git a/mysql-test/t/mysqltest.test b/mysql-test/t/mysqltest.test index 8ccf2cb0c7a..440a7787985 100644 --- a/mysql-test/t/mysqltest.test +++ b/mysql-test/t/mysqltest.test @@ -968,9 +968,9 @@ drop table t1; --error 1 --exec $MYSQL_TEST --record -x $MYSQL_TEST_DIR/var/tmp/bug11731.sql -R $MYSQL_TEST_DIR/var/tmp/bug11731.out -# The .out file should be empty, cat will fail! +# The .out file should be empty --error 1 ---exec cat $MYSQL_TEST_DIR/var/tmp/bug11731.out +--exec test -s $MYSQL_TEST_DIR/var/tmp/bug11731.out drop table t1; diff --git a/mysql-test/t/ndb_basic.test b/mysql-test/t/ndb_basic.test index 0510651a417..12aca73d82b 100644 --- a/mysql-test/t/ndb_basic.test +++ b/mysql-test/t/ndb_basic.test @@ -623,3 +623,14 @@ create table atablewithareallylongandirritatingname (a int); insert into atablewithareallylongandirritatingname values (2); select * from atablewithareallylongandirritatingname; drop table atablewithareallylongandirritatingname; + +# +# Bug#15682 +# +create table t1 (f1 varchar(50), f2 text,f3 int, primary key(f1)) engine=NDB; +insert into t1 (f1,f2,f3)VALUES("111111","aaaaaa",1); +insert into t1 (f1,f2,f3)VALUES("222222","bbbbbb",2); +select * from t1 order by f1; +select * from t1 order by f2; +select * from t1 order by f3; +drop table t1; diff --git a/mysql-test/t/ndb_multi.test b/mysql-test/t/ndb_multi.test index 760150c6f6a..1183f2b283f 100644 --- a/mysql-test/t/ndb_multi.test +++ b/mysql-test/t/ndb_multi.test @@ -40,6 +40,7 @@ connection server1; # Currently a retry is required remotely --error 1296 select * from t1; +flush table t1; select * from t1; # Connect to server2 and use the tables from there diff --git a/mysql-test/t/ndb_read_multi_range.test b/mysql-test/t/ndb_read_multi_range.test index 9d1f918fef0..b1bf7fe4258 100644 --- a/mysql-test/t/ndb_read_multi_range.test +++ b/mysql-test/t/ndb_read_multi_range.test @@ -2,7 +2,7 @@ -- source include/not_embedded.inc --disable_warnings -DROP TABLE IF EXISTS t1, r1; +DROP TABLE IF EXISTS t1, t2, r1; --enable_warnings # diff --git a/mysql-test/t/rpl000001.test b/mysql-test/t/rpl000001.test index 3d03823d474..45d621b730f 100644 --- a/mysql-test/t/rpl000001.test +++ b/mysql-test/t/rpl000001.test @@ -92,7 +92,7 @@ kill @id; # We don't drop t3 as this is a temporary table drop table t2; connection master; ---error 1053 +--error 1053,2013 reap; connection slave; # The SQL slave thread should now have stopped because the query was killed on diff --git a/mysql-test/t/rpl_deadlock.test b/mysql-test/t/rpl_deadlock.test index 08921caf897..c74ed989ece 100644 --- a/mysql-test/t/rpl_deadlock.test +++ b/mysql-test/t/rpl_deadlock.test @@ -58,7 +58,7 @@ while ($1) enable_query_log; select * from t1 for update; start slave; ---sleep 3 # hope that slave is blocked now +--real_sleep 3 # hope that slave is blocked now insert into t2 values(22); # provoke deadlock, slave should be victim commit; sync_with_master; @@ -76,7 +76,7 @@ change master to master_log_pos=532; # the BEGIN log event begin; select * from t2 for update; # hold lock start slave; ---sleep 10 # slave should have blocked, and be retrying +--real_sleep 10 # slave should have blocked, and be retrying commit; sync_with_master; select * from t1; # check that slave succeeded finally @@ -97,7 +97,7 @@ change master to master_log_pos=532; begin; select * from t2 for update; start slave; ---sleep 10 +--real_sleep 10 commit; sync_with_master; select * from t1; diff --git a/mysql-test/t/rpl_error_ignored_table.test b/mysql-test/t/rpl_error_ignored_table.test index cb4137c49e0..339d966dbb3 100644 --- a/mysql-test/t/rpl_error_ignored_table.test +++ b/mysql-test/t/rpl_error_ignored_table.test @@ -45,7 +45,7 @@ select (@id := id) - id from t3; kill @id; drop table t2,t3; connection master; ---error 0,1053 +--error 0,1053,2013 reap; connection master1; --replace_column 2 # 5 # diff --git a/mysql-test/t/rpl_relayrotate.test b/mysql-test/t/rpl_relayrotate.test index e9a4cdd05c5..04f03367e20 100644 --- a/mysql-test/t/rpl_relayrotate.test +++ b/mysql-test/t/rpl_relayrotate.test @@ -52,9 +52,8 @@ start slave; # which proves that the transaction restarted at # the right place. # We must wait for the transaction to commit before -# reading, MASTER_POS_WAIT() will do it for sure -# (the only statement with position>=3000 is COMMIT). -select master_pos_wait('master-bin.001',3000)>=0; +# reading: +sync_with_master; select max(a) from t1; connection master; diff --git a/mysql-test/t/rpl_trigger.test b/mysql-test/t/rpl_trigger.test index bf2836b6049..fa6054372c7 100644 --- a/mysql-test/t/rpl_trigger.test +++ b/mysql-test/t/rpl_trigger.test @@ -134,6 +134,35 @@ drop function bug12480; drop table t1; # +# #14614: Replication of tables with trigger generates error message if databases is changed +# Note. The error message is emitted by _myfree() using fprintf() to the stderr +# and because of that does not fall into the .result file. +# + +create table t1 (i int); +create table t2 (i int); + +delimiter |; +create trigger tr1 before insert on t1 for each row +begin + insert into t2 values (1); +end| +delimiter ;| + +create database other; +use other; +insert into test.t1 values (1); + +save_master_pos; +connection slave; +sync_with_master; + +connection master; +use test; +drop table t1,t2; +drop database other; + +# # End of test # save_master_pos; diff --git a/mysql-test/t/rpl_until.test b/mysql-test/t/rpl_until.test index 708f44a1ab6..e0ecf981fea 100644 --- a/mysql-test/t/rpl_until.test +++ b/mysql-test/t/rpl_until.test @@ -30,7 +30,7 @@ wait_for_slave_to_stop; # here table should be still not deleted select * from t1; --replace_result $MASTER_MYPORT MASTER_MYPORT ---replace_column 1 # 9 # 23 # 33 # +--replace_column 1 # 9 # 11 # 23 # 33 # show slave status; # this should fail right after start @@ -40,7 +40,7 @@ select * from t1; sleep 2; wait_for_slave_to_stop; --replace_result $MASTER_MYPORT MASTER_MYPORT ---replace_column 1 # 9 # 23 # 33 # +--replace_column 1 # 9 # 11 # 23 # 33 # show slave status; # try replicate all until second insert to t2; diff --git a/mysql-test/t/select.test b/mysql-test/t/select.test index a73d08f5f18..a85b82a7767 100644 --- a/mysql-test/t/select.test +++ b/mysql-test/t/select.test @@ -2805,3 +2805,13 @@ EXPLAIN SELECT t2.key_a,foo WHERE t2.key_a=2 and key_b=5; DROP TABLE t1,t2,t3; + +# +# Bug#15268 Unchecked null value caused server crash +# +create table t1(f1 char, f2 char not null); +insert into t1 values(null,'a'); +create table t2 (f2 char not null); +insert into t2 values('b'); +select * from t1 left join t2 on f1=t2.f2 where t1.f2='a'; +drop table t1,t2; diff --git a/mysql-test/t/sp-error.test b/mysql-test/t/sp-error.test index b6c7d5476e7..cf8f8dfc79c 100644 --- a/mysql-test/t/sp-error.test +++ b/mysql-test/t/sp-error.test @@ -1556,6 +1556,67 @@ drop procedure bug13012_1| drop function bug13012_2| delimiter ;| +# BUG#11555 "Stored procedures: current SP tables locking make +# impossible view security". We should not expose names of tables +# which are implicitly used by view (via stored routines/triggers). +# +# Note that SQL standard assumes that you simply won't be able drop table +# and leave some objects (routines/views/triggers) which were depending on +# it. Such objects should be dropped in advance (by default) or will be +# dropped simultaneously with table (DROP TABLE with CASCADE clause). +# So these tests probably should go away once we will implement standard +# behavior. +--disable_warnings +drop function if exists bug11555_1; +drop function if exists bug11555_2; +drop view if exists v1, v2, v3, v4; +--enable_warnings +create function bug11555_1() returns int return (select max(i) from t1); +create function bug11555_2() returns int return bug11555_1(); +# It is OK to report name of implicitly used table which is missing +# when we create view. +--error ER_NO_SUCH_TABLE +create view v1 as select bug11555_1(); +--error ER_NO_SUCH_TABLE +create view v2 as select bug11555_2(); +# But we should hide name of missing implicitly used table when we use view +create table t1 (i int); +create view v1 as select bug11555_1(); +create view v2 as select bug11555_2(); +create view v3 as select * from v1; +drop table t1; +--error ER_VIEW_INVALID +select * from v1; +--error ER_VIEW_INVALID +select * from v2; +--error ER_VIEW_INVALID +select * from v3; +# Note that creation of view which depends on broken view is yet +# another form of view usage. +--error ER_VIEW_INVALID +create view v4 as select * from v1; +drop view v1, v2, v3; +# We also should hide details about broken triggers which are +# invoked for view. +drop function bug11555_1; +drop function bug11555_2; +create table t1 (i int); +create table t2 (i int); +create trigger t1_ai after insert on t1 for each row insert into t2 values (new.i); +create view v1 as select * from t1; +drop table t2; +--error ER_VIEW_INVALID +insert into v1 values (1); +drop trigger t1_ai; +create function bug11555_1() returns int return (select max(i) from t2); +create trigger t1_ai after insert on t1 for each row set @a:=bug11555_1(); +--error ER_VIEW_INVALID +insert into v1 values (2); +drop function bug11555_1; +drop table t1; +drop view v1; + + # BUG#NNNN: New bug synopsis # #--disable_warnings diff --git a/mysql-test/t/sp.test b/mysql-test/t/sp.test index f8b638da59d..f73288f04ba 100644 --- a/mysql-test/t/sp.test +++ b/mysql-test/t/sp.test @@ -4914,24 +4914,24 @@ drop procedure bug14376| # --disable_warnings -drop procedure if exists p1| -drop table if exists t1| +drop procedure if exists bug5967| +drop table if exists t3| --enable_warnings -create table t1 (a varchar(255))| -insert into t1 (a) values ("a - table column")| -create procedure p1(a varchar(255)) +create table t3 (a varchar(255))| +insert into t3 (a) values ("a - table column")| +create procedure bug5967(a varchar(255)) begin declare i varchar(255); - declare c cursor for select a from t1; + declare c cursor for select a from t3; select a; - select a from t1 into i; + select a from t3 into i; select i as 'Parameter takes precedence over table column'; open c; fetch c into i; close c; select i as 'Parameter takes precedence over table column in cursors'; begin declare a varchar(255) default 'a - local variable'; - declare c1 cursor for select a from t1; + declare c1 cursor for select a from t3; select a as 'A local variable takes precedence over parameter'; open c1; fetch c1 into i; @@ -4939,9 +4939,9 @@ begin select i as 'A local variable takes precedence over parameter in cursors'; begin declare a varchar(255) default 'a - local variable in a nested compound statement'; - declare c2 cursor for select a from t1; + declare c2 cursor for select a from t3; select a as 'A local variable in a nested compound statement takes precedence over a local variable in the outer statement'; - select a from t1 into i; + select a from t3 into i; select i as 'A local variable in a nested compound statement takes precedence over table column'; open c2; fetch c2 into i; @@ -4950,8 +4950,8 @@ begin end; end; end| -call p1("a - stored procedure parameter")| -drop procedure p1| +call bug5967("a - stored procedure parameter")| +drop procedure bug5967| # # Bug#13012 "SP: REPAIR/BACKUP/RESTORE TABLE crashes the server" @@ -5029,6 +5029,56 @@ drop schema if exists mysqltest3| use test| # +# Bug#15441 "Running SP causes Server to Crash": check that an SP variable +# can not be used in VALUES() function. +# +--disable_warnings +drop table if exists t3| +drop procedure if exists bug15441| +--enable_warnings +create table t3 (id int not null primary key, county varchar(25))| +insert into t3 (id, county) values (1, 'York')| + +# First check that a stored procedure that refers to a parameter in VALUES() +# function won't parse. + +create procedure bug15441(c varchar(25)) +begin + update t3 set id=2, county=values(c); +end| +--error ER_BAD_FIELD_ERROR +call bug15441('county')| +drop procedure bug15441| + +# Now check the case when there is an ambiguity between column names +# and stored procedure parameters: the parser shall resolve the argument +# of VALUES() function to the column name. + +# It's hard to deduce what county refers to in every case (INSERT statement): +# 1st county refers to the column +# 2nd county refers to the procedure parameter +# 3d and 4th county refers to the column, again, but +# for 4th county it has the value of SP parameter + +# In UPDATE statement, just check that values() function returns NULL for +# non- INSERT...UPDATE statements, as stated in the manual. + +create procedure bug15441(county varchar(25)) +begin + declare c varchar(25) default "hello"; + + insert into t3 (id, county) values (1, county) + on duplicate key update county= values(county); + select * from t3; + + update t3 set id=2, county=values(id); + select * from t3; +end| +call bug15441('Yale')| +drop table t3| +drop procedure bug15441| + +# # BUG#NNNN: New bug synopsis # #--disable_warnings diff --git a/mysql-test/t/subselect.test b/mysql-test/t/subselect.test index cc621fb5835..762ff36ba63 100644 --- a/mysql-test/t/subselect.test +++ b/mysql-test/t/subselect.test @@ -1968,3 +1968,86 @@ drop table t1; purge master logs before (select adddate(current_timestamp(), interval -4 day)); +# +# Test for bug #11762: subquery with an aggregate function in HAVING +# + +CREATE TABLE t1 (a int, b int); +CREATE TABLE t2 (c int, d int); +CREATE TABLE t3 (e int); + +INSERT INTO t1 VALUES + (1,10), (2,10), (1,20), (2,20), (3,20), (2,30), (4,40); +INSERT INTO t2 VALUES + (2,10), (2,20), (4,10), (5,10), (3,20), (2,40); +INSERT INTO t3 VALUES (10), (30), (10), (20) ; + +SELECT a, MAX(b), MIN(b) FROM t1 GROUP BY a; +SELECT * FROM t2; +SELECT * FROM t3; + +SELECT a FROM t1 GROUP BY a + HAVING a IN (SELECT c FROM t2 WHERE MAX(b)>20); +SELECT a FROM t1 GROUP BY a + HAVING a IN (SELECT c FROM t2 WHERE MAX(b)<d); +SELECT a FROM t1 GROUP BY a + HAVING a IN (SELECT c FROM t2 WHERE MAX(b)>d); +SELECT a FROM t1 GROUP BY a + HAVING a IN (SELECT c FROM t2 + WHERE d >= SOME(SELECT e FROM t3 WHERE MAX(b)=e)); +SELECT a FROM t1 GROUP BY a + HAVING a IN (SELECT c FROM t2 + WHERE EXISTS(SELECT e FROM t3 WHERE MAX(b)=e AND e <= d)); +SELECT a FROM t1 GROUP BY a + HAVING a IN (SELECT c FROM t2 + WHERE d > SOME(SELECT e FROM t3 WHERE MAX(b)=e)); +SELECT a FROM t1 GROUP BY a + HAVING a IN (SELECT c FROM t2 + WHERE EXISTS(SELECT e FROM t3 WHERE MAX(b)=e AND e < d)); +SELECT a FROM t1 GROUP BY a + HAVING a IN (SELECT c FROM t2 + WHERE MIN(b) < d AND + EXISTS(SELECT e FROM t3 WHERE MAX(b)=e AND e <= d)); + +SELECT a, SUM(a) FROM t1 GROUP BY a; + +SELECT a FROM t1 + WHERE EXISTS(SELECT c FROM t2 GROUP BY c HAVING SUM(a) = c) GROUP BY a; +SELECT a FROM t1 GROUP BY a + HAVING EXISTS(SELECT c FROM t2 GROUP BY c HAVING SUM(a) = c); + +SELECT a FROM t1 + WHERE a < 3 AND + EXISTS(SELECT c FROM t2 GROUP BY c HAVING SUM(a) != c) GROUP BY a; +SELECT a FROM t1 + WHERE a < 3 AND + EXISTS(SELECT c FROM t2 GROUP BY c HAVING SUM(a) != c); + +SELECT t1.a FROM t1 GROUP BY t1.a + HAVING t1.a < ALL(SELECT t2.c FROM t2 GROUP BY t2.c + HAVING EXISTS(SELECT t3.e FROM t3 GROUP BY t3.e + HAVING SUM(t1.a+t2.c) < t3.e/4)); +SELECT t1.a FROM t1 GROUP BY t1.a + HAVING t1.a > ALL(SELECT t2.c FROM t2 + WHERE EXISTS(SELECT t3.e FROM t3 GROUP BY t3.e + HAVING SUM(t1.a+t2.c) < t3.e/4)); +-- error 1111 +SELECT t1.a FROM t1 GROUP BY t1.a + HAVING t1.a > ALL(SELECT t2.c FROM t2 + WHERE EXISTS(SELECT t3.e FROM t3 + WHERE SUM(t1.a+t2.c) < t3.e/4)); +-- error 1111 +SELECT t1.a from t1 GROUP BY t1.a HAVING AVG(SUM(t1.b)) > 20; + +SELECT t1.a FROM t1 GROUP BY t1.a + HAVING t1.a IN (SELECT t2.c FROM t2 GROUP BY t2.c + HAVING AVG(t2.c+SUM(t1.b)) > 20); +SELECT t1.a FROM t1 GROUP BY t1.a + HAVING t1.a IN (SELECT t2.c FROM t2 GROUP BY t2.c + HAVING AVG(SUM(t1.b)) > 20); + +SELECT t1.a, SUM(b) AS sum FROM t1 GROUP BY t1.a + HAVING t1.a IN (SELECT t2.c FROM t2 GROUP BY t2.c + HAVING t2.c+sum > 20); + +DROP TABLE t1,t2,t3; diff --git a/mysql-test/t/symlink.test b/mysql-test/t/symlink.test index b7a7e83d569..6a6dd305006 100644 --- a/mysql-test/t/symlink.test +++ b/mysql-test/t/symlink.test @@ -3,6 +3,8 @@ disable_query_log; show variables like "have_symlink"; enable_query_log; +--source include/not_windows.inc + --disable_warnings drop table if exists t1,t2,t7,t8,t9; drop database if exists mysqltest; diff --git a/mysql-test/t/trigger-compat.test b/mysql-test/t/trigger-compat.test index ace18639172..c2acc235135 100644 --- a/mysql-test/t/trigger-compat.test +++ b/mysql-test/t/trigger-compat.test @@ -61,7 +61,7 @@ CREATE TRIGGER wl2818_trg1 BEFORE INSERT ON t1 --echo --echo ---> patching t1.TRG... ---exec grep --text -v 'definers=' $MYSQL_TEST_DIR/var/master-data/mysqltest_db1/t1.TRG > $MYSQL_TEST_DIR/var/tmp/t1.TRG +--exec grep -v 'definers=' $MYSQL_TEST_DIR/var/master-data/mysqltest_db1/t1.TRG > $MYSQL_TEST_DIR/var/tmp/t1.TRG --exec mv $MYSQL_TEST_DIR/var/tmp/t1.TRG $MYSQL_TEST_DIR/var/master-data/mysqltest_db1/t1.TRG # diff --git a/mysql-test/t/trigger-grant.test b/mysql-test/t/trigger-grant.test index c058816ee75..deeaeacbccc 100644 --- a/mysql-test/t/trigger-grant.test +++ b/mysql-test/t/trigger-grant.test @@ -449,7 +449,7 @@ CREATE TRIGGER trg5 BEFORE DELETE ON t1 FOR EACH ROW SET @a = 5; ---exec egrep --text -v '^definers=' $MYSQL_TEST_DIR/var/master-data/mysqltest_db1/t1.TRG > $MYSQL_TEST_DIR/var/tmp/t1.TRG +--exec egrep -v '^definers=' $MYSQL_TEST_DIR/var/master-data/mysqltest_db1/t1.TRG > $MYSQL_TEST_DIR/var/tmp/t1.TRG --exec echo "definers='' '@' '@abc@def@@' '@hostname' '@abcdef@@@hostname'" >> $MYSQL_TEST_DIR/var/tmp/t1.TRG --exec mv $MYSQL_TEST_DIR/var/tmp/t1.TRG $MYSQL_TEST_DIR/var/master-data/mysqltest_db1/t1.TRG diff --git a/mysql-test/t/trigger.test b/mysql-test/t/trigger.test index d4fa5268762..b4074897689 100644 --- a/mysql-test/t/trigger.test +++ b/mysql-test/t/trigger.test @@ -13,6 +13,8 @@ drop procedure if exists p1; # Create additional connections used through test connect (addconroot1, localhost, root,,); connect (addconroot2, localhost, root,,); +# Connection without current database set +connect (addconwithoutdb, localhost, root,,*NO-ONE*); connection default; create table t1 (i int); @@ -946,3 +948,16 @@ CALL p2(); drop procedure p2; drop table t1; +# +# Test for bug #14863 "Triggers: crash if create and there is no current +# database". We should not crash and give proper error when database for +# trigger or its table is not specified and there is no current database. +# +connection addconwithoutdb; +--error ER_NO_DB_ERROR +create trigger t1_bi before insert on test.t1 for each row set @a:=0; +--error ER_NO_DB_ERROR +create trigger test.t1_bi before insert on t1 for each row set @a:=0; +--error ER_NO_DB_ERROR +drop trigger t1_bi; +connection default; diff --git a/mysql-test/t/type_time.test b/mysql-test/t/type_time.test index 7ae3f65f7cc..9abfe914335 100644 --- a/mysql-test/t/type_time.test +++ b/mysql-test/t/type_time.test @@ -21,4 +21,18 @@ select t, time_to_sec(t),sec_to_time(time_to_sec(t)) from t1; select sec_to_time(time_to_sec(t)) from t1; drop table t1; +# +# BUG #12440: Incorrect processing of time values containing +# long fraction part and/or large exponent part. +# +# These must return normal result: +SELECT CAST(235959.123456 AS TIME); +SELECT CAST(0.235959123456e+6 AS TIME); +SELECT CAST(235959123456e-6 AS TIME); +# These must cut fraction part and produce warning: +SELECT CAST(235959.1234567 AS TIME); +SELECT CAST(0.2359591234567e6 AS TIME); +# This must return NULL and produce warning: +SELECT CAST(0.2359591234567e+30 AS TIME); + # End of 4.1 tests diff --git a/mysql-test/t/view.test b/mysql-test/t/view.test index d58d74cdb7c..718e1a9932b 100644 --- a/mysql-test/t/view.test +++ b/mysql-test/t/view.test @@ -1744,7 +1744,6 @@ drop function f1; CHECK TABLE v1, v2, v3, v4, v5, v6; create function f1 () returns int return (select max(col1) from t1); DROP TABLE t1; -# following will show underlying table until BUG#11555 fix CHECK TABLE v1, v2, v3, v4, v5, v6; drop function f1; drop function f2; @@ -2320,3 +2319,22 @@ CREATE VIEW v2 AS SELECT f1(); select * from v2; drop view v2,v1; drop function f1; + +# +# Bug#14861: aliased column names are not preserved. +# +create table t1 (id numeric, warehouse_id numeric); +create view v1 as select id from t1; +create view v2 as +select t1.warehouse_id, v1.id as receipt_id +from t1, v1 where t1.id = v1.id; + +insert into t1 (id, warehouse_id) values(3, 2); +insert into t1 (id, warehouse_id) values(4, 2); +insert into t1 (id, warehouse_id) values(5, 1); + +select v2.receipt_id as alias1, v2.receipt_id as alias2 from v2 +order by v2.receipt_id; + +drop view v2, v1; +drop table t1; diff --git a/mysys/charset-def.c b/mysys/charset-def.c index 5b30d1ee135..0559fe59d06 100644 --- a/mysys/charset-def.c +++ b/mysys/charset-def.c @@ -43,6 +43,7 @@ extern CHARSET_INFO my_charset_ucs2_spanish2_uca_ci; extern CHARSET_INFO my_charset_ucs2_roman_uca_ci; extern CHARSET_INFO my_charset_ucs2_persian_uca_ci; extern CHARSET_INFO my_charset_ucs2_esperanto_uca_ci; +extern CHARSET_INFO my_charset_ucs2_hungarian_uca_ci; #endif #ifdef HAVE_CHARSET_utf8 @@ -64,6 +65,7 @@ extern CHARSET_INFO my_charset_utf8_spanish2_uca_ci; extern CHARSET_INFO my_charset_utf8_roman_uca_ci; extern CHARSET_INFO my_charset_utf8_persian_uca_ci; extern CHARSET_INFO my_charset_utf8_esperanto_uca_ci; +extern CHARSET_INFO my_charset_utf8_hungarian_uca_ci; #ifdef HAVE_UTF8_GENERAL_CS extern CHARSET_INFO my_charset_utf8_general_cs; #endif @@ -151,6 +153,7 @@ my_bool init_compiled_charsets(myf flags __attribute__((unused))) add_compiled_collation(&my_charset_ucs2_roman_uca_ci); add_compiled_collation(&my_charset_ucs2_persian_uca_ci); add_compiled_collation(&my_charset_ucs2_esperanto_uca_ci); + add_compiled_collation(&my_charset_ucs2_hungarian_uca_ci); #endif #endif @@ -184,6 +187,7 @@ my_bool init_compiled_charsets(myf flags __attribute__((unused))) add_compiled_collation(&my_charset_utf8_roman_uca_ci); add_compiled_collation(&my_charset_utf8_persian_uca_ci); add_compiled_collation(&my_charset_utf8_esperanto_uca_ci); + add_compiled_collation(&my_charset_utf8_hungarian_uca_ci); #endif #endif diff --git a/ndb/include/kernel/signaldata/DumpStateOrd.hpp b/ndb/include/kernel/signaldata/DumpStateOrd.hpp index bde690e056d..4dd22cf5092 100644 --- a/ndb/include/kernel/signaldata/DumpStateOrd.hpp +++ b/ndb/include/kernel/signaldata/DumpStateOrd.hpp @@ -78,6 +78,8 @@ public: LqhDumpAllScanRec = 2301, LqhDumpAllActiveScanRec = 2302, LqhDumpLcpState = 2303, + LqhErrorInsert5042 = 2315, + AccDumpOneScanRec = 2400, AccDumpAllScanRec = 2401, AccDumpAllActiveScanRec = 2402, diff --git a/ndb/include/ndb_version.h.in b/ndb/include/ndb_version.h.in index 826f5124407..38b72306d03 100644 --- a/ndb/include/ndb_version.h.in +++ b/ndb/include/ndb_version.h.in @@ -57,5 +57,8 @@ char ndb_version_string_buf[NDB_VERSION_STRING_BUF_SZ]; */ /*#define NDB_VERSION_ID 0*/ +#define NDBD_INCL_NODECONF_VERSION_4 MAKE_VERSION(4,1,17) +#define NDBD_INCL_NODECONF_VERSION_5 MAKE_VERSION(5,0,18) + #endif diff --git a/ndb/src/kernel/blocks/ERROR_codes.txt b/ndb/src/kernel/blocks/ERROR_codes.txt index 1a72537a77e..0be5e91cd71 100644 --- a/ndb/src/kernel/blocks/ERROR_codes.txt +++ b/ndb/src/kernel/blocks/ERROR_codes.txt @@ -61,6 +61,8 @@ Insert system error in GCP participant when receiving GCP_SAVEREQ. 5007: Delay GCP_SAVEREQ by 10 secs +7165: Delay INCL_NODE_REQ in starting node yeilding error in GCP_PREPARE + ERROR CODES FOR TESTING NODE FAILURE, LOCAL CHECKPOINT HANDLING: ----------------------------------------------------------------- @@ -155,11 +157,15 @@ Insert node failure handling when receiving COMPLETEREQ. 5006: Insert node failure handling when receiving ABORTREQ. +5042: +As 5002, but with specified table (see DumpStateOrd) + These error code can be combined with error codes for testing time-out handling in DBTC to ensure that node failures are also well handled in time-out handling. They can also be used to test multiple node failure handling. + ERROR CODES FOR TESTING TIME-OUT HANDLING IN DBLQH ------------------------------------------------- 5011: @@ -198,6 +204,9 @@ Delay execution of ABORTREQ signal 2 seconds to generate time-out. 8050: Send TCKEYREF is operation is non local +5100,5101: Drop ABORT req in primary replica + Crash on "next" ABORT + ERROR CODES FOR TESTING TIME-OUT HANDLING IN DBTC ------------------------------------------------- 8040: diff --git a/ndb/src/kernel/blocks/backup/Backup.cpp b/ndb/src/kernel/blocks/backup/Backup.cpp index 05ae8f3cbf3..2d50890e962 100644 --- a/ndb/src/kernel/blocks/backup/Backup.cpp +++ b/ndb/src/kernel/blocks/backup/Backup.cpp @@ -3871,7 +3871,7 @@ Backup::checkFile(Signal* signal, BackupFilePtr filePtr) req->userReference = reference(); req->varIndex = 0; req->offset = tmp - c_startOfPages; - req->size = sz; // Avrunda uppot + req->size = sz; // Round up sendSignal(NDBFS_REF, GSN_FSAPPENDREQ, signal, FsAppendReq::SignalLength, JBA); diff --git a/ndb/src/kernel/blocks/dbdih/DbdihMain.cpp b/ndb/src/kernel/blocks/dbdih/DbdihMain.cpp index 29de0368212..2a28c4db770 100644 --- a/ndb/src/kernel/blocks/dbdih/DbdihMain.cpp +++ b/ndb/src/kernel/blocks/dbdih/DbdihMain.cpp @@ -215,7 +215,7 @@ void Dbdih::sendINCL_NODEREQ(Signal* signal, Uint32 nodeId) signal->theData[2] = c_nodeStartMaster.failNr; signal->theData[3] = 0; signal->theData[4] = currentgcp; - sendSignal(nodeDihRef, GSN_INCL_NODEREQ, signal, 5, JBB); + sendSignal(nodeDihRef, GSN_INCL_NODEREQ, signal, 5, JBA); }//Dbdih::sendINCL_NODEREQ() void Dbdih::sendMASTER_GCPREQ(Signal* signal, Uint32 nodeId) @@ -1863,6 +1863,14 @@ void Dbdih::gcpBlockedLab(Signal* signal) // global checkpoint id and the correct state. We do not wait for any reply // since the starting node will not send any. /*-------------------------------------------------------------------------*/ + Uint32 startVersion = getNodeInfo(c_nodeStartMaster.startNode).m_version; + + if ((getMajor(startVersion) == 4 && startVersion >= NDBD_INCL_NODECONF_VERSION_4) || + (getMajor(startVersion) == 5 && startVersion >= NDBD_INCL_NODECONF_VERSION_5)) + { + c_INCL_NODEREQ_Counter.setWaitingFor(c_nodeStartMaster.startNode); + } + sendINCL_NODEREQ(signal, c_nodeStartMaster.startNode); }//Dbdih::gcpBlockedLab() @@ -2065,6 +2073,13 @@ void Dbdih::execINCL_NODEREQ(Signal* signal) jamEntry(); Uint32 retRef = signal->theData[0]; Uint32 nodeId = signal->theData[1]; + if (nodeId == getOwnNodeId() && ERROR_INSERTED(7165)) + { + CLEAR_ERROR_INSERT_VALUE; + sendSignalWithDelay(reference(), GSN_INCL_NODEREQ, signal, 5000, signal->getLength()); + return; + } + Uint32 tnodeStartFailNr = signal->theData[2]; currentgcp = signal->theData[4]; CRASH_INSERTION(7127); @@ -2092,6 +2107,15 @@ void Dbdih::execINCL_NODEREQ(Signal* signal) // id's and the lcp status. /*-----------------------------------------------------------------------*/ CRASH_INSERTION(7171); + Uint32 masterVersion = getNodeInfo(refToNode(cmasterdihref)).m_version; + + if ((NDB_VERSION_MAJOR == 4 && masterVersion >= NDBD_INCL_NODECONF_VERSION_4) || + (NDB_VERSION_MAJOR == 5 && masterVersion >= NDBD_INCL_NODECONF_VERSION_5)) + { + signal->theData[0] = getOwnNodeId(); + signal->theData[1] = getOwnNodeId(); + sendSignal(cmasterdihref, GSN_INCL_NODECONF, signal, 2, JBB); + } return; }//if if (getNodeStatus(nodeId) != NodeRecord::STARTING) { @@ -3741,9 +3765,23 @@ void Dbdih::execNODE_FAILREP(Signal* signal) /*------------------------------------------------------------------------*/ // Verify that a starting node has also crashed. Reset the node start record. /*-------------------------------------------------------------------------*/ - if (c_nodeStartMaster.startNode != RNIL) { - ndbrequire(getNodeStatus(c_nodeStartMaster.startNode)!= NodeRecord::ALIVE); +#if 0 + /** + * Node will crash by itself... + * nodeRestart is run then... + */ + if (false && c_nodeStartMaster.startNode != RNIL && getNodeStatus(c_nodeStartMaster.startNode) == NodeRecord::ALIVE) + { + BlockReference cntrRef = calcNdbCntrBlockRef(c_nodeStartMaster.startNode); + SystemError * const sysErr = (SystemError*)&signal->theData[0]; + sysErr->errorCode = SystemError::StartInProgressError; + sysErr->errorRef = reference(); + sysErr->data1= 0; + sysErr->data2= __LINE__; + sendSignal(cntrRef, GSN_SYSTEM_ERROR, signal, SystemError::SignalLength, JBA); + nodeResetStart(); }//if +#endif /*--------------------------------------------------*/ /* */ @@ -5189,15 +5227,16 @@ void Dbdih::removeNodeFromTable(Signal* signal, /** * For each of replica record */ - Uint32 replicaNo = 0; + bool found = false; ReplicaRecordPtr replicaPtr; for(replicaPtr.i = fragPtr.p->storedReplicas; replicaPtr.i != RNIL; - replicaPtr.i = replicaPtr.p->nextReplica, replicaNo++) { + replicaPtr.i = replicaPtr.p->nextReplica) { jam(); ptrCheckGuard(replicaPtr, creplicaFileSize, replicaRecord); if(replicaPtr.p->procNode == nodeId){ jam(); + found = true; noOfRemovedReplicas++; removeNodeFromStored(nodeId, fragPtr, replicaPtr); if(replicaPtr.p->lcpOngoingFlag){ @@ -5213,6 +5252,15 @@ void Dbdih::removeNodeFromTable(Signal* signal, } } } + if (!found) + { + jam(); + /** + * Run updateNodeInfo to remove any dead nodes from list of activeNodes + * see bug#15587 + */ + updateNodeInfo(fragPtr); + } noOfRemainingLcpReplicas += fragPtr.p->noLcpReplicas; } @@ -11087,7 +11135,11 @@ void Dbdih::initCommonData() cnoReplicas = 1; ndb_mgm_get_int_parameter(p, CFG_DB_NO_REPLICAS, &cnoReplicas); - cnoReplicas = cnoReplicas > 4 ? 4 : cnoReplicas; + if (cnoReplicas > 4) + { + progError(__LINE__, NDBD_EXIT_INVALID_CONFIG, + "Only up to four replicas are supported. Check NoOfReplicas."); + } cgcpDelay = 2000; ndb_mgm_get_int_parameter(p, CFG_DB_GCP_INTERVAL, &cgcpDelay); @@ -11675,14 +11727,14 @@ void Dbdih::execCHECKNODEGROUPSREQ(Signal* signal) break; case CheckNodeGroups::GetNodeGroupMembers: { ok = true; - Uint32 ownNodeGoup = + Uint32 ownNodeGroup = Sysfile::getNodeGroup(sd->nodeId, SYSFILE->nodeGroups); - sd->output = ownNodeGoup; + sd->output = ownNodeGroup; sd->mask.clear(); NodeGroupRecordPtr ngPtr; - ngPtr.i = ownNodeGoup; + ngPtr.i = ownNodeGroup; ptrAss(ngPtr, nodeGroupRecord); for (Uint32 j = 0; j < ngPtr.p->nodeCount; j++) { jam(); @@ -11690,7 +11742,7 @@ void Dbdih::execCHECKNODEGROUPSREQ(Signal* signal) } #if 0 for (int i = 0; i < MAX_NDB_NODES; i++) { - if (ownNodeGoup == + if (ownNodeGroup == Sysfile::getNodeGroup(i, SYSFILE->nodeGroups)) { sd->mask.set(i); } diff --git a/ndb/src/kernel/blocks/dblqh/Dblqh.hpp b/ndb/src/kernel/blocks/dblqh/Dblqh.hpp index 94a40adcd4a..1ed383853ba 100644 --- a/ndb/src/kernel/blocks/dblqh/Dblqh.hpp +++ b/ndb/src/kernel/blocks/dblqh/Dblqh.hpp @@ -2885,6 +2885,7 @@ private: UintR ctransidHash[1024]; Uint32 c_diskless; + Uint32 c_error_insert_table_id; public: /** diff --git a/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp b/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp index 2170f890f35..803377f9dd1 100644 --- a/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp +++ b/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp @@ -3543,6 +3543,7 @@ void Dblqh::execLQHKEYREQ(Signal* signal) jam(); regTcPtr->activeCreat = ZTRUE; CRASH_INSERTION(5002); + CRASH_INSERTION2(5042, tabptr.i == c_error_insert_table_id); } else { regTcPtr->activeCreat = ZFALSE; }//if @@ -5880,12 +5881,21 @@ void Dblqh::execABORT(Signal* signal) warningReport(signal, 8); return; }//if + + TcConnectionrec * const regTcPtr = tcConnectptr.p; + + if (ERROR_INSERTED(5100)) + { + SET_ERROR_INSERT_VALUE(5101); + return; + } + CRASH_INSERTION2(5101, regTcPtr->nextReplica != ZNIL); + /* ------------------------------------------------------------------------- */ /*A GUIDING DESIGN PRINCIPLE IN HANDLING THESE ERROR SITUATIONS HAVE BEEN */ /*KEEP IT SIMPLE. THUS WE RATHER INSERT A WAIT AND SET THE ABORT_STATE TO */ /*ACTIVE RATHER THAN WRITE NEW CODE TO HANDLE EVERY SPECIAL SITUATION. */ /* ------------------------------------------------------------------------- */ - TcConnectionrec * const regTcPtr = tcConnectptr.p; if (regTcPtr->nextReplica != ZNIL) { /* ------------------------------------------------------------------------- */ // We will immediately send the ABORT message also to the next LQH node in line. @@ -18522,6 +18532,12 @@ Dblqh::execDUMP_STATE_ORD(Signal* signal) } } + + if (dumpState->args[0] == DumpStateOrd::LqhErrorInsert5042 && signal->getLength() == 2) + { + c_error_insert_table_id = dumpState->args[1]; + SET_ERROR_INSERT_VALUE(5042); + } }//Dblqh::execDUMP_STATE_ORD() void Dblqh::execSET_VAR_REQ(Signal* signal) @@ -18562,60 +18578,54 @@ void Dblqh::execCREATE_TRIG_REQ(Signal* signal) { jamEntry(); - NodeId myNodeId = getOwnNodeId(); - BlockReference tupref = calcTupBlockRef(myNodeId); - sendSignal(tupref, GSN_CREATE_TRIG_REQ, signal, CreateTrigReq::SignalLength, JBB); + sendSignal(DBTUP_REF, GSN_CREATE_TRIG_REQ, signal, + CreateTrigReq::SignalLength, JBB); } void Dblqh::execCREATE_TRIG_CONF(Signal* signal) { jamEntry(); - NodeId myNodeId = getOwnNodeId(); - BlockReference dictref = calcDictBlockRef(myNodeId); - sendSignal(dictref, GSN_CREATE_TRIG_CONF, signal, CreateTrigConf::SignalLength, JBB); + sendSignal(DBDICT_REF, GSN_CREATE_TRIG_CONF, signal, + CreateTrigConf::SignalLength, JBB); } void Dblqh::execCREATE_TRIG_REF(Signal* signal) { jamEntry(); - NodeId myNodeId = getOwnNodeId(); - BlockReference dictref = calcDictBlockRef(myNodeId); - sendSignal(dictref, GSN_CREATE_TRIG_REF, signal, CreateTrigRef::SignalLength, JBB); + sendSignal(DBDICT_REF, GSN_CREATE_TRIG_REF, signal, + CreateTrigRef::SignalLength, JBB); } void Dblqh::execDROP_TRIG_REQ(Signal* signal) { jamEntry(); - NodeId myNodeId = getOwnNodeId(); - BlockReference tupref = calcTupBlockRef(myNodeId); - sendSignal(tupref, GSN_DROP_TRIG_REQ, signal, DropTrigReq::SignalLength, JBB); + sendSignal(DBTUP_REF, GSN_DROP_TRIG_REQ, signal, + DropTrigReq::SignalLength, JBB); } void Dblqh::execDROP_TRIG_CONF(Signal* signal) { jamEntry(); - NodeId myNodeId = getOwnNodeId(); - BlockReference dictref = calcDictBlockRef(myNodeId); - sendSignal(dictref, GSN_DROP_TRIG_CONF, signal, DropTrigConf::SignalLength, JBB); + sendSignal(DBDICT_REF, GSN_DROP_TRIG_CONF, signal, + DropTrigConf::SignalLength, JBB); } void Dblqh::execDROP_TRIG_REF(Signal* signal) { jamEntry(); - NodeId myNodeId = getOwnNodeId(); - BlockReference dictref = calcDictBlockRef(myNodeId); - sendSignal(dictref, GSN_DROP_TRIG_REF, signal, DropTrigRef::SignalLength, JBB); + sendSignal(DBDICT_REF, GSN_DROP_TRIG_REF, signal, + DropTrigRef::SignalLength, JBB); } Uint32 Dblqh::calcPageCheckSum(LogPageRecordPtr logP){ diff --git a/ndb/src/kernel/blocks/dbtc/Dbtc.hpp b/ndb/src/kernel/blocks/dbtc/Dbtc.hpp index 8218acc0ea7..cb4f1c6244b 100644 --- a/ndb/src/kernel/blocks/dbtc/Dbtc.hpp +++ b/ndb/src/kernel/blocks/dbtc/Dbtc.hpp @@ -141,6 +141,8 @@ #define ZALREADYEXIST 630 #define ZINCONSISTENTHASHINDEX 892 #define ZNOTUNIQUE 893 + +#define ZINVALID_KEY 290 #endif class Dbtc: public SimulatedBlock { diff --git a/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp b/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp index f2646fd4176..d7232030c41 100644 --- a/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp +++ b/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp @@ -2313,7 +2313,10 @@ Dbtc::handle_special_hash(Uint32 dstHash[4], Uint32* src, Uint32 srcLen, { keyPartLenPtr = keyPartLen; dstPos = xfrm_key(tabPtrI, src, dst, sizeof(Tmp) >> 2, keyPartLenPtr); - ndbrequire(dstPos); + if (unlikely(dstPos == 0)) + { + goto error; + } } else { @@ -2334,6 +2337,10 @@ Dbtc::handle_special_hash(Uint32 dstHash[4], Uint32* src, Uint32 srcLen, dstHash[1] = tmp[1]; } return true; // success + +error: + terrorCode = ZINVALID_KEY; + return false; } /* @@ -2941,7 +2948,15 @@ void Dbtc::tckeyreq050Lab(Signal* signal) UintR tnoOfStandby; UintR tnodeinfo; + terrorCode = 0; + hash(signal); /* NOW IT IS TIME TO CALCULATE THE HASH VALUE*/ + + if (unlikely(terrorCode)) + { + releaseAtErrorLab(signal); + return; + } CacheRecord * const regCachePtr = cachePtr.p; TcConnectRecord * const regTcPtr = tcConnectptr.p; @@ -6183,7 +6198,6 @@ void Dbtc::timeOutFoundLab(Signal* signal, Uint32 TapiConPtr) << " - place: " << c_apiConTimer_line[apiConnectptr.i]); switch (apiConnectptr.p->apiConnectstate) { case CS_STARTED: - ndbrequire(c_apiConTimer_line[apiConnectptr.i] != 3615); if(apiConnectptr.p->lqhkeyreqrec == apiConnectptr.p->lqhkeyconfrec){ jam(); /* @@ -6443,8 +6457,8 @@ void Dbtc::sendAbortedAfterTimeout(Signal* signal, int Tcheck) warningEvent(buf); ndbout_c(buf); ndbrequire(false); + releaseAbortResources(signal); } - releaseAbortResources(signal); return; }//if TloopCount++; diff --git a/ndb/src/kernel/vm/SimulatedBlock.cpp b/ndb/src/kernel/vm/SimulatedBlock.cpp index 4625cd43640..3fe76e45322 100644 --- a/ndb/src/kernel/vm/SimulatedBlock.cpp +++ b/ndb/src/kernel/vm/SimulatedBlock.cpp @@ -1872,6 +1872,8 @@ SimulatedBlock::xfrm_key(Uint32 tab, const Uint32* src, xfrm_attr(keyAttr.attributeDescriptor, keyAttr.charsetInfo, src, srcPos, dst, dstPos, dstSize); keyPartLen[i++] = dstWords; + if (unlikely(dstWords == 0)) + return 0; } return dstPos; @@ -1900,7 +1902,8 @@ SimulatedBlock::xfrm_attr(Uint32 attrDesc, CHARSET_INFO* cs, Uint32 typeId = AttributeDescriptor::getType(attrDesc); Uint32 lb, len; bool ok = NdbSqlUtil::get_var_length(typeId, srcPtr, srcBytes, lb, len); - ndbrequire(ok); + if (unlikely(!ok)) + return 0; Uint32 xmul = cs->strxfrm_multiply; if (xmul == 0) xmul = 1; @@ -1911,7 +1914,8 @@ SimulatedBlock::xfrm_attr(Uint32 attrDesc, CHARSET_INFO* cs, Uint32 dstLen = xmul * (srcBytes - lb); ndbrequire(dstLen <= ((dstSize - dstPos) << 2)); int n = NdbSqlUtil::strnxfrm_bug7284(cs, dstPtr, dstLen, srcPtr + lb, len); - ndbrequire(n != -1); + if (unlikely(n == -1)) + return 0; while ((n & 3) != 0) { dstPtr[n++] = 0; diff --git a/ndb/src/ndbapi/ndberror.c b/ndb/src/ndbapi/ndberror.c index 4a9ac9affb7..5ca8ad7be60 100644 --- a/ndb/src/ndbapi/ndberror.c +++ b/ndb/src/ndbapi/ndberror.c @@ -227,6 +227,7 @@ ErrorBundle ErrorCodes[] = { { 277, IE, "277" }, { 278, IE, "278" }, { 287, IE, "Index corrupted" }, + { 290, IE, "Corrupt key in TC, unable to xfrm" }, { 631, IE, "631" }, { 632, IE, "632" }, { 702, IE, "Request to non-master" }, @@ -295,7 +296,6 @@ ErrorBundle ErrorCodes[] = { { 4608, AE, "You can not takeOverScan unless you have used openScanExclusive"}, { 4609, AE, "You must call nextScanResult before trying to takeOverScan"}, { 4232, AE, "Parallelism can only be between 1 and 240" }, - { 290, AE, "Scan not started or has been closed by kernel due to timeout" }, /** * Event schema errors diff --git a/ndb/test/ndbapi/testNodeRestart.cpp b/ndb/test/ndbapi/testNodeRestart.cpp index 6ef3da2d760..92d6c1830ef 100644 --- a/ndb/test/ndbapi/testNodeRestart.cpp +++ b/ndb/test/ndbapi/testNodeRestart.cpp @@ -21,6 +21,7 @@ #include <NdbRestarter.hpp> #include <NdbRestarts.hpp> #include <Vector.hpp> +#include <signaldata/DumpStateOrd.hpp> int runLoadTable(NDBT_Context* ctx, NDBT_Step* step){ @@ -409,6 +410,132 @@ int runLateCommit(NDBT_Context* ctx, NDBT_Step* step){ return NDBT_OK; } +int runBug15587(NDBT_Context* ctx, NDBT_Step* step){ + int result = NDBT_OK; + int loops = ctx->getNumLoops(); + int records = ctx->getNumRecords(); + NdbRestarter restarter; + + Uint32 tableId = ctx->getTab()->getTableId(); + int dump[2] = { DumpStateOrd::LqhErrorInsert5042, 0 }; + dump[1] = tableId; + + int nodeId = restarter.getDbNodeId(1); + + ndbout << "Restart node " << nodeId << endl; + + if (restarter.restartOneDbNode(nodeId, + /** initial */ false, + /** nostart */ true, + /** abort */ true)) + return NDBT_FAILED; + + if (restarter.waitNodesNoStart(&nodeId, 1)) + return NDBT_FAILED; + + if (restarter.dumpStateOneNode(nodeId, dump, 2)) + return NDBT_FAILED; + + if (restarter.startNodes(&nodeId, 1)) + return NDBT_FAILED; + + if (restarter.waitNodesStarted(&nodeId, 1)) + return NDBT_FAILED; + + ctx->stopTest(); + return NDBT_OK; +} + +int runBug15632(NDBT_Context* ctx, NDBT_Step* step){ + int result = NDBT_OK; + int loops = ctx->getNumLoops(); + int records = ctx->getNumRecords(); + NdbRestarter restarter; + + int nodeId = restarter.getDbNodeId(1); + + ndbout << "Restart node " << nodeId << endl; + + if (restarter.restartOneDbNode(nodeId, + /** initial */ false, + /** nostart */ true, + /** abort */ true)) + return NDBT_FAILED; + + if (restarter.waitNodesNoStart(&nodeId, 1)) + return NDBT_FAILED; + + if (restarter.insertErrorInNode(nodeId, 7165)) + return NDBT_FAILED; + + if (restarter.startNodes(&nodeId, 1)) + return NDBT_FAILED; + + if (restarter.waitNodesStarted(&nodeId, 1)) + return NDBT_FAILED; + + if (restarter.restartOneDbNode(nodeId, + /** initial */ false, + /** nostart */ true, + /** abort */ true)) + return NDBT_FAILED; + + if (restarter.waitNodesNoStart(&nodeId, 1)) + return NDBT_FAILED; + + if (restarter.insertErrorInNode(nodeId, 7171)) + return NDBT_FAILED; + + if (restarter.startNodes(&nodeId, 1)) + return NDBT_FAILED; + + if (restarter.waitNodesStarted(&nodeId, 1)) + return NDBT_FAILED; + + ctx->stopTest(); + return NDBT_OK; +} + +int runBug15685(NDBT_Context* ctx, NDBT_Step* step){ + + Ndb* pNdb = GETNDB(step); + HugoOperations hugoOps(*ctx->getTab()); + NdbRestarter restarter; + + HugoTransactions hugoTrans(*ctx->getTab()); + if (hugoTrans.loadTable(GETNDB(step), 10) != 0){ + return NDBT_FAILED; + } + + if(hugoOps.startTransaction(pNdb) != 0) + goto err; + + if(hugoOps.pkUpdateRecord(pNdb, 0, 1, rand()) != 0) + goto err; + + if(hugoOps.execute_NoCommit(pNdb) != 0) + goto err; + + if (restarter.insertErrorInAllNodes(5100)) + return NDBT_FAILED; + + hugoOps.execute_Rollback(pNdb); + + if (restarter.waitClusterStarted() != 0) + goto err; + + if (restarter.insertErrorInAllNodes(0)) + return NDBT_FAILED; + + ctx->stopTest(); + return NDBT_OK; + +err: + ctx->stopTest(); + return NDBT_FAILED; +} + + NDBT_TESTSUITE(testNodeRestart); TESTCASE("NoLoad", "Test that one node at a time can be stopped and then restarted "\ @@ -558,6 +685,8 @@ TESTCASE("RestartNFDuringNR", INITIALIZER(runCheckAllNodesStarted); INITIALIZER(runLoadTable); STEP(runRestarts); + STEP(runPkUpdateUntilStopped); + STEP(runScanUpdateUntilStopped); FINALIZER(runScanReadVerify); FINALIZER(runClearTable); } @@ -647,6 +776,8 @@ TESTCASE("RestartNodeDuringLCP", INITIALIZER(runCheckAllNodesStarted); INITIALIZER(runLoadTable); STEP(runRestarts); + STEP(runPkUpdateUntilStopped); + STEP(runScanUpdateUntilStopped); FINALIZER(runScanReadVerify); FINALIZER(runClearTable); } @@ -671,6 +802,24 @@ TESTCASE("LateCommit", STEP(runLateCommit); FINALIZER(runClearTable); } +TESTCASE("Bug15587", + "Test bug with NF during NR"){ + INITIALIZER(runLoadTable); + STEP(runScanUpdateUntilStopped); + STEP(runBug15587); + FINALIZER(runClearTable); +} +TESTCASE("Bug15632", + "Test bug with NF during NR"){ + INITIALIZER(runLoadTable); + STEP(runBug15632); + FINALIZER(runClearTable); +} +TESTCASE("Bug15685", + "Test bug with NF during abort"){ + STEP(runBug15685); + FINALIZER(runClearTable); +} NDBT_TESTSUITE_END(testNodeRestart); int main(int argc, const char** argv){ diff --git a/ndb/test/run-test/daily-basic-tests.txt b/ndb/test/run-test/daily-basic-tests.txt index 8b44594a9b5..59f51044b51 100644 --- a/ndb/test/run-test/daily-basic-tests.txt +++ b/ndb/test/run-test/daily-basic-tests.txt @@ -413,6 +413,27 @@ max-time: 500 cmd: testScan args: -n ScanParallelism +max-time: 500 +cmd: testNodeRestart +args: -n Bug15587 T1 + +max-time: 500 +cmd: testNodeRestart +args: -n Bug15632 T1 + +max-time: 500 +cmd: testNodeRestart +args: -n Bug15685 T1 + +# OLD FLEX +max-time: 500 +cmd: flexBench +args: -c 25 -t 10 + +max-time: 500 +cmd: flexHammer +args: -r 5 -t 32 + # # DICT TESTS max-time: 1500 diff --git a/ndb/tools/ndb_size.pl b/ndb/tools/ndb_size.pl index ece0901e0b2..e0085c619f0 100644 --- a/ndb/tools/ndb_size.pl +++ b/ndb/tools/ndb_size.pl @@ -146,9 +146,9 @@ foreach(@{$tables}) elsif($type =~ /varchar/ || $type =~ /varbinary/) { my $fixed= 1+$size; - my @dynamic=$dbh->selectrow_array("select avg(length(" - .$dbh->quote($name) - .")) from `".$table.'`'); + my @dynamic=$dbh->selectrow_array("select avg(length(`" + .$name. + ."`)) from `".$table.'`'); $dynamic[0]=0 if !$dynamic[0]; @realsize= ($fixed,$fixed,ceil($dynamic[0])); } diff --git a/netware/BUILD/compile-linux-tools b/netware/BUILD/compile-linux-tools index 26ac1d79f37..14422ea5a3f 100755 --- a/netware/BUILD/compile-linux-tools +++ b/netware/BUILD/compile-linux-tools @@ -28,7 +28,8 @@ rm -f */*.linux ./configure --without-innodb --without-docs # build tools only -make clean all-local +make clean +make # Create mysql_version.h which was deleted my previous step ./config.status include/mysql_version.h @@ -55,7 +56,7 @@ make clean all-local # copying required linux tools cp extra/comp_err extra/comp_err.linux cp libmysql/conf_to_src libmysql/conf_to_src.linux -cp libmysql_r/conf_to_src libmysql_r/conf_to_src.linux +#cp libmysql_r/conf_to_src libmysql_r/conf_to_src.linux cp sql/gen_lex_hash sql/gen_lex_hash.linux cp strings/conf_to_src strings/conf_to_src.linux diff --git a/netware/libmysql.def b/netware/libmysql.def index fea117dedd1..8a34754e092 100644 --- a/netware/libmysql.def +++ b/netware/libmysql.def @@ -7,5 +7,6 @@ COPYRIGHT "(c) 2003-2005 Novell, Inc. Portions (c) 2003 MySQL AB. All Rights Res DESCRIPTION "MySQL Client Library" VERSION 4, 0 AUTOUNLOAD +STACKSIZE 32768 XDCDATA ../netware/mysql.xdc #DEBUG diff --git a/netware/my_print_defaults.def b/netware/my_print_defaults.def index d88c5adf4cc..778a5204ebd 100644 --- a/netware/my_print_defaults.def +++ b/netware/my_print_defaults.def @@ -4,7 +4,7 @@ MODULE libc.nlm COPYRIGHT "(c) 2003-2005 Novell, Inc. Portions (c) 2003 MySQL AB. All Rights Reserved." DESCRIPTION "MySQL Print Defaults Tool" -VERSION 5, 0, 8 +VERSION 5, 0, 17 STACKSIZE 32767 XDCDATA ../netware/mysql.xdc #DEBUG diff --git a/netware/myisamlog.def b/netware/myisamlog.def index 3580c870c10..553a818a2ae 100644 --- a/netware/myisamlog.def +++ b/netware/myisamlog.def @@ -6,6 +6,7 @@ SCREENNAME "MySQL MyISAM Table Log Tool" COPYRIGHT "(c) 2003-2005 Novell, Inc. Portions (c) 2003 MySQL AB. All Rights Reserved." DESCRIPTION "MySQL MyISAM Table Log Tool" VERSION 4, 0 +STACKSIZE 32768 XDCDATA ../netware/mysql.xdc #DEBUG diff --git a/netware/myisampack.def b/netware/myisampack.def index a6946982236..d1f85fe03f8 100644 --- a/netware/myisampack.def +++ b/netware/myisampack.def @@ -6,6 +6,7 @@ SCREENNAME "MySQL MyISAM Table Pack Tool" COPYRIGHT "(c) 2003-2005 Novell, Inc. Portions (c) 2003 MySQL AB. All Rights Reserved." DESCRIPTION "MySQL MyISAM Table Pack Tool" VERSION 4, 0 +STACKSIZE 32768 XDCDATA ../netware/mysql.xdc #DEBUG diff --git a/netware/mysql_install_db.def b/netware/mysql_install_db.def index 1657b7c17af..372bbf15570 100644 --- a/netware/mysql_install_db.def +++ b/netware/mysql_install_db.def @@ -6,6 +6,7 @@ SCREENNAME "MySQL Install" COPYRIGHT "(c) 2003-2005 Novell, Inc. Portions (c) 2003 MySQL AB. All Rights Reserved." DESCRIPTION "MySQL Initial Database Installer" VERSION 4, 0 +STACKSIZE 32768 XDCDATA ../netware/mysql.xdc #DEBUG diff --git a/netware/mysqladmin.def b/netware/mysqladmin.def index e7f2d90bf9e..6532cab84a0 100644 --- a/netware/mysqladmin.def +++ b/netware/mysqladmin.def @@ -6,7 +6,7 @@ SCREENNAME "MySQL Admin[scrollable]" COPYRIGHT "(c) 2003-2005 Novell, Inc. Portions (c) 2003 MySQL AB. All Rights Reserved." DESCRIPTION "MySQL Admin Tool" VERSION 4, 0 -STACKSIZE 32767 +STACKSIZE 32768 XDCDATA ../netware/mysql.xdc #DEBUG diff --git a/netware/mysqlbinlog.def b/netware/mysqlbinlog.def index 3e75cf07a57..aced63429c5 100644 --- a/netware/mysqlbinlog.def +++ b/netware/mysqlbinlog.def @@ -6,6 +6,7 @@ SCREENNAME "MySQL Binary Log Dump Tool[scrollable]" COPYRIGHT "(c) 2003-2005 Novell, Inc. Portions (c) 2003 MySQL AB. All Rights Reserved." DESCRIPTION "MySQL Binary Log Dump Tool" VERSION 4, 0 +STACKSIZE 32768 XDCDATA ../netware/mysql.xdc #DEBUG diff --git a/netware/mysqlcheck.def b/netware/mysqlcheck.def index cb70c1b394d..1b90b2a1dbe 100644 --- a/netware/mysqlcheck.def +++ b/netware/mysqlcheck.def @@ -6,6 +6,7 @@ SCREENNAME "MySQL Check Tool[scrollable]" COPYRIGHT "(c) 2003-2005 Novell, Inc. Portions (c) 2003 MySQL AB. All Rights Reserved." DESCRIPTION "MySQL Check Tool" VERSION 4, 0 +STACKSIZE 32768 XDCDATA ../netware/mysql.xdc #DEBUG diff --git a/netware/mysqld_safe.def b/netware/mysqld_safe.def index 2a9ef04b47d..ff3f1924906 100644 --- a/netware/mysqld_safe.def +++ b/netware/mysqld_safe.def @@ -6,6 +6,7 @@ SCREENNAME "MySQL Database Server" COPYRIGHT "(c) 2003-2005 Novell, Inc. Portions (c) 2003 MySQL AB. All Rights Reserved." DESCRIPTION "MySQL Database Server Monitor" VERSION 4, 0 +STACKSIZE 32768 MULTIPLE XDCDATA ../netware/mysql.xdc #DEBUG diff --git a/netware/mysqldump.def b/netware/mysqldump.def index 811c53ce5f6..5d7999c789f 100644 --- a/netware/mysqldump.def +++ b/netware/mysqldump.def @@ -6,6 +6,7 @@ SCREENNAME "MySQL Dump Tool[scrollable]" COPYRIGHT "(c) 2003-2005 Novell, Inc. Portions (c) 2003 MySQL AB. All Rights Reserved." DESCRIPTION "MySQL Dump Tool" VERSION 4, 0 +STACKSIZE 32768 XDCDATA ../netware/mysql.xdc #DEBUG diff --git a/netware/mysqlimport.def b/netware/mysqlimport.def index dc9af18aa09..f98d8021a73 100644 --- a/netware/mysqlimport.def +++ b/netware/mysqlimport.def @@ -6,6 +6,7 @@ SCREENNAME "MySQL Import[scrollable]" COPYRIGHT "(c) 2003-2005 Novell, Inc. Portions (c) 2003 MySQL AB. All Rights Reserved." DESCRIPTION "MySQL Import Tool" VERSION 4, 0 +STACKSIZE 32768 XDCDATA ../netware/mysql.xdc #DEBUG diff --git a/netware/perror.def b/netware/perror.def index 18c95d8b236..d67bd6191b4 100644 --- a/netware/perror.def +++ b/netware/perror.def @@ -5,6 +5,7 @@ MODULE libc.nlm COPYRIGHT "(c) 2003-2005 Novell, Inc. Portions (c) 2003 MySQL AB. All Rights Reserved." DESCRIPTION "MySQL Error Code Description Tool" VERSION 4, 0 +STACKSIZE 32768 XDCDATA ../netware/mysql.xdc #DEBUG diff --git a/scripts/make_binary_distribution.sh b/scripts/make_binary_distribution.sh index 5767728fe4f..d4d96d38d14 100644 --- a/scripts/make_binary_distribution.sh +++ b/scripts/make_binary_distribution.sh @@ -193,6 +193,7 @@ if [ $BASE_SYSTEM = "netware" ] ; then libname=`basename $i .a` $MV $i $BASE/lib/$libname.lib done + rm -f $BASE/lib/*.la fi copyfileto $BASE/include config.h include/* @@ -288,6 +289,9 @@ if [ $BASE_SYSTEM = "netware" ] ; then $BASE/support-files/mysql*.spec \ $BASE/support-files/mysql-log-rotate \ $BASE/support-files/binary-configure \ + $BASE/support-files/build-tags \ + $BASE/support-files/MySQL-shared-compat.spec \ + $BASE/support-files/ndb-config-2-node.ini \ $BASE/INSTALL-BINARY \ $BASE/MySQLEULA.txt else diff --git a/scripts/make_win_src_distribution.sh b/scripts/make_win_src_distribution.sh index ea3ca66db6e..53f05c131ac 100644 --- a/scripts/make_win_src_distribution.sh +++ b/scripts/make_win_src_distribution.sh @@ -199,7 +199,7 @@ copy_dir_files() print_debug "Creating directory '$arg'" mkdir $BASE/$arg fi - for i in *.c *.cpp *.h *.ih *.i *.ic *.asm *.def *.hpp *.dsp *.dsw \ + for i in *.c *.cpp *.h *.ih *.i *.ic *.asm *.def *.hpp \ README INSTALL* LICENSE AUTHORS NEWS ChangeLog \ *.inc *.test *.result *.pem Moscow_leap des_key_file \ *.vcproj *.sln *.dat *.000001 *.require *.opt @@ -342,7 +342,7 @@ mv $BASE/sql/sql_yacc.cpp-new $BASE/sql/sql_yacc.cpp # # Search the tree for plain text files and adapt the line end marker # -find $BASE \( -name "*.dsp" -o -name "*.dsw" -o -name "*.cnf" -o -name "*.ini" \ +find $BASE \( -name "*.cnf" -o -name "*.ini" \ -o -name COPYING -o -name ChangeLog -o -name EXCEPTIONS-CLIENT \ -o -name "INSTALL*" -o -name LICENSE -o -name "README*" \ -o -name "*.vcproj" -o -name "*.sln" \) -type f -print \ diff --git a/sql-common/client.c b/sql-common/client.c index 976d59d83a4..4c2debd41ff 100644 --- a/sql-common/client.c +++ b/sql-common/client.c @@ -715,6 +715,7 @@ void free_old_query(MYSQL *mysql) init_alloc_root(&mysql->field_alloc,8192,0); /* Assume rowlength < 8192 */ mysql->fields= 0; mysql->field_count= 0; /* For API */ + mysql->warning_count= 0; mysql->info= 0; DBUG_VOID_RETURN; } @@ -2484,7 +2485,6 @@ get_info: DBUG_RETURN(1); mysql->status= MYSQL_STATUS_GET_RESULT; mysql->field_count= (uint) field_count; - mysql->warning_count= 0; DBUG_PRINT("exit",("ok")); DBUG_RETURN(0); } diff --git a/sql-common/my_time.c b/sql-common/my_time.c index 72809ee9b4b..c9d39260761 100644 --- a/sql-common/my_time.c +++ b/sql-common/my_time.c @@ -575,18 +575,34 @@ fractional: /* Get fractional second part */ if ((end-str) >= 2 && *str == '.' && my_isdigit(&my_charset_latin1,str[1])) { - uint field_length=5; + int field_length= 5; str++; value=(uint) (uchar) (*str - '0'); - while (++str != end && - my_isdigit(&my_charset_latin1,str[0]) && - field_length--) - value=value*10 + (uint) (uchar) (*str - '0'); - if (field_length) + while (++str != end && my_isdigit(&my_charset_latin1, *str)) + { + if (field_length-- > 0) + value= value*10 + (uint) (uchar) (*str - '0'); + } + if (field_length > 0) value*= (long) log_10_int[field_length]; + else if (field_length < 0) + *was_cut= 1; date[4]=value; } else date[4]=0; + + /* Check for exponent part: E<gigit> | E<sign><digit> */ + /* (may occur as result of %g formatting of time value) */ + if ((end - str) > 1 && + (*str == 'e' || *str == 'E') && + (my_isdigit(&my_charset_latin1, str[1]) || + ((str[1] == '-' || str[1] == '+') && + (end - str) > 2 && + my_isdigit(&my_charset_latin1, str[2])))) + { + *was_cut= 1; + return 1; + } if (internal_format_positions[7] != 255) { diff --git a/sql/ha_archive.cc b/sql/ha_archive.cc index 1e8fc582eb8..2747f678cc3 100644 --- a/sql/ha_archive.cc +++ b/sql/ha_archive.cc @@ -20,7 +20,7 @@ #include "mysql_priv.h" -#ifdef HAVE_ARCHIVE_DB +#if defined(HAVE_ARCHIVE_DB) && !defined(__NETWARE__) #include "ha_archive.h" #include <my_dir.h> diff --git a/sql/ha_innodb.cc b/sql/ha_innodb.cc index 6c8dc9f81f6..afeb1238aa7 100644 --- a/sql/ha_innodb.cc +++ b/sql/ha_innodb.cc @@ -5742,6 +5742,7 @@ ha_innobase::update_table_comment( uint length = (uint) strlen(comment); char* str; row_prebuilt_t* prebuilt = (row_prebuilt_t*)innobase_prebuilt; + long flen; /* We do not know if MySQL can call this function before calling external_lock(). To be safe, update the thd of the current table @@ -5761,43 +5762,43 @@ ha_innobase::update_table_comment( trx_search_latch_release_if_reserved(prebuilt->trx); str = NULL; - if (FILE* file = os_file_create_tmpfile()) { - long flen; + /* output the data to a temporary file */ - /* output the data to a temporary file */ - fprintf(file, "InnoDB free: %lu kB", + mutex_enter_noninline(&srv_dict_tmpfile_mutex); + rewind(srv_dict_tmpfile); + + fprintf(srv_dict_tmpfile, "InnoDB free: %lu kB", (ulong) fsp_get_available_space_in_free_extents( prebuilt->table->space)); - dict_print_info_on_foreign_keys(FALSE, file, + dict_print_info_on_foreign_keys(FALSE, srv_dict_tmpfile, prebuilt->trx, prebuilt->table); - flen = ftell(file); - if (flen < 0) { - flen = 0; - } else if (length + flen + 3 > 64000) { - flen = 64000 - 3 - length; - } + flen = ftell(srv_dict_tmpfile); + if (flen < 0) { + flen = 0; + } else if (length + flen + 3 > 64000) { + flen = 64000 - 3 - length; + } - /* allocate buffer for the full string, and - read the contents of the temporary file */ + /* allocate buffer for the full string, and + read the contents of the temporary file */ - str = my_malloc(length + flen + 3, MYF(0)); + str = my_malloc(length + flen + 3, MYF(0)); - if (str) { - char* pos = str + length; - if (length) { - memcpy(str, comment, length); - *pos++ = ';'; - *pos++ = ' '; - } - rewind(file); - flen = (uint) fread(pos, 1, flen, file); - pos[flen] = 0; + if (str) { + char* pos = str + length; + if (length) { + memcpy(str, comment, length); + *pos++ = ';'; + *pos++ = ' '; } - - fclose(file); + rewind(srv_dict_tmpfile); + flen = (uint) fread(pos, 1, flen, srv_dict_tmpfile); + pos[flen] = 0; } + mutex_exit_noninline(&srv_dict_tmpfile_mutex); + prebuilt->trx->op_info = (char*)""; return(str ? str : (char*) comment); @@ -5815,6 +5816,7 @@ ha_innobase::get_foreign_key_create_info(void) { row_prebuilt_t* prebuilt = (row_prebuilt_t*)innobase_prebuilt; char* str = 0; + long flen; ut_a(prebuilt != NULL); @@ -5824,47 +5826,42 @@ ha_innobase::get_foreign_key_create_info(void) update_thd(current_thd); - if (FILE* file = os_file_create_tmpfile()) { - long flen; + prebuilt->trx->op_info = (char*)"getting info on foreign keys"; - prebuilt->trx->op_info = (char*)"getting info on foreign keys"; + /* In case MySQL calls this in the middle of a SELECT query, + release possible adaptive hash latch to avoid + deadlocks of threads */ - /* In case MySQL calls this in the middle of a SELECT query, - release possible adaptive hash latch to avoid - deadlocks of threads */ + trx_search_latch_release_if_reserved(prebuilt->trx); - trx_search_latch_release_if_reserved(prebuilt->trx); + mutex_enter_noninline(&srv_dict_tmpfile_mutex); + rewind(srv_dict_tmpfile); - /* output the data to a temporary file */ - dict_print_info_on_foreign_keys(TRUE, file, + /* output the data to a temporary file */ + dict_print_info_on_foreign_keys(TRUE, srv_dict_tmpfile, prebuilt->trx, prebuilt->table); - prebuilt->trx->op_info = (char*)""; - - flen = ftell(file); - if (flen < 0) { - flen = 0; - } else if (flen > 64000 - 1) { - flen = 64000 - 1; - } + prebuilt->trx->op_info = (char*)""; - /* allocate buffer for the string, and - read the contents of the temporary file */ + flen = ftell(srv_dict_tmpfile); + if (flen < 0) { + flen = 0; + } else if (flen > 64000 - 1) { + flen = 64000 - 1; + } - str = my_malloc(flen + 1, MYF(0)); + /* allocate buffer for the string, and + read the contents of the temporary file */ - if (str) { - rewind(file); - flen = (uint) fread(str, 1, flen, file); - str[flen] = 0; - } + str = my_malloc(flen + 1, MYF(0)); - fclose(file); - } else { - /* unable to create temporary file */ - str = my_strdup( -"/* Error: cannot display foreign key constraints */", MYF(0)); + if (str) { + rewind(srv_dict_tmpfile); + flen = (uint) fread(str, 1, flen, srv_dict_tmpfile); + str[flen] = 0; } + mutex_exit_noninline(&srv_dict_tmpfile_mutex); + return(str); } diff --git a/sql/ha_ndbcluster.cc b/sql/ha_ndbcluster.cc index 1156ba1317f..0552eded9b6 100644 --- a/sql/ha_ndbcluster.cc +++ b/sql/ha_ndbcluster.cc @@ -2812,8 +2812,26 @@ void ha_ndbcluster::position(const byte *record) } *buff++= 0; } - memcpy(buff, record + key_part->offset, key_part->length); - buff += key_part->length; + + size_t len = key_part->length; + const byte * ptr = record + key_part->offset; + Field *field = key_part->field; + if ((field->type() == MYSQL_TYPE_VARCHAR) && + ((Field_varstring*)field)->length_bytes == 1) + { + /** + * Keys always use 2 bytes length + */ + buff[0] = ptr[0]; + buff[1] = 0; + memcpy(buff+2, ptr + 1, len); + len += 2; + } + else + { + memcpy(buff, ptr, len); + } + buff += len; } } else diff --git a/sql/handler.cc b/sql/handler.cc index 477a6f9bdae..47010de3002 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -60,7 +60,7 @@ handlerton example_hton = { "EXAMPLE", SHOW_OPTION_NO, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, HTON_NO_FLAGS }; #endif -#ifdef HAVE_ARCHIVE_DB +#if defined(HAVE_ARCHIVE_DB) && !defined(__NETWARE__) #include "ha_archive.h" extern handlerton archive_hton; #else @@ -314,7 +314,7 @@ handler *get_new_handler(TABLE *table, MEM_ROOT *alloc, enum db_type db_type) case DB_TYPE_EXAMPLE_DB: return new (alloc) ha_example(table); #endif -#ifdef HAVE_ARCHIVE_DB +#if defined(HAVE_ARCHIVE_DB) && !defined(__NETWARE__) case DB_TYPE_ARCHIVE_DB: return new (alloc) ha_archive(table); #endif @@ -513,7 +513,7 @@ int ha_panic(enum ha_panic_function flag) if (have_federated_db == SHOW_OPTION_YES) error|= federated_db_end(); #endif -#ifdef HAVE_ARCHIVE_DB +#if defined(HAVE_ARCHIVE_DB) && !defined(__NETWARE__) if (have_archive_db == SHOW_OPTION_YES) error|= archive_db_end(); #endif diff --git a/sql/item.cc b/sql/item.cc index 3721528672a..210e5014f44 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -949,7 +949,7 @@ void Item_splocal::print(String *str) *****************************************************************************/ Item_case_expr::Item_case_expr(int case_expr_id) - :Item_sp_variable(STRING_WITH_LEN("case_expr")), + :Item_sp_variable((char *) STRING_WITH_LEN("case_expr")), m_case_expr_id(case_expr_id) { } @@ -1084,6 +1084,7 @@ void Item_name_const::print(String *str) ref_pointer_array Pointer to array of reference fields fields All fields in select ref Pointer to item + skip_registered <=> function be must skipped for registered SUM items NOTES This is from split_sum_func2() for items that should be split @@ -1096,8 +1097,13 @@ void Item_name_const::print(String *str) void Item::split_sum_func2(THD *thd, Item **ref_pointer_array, - List<Item> &fields, Item **ref) + List<Item> &fields, Item **ref, + bool skip_registered) { + /* An item of type Item_sum is registered <=> ref_by != 0 */ + if (type() == SUM_FUNC_ITEM && skip_registered && + ((Item_sum *) this)->ref_by) + return; if (type() != SUM_FUNC_ITEM && with_sum_func) { /* Will split complicated items and ignore simple ones */ @@ -3231,14 +3237,8 @@ resolve_ref_in_select_and_group(THD *thd, Item_ident *ref, SELECT_LEX *select) { for each outer query Q_k beginning from the inner-most one { - if - Q_k is not a group query AND - - Q_k is not inside an aggregate function - OR - - Q_(k-1) is not in a HAVING or SELECT clause of Q_k - { - search for a column or derived column named col_ref_i - [in table T_j] in the FROM clause of Q_k; - } + search for a column or derived column named col_ref_i + [in table T_j] in the FROM clause of Q_k; if such a column is not found Search for a column or derived column named col_ref_i @@ -3317,18 +3317,11 @@ bool Item_field::fix_fields(THD *thd, Item **reference) place= prev_subselect_item->parsing_place; /* - Check table fields only if the subquery is used somewhere out of - HAVING, or the outer SELECT does not use grouping (i.e. tables are - accessible). - In case of a view, find_field_in_tables() writes the pointer to the found view field into '*reference', in other words, it substitutes this Item_field with the found expression. */ - if ((place != IN_HAVING || - (!select->with_sum_func && - select->group_list.elements == 0)) && - (from_field= find_field_in_tables(thd, this, + if ((from_field= find_field_in_tables(thd, this, outer_context-> first_name_resolution_table, outer_context-> @@ -3344,6 +3337,21 @@ bool Item_field::fix_fields(THD *thd, Item **reference) { prev_subselect_item->used_tables_cache|= from_field->table->map; prev_subselect_item->const_item_cache= 0; + if (thd->lex->in_sum_func && + thd->lex->in_sum_func->nest_level == + thd->lex->current_select->nest_level) + { + Item::Type type= (*reference)->type(); + set_if_bigger(thd->lex->in_sum_func->max_arg_level, + select->nest_level); + set_field(from_field); + fixed= 1; + mark_as_dependent(thd, last_checked_context->select_lex, + context->select_lex, this, + ((type == REF_ITEM || type == FIELD_ITEM) ? + (Item_ident*) (*reference) : 0)); + return FALSE; + } } else { @@ -3495,6 +3503,11 @@ bool Item_field::fix_fields(THD *thd, Item **reference) return FALSE; set_field(from_field); + if (thd->lex->in_sum_func && + thd->lex->in_sum_func->nest_level == + thd->lex->current_select->nest_level) + set_if_bigger(thd->lex->in_sum_func->max_arg_level, + thd->lex->current_select->nest_level); } else if (thd->set_query_id && field->query_id != thd->query_id) { @@ -4653,9 +4666,8 @@ bool Item_ref::fix_fields(THD *thd, Item **reference) aggregate function. */ if (((*ref)->with_sum_func && name && - (depended_from || - !(current_sel->linkage != GLOBAL_OPTIONS_TYPE && - current_sel->having_fix_field))) || + !(current_sel->linkage != GLOBAL_OPTIONS_TYPE && + current_sel->having_fix_field)) || !(*ref)->fixed) { my_error(ER_ILLEGAL_REFERENCE, MYF(0), @@ -5148,10 +5160,17 @@ bool Item_insert_value::fix_fields(THD *thd, Item **items) Item_ref *ref= (Item_ref *)arg; if (ref->ref[0]->type() != FIELD_ITEM) { + my_error(ER_BAD_FIELD_ERROR, MYF(0), "", "VALUES() function"); return TRUE; } arg= ref->ref[0]; } + /* + According to our SQL grammar, VALUES() function can reference + only to a column. + */ + DBUG_ASSERT(arg->type() == FIELD_ITEM); + Item_field *field_arg= (Item_field *)arg; if (field_arg->field->table->insert_values) diff --git a/sql/item.h b/sql/item.h index 900442a45e9..4b49ff907d3 100644 --- a/sql/item.h +++ b/sql/item.h @@ -640,7 +640,7 @@ public: List<Item> &fields) {} /* Called for items that really have to be split */ void split_sum_func2(THD *thd, Item **ref_pointer_array, List<Item> &fields, - Item **ref); + Item **ref, bool skip_registered); virtual bool get_date(TIME *ltime,uint fuzzydate); virtual bool get_time(TIME *ltime); virtual bool get_date_result(TIME *ltime,uint fuzzydate) @@ -2056,6 +2056,16 @@ public: } }; +/* + Item_insert_value -- an implementation of VALUES() function. + You can use the VALUES(col_name) function in the UPDATE clause + to refer to column values from the INSERT portion of the INSERT + ... UPDATE statement. In other words, VALUES(col_name) in the + UPDATE clause refers to the value of col_name that would be + inserted, had no duplicate-key conflict occurred. + In all other places this function returns NULL. +*/ + class Item_insert_value : public Item_field { public: diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index 0252d20d1f1..15614a32c39 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -2676,7 +2676,7 @@ void Item_cond::split_sum_func(THD *thd, Item **ref_pointer_array, List_iterator<Item> li(list); Item *item; while ((item= li++)) - item->split_sum_func2(thd, ref_pointer_array, fields, li.ref()); + item->split_sum_func2(thd, ref_pointer_array, fields, li.ref(), TRUE); } diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h index bfd32223d4c..b4064fb45b8 100644 --- a/sql/item_cmpfunc.h +++ b/sql/item_cmpfunc.h @@ -723,9 +723,9 @@ public: { char buff[STRING_BUFFER_USUAL_SIZE]; String tmp(buff, sizeof(buff), cmp_charset), *res; - if (!(res= arg->val_str(&tmp))) - return 1; /* Can't be right */ - return sortcmp(value_res, res, cmp_charset); + res= arg->val_str(&tmp); + return (value_res ? (res ? sortcmp(value_res, res, cmp_charset) : 1) : + (res ? -1 : 0)); } int compare(cmp_item *c) { diff --git a/sql/item_func.cc b/sql/item_func.cc index 0d3bd08b230..272e77a4318 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -280,7 +280,7 @@ void Item_func::split_sum_func(THD *thd, Item **ref_pointer_array, { Item **arg, **arg_end; for (arg= args, arg_end= args+arg_count; arg != arg_end ; arg++) - (*arg)->split_sum_func2(thd, ref_pointer_array, fields, arg); + (*arg)->split_sum_func2(thd, ref_pointer_array, fields, arg, TRUE); } diff --git a/sql/item_row.cc b/sql/item_row.cc index 9362518e6ef..75c3f8a2922 100644 --- a/sql/item_row.cc +++ b/sql/item_row.cc @@ -90,7 +90,7 @@ void Item_row::split_sum_func(THD *thd, Item **ref_pointer_array, { Item **arg, **arg_end; for (arg= items, arg_end= items+arg_count; arg != arg_end ; arg++) - (*arg)->split_sum_func2(thd, ref_pointer_array, fields, arg); + (*arg)->split_sum_func2(thd, ref_pointer_array, fields, arg, TRUE); } diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index 8c0dea4efb2..8056e00e0cf 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -1896,7 +1896,7 @@ String *Item_func_elt::val_str(String *str) void Item_func_make_set::split_sum_func(THD *thd, Item **ref_pointer_array, List<Item> &fields) { - item->split_sum_func2(thd, ref_pointer_array, fields, &item); + item->split_sum_func2(thd, ref_pointer_array, fields, &item, TRUE); Item_str_func::split_sum_func(thd, ref_pointer_array, fields); } diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc index f2d6f2b5899..88620634354 100644 --- a/sql/item_subselect.cc +++ b/sql/item_subselect.cc @@ -803,6 +803,7 @@ Item_in_subselect::single_value_transformer(JOIN *join, !(select_lex->next_select())) { Item_sum_hybrid *item; + nesting_map save_allow_sum_func; if (func->l_op()) { /* @@ -828,6 +829,8 @@ Item_in_subselect::single_value_transformer(JOIN *join, it.replace(item); } + save_allow_sum_func= thd->lex->allow_sum_func; + thd->lex->allow_sum_func|= 1 << thd->lex->current_select->nest_level; /* Item_sum_(max|min) can't substitute other item => we can use 0 as reference, also Item_sum_(max|min) can't be fixed after creation, so @@ -835,6 +838,7 @@ Item_in_subselect::single_value_transformer(JOIN *join, */ if (item->fix_fields(thd, 0)) DBUG_RETURN(RES_ERROR); + thd->lex->allow_sum_func= save_allow_sum_func; /* we added aggregate function => we have to change statistic */ count_field_types(&join->tmp_table_param, join->all_fields, 0); diff --git a/sql/item_sum.cc b/sql/item_sum.cc index 626eb63d04f..a3a25ec8d6f 100644 --- a/sql/item_sum.cc +++ b/sql/item_sum.cc @@ -24,6 +24,234 @@ #include "mysql_priv.h" #include "sql_select.h" +/* + Prepare an aggregate function item for checking context conditions + + SYNOPSIS + init_sum_func_check() + thd reference to the thread context info + + DESCRIPTION + The function initializes the members of the Item_sum object created + for a set function that are used to check validity of the set function + occurrence. + If the set function is not allowed in any subquery where it occurs + an error is reported immediately. + + NOTES + This function is to be called for any item created for a set function + object when the traversal of trees built for expressions used in the query + is performed at the phase of context analysis. This function is to + be invoked at the descent of this traversal. + + RETURN + TRUE if an error is reported + FALSE otherwise +*/ + +bool Item_sum::init_sum_func_check(THD *thd) +{ + if (!thd->lex->allow_sum_func) + { + my_message(ER_INVALID_GROUP_FUNC_USE, ER(ER_INVALID_GROUP_FUNC_USE), + MYF(0)); + return TRUE; + } + /* Set a reference to the nesting set function if there is any */ + in_sum_func= thd->lex->in_sum_func; + /* Save a pointer to object to be used in items for nested set functions */ + thd->lex->in_sum_func= this; + nest_level= thd->lex->current_select->nest_level; + ref_by= 0; + aggr_level= -1; + max_arg_level= -1; + max_sum_func_level= -1; + return FALSE; +} + +/* + Check constraints imposed on a usage of a set function + + SYNOPSIS + check_sum_func() + thd reference to the thread context info + ref location of the pointer to this item in the embedding expression + + DESCRIPTION + The method verifies whether context conditions imposed on a usage + of any set function are met for this occurrence. + It checks whether the set function occurs in the position where it + can be aggregated and, when it happens to occur in argument of another + set function, the method checks that these two functions are aggregated in + different subqueries. + If the context conditions are not met the method reports an error. + If the set function is aggregated in some outer subquery the method + adds it to the chain of items for such set functions that is attached + to the the st_select_lex structure for this subquery. + + NOTES + This function is to be called for any item created for a set function + object when the traversal of trees built for expressions used in the query + is performed at the phase of context analysis. This function is to + be invoked at the ascent of this traversal. + + IMPLEMENTATION + A number of designated members of the object are used to check the + conditions. They are specified in the comment before the Item_sum + class declaration. + Additionally a bitmap variable called allow_sum_func is employed. + It is included into the thd->lex structure. + The bitmap contains 1 at n-th position if the set function happens + to occur under a construct of the n-th level subquery where usage + of set functions are allowed (i.e either in the SELECT list or + in the HAVING clause of the corresponding subquery) + Consider the query: + SELECT SUM(t1.b) FROM t1 GROUP BY t1.a + HAVING t1.a IN (SELECT t2.c FROM t2 WHERE AVG(t1.b) > 20) AND + t1.a > (SELECT MIN(t2.d) FROM t2); + allow_sum_func will contain: + for SUM(t1.b) - 1 at the first position + for AVG(t1.b) - 1 at the first position, 0 at the second position + for MIN(t2.d) - 1 at the first position, 1 at the second position. + + RETURN + TRUE if an error is reported + FALSE otherwise +*/ + +bool Item_sum::check_sum_func(THD *thd, Item **ref) +{ + bool invalid= FALSE; + nesting_map allow_sum_func= thd->lex->allow_sum_func; + /* + The value of max_arg_level is updated if an argument of the set function + contains a column reference resolved against a subquery whose level is + greater than the current value of max_arg_level. + max_arg_level cannot be greater than nest level. + nest level is always >= 0 + */ + if (nest_level == max_arg_level) + { + /* + The function must be aggregated in the current subquery, + If it is there under a construct where it is not allowed + we report an error. + */ + invalid= !(allow_sum_func & (1 << max_arg_level)); + } + else if (max_arg_level >= 0 || !(allow_sum_func & (1 << nest_level))) + { + /* + The set function can be aggregated only in outer subqueries. + Try to find a subquery where it can be aggregated; + If we fail to find such a subquery report an error. + */ + if (register_sum_func(thd, ref)) + return TRUE; + invalid= aggr_level < 0 && !(allow_sum_func & (1 << nest_level)); + } + if (!invalid && aggr_level < 0) + aggr_level= nest_level; + /* + By this moment we either found a subquery where the set function is + to be aggregated and assigned a value that is >= 0 to aggr_level, + or set the value of 'invalid' to TRUE to report later an error. + */ + /* + Additionally we have to check whether possible nested set functions + are acceptable here: they are not, if the level of aggregation of + some of them is less than aggr_level. + */ + invalid= aggr_level <= max_sum_func_level; + if (invalid) + { + my_message(ER_INVALID_GROUP_FUNC_USE, ER(ER_INVALID_GROUP_FUNC_USE), + MYF(0)); + return TRUE; + } + if (in_sum_func && in_sum_func->nest_level == nest_level) + { + /* + If the set function is nested adjust the value of + max_sum_func_level for the nesting set function. + */ + set_if_bigger(in_sum_func->max_sum_func_level, aggr_level); + } + thd->lex->in_sum_func= in_sum_func; + return FALSE; +} + +/* + Attach a set function to the subquery where it must be aggregated + + SYNOPSIS + register_sum_func() + thd reference to the thread context info + ref location of the pointer to this item in the embedding expression + + DESCRIPTION + The function looks for an outer subquery where the set function must be + aggregated. If it finds such a subquery then aggr_level is set to + the nest level of this subquery and the item for the set function + is added to the list of set functions used in nested subqueries + inner_sum_func_list defined for each subquery. When the item is placed + there the field 'ref_by' is set to ref. + + NOTES. + Now we 'register' only set functions that are aggregated in outer + subqueries. Actually it makes sense to link all set function for + a subquery in one chain. It would simplify the process of 'splitting' + for set functions. + + RETURN + FALSE if the executes without failures (currently always) + TRUE otherwise +*/ + +bool Item_sum::register_sum_func(THD *thd, Item **ref) +{ + SELECT_LEX *sl; + SELECT_LEX *aggr_sl= NULL; + nesting_map allow_sum_func= thd->lex->allow_sum_func; + for (sl= thd->lex->current_select->master_unit()->outer_select() ; + sl && sl->nest_level > max_arg_level; + sl= sl->master_unit()->outer_select() ) + { + if (aggr_level < 0 && (allow_sum_func & (1 << sl->nest_level))) + { + /* Found the most nested subquery where the function can be aggregated */ + aggr_level= sl->nest_level; + aggr_sl= sl; + } + } + if (sl && (allow_sum_func & (1 << sl->nest_level))) + { + /* + We reached the subquery of level max_arg_level and checked + that the function can be aggregated here. + The set function will be aggregated in this subquery. + */ + aggr_level= sl->nest_level; + aggr_sl= sl; + } + if (aggr_level >= 0) + { + ref_by= ref; + /* Add the object to the list of registered objects assigned to aggr_sl */ + if (!aggr_sl->inner_sum_func_list) + next= this; + else + { + next= aggr_sl->inner_sum_func_list->next; + aggr_sl->inner_sum_func_list->next= this; + } + aggr_sl->inner_sum_func_list= this; + + } + return FALSE; +} + + Item_sum::Item_sum(List<Item> &list) :arg_count(list.elements) { @@ -197,13 +425,9 @@ Item_sum_num::fix_fields(THD *thd, Item **ref) { DBUG_ASSERT(fixed == 0); - if (!thd->allow_sum_func) - { - my_message(ER_INVALID_GROUP_FUNC_USE, ER(ER_INVALID_GROUP_FUNC_USE), - MYF(0)); + if (init_sum_func_check(thd)) return TRUE; - } - thd->allow_sum_func=0; // No included group funcs + decimals=0; maybe_null=0; for (uint i=0 ; i < arg_count ; i++) @@ -217,7 +441,10 @@ Item_sum_num::fix_fields(THD *thd, Item **ref) max_length=float_length(decimals); null_value=1; fix_length_and_dec(); - thd->allow_sum_func=1; // Allow group functions + + if (check_sum_func(thd, ref)) + return TRUE; + fixed= 1; return FALSE; } @@ -258,13 +485,9 @@ Item_sum_hybrid::fix_fields(THD *thd, Item **ref) DBUG_ASSERT(fixed == 0); Item *item= args[0]; - if (!thd->allow_sum_func) - { - my_message(ER_INVALID_GROUP_FUNC_USE, ER(ER_INVALID_GROUP_FUNC_USE), - MYF(0)); + + if (init_sum_func_check(thd)) return TRUE; - } - thd->allow_sum_func=0; // No included group funcs // 'item' can be changed during fix_fields if (!item->fixed && @@ -300,11 +523,14 @@ Item_sum_hybrid::fix_fields(THD *thd, Item **ref) result_field=0; null_value=1; fix_length_and_dec(); - thd->allow_sum_func=1; // Allow group functions if (item->type() == Item::FIELD_ITEM) hybrid_field_type= ((Item_field*) item)->field->type(); else hybrid_field_type= Item::field_type(); + + if (check_sum_func(thd, ref)) + return TRUE; + fixed= 1; return FALSE; } @@ -2979,14 +3205,9 @@ Item_func_group_concat::fix_fields(THD *thd, Item **ref) uint i; /* for loop variable */ DBUG_ASSERT(fixed == 0); - if (!thd->allow_sum_func) - { - my_message(ER_INVALID_GROUP_FUNC_USE, ER(ER_INVALID_GROUP_FUNC_USE), - MYF(0)); + if (init_sum_func_check(thd)) return TRUE; - } - thd->allow_sum_func= 0; maybe_null= 1; /* @@ -3008,8 +3229,11 @@ Item_func_group_concat::fix_fields(THD *thd, Item **ref) result.set_charset(collation.collation); result_field= 0; null_value= 1; - thd->allow_sum_func= 1; max_length= thd->variables.group_concat_max_len; + + if (check_sum_func(thd, ref)) + return TRUE; + fixed= 1; return FALSE; } diff --git a/sql/item_sum.h b/sql/item_sum.h index 2c2bcedab9b..a8242d76287 100644 --- a/sql/item_sum.h +++ b/sql/item_sum.h @@ -23,6 +23,201 @@ #include <my_tree.h> +/* + Class Item_sum is the base class used for special expressions that SQL calls + 'set functions'. These expressions are formed with the help of aggregate + functions such as SUM, MAX, GROUP_CONCAT etc. + + GENERAL NOTES + + A set function cannot be used in certain positions where expressions are + accepted. There are some quite explicable restrictions for the usage of + set functions. + + In the query: + SELECT AVG(b) FROM t1 WHERE SUM(b) > 20 GROUP by a + the usage of the set function AVG(b) is legal, while the usage of SUM(b) + is illegal. A WHERE condition must contain expressions that can be + evaluated for each row of the table. Yet the expression SUM(b) can be + evaluated only for each group of rows with the same value of column a. + In the query: + SELECT AVG(b) FROM t1 WHERE c > 30 GROUP BY a HAVING SUM(b) > 20 + both set function expressions AVG(b) and SUM(b) are legal. + + We can say that in a query without nested selects an occurrence of a + set function in an expression of the SELECT list or/and in the HAVING + clause is legal, while in the WHERE clause it's illegal. + + The general rule to detect whether a set function is legal in a query with + nested subqueries is much more complicated. + + Consider the the following query: + SELECT t1.a FROM t1 GROUP BY t1.a + HAVING t1.a > ALL (SELECT t2.c FROM t2 WHERE SUM(t1.b) < t2.c). + The set function SUM(b) is used here in the WHERE clause of the subquery. + Nevertheless it is legal since it is under the HAVING clause of the query + to which this function relates. The expression SUM(t1.b) is evaluated + for each group defined in the main query, not for groups of the subquery. + + The problem of finding the query where to aggregate a particular + set function is not so simple as it seems to be. + + In the query: + SELECT t1.a FROM t1 GROUP BY t1.a + HAVING t1.a > ALL(SELECT t2.c FROM t2 GROUP BY t2.c + HAVING SUM(t1.a) < t2.c) + the set function can be evaluated for both outer and inner selects. + If we evaluate SUM(t1.a) for the outer query then we get the value of t1.a + multiplied by the cardinality of a group in table t1. In this case + in each correlated subquery SUM(t1.a) is used as a constant. But we also + can evaluate SUM(t1.a) for the inner query. In this case t1.a will be a + constant for each correlated subquery and summation is performed + for each group of table t2. + (Here it makes sense to remind that the query + SELECT c FROM t GROUP BY a HAVING SUM(1) < a + is quite legal in our SQL). + + So depending on what query we assign the set function to we + can get different result sets. + + The general rule to detect the query where a set function is to be + evaluated can be formulated as follows. + Consider a set function S(E) where E is an expression with occurrences + of column references C1, ..., CN. Resolve these column references against + subqueries that contain the set function S(E). Let Q be the innermost + subquery of those subqueries. (It should be noted here that S(E) + in no way can be evaluated in the subquery embedding the subquery Q, + otherwise S(E) would refer to at least one unbound column reference) + If S(E) is used in a construct of Q where set functions are allowed then + we evaluate S(E) in Q. + Otherwise we look for a innermost subquery containing S(E) of those where + usage of S(E) is allowed. + + Let's demonstrate how this rule is applied to the following queries. + + 1. SELECT t1.a FROM t1 GROUP BY t1.a + HAVING t1.a > ALL(SELECT t2.b FROM t2 GROUP BY t2.b + HAVING t2.b > ALL(SELECT t3.c FROM t3 GROUP BY t3.c + HAVING SUM(t1.a+t2.b) < t3.c)) + For this query the set function SUM(t1.a+t2.b) depends on t1.a and t2.b + with t1.a defined in the outermost query, and t2.b defined for its + subquery. The set function is in the HAVING clause of the subquery and can + be evaluated in this subquery. + + 2. SELECT t1.a FROM t1 GROUP BY t1.a + HAVING t1.a > ALL(SELECT t2.b FROM t2 + WHERE t2.b > ALL (SELECT t3.c FROM t3 GROUP BY t3.c + HAVING SUM(t1.a+t2.b) < t3.c)) + Here the set function SUM(t1.a+t2.b)is in the WHERE clause of the second + subquery - the most upper subquery where t1.a and t2.b are defined. + If we evaluate the function in this subquery we violate the context rules. + So we evaluate the function in the third subquery (over table t3) where it + is used under the HAVING clause. + + 3. SELECT t1.a FROM t1 GROUP BY t1.a + HAVING t1.a > ALL(SELECT t2.b FROM t2 + WHERE t2.b > ALL (SELECT t3.c FROM t3 + WHERE SUM(t1.a+t2.b) < t3.c)) + In this query evaluation of SUM(t1.a+t2.b) is not legal neither in the second + nor in the third subqueries. So this query is invalid. + + Mostly set functions cannot be nested. In the query + SELECT t1.a from t1 GROUP BY t1.a HAVING AVG(SUM(t1.b)) > 20 + the expression SUM(b) is not acceptable, though it is under a HAVING clause. + Yet it is acceptable in the query: + SELECT t.1 FROM t1 GROUP BY t1.a HAVING SUM(t1.b) > 20. + + An argument of a set function does not have to be a reference to a table + column as we saw it in examples above. This can be a more complex expression + SELECT t1.a FROM t1 GROUP BY t1.a HAVING SUM(t1.b+1) > 20. + The expression SUM(t1.b+1) has a very clear semantics in this context: + we sum up the values of t1.b+1 where t1.b varies for all values within a + group of rows that contain the same t1.a value. + + A set function for an outer query yields a constant within a subquery. So + the semantics of the query + SELECT t1.a FROM t1 GROUP BY t1.a + HAVING t1.a IN (SELECT t2.c FROM t2 GROUP BY t2.c + HAVING AVG(t2.c+SUM(t1.b)) > 20) + is still clear. For a group of the rows with the same t1.a values we + calculate the value of SUM(t1.b). This value 's' is substituted in the + the subquery: + SELECT t2.c FROM t2 GROUP BY t2.c HAVING AVG(t2.c+s) + than returns some result set. + + By the same reason the following query with a subquery + SELECT t1.a FROM t1 GROUP BY t1.a + HAVING t1.a IN (SELECT t2.c FROM t2 GROUP BY t2.c + HAVING AVG(SUM(t1.b)) > 20) + is also acceptable. + + IMPLEMENTATION NOTES + + Three methods were added to the class to check the constraints specified + in the previous section. These methods utilize several new members. + + The field 'nest_level' contains the number of the level for the subquery + containing the set function. The main SELECT is of level 0, its subqueries + are of levels 1, the subqueries of the latter are of level 2 and so on. + + The field 'aggr_level' is to contain the nest level of the subquery + where the set function is aggregated. + + The field 'max_arg_level' is for the maximun of the nest levels of the + unbound column references occurred in the set function. A column reference + is unbound within a set function if it is not bound by any subquery + used as a subexpression in this function. A column reference is bound by + a subquery if it is a reference to the column by which the aggregation + of some set function that is used in the subquery is calculated. + For the set function used in the query + SELECT t1.a FROM t1 GROUP BY t1.a + HAVING t1.a > ALL(SELECT t2.b FROM t2 GROUP BY t2.b + HAVING t2.b > ALL(SELECT t3.c FROM t3 GROUP BY t3.c + HAVING SUM(t1.a+t2.b) < t3.c)) + the value of max_arg_level is equal to 1 since t1.a is bound in the main + query, and t2.b is bound by the first subquery whose nest level is 1. + Obviously a set function cannot be aggregated in the subquery whose + nest level is less than max_arg_level. (Yet it can be aggregated in the + subqueries whose nest level is greater than max_arg_level.) + In the query + SELECT t.a FROM t1 HAVING AVG(t1.a+(SELECT MIN(t2.c) FROM t2)) + the value of the max_arg_level for the AVG set function is 0 since + the reference t2.c is bound in the subquery. + + The field 'max_sum_func_level' is to contain the maximum of the + nest levels of the set functions that are used as subexpressions of + the arguments of the given set function, but not aggregated in any + subquery within this set function. A nested set function s1 can be + used within set function s0 only if s1.max_sum_func_level < + s0.max_sum_func_level. Set function s1 is considered as nested + for set function s0 if s1 is not calculated in any subquery + within s0. + + A set function that is used as a subexpression in an argument of another + set function refers to the latter via the field 'in_sum_func'. + + The condition imposed on the usage of set functions are checked when + we traverse query subexpressions with the help of the recursive method + fix_fields. When we apply this method to an object of the class + Item_sum, first, on the descent, we call the method init_sum_func_check + that initialize members used at checking. Then, on the ascent, we + call the method check_sum_func that validates the set function usage + and reports an error if it is illegal. + The method register_sum_func serves to link the items for the set functions + that are aggregated in the embedding (sub)queries. Circular chains of such + functions are attached to the corresponding st_select_lex structures + through the field inner_sum_func_list. + + Exploiting the fact that the members mentioned above are used in one + recursive function we could have allocated them on the thread stack. + Yet we don't do it now. + + We assume that the nesting level of subquries does not exceed 127. + TODO: to catch queries where the limit is exceeded to make the + code clean here. + +*/ + class Item_sum :public Item_result_field { public: @@ -33,7 +228,14 @@ public: }; Item **args, *tmp_args[2]; + Item **ref_by; /* pointer to a ref to the object used to register it */ + Item_sum *next; /* next in the circular chain of registered objects */ uint arg_count; + Item_sum *in_sum_func; /* embedding set function if any */ + int8 nest_level; /* number of the nesting level of the set function */ + int8 aggr_level; /* nesting level of the aggregating subquery */ + int8 max_arg_level; /* max level of unbound column references */ + int8 max_sum_func_level;/* max level of aggregation for embedded functions */ bool quick_group; /* If incremental update of fields */ void mark_as_sum_func(); @@ -111,6 +313,9 @@ public: virtual Field *create_tmp_field(bool group, TABLE *table, uint convert_blob_length); bool walk (Item_processor processor, byte *argument); + bool init_sum_func_check(THD *thd); + bool check_sum_func(THD *thd, Item **ref); + bool register_sum_func(THD *thd, Item **ref); }; diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index 3f4ed137a59..aac3511ef9d 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -42,8 +42,13 @@ /* TODO convert all these three maps to Bitmap classes */ typedef ulonglong table_map; /* Used for table bits in join */ -typedef Bitmap<64> key_map; /* Used for finding keys */ +#if MAX_INDEXES <= 64 +typedef Bitmap<64> key_map; /* Used for finding keys */ +#else +typedef Bitmap<((MAX_INDEXES+7)/8*8)> key_map; /* Used for finding keys */ +#endif typedef ulong key_part_map; /* Used for finding key parts */ +typedef ulong nesting_map; /* Used for flags of nesting constructs */ /* Used to identify NESTED_JOIN structures within a join (applicable only to structures that have not been simplified away and embed more the one diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 8792d2560ae..aaa467603f5 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -6323,7 +6323,7 @@ static void mysql_init_variables(void) #else have_example_db= SHOW_OPTION_NO; #endif -#ifdef HAVE_ARCHIVE_DB +#if defined(HAVE_ARCHIVE_DB) && !defined(__NETWARE__) have_archive_db= SHOW_OPTION_YES; #else have_archive_db= SHOW_OPTION_NO; @@ -6358,7 +6358,7 @@ static void mysql_init_variables(void) #else have_openssl=SHOW_OPTION_NO; #endif -#if !defined(HAVE_REALPATH) || defined(HAVE_BROKEN_REALPATH) +#ifdef HAVE_BROKEN_REALPATH have_symlink=SHOW_OPTION_NO; #else have_symlink=SHOW_OPTION_YES; @@ -7053,7 +7053,7 @@ static void get_options(int argc,char **argv) usage(); exit(0); } -#if !defined(HAVE_REALPATH) || defined(HAVE_BROKEN_REALPATH) +#if defined(HAVE_BROKEN_REALPATH) my_use_symdir=0; my_disable_symlinks=1; have_symlink=SHOW_OPTION_NO; diff --git a/sql/opt_range.cc b/sql/opt_range.cc index d9a608eb064..221a343053d 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -3172,6 +3172,7 @@ TRP_ROR_INTERSECT *get_best_covering_ror_intersect(PARAM *param, trp->is_covering= TRUE; trp->read_cost= total_cost; trp->records= records; + trp->cpk_scan= NULL; DBUG_PRINT("info", ("Returning covering ROR-intersect plan: cost %g, records %lu", diff --git a/sql/share/charsets/latin5.xml b/sql/share/charsets/latin5.xml index 67e5873c503..5004f045889 100644 --- a/sql/share/charsets/latin5.xml +++ b/sql/share/charsets/latin5.xml @@ -112,11 +112,6 @@ <collation name="latin5_turkish_ci"> -<!-- -# Note: all accented characters are compared separately (this -# is different from the default latin1 character set, where -# e.g. a = ä = á, etc.). ---> <map> 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F @@ -130,10 +125,10 @@ 9C 9D 9E 9F A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 AA AB AC AD AE AF B0 B1 B2 B3 B4 B5 B6 B7 B8 B9 BA BB BC BD BE BF C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 CA CB - CC CD CE CF D0 D1 D2 44 D3 D4 D5 D6 D7 D8 D9 DA - 49 DB DC DD DE DF 53 E0 E1 E2 E3 E4 5B 4C 58 E5 - CC CD CE CF D0 D1 D2 44 D3 D4 D5 D6 D7 D8 D9 DA - 49 DB DC DD DE DF 53 FA E1 E2 E3 E4 5B 4B 58 FF + 41 41 41 41 41 41 41 44 46 46 46 46 4C 4C 4C 4C + 49 51 52 52 52 52 53 E0 52 5A 5A 5A 5B 4C 58 57 + 41 41 41 41 41 41 41 44 46 46 46 46 4C 4C 4C 4C + 49 51 52 52 52 52 53 FA 52 5A 5A 5A 5B 4B 58 5F </map> </collation> diff --git a/sql/share/errmsg.txt b/sql/share/errmsg.txt index efa7860f251..185b4326c5c 100644 --- a/sql/share/errmsg.txt +++ b/sql/share/errmsg.txt @@ -5375,7 +5375,7 @@ ER_WSAS_FAILED eng "WSAStartup Failed" ger "WSAStartup fehlgeschlagen" ER_DIFF_GROUPS_PROC - eng "Can't handle procedures with differents groups yet" + eng "Can't handle procedures with different groups yet" ger "Kann Prozeduren mit unterschiedlichen Gruppen noch nicht verarbeiten" ER_NO_GROUP_FOR_PROC eng "Select must have a group with this procedure" diff --git a/sql/sp.cc b/sql/sp.cc index debd3121058..d5b93f0d2f2 100644 --- a/sql/sp.cc +++ b/sql/sp.cc @@ -1199,6 +1199,12 @@ struct Sroutine_hash_entry for LEX::sroutine/sroutine_list and sp_head::m_sroutines. */ Sroutine_hash_entry *next; + /* + Uppermost view which directly or indirectly uses this routine. + 0 if routine is not used in view. Note that it also can be 0 if + statement uses routine both via view and directly. + */ + TABLE_LIST *belong_to_view; }; @@ -1253,9 +1259,11 @@ void sp_get_prelocking_info(THD *thd, bool *need_prelocking, SYNOPSIS add_used_routine() - lex - LEX representing statement - arena - arena in which memory for new element will be allocated - key - key for the hash representing set + lex LEX representing statement + arena Arena in which memory for new element will be allocated + key Key for the hash representing set + belong_to_view Uppermost view which uses this routine + (0 if routine is not used by view) NOTES Will also add element to end of 'LEX::sroutines_list' list. @@ -1278,7 +1286,8 @@ void sp_get_prelocking_info(THD *thd, bool *need_prelocking, */ static bool add_used_routine(LEX *lex, Query_arena *arena, - const LEX_STRING *key) + const LEX_STRING *key, + TABLE_LIST *belong_to_view) { if (!hash_search(&lex->sroutines, (byte *)key->str, key->length)) { @@ -1292,6 +1301,7 @@ static bool add_used_routine(LEX *lex, Query_arena *arena, memcpy(rn->key.str, key->str, key->length); my_hash_insert(&lex->sroutines, (byte *)rn); lex->sroutines_list.link_in_list((byte *)rn, (byte **)&rn->next); + rn->belong_to_view= belong_to_view; return TRUE; } return FALSE; @@ -1322,7 +1332,7 @@ void sp_add_used_routine(LEX *lex, Query_arena *arena, sp_name *rt, char rt_type) { rt->set_routine_type(rt_type); - (void)add_used_routine(lex, arena, &rt->m_sroutines_key); + (void)add_used_routine(lex, arena, &rt->m_sroutines_key, 0); lex->sroutines_list_own_last= lex->sroutines_list.next; lex->sroutines_list_own_elements= lex->sroutines_list.elements; } @@ -1392,20 +1402,23 @@ void sp_update_sp_used_routines(HASH *dst, HASH *src) SYNOPSIS sp_update_stmt_used_routines() - thd - thread context - lex - LEX representing statement - src - hash representing set from which routines will be added + thd Thread context + lex LEX representing statement + src Hash representing set from which routines will be added + belong_to_view Uppermost view which uses these routines, 0 if none NOTE It will also add elements to end of 'LEX::sroutines_list' list. */ -static void sp_update_stmt_used_routines(THD *thd, LEX *lex, HASH *src) +static void +sp_update_stmt_used_routines(THD *thd, LEX *lex, HASH *src, + TABLE_LIST *belong_to_view) { for (uint i=0 ; i < src->records ; i++) { Sroutine_hash_entry *rt= (Sroutine_hash_entry *)hash_element(src, i); - (void)add_used_routine(lex, thd->stmt_arena, &rt->key); + (void)add_used_routine(lex, thd->stmt_arena, &rt->key, belong_to_view); } } @@ -1416,19 +1429,21 @@ static void sp_update_stmt_used_routines(THD *thd, LEX *lex, HASH *src) SYNOPSIS sp_update_stmt_used_routines() - thd Thread context - lex LEX representing statement - src List representing set from which routines will be added + thd Thread context + lex LEX representing statement + src List representing set from which routines will be added + belong_to_view Uppermost view which uses these routines, 0 if none NOTE It will also add elements to end of 'LEX::sroutines_list' list. */ -static void sp_update_stmt_used_routines(THD *thd, LEX *lex, SQL_LIST *src) +static void sp_update_stmt_used_routines(THD *thd, LEX *lex, SQL_LIST *src, + TABLE_LIST *belong_to_view) { for (Sroutine_hash_entry *rt= (Sroutine_hash_entry *)src->first; rt; rt= rt->next) - (void)add_used_routine(lex, thd->stmt_arena, &rt->key); + (void)add_used_routine(lex, thd->stmt_arena, &rt->key, belong_to_view); } @@ -1533,9 +1548,11 @@ sp_cache_routines_and_add_tables_aux(THD *thd, LEX *lex, { if (!(first && first_no_prelock)) { - sp_update_stmt_used_routines(thd, lex, &sp->m_sroutines); + sp_update_stmt_used_routines(thd, lex, &sp->m_sroutines, + rt->belong_to_view); tabschnd|= - sp->add_used_tables_to_table_list(thd, &lex->query_tables_last); + sp->add_used_tables_to_table_list(thd, &lex->query_tables_last, + rt->belong_to_view); } } first= FALSE; @@ -1581,21 +1598,22 @@ sp_cache_routines_and_add_tables(THD *thd, LEX *lex, bool first_no_prelock, SYNOPSIS sp_cache_routines_and_add_tables_for_view() - thd - thread context - lex - LEX representing statement - aux_lex - LEX representing view - + thd Thread context + lex LEX representing statement + view Table list element representing view + RETURN VALUE 0 - success non-0 - failure */ int -sp_cache_routines_and_add_tables_for_view(THD *thd, LEX *lex, LEX *aux_lex) +sp_cache_routines_and_add_tables_for_view(THD *thd, LEX *lex, TABLE_LIST *view) { Sroutine_hash_entry **last_cached_routine_ptr= (Sroutine_hash_entry **)lex->sroutines_list.next; - sp_update_stmt_used_routines(thd, lex, &aux_lex->sroutines_list); + sp_update_stmt_used_routines(thd, lex, &view->view->sroutines_list, + view->top_table()); return sp_cache_routines_and_add_tables_aux(thd, lex, *last_cached_routine_ptr, FALSE, NULL); @@ -1609,9 +1627,9 @@ sp_cache_routines_and_add_tables_for_view(THD *thd, LEX *lex, LEX *aux_lex) SYNOPSIS sp_cache_routines_and_add_tables_for_triggers() - thd - thread context - lex - LEX respresenting statement - triggers - triggers of the table + thd thread context + lex LEX respresenting statement + table Table list element for table with trigger RETURN VALUE 0 - success @@ -1620,11 +1638,12 @@ sp_cache_routines_and_add_tables_for_view(THD *thd, LEX *lex, LEX *aux_lex) int sp_cache_routines_and_add_tables_for_triggers(THD *thd, LEX *lex, - Table_triggers_list *triggers) + TABLE_LIST *table) { int ret= 0; - - if (add_used_routine(lex, thd->stmt_arena, &triggers->sroutines_key)) + Table_triggers_list *triggers= table->table->triggers; + if (add_used_routine(lex, thd->stmt_arena, &triggers->sroutines_key, + table->belong_to_view)) { Sroutine_hash_entry **last_cached_routine_ptr= (Sroutine_hash_entry **)lex->sroutines_list.next; @@ -1634,10 +1653,12 @@ sp_cache_routines_and_add_tables_for_triggers(THD *thd, LEX *lex, { if (triggers->bodies[i][j]) { - (void)triggers->bodies[i][j]->add_used_tables_to_table_list(thd, - &lex->query_tables_last); + (void)triggers->bodies[i][j]-> + add_used_tables_to_table_list(thd, &lex->query_tables_last, + table->belong_to_view); sp_update_stmt_used_routines(thd, lex, - &triggers->bodies[i][j]->m_sroutines); + &triggers->bodies[i][j]->m_sroutines, + table->belong_to_view); } } } @@ -84,12 +84,13 @@ void sp_add_used_routine(LEX *lex, Query_arena *arena, sp_name *rt, char rt_type); void sp_remove_not_own_routines(LEX *lex); void sp_update_sp_used_routines(HASH *dst, HASH *src); -int sp_cache_routines_and_add_tables(THD *thd, LEX *lex, - bool first_no_prelock, bool *tabs_changed); +int sp_cache_routines_and_add_tables(THD *thd, LEX *lex, + bool first_no_prelock, + bool *tabs_changed); int sp_cache_routines_and_add_tables_for_view(THD *thd, LEX *lex, - LEX *aux_lex); + TABLE_LIST *view); int sp_cache_routines_and_add_tables_for_triggers(THD *thd, LEX *lex, - Table_triggers_list *triggers); + TABLE_LIST *table); extern "C" byte* sp_sroutine_key(const byte *ptr, uint *plen, my_bool first); diff --git a/sql/sp_head.cc b/sql/sp_head.cc index 9f61778202c..88d3ed83278 100644 --- a/sql/sp_head.cc +++ b/sql/sp_head.cc @@ -880,7 +880,7 @@ void sp_head::recursion_level_error() THD *thd= current_thd; my_error(ER_SP_RECURSION_LIMIT, MYF(0), thd->variables.max_sp_recursion_depth, - m_name); + m_name.str); } else my_error(ER_SP_NO_RECURSION, MYF(0)); @@ -3238,10 +3238,12 @@ sp_head::merge_table_list(THD *thd, TABLE_LIST *table, LEX *lex_for_tmp_check) SYNOPSIS add_used_tables_to_table_list() - thd - thread context - query_tables_last_ptr - (in/out) pointer the next_global member of last - element of the list where tables will be added - (or to its root). + thd [in] Thread context + query_tables_last_ptr [in/out] Pointer to the next_global member of + last element of the list where tables + will be added (or to its root). + belong_to_view [in] Uppermost view which uses this routine, + 0 if none. DESCRIPTION Converts multi-set of tables used by this routine to table list and adds @@ -3256,7 +3258,8 @@ sp_head::merge_table_list(THD *thd, TABLE_LIST *table, LEX *lex_for_tmp_check) bool sp_head::add_used_tables_to_table_list(THD *thd, - TABLE_LIST ***query_tables_last_ptr) + TABLE_LIST ***query_tables_last_ptr, + TABLE_LIST *belong_to_view) { uint i; Query_arena *arena, backup; @@ -3299,6 +3302,7 @@ sp_head::add_used_tables_to_table_list(THD *thd, table->lock_type= stab->lock_type; table->cacheable_table= 1; table->prelocking_placeholder= 1; + table->belong_to_view= belong_to_view; /* Everyting else should be zeroed */ diff --git a/sql/sp_head.h b/sql/sp_head.h index 398beb2d1f2..ad747b3466f 100644 --- a/sql/sp_head.h +++ b/sql/sp_head.h @@ -310,7 +310,8 @@ public: /* Add tables used by routine to the table list. */ bool add_used_tables_to_table_list(THD *thd, - TABLE_LIST ***query_tables_last_ptr); + TABLE_LIST ***query_tables_last_ptr, + TABLE_LIST *belong_to_view); /* Check if this stored routine contains statements disallowed diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 0e1c1525c9e..51d2317cad4 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -2128,7 +2128,7 @@ int open_tables(THD *thd, TABLE_LIST **start, uint *counter, uint flags) if (!query_tables_last_own) query_tables_last_own= thd->lex->query_tables_last; if (sp_cache_routines_and_add_tables_for_triggers(thd, thd->lex, - tables->table->triggers)) + tables)) { /* Serious error during reading stored routines from mysql.proc table. @@ -2158,8 +2158,7 @@ process_view_routines: /* We have at least one table in TL here. */ if (!query_tables_last_own) query_tables_last_own= thd->lex->query_tables_last; - if (sp_cache_routines_and_add_tables_for_view(thd, thd->lex, - tables->view)) + if (sp_cache_routines_and_add_tables_for_view(thd, thd->lex, tables)) { /* Serious error during reading stored routines from mysql.proc table. @@ -4238,11 +4237,13 @@ bool setup_fields(THD *thd, Item **ref_pointer_array, { reg2 Item *item; bool save_set_query_id= thd->set_query_id; + nesting_map save_allow_sum_func= thd->lex->allow_sum_func; List_iterator<Item> it(fields); DBUG_ENTER("setup_fields"); thd->set_query_id=set_query_id; - thd->allow_sum_func= allow_sum_func; + if (allow_sum_func) + thd->lex->allow_sum_func|= 1 << thd->lex->current_select->nest_level; thd->where= THD::DEFAULT_WHERE; /* @@ -4265,6 +4266,7 @@ bool setup_fields(THD *thd, Item **ref_pointer_array, if (!item->fixed && item->fix_fields(thd, it.ref()) || (item= *(it.ref()))->check_cols(1)) { + thd->lex->allow_sum_func= save_allow_sum_func; thd->set_query_id= save_set_query_id; DBUG_RETURN(TRUE); /* purecov: inspected */ } @@ -4275,6 +4277,7 @@ bool setup_fields(THD *thd, Item **ref_pointer_array, item->split_sum_func(thd, ref_pointer_array, *sum_func_list); thd->used_tables|= item->used_tables(); } + thd->lex->allow_sum_func= save_allow_sum_func; thd->set_query_id= save_set_query_id; DBUG_RETURN(test(thd->net.report_error)); } diff --git a/sql/sql_class.cc b/sql/sql_class.cc index f24d8ed4e50..ed2089546da 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -473,10 +473,12 @@ void THD::awake(THD::killed_state state_to_set) killed= state_to_set; if (state_to_set != THD::KILL_QUERY) + { thr_alarm_kill(real_id); #ifdef SIGNAL_WITH_VIO_CLOSE - close_active_vio(); + close_active_vio(); #endif + } if (mysys_var) { pthread_mutex_lock(&mysys_var->mutex); @@ -1578,7 +1580,6 @@ Statement::Statement(enum enum_state state_arg, ulong id_arg, :Query_arena(&main_mem_root, state_arg), id(id_arg), set_query_id(1), - allow_sum_func(0), lex(&main_lex), query(0), query_length(0), @@ -1599,7 +1600,6 @@ void Statement::set_statement(Statement *stmt) { id= stmt->id; set_query_id= stmt->set_query_id; - allow_sum_func= stmt->allow_sum_func; lex= stmt->lex; query= stmt->query; query_length= stmt->query_length; diff --git a/sql/sql_class.h b/sql/sql_class.h index 108e4723070..c025b4f0774 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -218,7 +218,6 @@ class MYSQL_LOG: public TC_LOG uint file_id; uint open_count; // For replication int readers_count; - bool reset_pending; bool write_error, inited; bool need_start_event; /* @@ -780,19 +779,6 @@ public: field list can not contain duplicates. */ bool set_query_id; - /* - This variable is used in post-parse stage to declare that sum-functions, - or functions which have sense only if GROUP BY is present, are allowed. - For example in queries - SELECT MIN(i) FROM foo - SELECT GROUP_CONCAT(a, b, MIN(i)) FROM ... GROUP BY ... - MIN(i) have no sense. - Though it's grammar-related issue, it's hard to catch it out during the - parse stage because GROUP BY clause goes in the end of query. This - variable is mainly used in setup_fields/fix_fields. - See item_sum.cc for details. - */ - bool allow_sum_func; LEX_STRING name; /* name for named prepared statements */ LEX *lex; // parse tree descriptor diff --git a/sql/sql_db.cc b/sql/sql_db.cc index bde6522a38b..2500b213f4c 100644 --- a/sql/sql_db.cc +++ b/sql/sql_db.cc @@ -1162,10 +1162,12 @@ bool mysql_change_db(THD *thd, const char *name, bool no_access_check) DBUG_RETURN(1); } end: - x_free(thd->db); + if (!(thd->slave_thread)) + x_free(thd->db); if (dbname && dbname[0] == 0) { - x_free(dbname); + if (!(thd->slave_thread)) + x_free(dbname); thd->db= NULL; thd->db_length= 0; } diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc index 983f0931ef9..393e8184725 100644 --- a/sql/sql_delete.cc +++ b/sql/sql_delete.cc @@ -293,6 +293,7 @@ cleanup: if (!transactional_table) thd->options|=OPTION_STATUS_NO_TRANS_UPDATE; } + free_underlaid_joins(thd, select_lex); if (transactional_table) { if (ha_autocommit_or_rollback(thd,error >= 0)) @@ -304,7 +305,6 @@ cleanup: mysql_unlock_tables(thd, thd->lock); thd->lock=0; } - free_underlaid_joins(thd, select_lex); if (error < 0) { thd->row_count_func= deleted; @@ -333,7 +333,7 @@ bool mysql_prepare_delete(THD *thd, TABLE_LIST *table_list, Item **conds) SELECT_LEX *select_lex= &thd->lex->select_lex; DBUG_ENTER("mysql_prepare_delete"); - thd->allow_sum_func= 0; + thd->lex->allow_sum_func= 0; if (setup_tables(thd, &thd->lex->select_lex.context, &thd->lex->select_lex.top_join_list, table_list, conds, &select_lex->leaf_tables, diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index 8903f28be11..e5ea296afab 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -257,7 +257,7 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list, */ bool log_on= (thd->options & OPTION_BIN_LOG) || (!(thd->security_ctx->master_access & SUPER_ACL)); - bool transactional_table; + bool transactional_table, joins_freed= FALSE; uint value_count; ulong counter = 1; ulonglong id; @@ -513,6 +513,9 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list, thd->row_count++; } + free_underlaid_joins(thd, &thd->lex->select_lex); + joins_freed= TRUE; + /* Now all rows are inserted. Time to update logs and sends response to user @@ -611,7 +614,6 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list, thd->row_count_func= info.copied+info.deleted+info.updated; ::send_ok(thd, (ulong) thd->row_count_func, id, buff); } - free_underlaid_joins(thd, &thd->lex->select_lex); thd->abort_on_warning= 0; DBUG_RETURN(FALSE); @@ -620,7 +622,8 @@ abort: if (lock_type == TL_WRITE_DELAYED) end_delayed_insert(thd); #endif - free_underlaid_joins(thd, &thd->lex->select_lex); + if (!joins_freed) + free_underlaid_joins(thd, &thd->lex->select_lex); thd->abort_on_warning= 0; DBUG_RETURN(TRUE); } diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 22ec8241367..946b6a28430 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -182,6 +182,9 @@ void lex_start(THD *thd, uchar *buf,uint length) lex->sroutines_list.empty(); lex->sroutines_list_own_last= lex->sroutines_list.next; lex->sroutines_list_own_elements= 0; + lex->nest_level=0 ; + lex->allow_sum_func= 0; + lex->in_sum_func= NULL; DBUG_VOID_RETURN; } @@ -1144,6 +1147,7 @@ void st_select_lex::init_query() first_cond_optimization= 1; parsing_place= NO_MATTER; exclude_from_table_unique_test= no_wrap_view_item= FALSE; + nest_level= 0; link_next= 0; } @@ -1163,6 +1167,7 @@ void st_select_lex::init_select() interval_list.empty(); use_index.empty(); ftfunc_list_alloc.empty(); + inner_sum_func_list= 0; ftfunc_list= &ftfunc_list_alloc; linkage= UNSPECIFIED_TYPE; order_list.elements= 0; diff --git a/sql/sql_lex.h b/sql/sql_lex.h index f101b7c811b..5ba47d768fb 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -528,6 +528,8 @@ public: ulong table_join_options; uint in_sum_expr; uint select_number; /* number of select (used for EXPLAIN) */ + int nest_level; /* nesting level of select */ + Item_sum *inner_sum_func_list; /* list of sum func in nested selects */ uint with_wild; /* item list contain '*' */ bool braces; /* SELECT ... UNION (SELECT ... ) <- this braces */ /* TRUE when having fix field called in processing of this SELECT */ @@ -776,12 +778,23 @@ typedef struct st_lex SQL_LIST proc_list, auxilliary_table_list, save_list; create_field *last_field; + Item_sum *in_sum_func; udf_func udf; HA_CHECK_OPT check_opt; // check/repair options HA_CREATE_INFO create_info; LEX_MASTER_INFO mi; // used by CHANGE MASTER USER_RESOURCES mqh; ulong type; + /* + This variable is used in post-parse stage to declare that sum-functions, + or functions which have sense only if GROUP BY is present, are allowed. + For example in a query + SELECT ... FROM ...WHERE MIN(i) == 1 GROUP BY ... HAVING MIN(i) > 2 + MIN(i) in the WHERE clause is not allowed in the opposite to MIN(i) + in the HAVING clause. Due to possible nesting of select construct + the variable can contain 0 or 1 for each nest level. + */ + nesting_map allow_sum_func; enum_sql_command sql_command, orig_sql_command; thr_lock_type lock_option; enum SSL_type ssl_type; /* defined in violite.h */ @@ -800,6 +813,7 @@ typedef struct st_lex uint grant, grant_tot_col, which_columns; uint fk_delete_opt, fk_update_opt, fk_match_option; uint slave_thd_opt, start_transaction_opt; + int nest_level; /* In LEX representing update which were transformed to multi-update stores total number of tables. For LEX representing multi-delete diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 1428e50253a..664bdf9706b 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -5430,6 +5430,8 @@ mysql_new_select(LEX *lex, bool move_down) select_lex->parent_lex= lex; /* Used in init_query. */ select_lex->init_query(); select_lex->init_select(); + lex->nest_level++; + select_lex->nest_level= lex->nest_level; /* Don't evaluate this subquery during statement prepare even if it's a constant one. The flag is switched off in the end of diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc index d405f0791fb..ffbbf0c6476 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -2129,7 +2129,8 @@ void reinit_stmt_before_use(THD *thd, LEX *lex) lex->result->cleanup(); lex->result->set_thd(thd); } - thd->allow_sum_func= 0; + lex->allow_sum_func= 0; + lex->in_sum_func= NULL; DBUG_VOID_RETURN; } diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 8538372d607..1485f88610a 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -274,21 +274,20 @@ inline int setup_without_group(THD *thd, Item **ref_pointer_array, ORDER *order, ORDER *group, bool *hidden_group_fields) { - bool save_allow_sum_func; int res; + nesting_map save_allow_sum_func=thd->lex->allow_sum_func ; DBUG_ENTER("setup_without_group"); - save_allow_sum_func= thd->allow_sum_func; - thd->allow_sum_func= 0; + thd->lex->allow_sum_func&= ~(1 << thd->lex->current_select->nest_level); res= setup_conds(thd, tables, leaves, conds); - thd->allow_sum_func= save_allow_sum_func; + thd->lex->allow_sum_func|= 1 << thd->lex->current_select->nest_level; res= res || setup_order(thd, ref_pointer_array, tables, fields, all_fields, order); - thd->allow_sum_func= 0; + thd->lex->allow_sum_func&= ~(1 << thd->lex->current_select->nest_level); res= res || setup_group(thd, ref_pointer_array, tables, fields, all_fields, group, hidden_group_fields); - thd->allow_sum_func= save_allow_sum_func; + thd->lex->allow_sum_func= save_allow_sum_func; DBUG_RETURN(res); } @@ -355,8 +354,9 @@ JOIN::prepare(Item ***rref_pointer_array, if (having) { + nesting_map save_allow_sum_func= thd->lex->allow_sum_func; thd->where="having clause"; - thd->allow_sum_func=1; + thd->lex->allow_sum_func|= 1 << select_lex_arg->nest_level; select_lex->having_fix_field= 1; bool having_fix_rc= (!having->fixed && (having->fix_fields(thd, &having) || @@ -366,6 +366,18 @@ JOIN::prepare(Item ***rref_pointer_array, DBUG_RETURN(-1); /* purecov: inspected */ if (having->with_sum_func) having->split_sum_func(thd, ref_pointer_array, all_fields); + thd->lex->allow_sum_func= save_allow_sum_func; + } + if (select_lex->inner_sum_func_list) + { + Item_sum *end=select_lex->inner_sum_func_list; + Item_sum *item_sum= end; + do + { + item_sum= item_sum->next; + item_sum->split_sum_func2(thd, ref_pointer_array, + all_fields, item_sum->ref_by, FALSE); + } while (item_sum != end); } if (!thd->lex->view_prepare_mode) @@ -5220,7 +5232,9 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond) join->const_table_map|=RAND_TABLE_BIT; { // Check const tables COND *const_cond= - make_cond_for_table(cond,join->const_table_map,(table_map) 0); + make_cond_for_table(cond, + join->const_table_map, + (table_map) 0); DBUG_EXECUTE("where",print_where(const_cond,"constants");); for (JOIN_TAB *tab= join->join_tab+join->const_tables; tab < join->join_tab+join->tables ; tab++) @@ -8175,7 +8189,7 @@ Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type, uint convert_blob_length) { Item::Type orig_type= type; - Item *orig_item; + Item *orig_item= 0; if (type != Item::FIELD_ITEM && item->real_item()->type() == Item::FIELD_ITEM && @@ -8226,10 +8240,12 @@ Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type, } else result= create_tmp_field_from_field(thd, (*from_field= field->field), - item->name, table, - modify_item ? field : - NULL, - convert_blob_length); + orig_item ? orig_item->name : + item->name, + table, + modify_item ? field : + NULL, + convert_blob_length); if (orig_type == Item::REF_ITEM && orig_modify) ((Item_ref*)orig_item)->set_result_field(result); return result; diff --git a/sql/sql_show.cc b/sql/sql_show.cc index 82870d46e6c..1b31e8f7dc3 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -2069,6 +2069,13 @@ int get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond) bool res; lex->all_selects_list= lsel; + /* + Restore thd->temporary_tables to be able to process + temporary tables(only for 'show index' & 'show columns'). + This should be changed when processing of temporary tables for + I_S tables will be done. + */ + thd->temporary_tables= open_tables_state_backup.temporary_tables; res= open_normal_and_derived_tables(thd, show_table_list, MYSQL_LOCK_IGNORE_FLUSH); /* @@ -2088,6 +2095,7 @@ int get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond) show_table_list->view_db.str : show_table_list->db), show_table_list->alias)); + thd->temporary_tables= 0; close_thread_tables(thd); show_table_list->table= 0; goto err; @@ -2608,7 +2616,9 @@ static int get_schema_column_record(THD *thd, struct st_table_list *tables, table->field[6]->store((const char*) pos, strlen((const char*) pos), cs); is_blob= (field->type() == FIELD_TYPE_BLOB); - if (field->has_charset() || is_blob) + if (field->has_charset() || is_blob || + field->real_type() == MYSQL_TYPE_VARCHAR || // For varbinary type + field->real_type() == MYSQL_TYPE_STRING) // For binary type { longlong char_max_len= is_blob ? (longlong) field->max_length() / field->charset()->mbminlen : diff --git a/sql/sql_string.h b/sql/sql_string.h index 67c3e0c62f2..0659f684afe 100644 --- a/sql/sql_string.h +++ b/sql/sql_string.h @@ -24,7 +24,7 @@ #define NOT_FIXED_DEC 31 #endif -#define STRING_WITH_LEN(X) ((char*) X), (sizeof(X)-1) +#define STRING_WITH_LEN(X) ((const char*) X), ((uint) (sizeof(X) - 1)) class String; int sortcmp(const String *a,const String *b, CHARSET_INFO *cs); diff --git a/sql/sql_trigger.cc b/sql/sql_trigger.cc index 779b044696e..8a26c2bafa2 100644 --- a/sql/sql_trigger.cc +++ b/sql/sql_trigger.cc @@ -21,7 +21,7 @@ #include "parse_file.h" static const LEX_STRING triggers_file_type= - {STRING_WITH_LEN("TRIGGERS")}; + {(char *) STRING_WITH_LEN("TRIGGERS")}; const char * const triggers_file_ext= ".TRG"; @@ -34,17 +34,17 @@ const char * const triggers_file_ext= ".TRG"; static File_option triggers_file_parameters[]= { { - {STRING_WITH_LEN("triggers") }, + {(char *) STRING_WITH_LEN("triggers") }, offsetof(class Table_triggers_list, definitions_list), FILE_OPTIONS_STRLIST }, { - {STRING_WITH_LEN("sql_modes") }, + {(char *) STRING_WITH_LEN("sql_modes") }, offsetof(class Table_triggers_list, definition_modes_list), FILE_OPTIONS_ULLLIST }, { - {STRING_WITH_LEN("definers") }, + {(char *) STRING_WITH_LEN("definers") }, offsetof(class Table_triggers_list, definers_list), FILE_OPTIONS_STRLIST }, @@ -71,18 +71,14 @@ struct st_trigname }; static const LEX_STRING trigname_file_type= - {STRING_WITH_LEN("TRIGGERNAME")}; + {(char *) STRING_WITH_LEN("TRIGGERNAME")}; const char * const trigname_file_ext= ".TRN"; static File_option trigname_file_parameters[]= { { - /* - FIXME: Length specified for "trigger_table" key is erroneous, problem - caused by this are reported as BUG#14090 and should be fixed ASAP. - */ - {STRING_WITH_LEN("trigger_table")}, + {(char *) STRING_WITH_LEN("trigger_table")}, offsetof(struct st_trigname, trigger_table), FILE_OPTIONS_ESTRING }, @@ -155,6 +151,17 @@ bool mysql_create_or_drop_trigger(THD *thd, TABLE_LIST *tables, bool create) But do we want this ? */ + /* + Note that once we will have check for TRIGGER privilege in place we won't + need second part of condition below, since check_access() function also + checks that db is specified. + */ + if (!thd->lex->spname->m_db.length || create && !tables->db_length) + { + my_error(ER_NO_DB_ERROR, MYF(0)); + DBUG_RETURN(TRUE); + } + if (!create && !(tables= add_table_for_trigger(thd, thd->lex->spname))) DBUG_RETURN(TRUE); @@ -285,6 +292,9 @@ end: definer. The caller is responsible to provide memory for storing LEX_STRING object. + NOTE + Assumes that trigger name is fully qualified. + RETURN VALUE False - success True - error @@ -307,9 +317,7 @@ bool Table_triggers_list::create_trigger(THD *thd, TABLE_LIST *tables, /* Trigger must be in the same schema as target table. */ - if (my_strcasecmp(table_alias_charset, table->s->db, - lex->spname->m_db.str ? lex->spname->m_db.str : - thd->db)) + if (my_strcasecmp(table_alias_charset, table->s->db, lex->spname->m_db.str)) { my_error(ER_TRG_IN_WRONG_SCHEMA, MYF(0)); return 1; @@ -1010,7 +1018,6 @@ bool Table_triggers_list::get_trigger_info(THD *thd, trg_event_type event, static TABLE_LIST *add_table_for_trigger(THD *thd, sp_name *trig) { - const char *db= !trig->m_db.str ? thd->db : trig->m_db.str; LEX *lex= thd->lex; char path_buff[FN_REFLEN]; LEX_STRING path; @@ -1018,7 +1025,7 @@ static TABLE_LIST *add_table_for_trigger(THD *thd, sp_name *trig) struct st_trigname trigname; DBUG_ENTER("add_table_for_trigger"); - strxnmov(path_buff, FN_REFLEN, mysql_data_home, "/", db, "/", + strxnmov(path_buff, FN_REFLEN, mysql_data_home, "/", trig->m_db.str, "/", trig->m_name.str, trigname_file_ext, NullS); path.length= unpack_filename(path_buff, path_buff); path.str= path_buff; @@ -1047,7 +1054,7 @@ static TABLE_LIST *add_table_for_trigger(THD *thd, sp_name *trig) /* We need to reset statement table list to be PS/SP friendly. */ lex->query_tables= 0; lex->query_tables_last= &lex->query_tables; - DBUG_RETURN(sp_add_to_query_tables(thd, lex, db, + DBUG_RETURN(sp_add_to_query_tables(thd, lex, trig->m_db.str, trigname.trigger_table.str, TL_WRITE)); } @@ -1236,7 +1243,7 @@ Handle_old_incorrect_sql_modes_hook::process_unknown_string(char *&unknown_key, (char *)path, "TRIGGER"); File_option sql_modes_parameters= { - {STRING_WITH_LEN("sql_modes") }, + {(char *) STRING_WITH_LEN("sql_modes") }, offsetof(class Table_triggers_list, definition_modes_list), FILE_OPTIONS_ULLLIST }; diff --git a/sql/sql_trigger.h b/sql/sql_trigger.h index 143f9f4d5bd..51002683897 100644 --- a/sql/sql_trigger.h +++ b/sql/sql_trigger.h @@ -118,7 +118,7 @@ public: friend class Item_trigger_field; friend int sp_cache_routines_and_add_tables_for_triggers(THD *thd, LEX *lex, - Table_triggers_list *triggers); + TABLE_LIST *table); private: bool prepare_record1_accessors(TABLE *table); diff --git a/sql/sql_update.cc b/sql/sql_update.cc index 94c00036540..a86d1b57190 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -527,6 +527,7 @@ int mysql_update(THD *thd, if (!transactional_table) thd->options|=OPTION_STATUS_NO_TRANS_UPDATE; } + free_underlaid_joins(thd, select_lex); if (transactional_table) { if (ha_autocommit_or_rollback(thd, error >= 0)) @@ -539,7 +540,6 @@ int mysql_update(THD *thd, thd->lock=0; } - free_underlaid_joins(thd, select_lex); if (error < 0) { char buff[STRING_BUFFER_USUAL_SIZE]; @@ -601,7 +601,7 @@ bool mysql_prepare_update(THD *thd, TABLE_LIST *table_list, bzero((char*) &tables,sizeof(tables)); // For ORDER BY tables.table= table; tables.alias= table_list->alias; - thd->allow_sum_func= 0; + thd->lex->allow_sum_func= 0; if (setup_tables(thd, &select_lex->context, &select_lex->top_join_list, table_list, conds, &select_lex->leaf_tables, diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 10ba5e8b271..25e10362ece 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -4438,7 +4438,7 @@ simple_expr: } $$= new Item_default_value(Lex->current_context(), $3); } - | VALUES '(' simple_ident ')' + | VALUES '(' simple_ident_nospvar ')' { $$= new Item_insert_value(Lex->current_context(), $3); } | FUNC_ARG0 '(' ')' { @@ -8900,6 +8900,7 @@ subselect_end: LEX *lex=Lex; lex->pop_context(); lex->current_select = lex->current_select->return_after_parsing(); + lex->nest_level--; }; definer: diff --git a/sql/table.cc b/sql/table.cc index 268d7a0be49..fc75568b615 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -1403,13 +1403,12 @@ File create_frm(THD *thd, my_string name, const char *db, if (create_info->options & HA_LEX_CREATE_TMP_TABLE) create_flags|= O_EXCL | O_NOFOLLOW; -#if SIZEOF_OFF_T > 4 /* Fix this when we have new .frm files; Current limit is 4G rows (QQ) */ if (create_info->max_rows > UINT_MAX32) create_info->max_rows= UINT_MAX32; if (create_info->min_rows > UINT_MAX32) create_info->min_rows= UINT_MAX32; -#endif + /* Ensure that raid_chunks can't be larger than 255, as this would cause problems with drop database diff --git a/sql/tztime.cc b/sql/tztime.cc index e73d3f237ad..3a9d9a60aed 100644 --- a/sql/tztime.cc +++ b/sql/tztime.cc @@ -2443,6 +2443,7 @@ scan_tz_dir(char * name_end) int main(int argc, char **argv) { +#ifndef __NETWARE__ MY_INIT(argv[0]); if (argc != 2 && argc != 3) @@ -2501,6 +2502,10 @@ main(int argc, char **argv) free_root(&tz_storage, MYF(0)); } +#else + fprintf(stderr, "This tool has not been ported to NetWare\n"); +#endif /* __NETWARE__ */ + return 0; } diff --git a/sql/unireg.h b/sql/unireg.h index 40499261a4d..b932a2f320c 100644 --- a/sql/unireg.h +++ b/sql/unireg.h @@ -48,7 +48,7 @@ #define MAX_ALIAS_NAME 256 #define MAX_FIELD_NAME 34 /* Max colum name length +2 */ #define MAX_SYS_VAR_LENGTH 32 -#define MAX_KEY 64 /* Max used keys */ +#define MAX_KEY MAX_INDEXES /* Max used keys */ #define MAX_REF_PARTS 16 /* Max parts used as ref */ #define MAX_KEY_LENGTH 3072 /* max possible key */ #if SIZEOF_OFF_T > 4 diff --git a/strings/ctype-uca.c b/strings/ctype-uca.c index 4768e42a0b0..b18e5ee59d2 100644 --- a/strings/ctype-uca.c +++ b/strings/ctype-uca.c @@ -6706,6 +6706,14 @@ static const char esperanto[]= "& U < \\u016d <<< \\u016c"; /* + A simplified version of Hungarian, without consonant contractions. +*/ +static const char hungarian[]= + "&O < \\u00F6 <<< \\u00D6 << \\u0151 <<< \\u0150" + "&U < \\u00FC <<< \\u00DC << \\u0171 <<< \\u0170"; + + +/* Unicode Collation Algorithm: Collation element (weight) scanner, for consequent scan of collations @@ -8627,6 +8635,39 @@ CHARSET_INFO my_charset_ucs2_esperanto_uca_ci= }; +CHARSET_INFO my_charset_ucs2_hungarian_uca_ci= +{ + 146,0,0, /* number */ + MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE, + "ucs2", /* cs name */ + "ucs2_hungarian_ci",/* name */ + "", /* comment */ + hungarian, /* tailoring */ + NULL, /* ctype */ + NULL, /* to_lower */ + NULL, /* to_upper */ + NULL, /* sort_order */ + NULL, /* contractions */ + NULL, /* sort_order_big*/ + NULL, /* tab_to_uni */ + NULL, /* tab_from_uni */ + my_unicase_default, /* caseinfo */ + NULL, /* state_map */ + NULL, /* ident_map */ + 8, /* strxfrm_multiply */ + 1, /* caseup_multiply */ + 1, /* casedn_multiply */ + 2, /* mbminlen */ + 2, /* mbmaxlen */ + 9, /* min_sort_char */ + 0xFFFF, /* max_sort_char */ + ' ', /* pad char */ + 0, /* escape_with_backslash_is_dangerous */ + &my_charset_ucs2_handler, + &my_collation_ucs2_uca_handler +}; + + #endif @@ -9252,6 +9293,38 @@ CHARSET_INFO my_charset_utf8_esperanto_uca_ci= &my_collation_any_uca_handler }; +CHARSET_INFO my_charset_utf8_hungarian_uca_ci= +{ + 210,0,0, /* number */ + MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_UNICODE, + "utf8", /* cs name */ + "utf8_hungarian_ci",/* name */ + "", /* comment */ + hungarian, /* tailoring */ + ctype_utf8, /* ctype */ + NULL, /* to_lower */ + NULL, /* to_upper */ + NULL, /* sort_order */ + NULL, /* contractions */ + NULL, /* sort_order_big*/ + NULL, /* tab_to_uni */ + NULL, /* tab_from_uni */ + my_unicase_default, /* caseinfo */ + NULL, /* state_map */ + NULL, /* ident_map */ + 8, /* strxfrm_multiply */ + 1, /* caseup_multiply */ + 1, /* casedn_multiply */ + 1, /* mbminlen */ + 3, /* mbmaxlen */ + 9, /* min_sort_char */ + 0xFFFF, /* max_sort_char */ + ' ', /* pad char */ + 0, /* escape_with_backslash_is_dangerous */ + &my_charset_utf8_handler, + &my_collation_any_uca_handler +}; + #endif /* HAVE_CHARSET_utf8 */ #endif /* HAVE_UCA_COLLATIONS */ diff --git a/support-files/mysql.server.sh b/support-files/mysql.server.sh index 6dbffdc9778..1892e8b4a46 100644 --- a/support-files/mysql.server.sh +++ b/support-files/mysql.server.sh @@ -56,12 +56,18 @@ if test -z "$basedir" then basedir=@prefix@ bindir=@bindir@ - datadir=@localstatedir@ + if test -z "$datadir" + then + datadir=@localstatedir@ + fi sbindir=@sbindir@ libexecdir=@libexecdir@ else bindir="$basedir/bin" - datadir="$basedir/data" + if test -z "$datadir" + then + datadir="$basedir/data" + fi sbindir="$basedir/sbin" libexecdir="$basedir/libexec" fi diff --git a/support-files/mysql.spec.sh b/support-files/mysql.spec.sh index 379f7fc966a..912c6f9e051 100644 --- a/support-files/mysql.spec.sh +++ b/support-files/mysql.spec.sh @@ -35,7 +35,7 @@ Release: %{release} License: %{license} Source: http://www.mysql.com/Downloads/MySQL-@MYSQL_BASE_VERSION@/mysql-%{mysql_version}.tar.gz URL: http://www.mysql.com/ -Packager: Lenz Grimmer <build@mysql.com> +Packager: MySQL Production Engineering Team <build@mysql.com> Vendor: MySQL AB Provides: msqlormysql MySQL-server mysql BuildRequires: ncurses-devel @@ -325,7 +325,13 @@ fi make test-force || true # Save mysqld-max -mv sql/mysqld sql/mysqld-max +# check if mysqld was installed in .libs/ +if test -f sql/.libs/mysqld +then + cp sql/.libs/mysqld sql/mysqld-max +else + cp sql/mysqld sql/mysqld-max +fi nm --numeric-sort sql/mysqld-max > sql/mysqld-max.sym # Save the perror binary so it supports the NDB error codes (BUG#13740) mv extra/perror extra/perror.ndb @@ -363,14 +369,19 @@ BuildMySQL "--disable-shared \ --with-client-ldflags='-all-static' \ $USE_OTHER_LIBC_DIR \ %else - --with-zlib-dir=bundled \ %endif + --with-zlib-dir=bundled \ --with-comment=\"MySQL Community Edition - Standard (GPL)\" \ --with-server-suffix='%{server_suffix}' \ --with-archive-storage-engine \ --with-innodb \ --with-big-tables" -nm --numeric-sort sql/mysqld > sql/mysqld.sym +if test -f sql/.libs/mysqld +then + nm --numeric-sort sql/.libs/mysqld > sql/mysqld.sym +else + nm --numeric-sort sql/mysqld > sql/mysqld.sym +fi # We might want to save the config log file if test -n "$MYSQL_CONFLOG_DEST" @@ -679,6 +690,8 @@ fi %{_libdir}/mysql/libndbclient.a %{_libdir}/mysql/libndbclient.la %{_libdir}/mysql/libvio.a +%{_libdir}/mysql/libz.a +%{_libdir}/mysql/libz.la %files shared %defattr(-, root, root, 0755) @@ -707,6 +720,13 @@ fi # itself - note that they must be ordered by date (important when # merging BK trees) %changelog +* Fri Dec 12 2005 Rodrigo Novo <rodrigo@mysql.com> + +- Added zlib to the list of (static) libraries installed +- Added check against libtool wierdness (WRT: sql/mysqld || sql/.libs/mysqld) +- Compile MySQL with bundled zlib +- Fixed %packager name to "MySQL Production Engineering Team" + * Mon Dec 05 2005 Joerg Bruehe <joerg@mysql.com> - Avoid using the "bundled" zlib on "shared" builds: diff --git a/tests/mysql_client_test.c b/tests/mysql_client_test.c index ce732690700..216961b3a80 100644 --- a/tests/mysql_client_test.c +++ b/tests/mysql_client_test.c @@ -36,7 +36,7 @@ #define VER "2.1" #define MAX_TEST_QUERY_LENGTH 300 /* MAX QUERY BUFFER LENGTH */ -#define MAX_KEY 64 +#define MAX_KEY MAX_INDEXES #define MAX_SERVER_ARGS 64 /* set default options */ @@ -14590,6 +14590,40 @@ static void test_bug14845() myquery(rc); } + +/* + Bug #15510: mysql_warning_count returns 0 after mysql_stmt_fetch which + should warn +*/ +static void test_bug15510() +{ + MYSQL_STMT *stmt; + MYSQL_RES *res; + int rc; + const char *query= "select 1 from dual where 1/0"; + + myheader("test_bug15510"); + + rc= mysql_query(mysql, "set @@sql_mode='ERROR_FOR_DIVISION_BY_ZERO'"); + myquery(rc); + + stmt= mysql_stmt_init(mysql); + + rc= mysql_stmt_prepare(stmt, query, strlen(query)); + check_execute(stmt, rc); + + rc= mysql_stmt_execute(stmt); + check_execute(stmt, rc); + + rc= mysql_stmt_fetch(stmt); + DIE_UNLESS(mysql_warning_count(mysql)); + + /* Cleanup */ + mysql_stmt_close(stmt); + rc= mysql_query(mysql, "set @@sql_mode=''"); + myquery(rc); +} + /* Read and parse arguments and MySQL options from my.cnf */ @@ -14849,6 +14883,7 @@ static struct my_tests_st my_tests[]= { { "test_bug13488", test_bug13488 }, { "test_bug13524", test_bug13524 }, { "test_bug14845", test_bug14845 }, + { "test_bug15510", test_bug15510}, { 0, 0 } }; diff --git a/zlib/Makefile.am b/zlib/Makefile.am index e94d184a841..11b1991fa62 100644 --- a/zlib/Makefile.am +++ b/zlib/Makefile.am @@ -18,6 +18,8 @@ pkglib_LTLIBRARIES=libz.la +libz_la_LDFLAGS= -version-info 3:3:2 + noinst_HEADERS= crc32.h deflate.h inffast.h inffixed.h inflate.h \ inftrees.h trees.h zconf.h zlib.h zutil.h |