diff --git a/.bzrignore b/.bzrignore index 555199fd166..ecaa4b60c51 100644 --- a/.bzrignore +++ b/.bzrignore @@ -4,6 +4,7 @@ *.bb *.bbg *.bin +*.cmake *.core *.d *.da @@ -17,6 +18,7 @@ *.map *.o *.obj +*.old *.pch *.pdb *.reject @@ -25,11 +27,23 @@ *.so *.so.* *.spec +*.user +*.vcproj +*/*.dir/* */*_pure_*warnings +*/.deps +*/.libs/* */.pure +*/debug/* +*/release/* *~ .*.swp +./CMakeCache.txt +./MySql.ncb +./MySql.sln +./MySql.suo ./README.build-files +./cmakecache.txt ./config.h ./copy_mysql_files.bat ./fix-project-files @@ -65,6 +79,7 @@ BitKeeper/post-commit-manual BitKeeper/tmp/* BitKeeper/tmp/bkr3sAHD BitKeeper/tmp/gone +CMakeFiles/* COPYING COPYING.LIB Docs/#manual.texi# @@ -1036,6 +1051,7 @@ ndbcluster-1186/ndb_3.pid ndbcluster-1186/ndb_3_cluster.log ndbcluster-1186/ndb_3_out.log ndbcluster-1186/ndbcluster.pid +netware/libmysql.imp pack_isam/*.ds? perror/*.ds? perror/*.vcproj @@ -1195,6 +1211,7 @@ strings/ctype_autoconf.c strings/ctype_extra_sources.c strings/str_test strings/test_decimal +support-files/*.ini support-files/MacOSX/Description.plist support-files/MacOSX/Info.plist support-files/MacOSX/ReadMe.txt @@ -1297,5 +1314,8 @@ vio/test-sslserver vio/viotest-ssl vio/viotest-sslconnect.cpp vio/viotest.cpp +win/configure.data +win/vs71cache.txt +win/vs8cache.txt zlib/*.ds? zlib/*.vcproj diff --git a/BitKeeper/etc/collapsed b/BitKeeper/etc/collapsed index d4d681937a2..79836bb030e 100644 --- a/BitKeeper/etc/collapsed +++ b/BitKeeper/etc/collapsed @@ -2,3 +2,8 @@ 44ec850ac2k4y2Omgr92GiWPBAVKGQ 44edb86b1iE5knJ97MbliK_3lCiAXA 44f33f3aj5KW5qweQeekY1LU0E9ZCg +45001f7c3b2hhCXDKfUvzkX9TNe6VA +45002051rHJfMEXAIMiAZV0clxvKSA +4513d8e4Af4dQWuk13sArwofRgFDQw +4519a6c5BVUxEHTf5iJnjZkixMBs8g +451ab499rgdjXyOnUDqHu-wBDoS-OQ diff --git a/BitKeeper/etc/config b/BitKeeper/etc/config index 6d06edd193e..1a027813ff4 100644 --- a/BitKeeper/etc/config +++ b/BitKeeper/etc/config @@ -75,5 +75,6 @@ hours: [tomas:]checkout:get [guilhem:]checkout:get [pekka:]checkout:get +[msvensson:]checkout:get checkout:edit eoln:unix diff --git a/BitKeeper/triggers/post-commit b/BitKeeper/triggers/post-commit index 22d183eae3a..981b55c66ec 100755 --- a/BitKeeper/triggers/post-commit +++ b/BitKeeper/triggers/post-commit @@ -6,6 +6,13 @@ COMMITS=commits@lists.mysql.com DOCS=docs-commit@mysql.com LIMIT=10000 VERSION="5.0" +BKROOT=`bk root` + +if [ -x /usr/sbin/sendmail ]; then + SENDMAIL=/usr/sbin/sendmail +else + SENDMAIL=sendmail +fi if [ "$REAL_EMAIL" = "" ] then @@ -58,7 +65,9 @@ $BH EOF bk changes -v -r+ bk cset -r+ -d - ) | /usr/sbin/sendmail -t + ) > $BKROOT/BitKeeper/tmp/dev_public.txt + +$SENDMAIL -t < $BKROOT/BitKeeper/tmp/dev_public.txt #++ # commits@ mail @@ -82,7 +91,9 @@ see http://dev.mysql.com/doc/mysql/en/installing-source-tree.html EOF bk changes -v -r+ bk cset -r+ -d - ) | head -n $LIMIT | /usr/sbin/sendmail -t + ) | bk sed -e ${LIMIT}q > $BKROOT/BitKeeper/tmp/commits.txt + +$SENDMAIL -t < $BKROOT/BitKeeper/tmp/commits.txt #++ # docs-commit@ mail @@ -102,7 +113,8 @@ Subject: bk commit - $VERSION tree (Manual) ($CHANGESET)$BS EOF bk changes -v -r+ bk cset -r+ -d - ) | /usr/sbin/sendmail -t + ) > $BKROOT/BitKeeper/tmp/docs.txt + $SENDMAIL -t < $BKROOT/BitKeeper/tmp/docs.txt fi else diff --git a/CMakeLists.txt b/CMakeLists.txt index fd780ec6a13..8058f615f7c 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -29,8 +29,6 @@ IF (WITH_MYISAMMRG_STORAGE_ENGINE) ENDIF (WITH_MYISAMMRG_STORAGE_ENGINE) IF(WITH_INNOBASE_STORAGE_ENGINE) - CONFIGURE_FILE(${CMAKE_SOURCE_DIR}/innobase/ib_config.h.in - ${CMAKE_SOURCE_DIR}/innobase/ib_config.h @ONLY) ADD_DEFINITIONS(-D HAVE_INNOBASE_DB) ADD_DEFINITIONS(-D WITH_INNOBASE_STORAGE_ENGINE) SET (mysql_plugin_defs "${mysql_plugin_defs},builtin_innobase_plugin") @@ -123,8 +121,12 @@ ADD_SUBDIRECTORY(heap) ADD_SUBDIRECTORY(myisam) ADD_SUBDIRECTORY(myisammrg) ADD_SUBDIRECTORY(client) +IF(WITH_BERKELEY_STORAGE_ENGINE) ADD_SUBDIRECTORY(bdb) +ENDIF(WITH_BERKELEY_STORAGE_ENGINE) +IF(WITH_INNOBASE_STORAGE_ENGINE) ADD_SUBDIRECTORY(innobase) +ENDIF(WITH_INNOBASE_STORAGE_ENGINE) ADD_SUBDIRECTORY(sql) ADD_SUBDIRECTORY(sql/examples) ADD_SUBDIRECTORY(server-tools/instance-manager) diff --git a/Docs/Makefile.am b/Docs/Makefile.am index f512aa9e29e..4722f61f5b9 100644 --- a/Docs/Makefile.am +++ b/Docs/Makefile.am @@ -16,7 +16,7 @@ noinst_SCRIPTS = Support/generate-text-files.pl -EXTRA_DIST = $(noinst_SCRIPTS) mysql.info INSTALL-BINARY +EXTRA_DIST = $(noinst_SCRIPTS) manual.chm mysql.info INSTALL-BINARY TXT_FILES= ../INSTALL-SOURCE ../INSTALL-WIN-SOURCE ../EXCEPTIONS-CLIENT \ INSTALL-BINARY ../support-files/MacOSX/ReadMe.txt diff --git a/Docs/manual.chm b/Docs/manual.chm new file mode 100644 index 00000000000..28c3e1b5a86 --- /dev/null +++ b/Docs/manual.chm @@ -0,0 +1,14 @@ + +********************************************************* + +This is a dummy placeholder file for "manual.chm" in the +MySQL source trees. + +Note, that the documentation has been moved into a separate +BitKeeper source tree named "mysqldoc" - do not attempt to edit this +file! All changes to it should be done in the mysqldoc tree. + +This dummy file is being replaced with the actual file from the +mysqldoc tree when building the official source distribution. + +********************************************************* diff --git a/Makefile.am b/Makefile.am index d48f0e24966..474d268db38 100644 --- a/Makefile.am +++ b/Makefile.am @@ -89,8 +89,18 @@ bin-dist: all $(top_builddir)/scripts/make_binary_distribution @MAKE_BINARY_DISTRIBUTION_OPTIONS@ # Remove BK's "SCCS" subdirectories from source distribution +# Create initial database files for Windows installations. dist-hook: rm -rf `find $(distdir) -type d -name SCCS -print` + if echo "$(distdir)" | grep -q '^/' ; then \ + scripts/mysql_install_db --no-defaults --windows \ + --basedir=$(top_srcdir) \ + --datadir="$(distdir)/win/data"; \ + else \ + scripts/mysql_install_db --no-defaults --windows \ + --basedir=$(top_srcdir) \ + --datadir="$$(pwd)/$(distdir)/win/data"; \ + fi tags: support-files/build-tags diff --git a/client/CMakeLists.txt b/client/CMakeLists.txt index 3e7f1a48c70..09a6a3f1e2a 100755 --- a/client/CMakeLists.txt +++ b/client/CMakeLists.txt @@ -66,6 +66,9 @@ TARGET_LINK_LIBRARIES(mysqldump mysqlclient mysys dbug yassl taocrypt zlib wsock ADD_EXECUTABLE(mysqlimport mysqlimport.c) TARGET_LINK_LIBRARIES(mysqlimport mysqlclient mysys dbug yassl taocrypt zlib wsock32) +ADD_EXECUTABLE(mysql_upgrade mysql_upgrade.c) +TARGET_LINK_LIBRARIES(mysql_upgrade mysqlclient mysys dbug yassl taocrypt zlib wsock32) + ADD_EXECUTABLE(mysqlshow mysqlshow.c) TARGET_LINK_LIBRARIES(mysqlshow mysqlclient mysys dbug yassl taocrypt zlib wsock32) diff --git a/client/mysql.cc b/client/mysql.cc index 2ba9e896747..1d7abbbc38a 100644 --- a/client/mysql.cc +++ b/client/mysql.cc @@ -49,6 +49,9 @@ const char *VER= "14.12"; /* Don't try to make a nice table if the data is too big */ #define MAX_COLUMN_LENGTH 1024 +/* Buffer to hold 'version' and 'version_comment' */ +#define MAX_SERVER_VERSION_LENGTH 128 + gptr sql_alloc(unsigned size); // Don't use mysqld alloc for these void sql_element_free(void *ptr); #include "sql_string.h" @@ -208,6 +211,7 @@ static int com_nopager(String *str, char*), com_pager(String *str, char*), static int read_and_execute(bool interactive); static int sql_connect(char *host,char *database,char *user,char *password, uint silent); +static const char *server_version_string(MYSQL *mysql); static int put_info(const char *str,INFO_TYPE info,uint error=0, const char *sql_state=0); static int put_error(MYSQL *mysql); @@ -432,8 +436,8 @@ int main(int argc,char *argv[]) put_info("Welcome to the MySQL monitor. Commands end with ; or \\g.", INFO_INFO); sprintf((char*) glob_buffer.ptr(), - "Your MySQL connection id is %lu to server version: %s\n", - mysql_thread_id(&mysql),mysql_get_server_info(&mysql)); + "Your MySQL connection id is %lu\nServer version: %s\n", + mysql_thread_id(&mysql), server_version_string(&mysql)); put_info((char*) glob_buffer.ptr(),INFO_INFO); #ifdef HAVE_READLINE @@ -2321,10 +2325,8 @@ print_table_data(MYSQL_RES *result) MYSQL_ROW cur; MYSQL_FIELD *field; bool *num_flag; - bool *not_null_flag; num_flag=(bool*) my_alloca(sizeof(bool)*mysql_num_fields(result)); - not_null_flag=(bool*) my_alloca(sizeof(bool)*mysql_num_fields(result)); if (info_flag) { print_field_types(result); @@ -2363,7 +2365,6 @@ print_table_data(MYSQL_RES *result) MAX_COLUMN_LENGTH), field->name); num_flag[off]= IS_NUM(field->type); - not_null_flag[off]= IS_NOT_NULL(field->flags); } (void) tee_fputs("\n", PAGER); tee_puts((char*) separator.ptr(), PAGER); @@ -2384,7 +2385,7 @@ print_table_data(MYSQL_RES *result) uint extra_padding; /* If this column may have a null value, use "NULL" for empty. */ - if (! not_null_flag[off] && (cur[off] == NULL)) + if (cur[off] == NULL) { buffer= "NULL"; data_length= 4; @@ -2424,7 +2425,6 @@ print_table_data(MYSQL_RES *result) } tee_puts((char*) separator.ptr(), PAGER); my_afree((gptr) num_flag); - my_afree((gptr) not_null_flag); } @@ -2513,9 +2513,14 @@ print_table_data_xml(MYSQL_RES *result) { tee_fprintf(PAGER, "\t"); - xmlencode_print(cur[i], lengths[i]); - tee_fprintf(PAGER, "\n"); + if (cur[i]) + { + tee_fprintf(PAGER, "\">"); + xmlencode_print(cur[i], lengths[i]); + tee_fprintf(PAGER, "\n"); + } + else + tee_fprintf(PAGER, "\" xsi:nil=\"true\" />\n"); } (void) tee_fputs(" \n", PAGER); } @@ -2914,7 +2919,7 @@ com_connect(String *buffer, char *line) bzero(buff, sizeof(buff)); if (buffer) { - strmake(buff, line, sizeof(buff)); + strmake(buff, line, sizeof(buff) - 1); tmp= get_arg(buff, 0); if (tmp && *tmp) { @@ -3029,7 +3034,7 @@ com_use(String *buffer __attribute__((unused)), char *line) int select_db; bzero(buff, sizeof(buff)); - strmov(buff, line); + strmake(buff, line, sizeof(buff) - 1); tmp= get_arg(buff, 0); if (!tmp || !*tmp) { @@ -3339,16 +3344,13 @@ com_status(String *buffer __attribute__((unused)), tee_fprintf(stdout, "Using outfile:\t\t'%s'\n", opt_outfile ? outfile : ""); #endif tee_fprintf(stdout, "Using delimiter:\t%s\n", delimiter); - tee_fprintf(stdout, "Server version:\t\t%s\n", mysql_get_server_info(&mysql)); + tee_fprintf(stdout, "Server version:\t\t%s\n", server_version_string(&mysql)); tee_fprintf(stdout, "Protocol version:\t%d\n", mysql_get_proto_info(&mysql)); tee_fprintf(stdout, "Connection:\t\t%s\n", mysql_get_host_info(&mysql)); if ((id= mysql_insert_id(&mysql))) tee_fprintf(stdout, "Insert id:\t\t%s\n", llstr(id, buff)); - /* - Don't remove "limit 1", - it is protection againts SQL_SELECT_LIMIT=0 - */ + /* "limit 1" is protection against SQL_SELECT_LIMIT=0 */ if (!mysql_query(&mysql,"select @@character_set_client, @@character_set_connection, @@character_set_server, @@character_set_database limit 1") && (result=mysql_use_result(&mysql))) { @@ -3413,6 +3415,39 @@ select_limit, max_join_size); return 0; } +static const char * +server_version_string(MYSQL *mysql) +{ + static char buf[MAX_SERVER_VERSION_LENGTH] = ""; + + /* Only one thread calls this, so no synchronization is needed */ + if (buf[0] == '\0') + { + char *bufp = buf; + MYSQL_RES *result; + MYSQL_ROW cur; + + bufp = strnmov(buf, mysql_get_server_info(mysql), sizeof buf); + + /* "limit 1" is protection against SQL_SELECT_LIMIT=0 */ + if (!mysql_query(mysql, "select @@version_comment limit 1") && + (result = mysql_use_result(mysql))) + { + MYSQL_ROW cur = mysql_fetch_row(result); + if (cur && cur[0]) + { + bufp = strxnmov(bufp, sizeof buf - (bufp - buf), " ", cur[0], NullS); + } + mysql_free_result(result); + } + + /* str*nmov doesn't guarantee NUL-termination */ + if (bufp == buf + sizeof buf) + buf[sizeof buf - 1] = '\0'; + } + + return buf; +} static int put_info(const char *str,INFO_TYPE info_type, uint error, const char *sqlstate) @@ -3540,14 +3575,14 @@ void tee_puts(const char *s, FILE *file) { NETWARE_YIELD; fputs(s, file); - fputs("\n", file); + fputc('\n', file); #ifdef OS2 - fflush( file); + fflush(file); #endif if (opt_outfile) { fputs(s, OUTFILE); - fputs("\n", OUTFILE); + fputc('\n', OUTFILE); } } diff --git a/client/mysql_upgrade.c b/client/mysql_upgrade.c index 9a73263f558..6ec361392c8 100644 --- a/client/mysql_upgrade.c +++ b/client/mysql_upgrade.c @@ -200,7 +200,7 @@ retry_open: } buffer_end= strnmov(buffer, "\n[client]", sizeof(buffer)); if (opt_password) - buffer_end= strxnmov(buffer, sizeof(buffer), + buffer_end= strxnmov(buffer_end, sizeof(buffer), "\npassword=", opt_password, NullS); error= my_write(defaults_file, buffer, (int) (buffer_end - buffer), MYF(MY_WME | MY_FNABP)); diff --git a/client/mysqldump.c b/client/mysqldump.c index e774a07295b..b3a209c6086 100644 --- a/client/mysqldump.c +++ b/client/mysqldump.c @@ -85,7 +85,7 @@ static char *alloc_query_str(ulong size); static char *field_escape(char *to,const char *from,uint length); static my_bool verbose= 0, opt_no_create_info= 0, opt_no_data= 0, quick= 1, extended_insert= 1, - lock_tables=1,ignore_errors=0,flush_logs=0, + lock_tables=1,ignore_errors=0,flush_logs=0,flush_privileges=0, opt_drop=1,opt_keywords=0,opt_lock=1,opt_compress=0, opt_delayed=0,create_options=1,opt_quoted=0,opt_databases=0, opt_alldbs=0,opt_create_db=0,opt_lock_all_tables=0, @@ -256,6 +256,12 @@ static struct my_option my_long_options[] = "--lock-all-tables or --master-data with --flush-logs", (gptr*) &flush_logs, (gptr*) &flush_logs, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, + {"flush-privileges", OPT_ESC, "Emit a FLUSH PRIVILEGES statement " + "after dumping the mysql database. This option should be used any " + "time the dump contains the mysql database and any other database " + "that depends on the data in the mysql database for proper restore. ", + (gptr*) &flush_privileges, (gptr*) &flush_privileges, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, + 0, 0}, {"force", 'f', "Continue even if we get an sql-error.", (gptr*) &ignore_errors, (gptr*) &ignore_errors, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, @@ -652,13 +658,13 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)), tty_password=1; break; case 'r': - if (!(md_result_file = my_fopen(argument, O_WRONLY | FILE_BINARY, + if (!(md_result_file= my_fopen(argument, O_WRONLY | FILE_BINARY, MYF(MY_WME)))) exit(1); break; case 'W': #ifdef __WIN__ - opt_protocol = MYSQL_PROTOCOL_PIPE; + opt_protocol= MYSQL_PROTOCOL_PIPE; #endif break; case 'N': @@ -673,7 +679,7 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)), #include case 'V': print_version(); exit(0); case 'X': - opt_xml = 1; + opt_xml= 1; extended_insert= opt_drop= opt_lock= opt_disable_keys= opt_autocommit= opt_create_db= 0; break; @@ -1436,7 +1442,7 @@ static uint get_table_structure(char *table, char *db, char *table_type, const char *insert_option; char name_buff[NAME_LEN+3],table_buff[NAME_LEN*2+3]; char table_buff2[NAME_LEN*2+3], query_buff[512]; - FILE *sql_file = md_result_file; + FILE *sql_file= md_result_file; int len; MYSQL_RES *result; MYSQL_ROW row; @@ -1480,7 +1486,7 @@ static uint get_table_structure(char *table, char *db, char *table_type, opt_quoted_table= quote_name(table, table_buff2, 0); if (opt_order_by_primary) - order_by = primary_key_fields(result_table); + order_by= primary_key_fields(result_table); if (!opt_xml && !mysql_query_with_error_report(mysql, 0, query_buff)) { @@ -1532,7 +1538,7 @@ static uint get_table_structure(char *table, char *db, char *table_type, field= mysql_fetch_field_direct(result, 0); if (strcmp(field->name, "View") == 0) { - char *scv_buff = NULL; + char *scv_buff= NULL; verbose_msg("-- It's a view, create dummy table for view\n"); @@ -1569,7 +1575,7 @@ static uint get_table_structure(char *table, char *db, char *table_type, my_free(scv_buff, MYF(MY_ALLOW_ZERO_PTR)); safe_exit(EX_MYSQLERR); - DBUG_RETURN(0); + DBUG_RETURN(0); } else my_free(scv_buff, MYF(MY_ALLOW_ZERO_PTR)); @@ -1933,7 +1939,7 @@ static void dump_triggers_for_table (char *table, char *db) char name_buff[NAME_LEN*4+3], table_buff[NAME_LEN*2+3]; char query_buff[512]; uint old_opt_compatible_mode=opt_compatible_mode; - FILE *sql_file = md_result_file; + FILE *sql_file= md_result_file; MYSQL_RES *result; MYSQL_ROW row; @@ -2177,15 +2183,15 @@ static void dump_table(char *table, char *db) end= strmov(end,buff); if (where || order_by) { - query = alloc_query_str((ulong) ((end - query) + 1 + + query= alloc_query_str((ulong) ((end - query) + 1 + (where ? strlen(where) + 7 : 0) + (order_by ? strlen(order_by) + 10 : 0))); - end = strmov(query, query_buf); + end= strmov(query, query_buf); if (where) - end = strxmov(end, " WHERE ", where, NullS); + end= strxmov(end, " WHERE ", where, NullS); if (order_by) - end = strxmov(end, " ORDER BY ", order_by, NullS); + end= strxmov(end, " ORDER BY ", order_by, NullS); } if (mysql_real_query(mysql, query, (uint) (end - query))) { @@ -2206,10 +2212,10 @@ static void dump_table(char *table, char *db) result_table); if (where || order_by) { - query = alloc_query_str((ulong) (strlen(query) + 1 + + query= alloc_query_str((ulong) (strlen(query) + 1 + (where ? strlen(where) + 7 : 0) + (order_by ? strlen(order_by) + 10 : 0))); - end = strmov(query, query_buf); + end= strmov(query, query_buf); if (where) { @@ -2218,7 +2224,7 @@ static void dump_table(char *table, char *db) fprintf(md_result_file, "-- WHERE: %s\n", where); check_io(md_result_file); } - end = strxmov(end, " WHERE ", where, NullS); + end= strxmov(end, " WHERE ", where, NullS); } if (order_by) { @@ -2227,7 +2233,7 @@ static void dump_table(char *table, char *db) fprintf(md_result_file, "-- ORDER BY: %s\n", order_by); check_io(md_result_file); } - end = strxmov(end, " ORDER BY ", order_by, NullS); + end= strxmov(end, " ORDER BY ", order_by, NullS); } } if (!opt_xml && !opt_compact) @@ -2303,12 +2309,12 @@ static void dump_table(char *table, char *db) check_io(md_result_file); } - for (i = 0; i < mysql_num_fields(res); i++) + for (i= 0; i < mysql_num_fields(res); i++) { int is_blob; ulong length= lengths[i]; - if (!(field = mysql_fetch_field(res))) + if (!(field= mysql_fetch_field(res))) { my_snprintf(query, QUERY_LENGTH, "%s: Not enough fields from table %s! Aborting.\n", @@ -2380,7 +2386,7 @@ static void dump_table(char *table, char *db) else { /* change any strings ("inf", "-inf", "nan") into NULL */ - char *ptr = row[i]; + char *ptr= row[i]; if (my_isalpha(charset_info, *ptr) || (*ptr == '-' && my_isalpha(charset_info, ptr[1]))) dynstr_append(&extended_row, "NULL"); @@ -2440,7 +2446,7 @@ static void dump_table(char *table, char *db) else { /* change any strings ("inf", "-inf", "nan") into NULL */ - char *ptr = row[i]; + char *ptr= row[i]; if (opt_xml) { print_xml_tag1(md_result_file, "\t\t", "field name=", @@ -2486,10 +2492,10 @@ static void dump_table(char *table, char *db) { ulong row_length; dynstr_append(&extended_row,")"); - row_length = 2 + extended_row.length; + row_length= 2 + extended_row.length; if (total_length + row_length < opt_net_buffer_length) { - total_length += row_length; + total_length+= row_length; fputc(',',md_result_file); /* Always row break */ fputs(extended_row.str,md_result_file); } @@ -2501,7 +2507,7 @@ static void dump_table(char *table, char *db) fputs(insert_pat.str,md_result_file); fputs(extended_row.str,md_result_file); - total_length = row_length+init_length; + total_length= row_length+init_length; } check_io(md_result_file); } @@ -2566,15 +2572,15 @@ err: static char *getTableName(int reset) { - static MYSQL_RES *res = NULL; + static MYSQL_RES *res= NULL; MYSQL_ROW row; if (!res) { - if (!(res = mysql_list_tables(mysql,NullS))) + if (!(res= mysql_list_tables(mysql,NullS))) return(NULL); } - if ((row = mysql_fetch_row(res))) + if ((row= mysql_fetch_row(res))) return((char*) row[0]); if (reset) @@ -2582,7 +2588,7 @@ static char *getTableName(int reset) else { mysql_free_result(res); - res = NULL; + res= NULL; } return(NULL); } /* getTableName */ @@ -2596,7 +2602,7 @@ static int dump_all_databases() if (mysql_query_with_error_report(mysql, &tableres, "SHOW DATABASES")) return 1; - while ((row = mysql_fetch_row(tableres))) + while ((row= mysql_fetch_row(tableres))) { if (dump_all_tables_in_db(row[0])) result=1; @@ -2604,13 +2610,13 @@ static int dump_all_databases() if (seen_views) { if (mysql_query(mysql, "SHOW DATABASES") || - !(tableres = mysql_store_result(mysql))) + !(tableres= mysql_store_result(mysql))) { my_printf_error(0, "Error: Couldn't execute 'SHOW DATABASES': %s", MYF(0), mysql_error(mysql)); return 1; } - while ((row = mysql_fetch_row(tableres))) + while ((row= mysql_fetch_row(tableres))) { if (dump_all_views_in_db(row[0])) result=1; @@ -2767,6 +2773,7 @@ static int dump_all_tables_in_db(char *database) char hash_key[2*NAME_LEN+2]; /* "db.tablename" */ char *afterdot; + int using_mysql_db= my_strcasecmp(&my_charset_latin1, database, "mysql"); afterdot= strmov(hash_key, database); *afterdot++= '.'; @@ -2821,6 +2828,11 @@ static int dump_all_tables_in_db(char *database) } if (lock_tables) VOID(mysql_query_with_error_report(mysql, 0, "UNLOCK TABLES")); + if (flush_privileges && using_mysql_db == 0) + { + fprintf(md_result_file,"\n--\n-- Flush Grant Tables \n--\n"); + fprintf(md_result_file,"\n/*! FLUSH PRIVILEGES */;\n"); + } return 0; } /* dump_all_tables_in_db */ @@ -3036,7 +3048,7 @@ static int do_show_master_status(MYSQL *mysql_con) } else { - row = mysql_fetch_row(master); + row= mysql_fetch_row(master); if (row && row[0] && row[1]) { /* SHOW MASTER STATUS reports file and position */ @@ -3163,7 +3175,7 @@ static void print_value(FILE *file, MYSQL_RES *result, MYSQL_ROW row, MYSQL_FIELD *field; mysql_field_seek(result, 0); - for ( ; (field = mysql_fetch_field(result)) ; row++) + for ( ; (field= mysql_fetch_field(result)) ; row++) { if (!strcmp(field->name,name)) { @@ -3291,17 +3303,19 @@ char check_if_ignore_table(const char *table_name, char *table_type) static char *primary_key_fields(const char *table_name) { - MYSQL_RES *res = NULL; + MYSQL_RES *res= NULL; MYSQL_ROW row; /* SHOW KEYS FROM + table name * 2 (escaped) + 2 quotes + \0 */ char show_keys_buff[15 + NAME_LEN * 2 + 3]; - uint result_length = 0; - char *result = 0; + uint result_length= 0; + char *result= 0; + char buff[NAME_LEN * 2 + 3]; + char *quoted_field; my_snprintf(show_keys_buff, sizeof(show_keys_buff), "SHOW KEYS FROM %s", table_name); if (mysql_query(mysql, show_keys_buff) || - !(res = mysql_store_result(mysql))) + !(res= mysql_store_result(mysql))) { fprintf(stderr, "Warning: Couldn't read keys from table %s;" " records are NOT sorted (%s)\n", @@ -3316,12 +3330,14 @@ static char *primary_key_fields(const char *table_name) * row, and UNIQUE keys come before others. So we only need to check * the first key, not all keys. */ - if ((row = mysql_fetch_row(res)) && atoi(row[1]) == 0) + if ((row= mysql_fetch_row(res)) && atoi(row[1]) == 0) { /* Key is unique */ do - result_length += strlen(row[4]) + 1; /* + 1 for ',' or \0 */ - while ((row = mysql_fetch_row(res)) && atoi(row[3]) > 1); + { + quoted_field= quote_name(row[4], buff, 0); + result_length+= strlen(quoted_field) + 1; /* + 1 for ',' or \0 */ + } while ((row= mysql_fetch_row(res)) && atoi(row[3]) > 1); } /* Build the ORDER BY clause result */ @@ -3329,17 +3345,21 @@ static char *primary_key_fields(const char *table_name) { char *end; /* result (terminating \0 is already in result_length) */ - result = my_malloc(result_length + 10, MYF(MY_WME)); + result= my_malloc(result_length + 10, MYF(MY_WME)); if (!result) { fprintf(stderr, "Error: Not enough memory to store ORDER BY clause\n"); goto cleanup; } mysql_data_seek(res, 0); - row = mysql_fetch_row(res); - end = strmov(result, row[4]); - while ((row = mysql_fetch_row(res)) && atoi(row[3]) > 1) - end = strxmov(end, ",", row[4], NullS); + row= mysql_fetch_row(res); + quoted_field= quote_name(row[4], buff, 0); + end= strmov(result, quoted_field); + while ((row= mysql_fetch_row(res)) && atoi(row[3]) > 1) + { + quoted_field= quote_name(row[4], buff, 0); + end= strxmov(end, ",", quoted_field, NullS); + } } cleanup: @@ -3407,7 +3427,7 @@ static my_bool get_view_structure(char *table, char* db) char table_buff[NAME_LEN*2+3]; char table_buff2[NAME_LEN*2+3]; char query[QUERY_LENGTH]; - FILE *sql_file = md_result_file; + FILE *sql_file= md_result_file; DBUG_ENTER("get_view_structure"); if (opt_no_create_info) /* Don't write table creation info */ diff --git a/client/mysqltest.c b/client/mysqltest.c index 0f0abe682b5..c0319eee259 100644 --- a/client/mysqltest.c +++ b/client/mysqltest.c @@ -1608,8 +1608,12 @@ int do_save_master_pos() int do_let(struct st_query *query) { + int ret; char *p= query->first_argument; - char *var_name, *var_name_end, *var_val_start; + char *var_name, *var_name_end; + DYNAMIC_STRING let_rhs_expr; + + init_dynamic_string(&let_rhs_expr, "", 512, 2048); /* Find */ if (!*p) @@ -1628,10 +1632,16 @@ int do_let(struct st_query *query) /* Find start of */ while (*p && my_isspace(charset_info,*p)) p++; - var_val_start= p; + + do_eval(&let_rhs_expr, p, FALSE); + query->last_argument= query->end; /* Assign var_val to var_name */ - return var_set(var_name, var_name_end, var_val_start, query->end); + ret= var_set(var_name, var_name_end, let_rhs_expr.str, + (let_rhs_expr.str + let_rhs_expr.length)); + dynstr_free(&let_rhs_expr); + + return(ret); } diff --git a/config/ac-macros/yassl.m4 b/config/ac-macros/yassl.m4 index 2dc231c1f5a..967dcbf764a 100644 --- a/config/ac-macros/yassl.m4 +++ b/config/ac-macros/yassl.m4 @@ -18,7 +18,8 @@ AC_DEFUN([MYSQL_CHECK_YASSL], [ fi AC_MSG_RESULT([using bundled yaSSL]) yassl_dir="extra/yassl" - yassl_libs="-L\$(top_srcdir)/extra/yassl/src -lyassl -L\$(top_srcdir)/extra/yassl/taocrypt/src -ltaocrypt" + yassl_libs="\$(top_builddir)/extra/yassl/src/libyassl.la \ + \$(top_builddir)/extra/yassl/taocrypt/src/libtaocrypt.la" AC_DEFINE([HAVE_OPENSSL], [1], [Defined by configure. Using yaSSL for OpenSSL emulation.]) AC_DEFINE([HAVE_YASSL], [1], [Defined by configure. Using yaSSL for OpenSSL emulation.]) # System specific checks diff --git a/configure.in b/configure.in index 58c19af5a50..55da1dfb241 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.25) +AM_INIT_AUTOMAKE(mysql, 5.0.27) AM_CONFIG_HEADER(config.h) PROTOCOL_VERSION=10 @@ -19,7 +19,7 @@ SHARED_LIB_VERSION=$SHARED_LIB_MAJOR_VERSION:0:0 # ndb version NDB_VERSION_MAJOR=5 NDB_VERSION_MINOR=0 -NDB_VERSION_BUILD=25 +NDB_VERSION_BUILD=27 NDB_VERSION_STATUS="" # Set all version vars based on $VERSION. How do we do this more elegant ? @@ -454,7 +454,7 @@ AC_PATH_PROG(PS, ps, ps) AC_MSG_CHECKING("how to check if pid exists") PS=$ac_cv_path_PS # Linux style -if $PS p $$ 2> /dev/null | grep $0 > /dev/null +if $PS p $$ 2> /dev/null | grep `echo $0 | sed s/\-//` > /dev/null then FIND_PROC="$PS p \$\$PID | grep -v grep | grep \$\$MYSQLD > /dev/null" # Solaris @@ -1216,6 +1216,7 @@ EOF # echo -n "making sure specific build files are writable... " for file in \ + Docs/manual.chm \ Docs/mysql.info \ Docs/INSTALL-BINARY \ INSTALL-SOURCE \ @@ -1946,7 +1947,7 @@ esac # isinf() could be a function or a macro (HPUX) AC_MSG_CHECKING(for isinf with ) -AC_TRY_LINK([#include ], [float f = 0.0; isinf(f)], +AC_TRY_LINK([#include ], [float f = 0.0; int r = isinf(f); return r], AC_MSG_RESULT(yes) AC_DEFINE(HAVE_ISINF, [1], [isinf() macro or function]), AC_MSG_RESULT(no)) @@ -2826,8 +2827,9 @@ AC_CONFIG_FILES(Makefile extra/Makefile mysys/Makefile dnl include/mysql_version.h dnl cmd-line-utils/Makefile dnl cmd-line-utils/libedit/Makefile dnl + win/Makefile dnl zlib/Makefile dnl - cmd-line-utils/readline/Makefile win/Makefile) + cmd-line-utils/readline/Makefile) AC_CONFIG_COMMANDS([default], , test -z "$CONFIG_HEADERS" || echo timestamp > stamp-h) AC_OUTPUT diff --git a/extra/Makefile.am b/extra/Makefile.am index 0de513ba15a..63d2b4055f7 100644 --- a/extra/Makefile.am +++ b/extra/Makefile.am @@ -22,14 +22,18 @@ BUILT_SOURCES= $(top_builddir)/include/mysqld_error.h \ $(top_builddir)/include/sql_state.h \ $(top_builddir)/include/mysqld_ername.h pkginclude_HEADERS= $(BUILT_SOURCES) -CLEANFILES = $(BUILT_SOURCES) +DISTCLEANFILES = $(BUILT_SOURCES) # We never use SUBDIRS here, but needed for automake 1.6.3 # to generate code to handle DIST_SUBDIRS SUBDIRS= DIST_SUBDIRS= yassl -# This will build mysqld_error.h and sql_state.h -$(top_builddir)/include/mysqld_error.h: comp_err$(EXEEXT) +# This will build mysqld_error.h, mysqld_ername.h and sql_state.h +# NOTE Built files should depend on their sources to avoid +# the built files being rebuilt in source dist +$(top_builddir)/include/mysqld_error.h: comp_err.c \ + $(top_srcdir)/sql/share/errmsg.txt + $(MAKE) $(AM_MAKEFLAGS) comp_err$(EXEEXT) $(top_builddir)/extra/comp_err$(EXEEXT) \ --charset=$(top_srcdir)/sql/share/charsets \ --out-dir=$(top_builddir)/sql/share/ \ diff --git a/extra/yassl/CMakeLists.txt b/extra/yassl/CMakeLists.txt index e5429876072..09bd2b046da 100755 --- a/extra/yassl/CMakeLists.txt +++ b/extra/yassl/CMakeLists.txt @@ -1,6 +1,6 @@ ADD_DEFINITIONS("-DWIN32 -D_LIB -DYASSL_PREFIX") -INCLUDE_DIRECTORIES(include taocrypt/include mySTL) +INCLUDE_DIRECTORIES(include taocrypt/include taocrypt/mySTL) ADD_LIBRARY(yassl src/buffer.cpp src/cert_wrapper.cpp src/crypto_wrapper.cpp src/handshake.cpp src/lock.cpp src/log.cpp src/socket_wrapper.cpp src/ssl.cpp src/timer.cpp src/yassl_error.cpp src/yassl_imp.cpp src/yassl_int.cpp) diff --git a/extra/yassl/FLOSS-EXCEPTIONS b/extra/yassl/FLOSS-EXCEPTIONS index 344083b0114..47f86ff65f2 100644 --- a/extra/yassl/FLOSS-EXCEPTIONS +++ b/extra/yassl/FLOSS-EXCEPTIONS @@ -1,7 +1,7 @@ yaSSL FLOSS License Exception **************************************** -Version 0.1, 26 June 2006 +Version 0.2, 31 August 2006 The Sawtooth Consulting Ltd. Exception for Free/Libre and Open Source Software-only Applications Using yaSSL Libraries (the "FLOSS Exception"). @@ -81,6 +81,7 @@ the GPL: Python license (CNRI Python License) - Python Software Foundation License 2.1.1 Sleepycat License "1999" + University of Illinois/NCSA Open Source License - W3C License "2001" X11 License "2001" Zlib/libpng License - diff --git a/extra/yassl/Makefile.am b/extra/yassl/Makefile.am index 12a7da1085b..b7657dc28f9 100644 --- a/extra/yassl/Makefile.am +++ b/extra/yassl/Makefile.am @@ -1,2 +1,2 @@ SUBDIRS = taocrypt src testsuite -EXTRA_DIST = yassl.dsp yassl.dsw $(wildcard mySTL/*.hpp) CMakeLists.txt +EXTRA_DIST = yassl.dsp yassl.dsw CMakeLists.txt diff --git a/extra/yassl/README b/extra/yassl/README index 25d4d94c306..2af4e98fe4c 100644 --- a/extra/yassl/README +++ b/extra/yassl/README @@ -1,4 +1,15 @@ -yaSSL Release notes, version 1.3.7 (06/26/06) +yaSSL Release notes, version 1.4.0 (08/13/06) + + + This release of yaSSL contains bug fixes, portability enhancements, + nonblocking connect and accept, better OpenSSL error mapping, and + certificate caching for session resumption. + +See normal build instructions below under 1.0.6. +See libcurl build instructions below under 1.3.0. + + +********************yaSSL Release notes, version 1.3.7 (06/26/06) This release of yaSSL contains bug fixes, portability enhancements, diff --git a/extra/yassl/examples/client/client.cpp b/extra/yassl/examples/client/client.cpp index 94bf753210b..d655011deb6 100644 --- a/extra/yassl/examples/client/client.cpp +++ b/extra/yassl/examples/client/client.cpp @@ -27,7 +27,13 @@ void client_test(void* args) SSL_set_fd(ssl, sockfd); - if (SSL_connect(ssl) != SSL_SUCCESS) err_sys("SSL_connect failed"); + if (SSL_connect(ssl) != SSL_SUCCESS) + { + SSL_CTX_free(ctx); + SSL_free(ssl); + tcp_close(sockfd); + err_sys("SSL_connect failed"); + } showPeer(ssl); const char* cipher = 0; @@ -39,11 +45,16 @@ void client_test(void* args) strncat(list, cipher, strlen(cipher) + 1); } printf("%s\n", list); - printf("Using Cipher Suite %s\n", SSL_get_cipher(ssl)); + printf("Using Cipher Suite: %s\n", SSL_get_cipher(ssl)); char msg[] = "hello yassl!"; if (SSL_write(ssl, msg, sizeof(msg)) != sizeof(msg)) + { + SSL_CTX_free(ctx); + SSL_free(ssl); + tcp_close(sockfd); err_sys("SSL_write failed"); + } char reply[1024]; reply[SSL_read(ssl, reply, sizeof(reply))] = 0; @@ -56,22 +67,36 @@ void client_test(void* args) SSL_shutdown(ssl); SSL_free(ssl); + tcp_close(sockfd); #ifdef TEST_RESUME tcp_connect(sockfd); SSL_set_fd(sslResume, sockfd); SSL_set_session(sslResume, session); - if (SSL_connect(sslResume) != SSL_SUCCESS) err_sys("SSL resume failed"); + if (SSL_connect(sslResume) != SSL_SUCCESS) + { + SSL_CTX_free(ctx); + SSL_free(ssl); + tcp_close(sockfd); + err_sys("SSL resume failed"); + } + showPeer(sslResume); if (SSL_write(sslResume, msg, sizeof(msg)) != sizeof(msg)) + { + SSL_CTX_free(ctx); + SSL_free(ssl); + tcp_close(sockfd); err_sys("SSL_write failed"); + } reply[SSL_read(sslResume, reply, sizeof(reply))] = 0; printf("Server response: %s\n", reply); SSL_shutdown(sslResume); SSL_free(sslResume); + tcp_close(sockfd); #endif // TEST_RESUME SSL_CTX_free(ctx); diff --git a/extra/yassl/examples/echoclient/echoclient.cpp b/extra/yassl/examples/echoclient/echoclient.cpp index fd3f7dd48a3..983254bf8a7 100644 --- a/extra/yassl/examples/echoclient/echoclient.cpp +++ b/extra/yassl/examples/echoclient/echoclient.cpp @@ -41,7 +41,14 @@ void echoclient_test(void* args) SSL* ssl = SSL_new(ctx); SSL_set_fd(ssl, sockfd); - if (SSL_connect(ssl) != SSL_SUCCESS) err_sys("SSL_connect failed"); + + if (SSL_connect(ssl) != SSL_SUCCESS) + { + SSL_CTX_free(ctx); + SSL_free(ssl); + tcp_close(sockfd); + err_sys("SSL_connect failed"); + } char send[1024]; char reply[1024]; @@ -50,7 +57,12 @@ void echoclient_test(void* args) int sendSz = strlen(send) + 1; if (SSL_write(ssl, send, sendSz) != sendSz) + { + SSL_CTX_free(ctx); + SSL_free(ssl); + tcp_close(sockfd); err_sys("SSL_write failed"); + } if (strncmp(send, "quit", 4) == 0) { fputs("sending server shutdown command: quit!\n", fout); @@ -63,6 +75,7 @@ void echoclient_test(void* args) SSL_CTX_free(ctx); SSL_free(ssl); + tcp_close(sockfd); fflush(fout); if (inCreated) fclose(fin); diff --git a/extra/yassl/examples/echoserver/echoserver.cpp b/extra/yassl/examples/echoserver/echoserver.cpp index 8e23ead20ab..cd31fedddd8 100644 --- a/extra/yassl/examples/echoserver/echoserver.cpp +++ b/extra/yassl/examples/echoserver/echoserver.cpp @@ -23,6 +23,18 @@ #endif // NO_MAIN_DRIVER + +void EchoError(SSL_CTX* ctx, SSL* ssl, SOCKET_T& s1, SOCKET_T& s2, + const char* msg) +{ + SSL_CTX_free(ctx); + SSL_free(ssl); + tcp_close(s1); + tcp_close(s2); + err_sys(msg); +} + + THREAD_RETURN YASSL_API echoserver_test(void* args) { #ifdef _WIN32 @@ -65,13 +77,18 @@ THREAD_RETURN YASSL_API echoserver_test(void* args) while (!shutdown) { sockaddr_in client; socklen_t client_len = sizeof(client); - int clientfd = accept(sockfd, (sockaddr*)&client, + SOCKET_T clientfd = accept(sockfd, (sockaddr*)&client, (ACCEPT_THIRD_T)&client_len); - if (clientfd == -1) err_sys("tcp accept failed"); + if (clientfd == -1) { + SSL_CTX_free(ctx); + tcp_close(sockfd); + err_sys("tcp accept failed"); + } SSL* ssl = SSL_new(ctx); SSL_set_fd(ssl, clientfd); - if (SSL_accept(ssl) != SSL_SUCCESS) err_sys("SSL_accept failed"); + if (SSL_accept(ssl) != SSL_SUCCESS) + EchoError(ctx, ssl, sockfd, clientfd, "SSL_accept failed"); char command[1024]; int echoSz(0); @@ -100,7 +117,8 @@ THREAD_RETURN YASSL_API echoserver_test(void* args) echoSz += sizeof(footer); if (SSL_write(ssl, command, echoSz) != echoSz) - err_sys("SSL_write failed"); + EchoError(ctx, ssl, sockfd, clientfd, "SSL_write failed"); + break; } command[echoSz] = 0; @@ -110,16 +128,13 @@ THREAD_RETURN YASSL_API echoserver_test(void* args) #endif if (SSL_write(ssl, command, echoSz) != echoSz) - err_sys("SSL_write failed"); + EchoError(ctx, ssl, sockfd, clientfd, "SSL_write failed"); } SSL_free(ssl); + tcp_close(clientfd); } -#ifdef _WIN32 - closesocket(sockfd); -#else - close(sockfd); -#endif + tcp_close(sockfd); DH_free(dh); SSL_CTX_free(ctx); diff --git a/extra/yassl/examples/server/server.cpp b/extra/yassl/examples/server/server.cpp index 73cff19e371..d0bf70cd634 100644 --- a/extra/yassl/examples/server/server.cpp +++ b/extra/yassl/examples/server/server.cpp @@ -4,6 +4,15 @@ #include "../../testsuite/test.hpp" +void ServerError(SSL_CTX* ctx, SSL* ssl, SOCKET_T& sockfd, const char* msg) +{ + SSL_CTX_free(ctx); + SSL_free(ssl); + tcp_close(sockfd); + err_sys(msg); +} + + THREAD_RETURN YASSL_API server_test(void* args) { #ifdef _WIN32 @@ -12,18 +21,14 @@ THREAD_RETURN YASSL_API server_test(void* args) #endif SOCKET_T sockfd = 0; - int clientfd = 0; + SOCKET_T clientfd = 0; int argc = 0; char** argv = 0; set_args(argc, argv, *static_cast(args)); tcp_accept(sockfd, clientfd, *static_cast(args)); -#ifdef _WIN32 - closesocket(sockfd); -#else - close(sockfd); -#endif + tcp_close(sockfd); SSL_METHOD* method = TLSv1_server_method(); SSL_CTX* ctx = SSL_CTX_new(method); @@ -36,9 +41,11 @@ THREAD_RETURN YASSL_API server_test(void* args) SSL* ssl = SSL_new(ctx); SSL_set_fd(ssl, clientfd); - if (SSL_accept(ssl) != SSL_SUCCESS) err_sys("SSL_accept failed"); + if (SSL_accept(ssl) != SSL_SUCCESS) + ServerError(ctx, ssl, clientfd, "SSL_accept failed"); + showPeer(ssl); - printf("Using Cipher Suite %s\n", SSL_get_cipher(ssl)); + printf("Using Cipher Suite: %s\n", SSL_get_cipher(ssl)); char command[1024]; command[SSL_read(ssl, command, sizeof(command))] = 0; @@ -46,12 +53,14 @@ THREAD_RETURN YASSL_API server_test(void* args) char msg[] = "I hear you, fa shizzle!"; if (SSL_write(ssl, msg, sizeof(msg)) != sizeof(msg)) - err_sys("SSL_write failed"); + ServerError(ctx, ssl, clientfd, "SSL_write failed"); DH_free(dh); SSL_CTX_free(ctx); SSL_free(ssl); + tcp_close(clientfd); + ((func_args*)args)->return_code = 0; return 0; } diff --git a/extra/yassl/include/buffer.hpp b/extra/yassl/include/buffer.hpp index 4816f79a9bc..c2709a8c847 100644 --- a/extra/yassl/include/buffer.hpp +++ b/extra/yassl/include/buffer.hpp @@ -34,7 +34,10 @@ #include // assert #include "yassl_types.hpp" // ysDelete #include "memory.hpp" // mySTL::auto_ptr -#include "algorithm.hpp" // mySTL::swap +#include STL_ALGORITHM_FILE + + +namespace STL = STL_NAMESPACE; #ifdef _MSC_VER @@ -199,7 +202,7 @@ struct del_ptr_zero void operator()(T*& p) const { T* tmp = 0; - mySTL::swap(tmp, p); + STL::swap(tmp, p); checked_delete(tmp); } }; diff --git a/extra/yassl/include/cert_wrapper.hpp b/extra/yassl/include/cert_wrapper.hpp index 8b5b7491772..761be0e9b04 100644 --- a/extra/yassl/include/cert_wrapper.hpp +++ b/extra/yassl/include/cert_wrapper.hpp @@ -41,8 +41,12 @@ #include "yassl_types.hpp" // SignatureAlgorithm #include "buffer.hpp" // input_buffer #include "asn.hpp" // SignerList -#include "list.hpp" // mySTL::list -#include "algorithm.hpp" // mySTL::for_each +#include STL_LIST_FILE +#include STL_ALGORITHM_FILE + + +namespace STL = STL_NAMESPACE; + namespace yaSSL { @@ -72,7 +76,7 @@ private: // Certificate Manager keeps a list of the cert chain and public key class CertManager { - typedef mySTL::list CertList; + typedef STL::list CertList; CertList list_; // self input_buffer privateKey_; @@ -120,6 +124,7 @@ public: void setVerifyNone(); void setFailNoCert(); void setSendVerify(); + void setPeerX509(X509*); private: CertManager(const CertManager&); // hide copy CertManager& operator=(const CertManager&); // and assign diff --git a/extra/yassl/include/crypto_wrapper.hpp b/extra/yassl/include/crypto_wrapper.hpp index 4c4e4d5da5b..83cf3d26398 100644 --- a/extra/yassl/include/crypto_wrapper.hpp +++ b/extra/yassl/include/crypto_wrapper.hpp @@ -416,7 +416,17 @@ private: class x509; -x509* PemToDer(FILE*, CertType); +struct EncryptedInfo { + enum { IV_SZ = 32, NAME_SZ = 80 }; + char name[NAME_SZ]; // max one line + byte iv[IV_SZ]; // in base16 rep + uint ivSz; + bool set; + + EncryptedInfo() : ivSz(0), set(false) {} +}; + +x509* PemToDer(FILE*, CertType, EncryptedInfo* info = 0); } // naemspace diff --git a/extra/yassl/include/factory.hpp b/extra/yassl/include/factory.hpp index 5619e90cd62..04d742431dc 100644 --- a/extra/yassl/include/factory.hpp +++ b/extra/yassl/include/factory.hpp @@ -35,10 +35,12 @@ #ifndef yaSSL_FACTORY_HPP #define yaSSL_FACTORY_HPP -#include "vector.hpp" -#include "pair.hpp" +#include STL_VECTOR_FILE +#include STL_PAIR_FILE +namespace STL = STL_NAMESPACE; + // VC60 workaround: it doesn't allow typename in some places #if defined(_MSC_VER) && (_MSC_VER < 1300) @@ -58,8 +60,8 @@ template class Factory { - typedef mySTL::pair CallBack; - typedef mySTL::vector CallBackVector; + typedef STL::pair CallBack; + typedef STL::vector CallBackVector; CallBackVector callbacks_; public: @@ -79,14 +81,16 @@ public: // register callback void Register(const IdentifierType& id, ProductCreator pc) { - callbacks_.push_back(mySTL::make_pair(id, pc)); + callbacks_.push_back(STL::make_pair(id, pc)); } // THE Creator, returns a new object of the proper type or 0 AbstractProduct* CreateObject(const IdentifierType& id) const { - const CallBack* first = callbacks_.begin(); - const CallBack* last = callbacks_.end(); + typedef typename STL::vector::const_iterator cIter; + + cIter first = callbacks_.begin(); + cIter last = callbacks_.end(); while (first != last) { if (first->first == id) diff --git a/extra/yassl/include/openssl/ssl.h b/extra/yassl/include/openssl/ssl.h index 47b4d075894..5e7290d2a7a 100644 --- a/extra/yassl/include/openssl/ssl.h +++ b/extra/yassl/include/openssl/ssl.h @@ -41,7 +41,7 @@ #include "rsa.h" -#define YASSL_VERSION "1.3.7" +#define YASSL_VERSION "1.4.3" #if defined(__cplusplus) @@ -505,6 +505,8 @@ ASN1_TIME* X509_get_notAfter(X509* x); #define V_ASN1_UTF8STRING 12 #define GEN_DNS 2 +#define CERTFICATE_ERROR 0x14090086 /* SSLv3 error */ + typedef struct MD4_CTX { int buffer[32]; /* big enough to hold, check size in Init */ diff --git a/extra/yassl/include/socket_wrapper.hpp b/extra/yassl/include/socket_wrapper.hpp index 1dd61b63148..9fc0d62f90e 100644 --- a/extra/yassl/include/socket_wrapper.hpp +++ b/extra/yassl/include/socket_wrapper.hpp @@ -71,6 +71,7 @@ typedef unsigned char byte; class Socket { socket_t socket_; // underlying socket descriptor bool wouldBlock_; // for non-blocking data + bool blocking_; // is option set public: explicit Socket(socket_t s = INVALID_SOCKET); ~Socket(); @@ -84,6 +85,7 @@ public: bool wait(); bool WouldBlock() const; + bool IsBlocking() const; void closeSocket(); void shutDown(int how = SD_SEND); diff --git a/extra/yassl/include/yassl_error.hpp b/extra/yassl/include/yassl_error.hpp index 3c3d5fa5231..72b79b05dbd 100644 --- a/extra/yassl/include/yassl_error.hpp +++ b/extra/yassl/include/yassl_error.hpp @@ -54,7 +54,11 @@ enum YasslError { verify_error = 112, send_error = 113, receive_error = 114, - certificate_error = 115 + certificate_error = 115, + privateKey_error = 116, + badVersion_error = 117 + + // !!!! add error message to .cpp !!!! // 1000+ from TaoCrypt error.hpp diff --git a/extra/yassl/include/yassl_imp.hpp b/extra/yassl/include/yassl_imp.hpp index 6e475c23db8..180d7fe7fe1 100644 --- a/extra/yassl/include/yassl_imp.hpp +++ b/extra/yassl/include/yassl_imp.hpp @@ -39,7 +39,10 @@ #include "yassl_types.hpp" #include "factory.hpp" -#include "list.hpp" // mySTL::list +#include STL_LIST_FILE + + +namespace STL = STL_NAMESPACE; namespace yaSSL { @@ -427,7 +430,7 @@ private: class CertificateRequest : public HandShakeBase { ClientCertificateType certificate_types_[CERT_TYPES]; int typeTotal_; - mySTL::list certificate_authorities_; + STL::list certificate_authorities_; public: CertificateRequest(); ~CertificateRequest(); diff --git a/extra/yassl/include/yassl_int.hpp b/extra/yassl/include/yassl_int.hpp index 26900aed3af..28e9d237622 100644 --- a/extra/yassl/include/yassl_int.hpp +++ b/extra/yassl/include/yassl_int.hpp @@ -40,6 +40,13 @@ #include "lock.hpp" #include "openssl/ssl.h" // ASN1_STRING and DH +#ifdef _POSIX_THREADS + #include +#endif + + +namespace STL = STL_NAMESPACE; + namespace yaSSL { @@ -80,12 +87,35 @@ enum ServerState { }; +// client connect state for nonblocking restart +enum ConnectState { + CONNECT_BEGIN = 0, + CLIENT_HELLO_SENT, + FIRST_REPLY_DONE, + FINISHED_DONE, + SECOND_REPLY_DONE +}; + + +// server accpet state for nonblocking restart +enum AcceptState { + ACCEPT_BEGIN = 0, + ACCEPT_FIRST_REPLY_DONE, + SERVER_HELLO_DONE, + ACCEPT_SECOND_REPLY_DONE, + ACCEPT_FINISHED_DONE, + ACCEPT_THIRD_REPLY_DONE +}; + + // combines all states class States { RecordLayerState recordLayer_; HandShakeState handshakeLayer_; ClientState clientState_; ServerState serverState_; + ConnectState connectState_; + AcceptState acceptState_; char errorString_[MAX_ERROR_SZ]; YasslError what_; public: @@ -95,6 +125,8 @@ public: const HandShakeState& getHandShake() const; const ClientState& getClient() const; const ServerState& getServer() const; + const ConnectState& GetConnect() const; + const AcceptState& GetAccept() const; const char* getString() const; YasslError What() const; @@ -102,6 +134,8 @@ public: HandShakeState& useHandShake(); ClientState& useClient(); ServerState& useServer(); + ConnectState& UseConnect(); + AcceptState& UseAccept(); char* useString(); void SetError(YasslError); private: @@ -142,8 +176,9 @@ public: X509_NAME(const char*, size_t sz); ~X509_NAME(); - char* GetName(); + const char* GetName() const; ASN1_STRING* GetEntry(int i); + size_t GetLength() const; private: X509_NAME(const X509_NAME&); // hide copy X509_NAME& operator=(const X509_NAME&); // and assign @@ -157,6 +192,9 @@ public: ~StringHolder(); ASN1_STRING* GetString(); +private: + StringHolder(const StringHolder&); // hide copy + StringHolder& operator=(const StringHolder&); // and assign }; @@ -176,6 +214,7 @@ public: ASN1_STRING* GetBefore(); ASN1_STRING* GetAfter(); + private: X509(const X509&); // hide copy X509& operator=(const X509&); // and assign @@ -202,6 +241,7 @@ class SSL_SESSION { uint bornOn_; // create time in seconds uint timeout_; // timeout in seconds RandomPool& random_; // will clean master secret + X509* peerX509_; public: explicit SSL_SESSION(RandomPool&); SSL_SESSION(const SSL&, RandomPool&); @@ -212,17 +252,20 @@ public: const Cipher* GetSuite() const; uint GetBornOn() const; uint GetTimeOut() const; + X509* GetPeerX509() const; void SetTimeOut(uint); SSL_SESSION& operator=(const SSL_SESSION&); // allow assign for resumption private: SSL_SESSION(const SSL_SESSION&); // hide copy + + void CopyX509(X509*); }; // holds all sessions class Sessions { - mySTL::list list_; + STL::list list_; RandomPool random_; // for session cleaning Mutex mutex_; // no-op for single threaded @@ -241,8 +284,42 @@ private: }; +#ifdef _POSIX_THREADS + typedef pthread_t THREAD_ID_T; +#else + typedef DWORD THREAD_ID_T; +#endif + +// thread error data +struct ThreadError { + THREAD_ID_T threadID_; + int errorID_; +}; + + +// holds all errors +class Errors { + STL::list list_; + Mutex mutex_; + + Errors() {} // only GetErrors can create +public: + int Lookup(bool peek); // self lookup + void Add(int); + void Remove(); // remove self + + ~Errors() {} + + friend Errors& GetErrors(); // singleton creator +private: + Errors(const Errors&); // hide copy + Errors& operator=(const Errors); // and assign +}; + + Sessions& GetSessions(); // forward singletons sslFactory& GetSSL_Factory(); +Errors& GetErrors(); // openSSL method and context types @@ -252,8 +329,10 @@ class SSL_METHOD { bool verifyPeer_; // request or send certificate bool verifyNone_; // whether to verify certificate bool failNoCert_; + bool multipleProtocol_; // for SSLv23 compatibility public: - explicit SSL_METHOD(ConnectionEnd ce, ProtocolVersion pv); + SSL_METHOD(ConnectionEnd ce, ProtocolVersion pv, + bool multipleProtocol = false); ProtocolVersion getVersion() const; ConnectionEnd getSide() const; @@ -265,6 +344,7 @@ public: bool verifyPeer() const; bool verifyNone() const; bool failNoCert() const; + bool multipleProtocol() const; private: SSL_METHOD(const SSL_METHOD&); // hide copy SSL_METHOD& operator=(const SSL_METHOD&); // and assign @@ -334,7 +414,7 @@ private: // the SSL context class SSL_CTX { public: - typedef mySTL::list CertList; + typedef STL::list CertList; private: SSL_METHOD* method_; x509* certificate_; @@ -342,6 +422,8 @@ private: CertList caList_; Ciphers ciphers_; DH_Parms dhParms_; + pem_password_cb passwordCb_; + void* userData_; Stats stats_; Mutex mutex_; // for Stats public: @@ -354,12 +436,16 @@ public: const Ciphers& GetCiphers() const; const DH_Parms& GetDH_Parms() const; const Stats& GetStats() const; + pem_password_cb GetPasswordCb() const; + void* GetUserData() const; void setVerifyPeer(); void setVerifyNone(); void setFailNoCert(); bool SetCipherList(const char*); bool SetDH(const DH&); + void SetPasswordCb(pem_password_cb cb); + void SetUserData(void*); void IncrementStats(StatsField); void AddCA(x509* ca); @@ -434,13 +520,14 @@ private: // holds input and output buffers class Buffers { public: - typedef mySTL::list inputList; - typedef mySTL::list outputList; + typedef STL::list inputList; + typedef STL::list outputList; private: inputList dataList_; // list of users app data / handshake outputList handShakeList_; // buffered handshake msgs + input_buffer* rawInput_; // buffered raw input yet to process public: - Buffers() {} + Buffers(); ~Buffers(); const inputList& getData() const; @@ -448,6 +535,9 @@ public: inputList& useData(); outputList& useHandShake(); + + void SetRawInput(input_buffer*); // takes ownership + input_buffer* TakeRawInput(); // takes ownership private: Buffers(const Buffers&); // hide copy Buffers& operator=(const Buffers&); // and assign @@ -502,6 +592,7 @@ public: const sslFactory& getFactory() const; const Socket& getSocket() const; YasslError GetError() const; + bool GetMultiProtocol() const; Crypto& useCrypto(); Security& useSecurity(); @@ -509,6 +600,7 @@ public: sslHashes& useHashes(); Socket& useSocket(); Log& useLog(); + Buffers& useBuffers(); // sets void set_pending(Cipher suite); diff --git a/extra/yassl/include/yassl_types.hpp b/extra/yassl/include/yassl_types.hpp index b75a2a45302..e602ee180bf 100644 --- a/extra/yassl/include/yassl_types.hpp +++ b/extra/yassl/include/yassl_types.hpp @@ -38,6 +38,8 @@ namespace yaSSL { +#define YASSL_LIB + #ifdef YASSL_PURE_C @@ -76,7 +78,7 @@ namespace yaSSL { ::operator delete[](ptr, yaSSL::ys); } - #define NEW_YS new (ys) + #define NEW_YS new (yaSSL::ys) // to resolve compiler generated operator delete on base classes with // virtual destructors (when on stack), make sure doesn't get called @@ -122,6 +124,39 @@ typedef opaque byte; typedef unsigned int uint; +#ifdef USE_SYS_STL + // use system STL + #define STL_VECTOR_FILE + #define STL_LIST_FILE + #define STL_ALGORITHM_FILE + #define STL_MEMORY_FILE + #define STL_PAIR_FILE + + #define STL_NAMESPACE std +#else + // use mySTL + #define STL_VECTOR_FILE "vector.hpp" + #define STL_LIST_FILE "list.hpp" + #define STL_ALGORITHM_FILE "algorithm.hpp" + #define STL_MEMORY_FILE "memory.hpp" + #define STL_PAIR_FILE "pair.hpp" + + #define STL_NAMESPACE mySTL +#endif + + +#ifdef min + #undef min +#endif + +template +T min(T a, T b) +{ + return a < b ? a : b; +} + + + // all length constants in bytes const int ID_LEN = 32; // session id length const int SUITE_LEN = 2; // cipher suite length @@ -163,6 +198,7 @@ const int DES_BLOCK = 8; // DES is always fixed block size 8 const int DES_IV_SZ = DES_BLOCK; // Init Vector length for DES const int RC4_KEY_SZ = 16; // RC4 Key length const int AES_128_KEY_SZ = 16; // AES 128bit Key length +const int AES_192_KEY_SZ = 24; // AES 192bit Key length const int AES_256_KEY_SZ = 32; // AES 256bit Key length const int AES_BLOCK_SZ = 16; // AES 128bit block size, rfc 3268 const int AES_IV_SZ = AES_BLOCK_SZ; // AES Init Vector length diff --git a/extra/yassl/src/Makefile.am b/extra/yassl/src/Makefile.am index 2b3e1aea5f5..910bbbdd13f 100644 --- a/extra/yassl/src/Makefile.am +++ b/extra/yassl/src/Makefile.am @@ -1,4 +1,4 @@ -INCLUDES = -I../include -I../taocrypt/include -I../mySTL +INCLUDES = -I../include -I../taocrypt/include -I../taocrypt/mySTL noinst_LTLIBRARIES = libyassl.la libyassl_la_SOURCES = buffer.cpp cert_wrapper.cpp crypto_wrapper.cpp \ @@ -6,3 +6,7 @@ libyassl_la_SOURCES = buffer.cpp cert_wrapper.cpp crypto_wrapper.cpp \ template_instnt.cpp timer.cpp yassl_imp.cpp yassl_error.cpp yassl_int.cpp EXTRA_DIST = $(wildcard ../include/*.hpp) $(wildcard ../include/openssl/*.h) AM_CXXFLAGS = -DYASSL_PURE_C -DYASSL_PREFIX + +# Don't update the files from bitkeeper +%::SCCS/s.% + diff --git a/extra/yassl/src/cert_wrapper.cpp b/extra/yassl/src/cert_wrapper.cpp index 6ad0aa568ed..c3ae9c0c561 100644 --- a/extra/yassl/src/cert_wrapper.cpp +++ b/extra/yassl/src/cert_wrapper.cpp @@ -63,8 +63,8 @@ x509::x509(const x509& that) : length_(that.length_), void x509::Swap(x509& that) { - mySTL::swap(length_, that.length_); - mySTL::swap(buffer_, that.buffer_); + STL::swap(length_, that.length_); + STL::swap(buffer_, that.buffer_); } @@ -105,11 +105,11 @@ CertManager::~CertManager() { ysDelete(peerX509_); - mySTL::for_each(signers_.begin(), signers_.end(), del_ptr_zero()) ; + STL::for_each(signers_.begin(), signers_.end(), del_ptr_zero()) ; - mySTL::for_each(peerList_.begin(), peerList_.end(), del_ptr_zero()) ; + STL::for_each(peerList_.begin(), peerList_.end(), del_ptr_zero()) ; - mySTL::for_each(list_.begin(), list_.end(), del_ptr_zero()) ; + STL::for_each(list_.begin(), list_.end(), del_ptr_zero()) ; } @@ -242,7 +242,7 @@ uint CertManager::get_privateKeyLength() const // Validate the peer's certificate list, from root to peer (last to first) int CertManager::Validate() { - CertList::iterator last = peerList_.rbegin(); // fix this + CertList::reverse_iterator last = peerList_.rbegin(); int count = peerList_.size(); while ( count > 1 ) { @@ -255,7 +255,7 @@ int CertManager::Validate() const TaoCrypt::PublicKey& key = cert.GetPublicKey(); signers_.push_back(NEW_YS TaoCrypt::Signer(key.GetKey(), key.size(), cert.GetCommonName(), cert.GetHash())); - --last; + ++last; --count; } @@ -310,6 +310,23 @@ int CertManager::SetPrivateKey(const x509& key) } +// Store OpenSSL type peer's cert +void CertManager::setPeerX509(X509* x) +{ + assert(peerX509_ == 0); + if (x == 0) return; + + X509_NAME* issuer = x->GetIssuer(); + X509_NAME* subject = x->GetSubject(); + ASN1_STRING* before = x->GetBefore(); + ASN1_STRING* after = x->GetAfter(); + + peerX509_ = NEW_YS X509(issuer->GetName(), issuer->GetLength(), + subject->GetName(), subject->GetLength(), (const char*) before->data, + before->length, (const char*) after->data, after->length); +} + + #if defined(USE_CML_LIB) // Get the peer's certificate, extract and save public key diff --git a/extra/yassl/src/crypto_wrapper.cpp b/extra/yassl/src/crypto_wrapper.cpp index 799106ec7c0..7344a70b367 100644 --- a/extra/yassl/src/crypto_wrapper.cpp +++ b/extra/yassl/src/crypto_wrapper.cpp @@ -908,7 +908,7 @@ void DiffieHellman::get_parms(byte* bp, byte* bg, byte* bpub) const // convert PEM file to DER x509 type -x509* PemToDer(FILE* file, CertType type) +x509* PemToDer(FILE* file, CertType type, EncryptedInfo* info) { using namespace TaoCrypt; @@ -935,6 +935,37 @@ x509* PemToDer(FILE* file, CertType type) break; } + // remove encrypted header if there + if (fgets(line, sizeof(line), file)) { + char encHeader[] = "Proc-Type"; + if (strncmp(encHeader, line, strlen(encHeader)) == 0 && + fgets(line,sizeof(line), file)) { + + char* start = strstr(line, "DES"); + char* finish = strstr(line, ","); + if (!start) + start = strstr(line, "AES"); + + if (!info) return 0; + + if ( start && finish && (start < finish)) { + memcpy(info->name, start, finish - start); + info->name[finish - start] = 0; + memcpy(info->iv, finish + 1, sizeof(info->iv)); + + char* newline = strstr(line, "\r"); + if (!newline) newline = strstr(line, "\n"); + if (newline && (newline > finish)) { + info->ivSz = newline - (finish + 1); + info->set = true; + } + } + fgets(line,sizeof(line), file); // get blank line + begin = ftell(file); + } + + } + while(fgets(line, sizeof(line), file)) if (strncmp(footer, line, strlen(footer)) == 0) { foundEnd = true; @@ -956,7 +987,7 @@ x509* PemToDer(FILE* file, CertType type) Base64Decoder b64Dec(der); uint sz = der.size(); - mySTL::auto_ptr x(NEW_YS x509(sz), ysDelete); + mySTL::auto_ptr x(NEW_YS x509(sz)); memcpy(x->use_buffer(), der.get_buffer(), sz); return x.release(); diff --git a/extra/yassl/src/handshake.cpp b/extra/yassl/src/handshake.cpp index e93f5385b3d..25f36c4ea8c 100644 --- a/extra/yassl/src/handshake.cpp +++ b/extra/yassl/src/handshake.cpp @@ -37,7 +37,6 @@ namespace yaSSL { -using mySTL::min; // Build a client hello message from cipher suites and compression method @@ -363,7 +362,7 @@ void p_hash(output_buffer& result, const output_buffer& secret, uint lastLen = result.get_capacity() % len; opaque previous[SHA_LEN]; // max size opaque current[SHA_LEN]; // max size - mySTL::auto_ptr hmac(ysDelete); + mySTL::auto_ptr hmac; if (lastLen) times += 1; @@ -582,7 +581,7 @@ void hmac(SSL& ssl, byte* digest, const byte* buffer, uint sz, void TLS_hmac(SSL& ssl, byte* digest, const byte* buffer, uint sz, ContentType content, bool verify) { - mySTL::auto_ptr hmac(ysDelete); + mySTL::auto_ptr hmac; opaque seq[SEQ_SZ] = { 0x00, 0x00, 0x00, 0x00 }; opaque length[LENGTH_SZ]; opaque inner[SIZEOF_ENUM + VERSION_SZ + LENGTH_SZ]; // type + version + len @@ -660,25 +659,25 @@ void build_certHashes(SSL& ssl, Hashes& hashes) -// do process input requests -mySTL::auto_ptr -DoProcessReply(SSL& ssl, mySTL::auto_ptr buffered) +// do process input requests, return 0 is done, 1 is call again to complete +int DoProcessReply(SSL& ssl) { // wait for input if blocking if (!ssl.useSocket().wait()) { ssl.SetError(receive_error); - buffered.reset(0); - return buffered; + return 0; } uint ready = ssl.getSocket().get_ready(); - if (!ready) return buffered; + if (!ready) return 1; // add buffered data if its there - uint buffSz = buffered.get() ? buffered.get()->get_size() : 0; + input_buffer* buffered = ssl.useBuffers().TakeRawInput(); + uint buffSz = buffered ? buffered->get_size() : 0; input_buffer buffer(buffSz + ready); if (buffSz) { - buffer.assign(buffered.get()->get_buffer(), buffSz); - buffered.reset(0); + buffer.assign(buffered->get_buffer(), buffSz); + ysDelete(buffered); + buffered = 0; } // add new data @@ -692,10 +691,8 @@ DoProcessReply(SSL& ssl, mySTL::auto_ptr buffered) ssl.getStates().getServer() == clientNull) if (buffer.peek() != handshake) { ProcessOldClientHello(buffer, ssl); - if (ssl.GetError()) { - buffered.reset(0); - return buffered; - } + if (ssl.GetError()) + return 0; } while(!buffer.eof()) { @@ -715,31 +712,28 @@ DoProcessReply(SSL& ssl, mySTL::auto_ptr buffered) // put header in front for next time processing uint extra = needHdr ? 0 : RECORD_HEADER; uint sz = buffer.get_remaining() + extra; - buffered.reset(NEW_YS input_buffer(sz, buffer.get_buffer() + - buffer.get_current() - extra, sz)); - break; + ssl.useBuffers().SetRawInput(NEW_YS input_buffer(sz, + buffer.get_buffer() + buffer.get_current() - extra, sz)); + return 1; } while (buffer.get_current() < hdr.length_ + RECORD_HEADER + offset) { // each message in record, can be more than 1 if not encrypted if (ssl.getSecurity().get_parms().pending_ == false) // cipher on decrypt_message(ssl, buffer, hdr.length_); - mySTL::auto_ptr msg(mf.CreateObject(hdr.type_), ysDelete); + mySTL::auto_ptr msg(mf.CreateObject(hdr.type_)); if (!msg.get()) { ssl.SetError(factory_error); - buffered.reset(0); - return buffered; + return 0; } buffer >> *msg; msg->Process(buffer, ssl); - if (ssl.GetError()) { - buffered.reset(0); - return buffered; - } + if (ssl.GetError()) + return 0; } offset += hdr.length_ + RECORD_HEADER; } - return buffered; + return 0; } @@ -747,16 +741,17 @@ DoProcessReply(SSL& ssl, mySTL::auto_ptr buffered) void processReply(SSL& ssl) { if (ssl.GetError()) return; - mySTL::auto_ptr buffered(ysDelete); - for (;;) { - mySTL::auto_ptr tmp(DoProcessReply(ssl, buffered)); - if (tmp.get()) // had only part of a record's data, call again - buffered = tmp; - else - break; - if (ssl.GetError()) return; + if (DoProcessReply(ssl)) + // didn't complete process + if (!ssl.getSocket().IsBlocking()) { + // keep trying now + while (!ssl.GetError()) + if (DoProcessReply(ssl) == 0) break; } + else + // user will have try again later + ssl.SetError(YasslError(SSL_ERROR_WANT_READ)); } @@ -793,7 +788,7 @@ void sendClientKeyExchange(SSL& ssl, BufferOutput buffer) RecordLayerHeader rlHeader; HandShakeHeader hsHeader; - mySTL::auto_ptr out(NEW_YS output_buffer, ysDelete); + mySTL::auto_ptr out(NEW_YS output_buffer); buildHeaders(ssl, hsHeader, rlHeader, ck); buildOutput(*out.get(), rlHeader, hsHeader, ck); hashHandShake(ssl, *out.get()); @@ -814,7 +809,7 @@ void sendServerKeyExchange(SSL& ssl, BufferOutput buffer) RecordLayerHeader rlHeader; HandShakeHeader hsHeader; - mySTL::auto_ptr out(NEW_YS output_buffer, ysDelete); + mySTL::auto_ptr out(NEW_YS output_buffer); buildHeaders(ssl, hsHeader, rlHeader, sk); buildOutput(*out.get(), rlHeader, hsHeader, sk); hashHandShake(ssl, *out.get()); @@ -839,7 +834,7 @@ void sendChangeCipher(SSL& ssl, BufferOutput buffer) ChangeCipherSpec ccs; RecordLayerHeader rlHeader; buildHeader(ssl, rlHeader, ccs); - mySTL::auto_ptr out(NEW_YS output_buffer, ysDelete); + mySTL::auto_ptr out(NEW_YS output_buffer); buildOutput(*out.get(), rlHeader, ccs); if (buffer == buffered) @@ -856,7 +851,7 @@ void sendFinished(SSL& ssl, ConnectionEnd side, BufferOutput buffer) Finished fin; buildFinished(ssl, fin, side == client_end ? client : server); - mySTL::auto_ptr out(NEW_YS output_buffer, ysDelete); + mySTL::auto_ptr out(NEW_YS output_buffer); cipherFinished(ssl, fin, *out.get()); // hashes handshake if (ssl.getSecurity().get_resuming()) { @@ -955,7 +950,7 @@ void sendServerHello(SSL& ssl, BufferOutput buffer) ServerHello sh(ssl.getSecurity().get_connection().version_); RecordLayerHeader rlHeader; HandShakeHeader hsHeader; - mySTL::auto_ptr out(NEW_YS output_buffer, ysDelete); + mySTL::auto_ptr out(NEW_YS output_buffer); buildServerHello(ssl, sh); ssl.set_random(sh.get_random(), server_end); @@ -978,7 +973,7 @@ void sendServerHelloDone(SSL& ssl, BufferOutput buffer) ServerHelloDone shd; RecordLayerHeader rlHeader; HandShakeHeader hsHeader; - mySTL::auto_ptr out(NEW_YS output_buffer, ysDelete); + mySTL::auto_ptr out(NEW_YS output_buffer); buildHeaders(ssl, hsHeader, rlHeader, shd); buildOutput(*out.get(), rlHeader, hsHeader, shd); @@ -999,7 +994,7 @@ void sendCertificate(SSL& ssl, BufferOutput buffer) Certificate cert(ssl.getCrypto().get_certManager().get_cert()); RecordLayerHeader rlHeader; HandShakeHeader hsHeader; - mySTL::auto_ptr out(NEW_YS output_buffer, ysDelete); + mySTL::auto_ptr out(NEW_YS output_buffer); buildHeaders(ssl, hsHeader, rlHeader, cert); buildOutput(*out.get(), rlHeader, hsHeader, cert); @@ -1021,7 +1016,7 @@ void sendCertificateRequest(SSL& ssl, BufferOutput buffer) request.Build(); RecordLayerHeader rlHeader; HandShakeHeader hsHeader; - mySTL::auto_ptr out(NEW_YS output_buffer, ysDelete); + mySTL::auto_ptr out(NEW_YS output_buffer); buildHeaders(ssl, hsHeader, rlHeader, request); buildOutput(*out.get(), rlHeader, hsHeader, request); @@ -1043,7 +1038,7 @@ void sendCertificateVerify(SSL& ssl, BufferOutput buffer) verify.Build(ssl); RecordLayerHeader rlHeader; HandShakeHeader hsHeader; - mySTL::auto_ptr out(NEW_YS output_buffer, ysDelete); + mySTL::auto_ptr out(NEW_YS output_buffer); buildHeaders(ssl, hsHeader, rlHeader, verify); buildOutput(*out.get(), rlHeader, hsHeader, verify); diff --git a/extra/yassl/src/socket_wrapper.cpp b/extra/yassl/src/socket_wrapper.cpp index 7790001fc2d..70944831884 100644 --- a/extra/yassl/src/socket_wrapper.cpp +++ b/extra/yassl/src/socket_wrapper.cpp @@ -41,9 +41,10 @@ #include #include #include + #include #endif // _WIN32 -#if defined(__sun) || defined(__SCO_VERSION__) +#if defined(__sun) || defined(__SCO_VERSION__) || defined(__NETWARE__) #include #endif @@ -62,7 +63,7 @@ namespace yaSSL { Socket::Socket(socket_t s) - : socket_(s), wouldBlock_(false) + : socket_(s), wouldBlock_(false), blocking_(false) {} @@ -148,6 +149,7 @@ uint Socket::receive(byte* buf, unsigned int sz, int flags) if (get_lastError() == SOCKET_EWOULDBLOCK || get_lastError() == SOCKET_EAGAIN) { wouldBlock_ = true; + blocking_ = true; // socket can block, only way to tell for win32 return 0; } } @@ -189,6 +191,12 @@ bool Socket::WouldBlock() const } +bool Socket::IsBlocking() const +{ + return blocking_; +} + + void Socket::set_lastError(int errorCode) { #ifdef _WIN32 diff --git a/extra/yassl/src/ssl.cpp b/extra/yassl/src/ssl.cpp index 81e585ff735..a008ea7228b 100644 --- a/extra/yassl/src/ssl.cpp +++ b/extra/yassl/src/ssl.cpp @@ -42,6 +42,9 @@ #include "yassl_int.hpp" #include "md5.hpp" // for TaoCrypt MD5 size assert #include "md4.hpp" // for TaoCrypt MD4 size assert +#include "file.hpp" // for TaoCrypt Source +#include "coding.hpp" // HexDecoder +#include "helpers.hpp" // for placement new hack #include #ifdef _WIN32 @@ -55,7 +58,6 @@ namespace yaSSL { -using mySTL::min; int read_file(SSL_CTX* ctx, const char* file, int format, CertType type) @@ -93,11 +95,55 @@ int read_file(SSL_CTX* ctx, const char* file, int format, CertType type) } } else { - x = PemToDer(input, type); + EncryptedInfo info; + x = PemToDer(input, type, &info); if (!x) { fclose(input); return SSL_BAD_FILE; } + if (info.set) { + // decrypt + char password[80]; + pem_password_cb cb = ctx->GetPasswordCb(); + if (!cb) { + fclose(input); + return SSL_BAD_FILE; + } + int passwordSz = cb(password, sizeof(password), 0, + ctx->GetUserData()); + byte key[AES_256_KEY_SZ]; // max sizes + byte iv[AES_IV_SZ]; + + // use file's salt for key derivation, but not real iv + TaoCrypt::Source source(info.iv, info.ivSz); + TaoCrypt::HexDecoder dec(source); + memcpy(info.iv, source.get_buffer(), min((uint)sizeof(info.iv), + source.size())); + EVP_BytesToKey(info.name, "MD5", info.iv, (byte*)password, + passwordSz, 1, key, iv); + + STL::auto_ptr cipher; + if (strncmp(info.name, "DES-CBC", 7) == 0) + cipher.reset(NEW_YS DES); + else if (strncmp(info.name, "DES-EDE3-CBC", 13) == 0) + cipher.reset(NEW_YS DES_EDE); + else if (strncmp(info.name, "AES-128-CBC", 13) == 0) + cipher.reset(NEW_YS AES(AES_128_KEY_SZ)); + else if (strncmp(info.name, "AES-192-CBC", 13) == 0) + cipher.reset(NEW_YS AES(AES_192_KEY_SZ)); + else if (strncmp(info.name, "AES-256-CBC", 13) == 0) + cipher.reset(NEW_YS AES(AES_256_KEY_SZ)); + else { + fclose(input); + return SSL_BAD_FILE; + } + cipher->set_decryptKey(key, info.iv); + STL::auto_ptr newx(NEW_YS x509(x->get_length())); + cipher->decrypt(newx->use_buffer(), x->get_buffer(), + x->get_length()); + ysDelete(x); + x = newx.release(); + } } } fclose(input); @@ -140,8 +186,17 @@ SSL_METHOD* TLSv1_client_method() SSL_METHOD* SSLv23_server_method() { - // compatibility only, no version 2 support - return SSLv3_server_method(); + // compatibility only, no version 2 support, but does SSL 3 and TLS 1 + return NEW_YS SSL_METHOD(server_end, ProtocolVersion(3,1), true); +} + + +SSL_METHOD* SSLv23_client_method() +{ + // compatibility only, no version 2 support, but does SSL 3 and TLS 1 + // though it sends TLS1 hello not SSLv2 so SSLv3 only servers will decline + // TODO: maybe add support to send SSLv2 hello ??? + return NEW_YS SSL_METHOD(client_end, ProtocolVersion(3,1), true); } @@ -178,14 +233,29 @@ int SSL_set_fd(SSL* ssl, int fd) int SSL_connect(SSL* ssl) { + if (ssl->GetError() == YasslError(SSL_ERROR_WANT_READ)) + ssl->SetError(no_error); + + ClientState neededState; + + switch (ssl->getStates().GetConnect()) { + + case CONNECT_BEGIN : sendClientHello(*ssl); - ClientState neededState = ssl->getSecurity().get_resuming() ? + if (!ssl->GetError()) + ssl->useStates().UseConnect() = CLIENT_HELLO_SENT; + + case CLIENT_HELLO_SENT : + neededState = ssl->getSecurity().get_resuming() ? serverFinishedComplete : serverHelloDoneComplete; while (ssl->getStates().getClient() < neededState) { if (ssl->GetError()) break; processReply(*ssl); } + if (!ssl->GetError()) + ssl->useStates().UseConnect() = FIRST_REPLY_DONE; + case FIRST_REPLY_DONE : if(ssl->getCrypto().get_certManager().sendVerify()) sendCertificate(*ssl); @@ -198,18 +268,32 @@ int SSL_connect(SSL* ssl) sendChangeCipher(*ssl); sendFinished(*ssl, client_end); ssl->flushBuffer(); + + if (!ssl->GetError()) + ssl->useStates().UseConnect() = FINISHED_DONE; + + case FINISHED_DONE : if (!ssl->getSecurity().get_resuming()) while (ssl->getStates().getClient() < serverFinishedComplete) { if (ssl->GetError()) break; processReply(*ssl); } + if (!ssl->GetError()) + ssl->useStates().UseConnect() = SECOND_REPLY_DONE; + case SECOND_REPLY_DONE : ssl->verifyState(serverFinishedComplete); ssl->useLog().ShowTCP(ssl->getSocket().get_fd()); - if (ssl->GetError()) + if (ssl->GetError()) { + GetErrors().Add(ssl->GetError()); return SSL_FATAL_ERROR; + } return SSL_SUCCESS; + + default : + return SSL_FATAL_ERROR; // unkown state + } } @@ -228,7 +312,17 @@ int SSL_read(SSL* ssl, void* buffer, int sz) int SSL_accept(SSL* ssl) { + if (ssl->GetError() == YasslError(SSL_ERROR_WANT_READ)) + ssl->SetError(no_error); + + switch (ssl->getStates().GetAccept()) { + + case ACCEPT_BEGIN : processReply(*ssl); + if (!ssl->GetError()) + ssl->useStates().UseAccept() = ACCEPT_FIRST_REPLY_DONE; + + case ACCEPT_FIRST_REPLY_DONE : sendServerHello(*ssl); if (!ssl->getSecurity().get_resuming()) { @@ -242,27 +336,51 @@ int SSL_accept(SSL* ssl) sendServerHelloDone(*ssl); ssl->flushBuffer(); + } + + if (!ssl->GetError()) + ssl->useStates().UseAccept() = SERVER_HELLO_DONE; + case SERVER_HELLO_DONE : + if (!ssl->getSecurity().get_resuming()) { while (ssl->getStates().getServer() < clientFinishedComplete) { if (ssl->GetError()) break; processReply(*ssl); } } + if (!ssl->GetError()) + ssl->useStates().UseAccept() = ACCEPT_SECOND_REPLY_DONE; + + case ACCEPT_SECOND_REPLY_DONE : sendChangeCipher(*ssl); sendFinished(*ssl, server_end); ssl->flushBuffer(); + + if (!ssl->GetError()) + ssl->useStates().UseAccept() = ACCEPT_FINISHED_DONE; + + case ACCEPT_FINISHED_DONE : if (ssl->getSecurity().get_resuming()) { while (ssl->getStates().getServer() < clientFinishedComplete) { if (ssl->GetError()) break; processReply(*ssl); } } + if (!ssl->GetError()) + ssl->useStates().UseAccept() = ACCEPT_THIRD_REPLY_DONE; + case ACCEPT_THIRD_REPLY_DONE : ssl->useLog().ShowTCP(ssl->getSocket().get_fd()); - if (ssl->GetError()) + if (ssl->GetError()) { + GetErrors().Add(ssl->GetError()); return SSL_FATAL_ERROR; + } return SSL_SUCCESS; + + default: + return SSL_FATAL_ERROR; // unknown state + } } @@ -278,6 +396,8 @@ int SSL_do_handshake(SSL* ssl) int SSL_clear(SSL* ssl) { ssl->useSocket().closeSocket(); + GetErrors().Remove(); + return SSL_SUCCESS; } @@ -289,6 +409,8 @@ int SSL_shutdown(SSL* ssl) ssl->useLog().ShowTCP(ssl->getSocket().get_fd(), true); ssl->useSocket().closeSocket(); + GetErrors().Remove(); + return SSL_SUCCESS; } @@ -762,9 +884,8 @@ void DH_free(DH* dh) // be created BIGNUM* BN_bin2bn(const unsigned char* num, int sz, BIGNUM* retVal) { - using mySTL::auto_ptr; bool created = false; - auto_ptr bn(ysDelete); + mySTL::auto_ptr bn; if (!retVal) { created = true; @@ -825,7 +946,7 @@ const EVP_MD* EVP_md5(void) const EVP_CIPHER* EVP_des_ede3_cbc(void) { - static const char* type = "DES_EDE3_CBC"; + static const char* type = "DES-EDE3-CBC"; return type; } @@ -836,16 +957,37 @@ int EVP_BytesToKey(const EVP_CIPHER* type, const EVP_MD* md, const byte* salt, // only support MD5 for now if (strncmp(md, "MD5", 3)) return 0; - // only support DES_EDE3_CBC for now - if (strncmp(type, "DES_EDE3_CBC", 12)) return 0; + int keyLen = 0; + int ivLen = 0; + + // only support CBC DES and AES for now + if (strncmp(type, "DES-CBC", 7) == 0) { + keyLen = DES_KEY_SZ; + ivLen = DES_IV_SZ; + } + else if (strncmp(type, "DES-EDE3-CBC", 12) == 0) { + keyLen = DES_EDE_KEY_SZ; + ivLen = DES_IV_SZ; + } + else if (strncmp(type, "AES-128-CBC", 11) == 0) { + keyLen = AES_128_KEY_SZ; + ivLen = AES_IV_SZ; + } + else if (strncmp(type, "AES-192-CBC", 11) == 0) { + keyLen = AES_192_KEY_SZ; + ivLen = AES_IV_SZ; + } + else if (strncmp(type, "AES-256-CBC", 11) == 0) { + keyLen = AES_256_KEY_SZ; + ivLen = AES_IV_SZ; + } + else + return 0; yaSSL::MD5 myMD; uint digestSz = myMD.get_digestSize(); byte digest[SHA_LEN]; // max size - yaSSL::DES_EDE cipher; - int keyLen = cipher.get_keySize(); - int ivLen = cipher.get_ivSize(); int keyLeft = keyLen; int ivLeft = ivLen; int keyOutput = 0; @@ -878,7 +1020,7 @@ int EVP_BytesToKey(const EVP_CIPHER* type, const EVP_MD* md, const byte* salt, if (ivLeft && digestLeft) { int store = min(ivLeft, digestLeft); - memcpy(&iv[ivLen - ivLeft], digest, store); + memcpy(&iv[ivLen - ivLeft], &digest[digestSz - digestLeft], store); keyOutput += store; ivLeft -= store; @@ -954,10 +1096,9 @@ void DES_ecb_encrypt(DES_cblock* input, DES_cblock* output, } -void SSL_CTX_set_default_passwd_cb_userdata(SSL_CTX*, void* userdata) +void SSL_CTX_set_default_passwd_cb_userdata(SSL_CTX* ctx, void* userdata) { - // yaSSL doesn't support yet, unencrypt your PEM file with userdata - // before handing off to yaSSL + ctx->SetUserData(userdata); } @@ -1034,12 +1175,6 @@ ASN1_TIME* X509_get_notAfter(X509* x) } -SSL_METHOD* SSLv23_client_method(void) /* doesn't actually roll back */ -{ - return SSLv3_client_method(); -} - - SSL_METHOD* SSLv2_client_method(void) /* will never work, no v 2 */ { return 0; @@ -1363,9 +1498,9 @@ int SSL_pending(SSL* ssl) } - void SSL_CTX_set_default_passwd_cb(SSL_CTX*, pem_password_cb) + void SSL_CTX_set_default_passwd_cb(SSL_CTX* ctx, pem_password_cb cb) { - // TDOD: + ctx->SetPasswordCb(cb); } @@ -1428,7 +1563,7 @@ int SSL_pending(SSL* ssl) void ERR_remove_state(unsigned long) { - // TODO: + GetErrors().Remove(); } @@ -1437,16 +1572,30 @@ int SSL_pending(SSL* ssl) return l & 0xfff; } + unsigned long err_helper(bool peek = false) + { + int ysError = GetErrors().Lookup(peek); + + // translate cert error for libcurl, it uses OpenSSL hex code + switch (ysError) { + case TaoCrypt::SIG_OTHER_E: + return CERTFICATE_ERROR; + break; + default : + return 0; + } + } + unsigned long ERR_peek_error() { - return 0; // TODO: + return err_helper(true); } unsigned long ERR_get_error() { - return ERR_peek_error(); + return err_helper(); } diff --git a/extra/yassl/src/template_instnt.cpp b/extra/yassl/src/template_instnt.cpp index c5fc23dabdb..fb488e47672 100644 --- a/extra/yassl/src/template_instnt.cpp +++ b/extra/yassl/src/template_instnt.cpp @@ -65,6 +65,19 @@ template yaSSL::del_ptr_zero for_each::iterat template yaSSL::del_ptr_zero for_each::iterator, yaSSL::del_ptr_zero>(mySTL::list::iterator, mySTL::list::iterator, yaSSL::del_ptr_zero); template yaSSL::del_ptr_zero for_each::iterator, yaSSL::del_ptr_zero>(mySTL::list::iterator, mySTL::list::iterator, yaSSL::del_ptr_zero); template yaSSL::del_ptr_zero for_each::iterator, yaSSL::del_ptr_zero>(mySTL::list::iterator, mySTL::list::iterator, yaSSL::del_ptr_zero); +template bool list::erase(list::iterator); +template void list::push_back(yaSSL::ThreadError); +template void list::pop_front(); +template void list::pop_back(); +template list::~list(); +template pair* GetArrayMemory >(size_t); +template void FreeArrayMemory >(pair*); +template pair* GetArrayMemory >(size_t); +template void FreeArrayMemory >(pair*); +template pair* GetArrayMemory >(size_t); +template void FreeArrayMemory >(pair*); +template pair* GetArrayMemory >(size_t); +template void FreeArrayMemory >(pair*); } namespace yaSSL { @@ -90,8 +103,13 @@ template void ysDelete(X509*); template void ysDelete(Message*); template void ysDelete(sslFactory*); template void ysDelete(Sessions*); +template void ysDelete(Errors*); template void ysArrayDelete(unsigned char*); template void ysArrayDelete(char*); + +template int min(int, int); +template unsigned int min(unsigned int, unsigned int); +template unsigned long min(unsigned long, unsigned long); } #endif // HAVE_EXPLICIT_TEMPLATE_INSTANTIATION diff --git a/extra/yassl/src/yassl.cpp b/extra/yassl/src/yassl.cpp index 5bc8bad8bbc..e253ef84bb5 100644 --- a/extra/yassl/src/yassl.cpp +++ b/extra/yassl/src/yassl.cpp @@ -36,21 +36,9 @@ #include "openssl/ssl.h" // get rid of this -// yaSSL overloads hide these -void* operator new[](size_t sz) -{ - return ::operator new(sz); -} - -void operator delete[](void* ptr) -{ - ::operator delete(ptr); -} - namespace yaSSL { -using mySTL::min; struct Base { diff --git a/extra/yassl/src/yassl_error.cpp b/extra/yassl/src/yassl_error.cpp index 4f75de34a98..3531c0a2c74 100644 --- a/extra/yassl/src/yassl_error.cpp +++ b/extra/yassl/src/yassl_error.cpp @@ -125,13 +125,21 @@ void SetErrorString(YasslError error, char* buffer) strncpy(buffer, "unable to proccess cerificate", max); break; + case privateKey_error : + strncpy(buffer, "unable to proccess private key, bad format", max); + break; + + case badVersion_error : + strncpy(buffer, "protocl version mismatch", max); + break; + // openssl errors case SSL_ERROR_WANT_READ : strncpy(buffer, "the read operation would block", max); break; // TaoCrypt errors - case NO_ERROR : + case NO_ERROR_E : strncpy(buffer, "not in error state", max); break; @@ -235,6 +243,10 @@ void SetErrorString(YasslError error, char* buffer) strncpy(buffer, "ASN: bad other signature confirmation", max); break; + case CERTFICATE_ERROR : + strncpy(buffer, "Unable to verify certificate", max); + break; + default : strncpy(buffer, "unknown error number", max); } diff --git a/extra/yassl/src/yassl_imp.cpp b/extra/yassl/src/yassl_imp.cpp index 98f8035732e..bd07f8b70f2 100644 --- a/extra/yassl/src/yassl_imp.cpp +++ b/extra/yassl/src/yassl_imp.cpp @@ -139,7 +139,7 @@ void DH_Server::build(SSL& ssl) parms_.alloc_pub(pubSz)); short sigSz = 0; - mySTL::auto_ptr auth(ysDelete); + mySTL::auto_ptr auth; const CertManager& cert = ssl.getCrypto().get_certManager(); if (ssl.getSecurity().get_parms().sig_algo_ == rsa_sa_algo) @@ -151,9 +151,11 @@ void DH_Server::build(SSL& ssl) sigSz += DSS_ENCODED_EXTRA; } - sigSz += auth->get_signatureLength(); - + if (!sigSz) { + ssl.SetError(privateKey_error); + return; + } length_ = 8; // pLen + gLen + YsLen + SigLen length_ += pSz + gSz + pubSz + sigSz; @@ -612,7 +614,7 @@ void HandShakeHeader::Process(input_buffer& input, SSL& ssl) { ssl.verifyState(*this); const HandShakeFactory& hsf = ssl.getFactory().getHandShake(); - mySTL::auto_ptr hs(hsf.CreateObject(type_), ysDelete); + mySTL::auto_ptr hs(hsf.CreateObject(type_)); if (!hs.get()) { ssl.SetError(factory_error); return; @@ -1214,6 +1216,20 @@ output_buffer& operator<<(output_buffer& output, const ServerHello& hello) // Server Hello processing handler void ServerHello::Process(input_buffer&, SSL& ssl) { + if (ssl.GetMultiProtocol()) { // SSLv23 support + if (ssl.isTLS() && server_version_.minor_ < 1) + // downgrade to SSLv3 + ssl.useSecurity().use_connection().TurnOffTLS(); + } + else if (ssl.isTLS() && server_version_.minor_ < 1) { + ssl.SetError(badVersion_error); + return; + } + else if (!ssl.isTLS() && (server_version_.major_ == 3 && + server_version_.minor_ >= 1)) { + ssl.SetError(badVersion_error); + return; + } ssl.set_pending(cipher_suite_[1]); ssl.set_random(random_, server_end); if (id_len_) @@ -1384,11 +1400,23 @@ output_buffer& operator<<(output_buffer& output, const ClientHello& hello) // Client Hello processing handler void ClientHello::Process(input_buffer&, SSL& ssl) { - if (ssl.isTLS() && client_version_.minor_ == 0) { + if (ssl.GetMultiProtocol()) { // SSLv23 support + if (ssl.isTLS() && client_version_.minor_ < 1) { + // downgrade to SSLv3 ssl.useSecurity().use_connection().TurnOffTLS(); ProtocolVersion pv = ssl.getSecurity().get_connection().version_; ssl.useSecurity().use_parms().SetSuites(pv); // reset w/ SSL suites } + } + else if (ssl.isTLS() && client_version_.minor_ < 1) { + ssl.SetError(badVersion_error); + return; + } + else if (!ssl.isTLS() && (client_version_.major_ == 3 && + client_version_.minor_ >= 1)) { + ssl.SetError(badVersion_error); + return; + } ssl.set_random(random_, client_end); while (id_len_) { // trying to resume @@ -1541,7 +1569,7 @@ CertificateRequest::CertificateRequest() CertificateRequest::~CertificateRequest() { - mySTL::for_each(certificate_authorities_.begin(), + STL::for_each(certificate_authorities_.begin(), certificate_authorities_.end(), del_ptr_zero()) ; } @@ -1634,9 +1662,9 @@ output_buffer& operator<<(output_buffer& output, request.typeTotal_ - REQUEST_HEADER, tmp); output.write(tmp, sizeof(tmp)); - mySTL::list::const_iterator first = + STL::list::const_iterator first = request.certificate_authorities_.begin(); - mySTL::list::const_iterator last = + STL::list::const_iterator last = request.certificate_authorities_.end(); while (first != last) { uint16 sz; @@ -1684,7 +1712,7 @@ void CertificateVerify::Build(SSL& ssl) uint16 sz = 0; byte len[VERIFY_HEADER]; - mySTL::auto_ptr sig(ysArrayDelete); + mySTL::auto_array sig; // sign const CertManager& cert = ssl.getCrypto().get_certManager(); diff --git a/extra/yassl/src/yassl_int.cpp b/extra/yassl/src/yassl_int.cpp index 9b83f964348..5288acb2bcd 100644 --- a/extra/yassl/src/yassl_int.cpp +++ b/extra/yassl/src/yassl_int.cpp @@ -33,6 +33,10 @@ #include "handshake.hpp" #include "timer.hpp" +#ifdef _POSIX_THREADS + #include "pthread.h" +#endif + #ifdef YASSL_PURE_C @@ -74,7 +78,6 @@ namespace yaSSL { -using mySTL::min; @@ -155,6 +158,7 @@ void c32toa(uint32 u32, opaque* c) States::States() : recordLayer_(recordReady), handshakeLayer_(preHandshake), clientState_(serverNull), serverState_(clientNull), + connectState_(CONNECT_BEGIN), acceptState_(ACCEPT_BEGIN), what_(no_error) {} const RecordLayerState& States::getRecord() const @@ -181,6 +185,18 @@ const ServerState& States::getServer() const } +const ConnectState& States::GetConnect() const +{ + return connectState_; +} + + +const AcceptState& States::GetAccept() const +{ + return acceptState_; +} + + const char* States::getString() const { return errorString_; @@ -217,6 +233,18 @@ ServerState& States::useServer() } +ConnectState& States::UseConnect() +{ + return connectState_; +} + + +AcceptState& States::UseAccept() +{ + return acceptState_; +} + + char* States::useString() { return errorString_; @@ -722,6 +750,12 @@ void SSL::SetError(YasslError ye) } +Buffers& SSL::useBuffers() +{ + return buffers_; +} + + // locals namespace { @@ -959,7 +993,7 @@ using namespace yassl_int_cpp_local1; uint SSL::bufferedData() { - return mySTL::for_each(buffers_.getData().begin(),buffers_.getData().end(), + return STL::for_each(buffers_.getData().begin(),buffers_.getData().end(), SumData()).total_; } @@ -1002,7 +1036,7 @@ void SSL::PeekData(Data& data) data.set_length(0); // output, actual data filled dataSz = min(dataSz, bufferedData()); - Buffers::inputList::iterator front = buffers_.getData().begin(); + Buffers::inputList::iterator front = buffers_.useData().begin(); while (elements) { uint frontSz = (*front)->get_remaining(); @@ -1027,7 +1061,7 @@ void SSL::flushBuffer() { if (GetError()) return; - uint sz = mySTL::for_each(buffers_.getHandShake().begin(), + uint sz = STL::for_each(buffers_.getHandShake().begin(), buffers_.getHandShake().end(), SumBuffer()).total_; output_buffer out(sz); @@ -1213,8 +1247,10 @@ void SSL::matchSuite(const opaque* peer, uint length) void SSL::set_session(SSL_SESSION* s) { - if (s && GetSessions().lookup(s->GetID(), &secure_.use_resume())) + if (s && GetSessions().lookup(s->GetID(), &secure_.use_resume())) { secure_.set_resuming(true); + crypto_.use_certManager().setPeerX509(s->GetPeerX509()); + } } @@ -1260,6 +1296,12 @@ YasslError SSL::GetError() const } +bool SSL::GetMultiProtocol() const +{ + return secure_.GetContext()->getMethod()->multipleProtocol(); +} + + Crypto& SSL::useCrypto() { return crypto_; @@ -1314,9 +1356,25 @@ void SSL::addBuffer(output_buffer* b) } +void SSL_SESSION::CopyX509(X509* x) +{ + assert(peerX509_ == 0); + if (x == 0) return; + + X509_NAME* issuer = x->GetIssuer(); + X509_NAME* subject = x->GetSubject(); + ASN1_STRING* before = x->GetBefore(); + ASN1_STRING* after = x->GetAfter(); + + peerX509_ = NEW_YS X509(issuer->GetName(), issuer->GetLength(), + subject->GetName(), subject->GetLength(), (const char*) before->data, + before->length, (const char*) after->data, after->length); +} + + // store connection parameters SSL_SESSION::SSL_SESSION(const SSL& ssl, RandomPool& ran) - : timeout_(DEFAULT_TIMEOUT), random_(ran) + : timeout_(DEFAULT_TIMEOUT), random_(ran), peerX509_(0) { const Connection& conn = ssl.getSecurity().get_connection(); @@ -1325,12 +1383,14 @@ SSL_SESSION::SSL_SESSION(const SSL& ssl, RandomPool& ran) memcpy(suite_, ssl.getSecurity().get_parms().suite_, SUITE_LEN); bornOn_ = lowResTimer(); + + CopyX509(ssl.getCrypto().get_certManager().get_peerX509()); } // for resumption copy in ssl::parameters SSL_SESSION::SSL_SESSION(RandomPool& ran) - : bornOn_(0), timeout_(0), random_(ran) + : bornOn_(0), timeout_(0), random_(ran), peerX509_(0) { memset(sessionID_, 0, ID_LEN); memset(master_secret_, 0, SECRET_LEN); @@ -1347,6 +1407,12 @@ SSL_SESSION& SSL_SESSION::operator=(const SSL_SESSION& that) bornOn_ = that.bornOn_; timeout_ = that.timeout_; + if (peerX509_) { + ysDelete(peerX509_); + peerX509_ = 0; + } + CopyX509(that.peerX509_); + return *this; } @@ -1369,6 +1435,12 @@ const Cipher* SSL_SESSION::GetSuite() const } +X509* SSL_SESSION::GetPeerX509() const +{ + return peerX509_; +} + + uint SSL_SESSION::GetBornOn() const { return bornOn_; @@ -1395,6 +1467,8 @@ SSL_SESSION::~SSL_SESSION() { volatile opaque* p = master_secret_; clean(p, SECRET_LEN, random_); + + ysDelete(peerX509_); } @@ -1418,6 +1492,15 @@ sslFactory& GetSSL_Factory() } +static Errors* errorsInstance = 0; + +Errors& GetErrors() +{ + if (!errorsInstance) + errorsInstance = NEW_YS Errors; + return *errorsInstance; +} + typedef Mutex::Lock Lock; @@ -1433,14 +1516,15 @@ void Sessions::add(const SSL& ssl) Sessions::~Sessions() { - mySTL::for_each(list_.begin(), list_.end(), del_ptr_zero()); + STL::for_each(list_.begin(), list_.end(), del_ptr_zero()); } // locals namespace yassl_int_cpp_local2 { // for explicit templates -typedef mySTL::list::iterator iterator; +typedef STL::list::iterator sess_iterator; +typedef STL::list::iterator thr_iterator; struct sess_match { const opaque* id_; @@ -1455,6 +1539,28 @@ struct sess_match { }; +THREAD_ID_T GetSelf() +{ +#ifndef _POSIX_THREADS + return GetCurrentThreadId(); +#else + return pthread_self(); +#endif +} + +struct thr_match { + THREAD_ID_T id_; + explicit thr_match() : id_(GetSelf()) {} + + bool operator()(ThreadError thr) + { + if (thr.threadID_ == id_) + return true; + return false; + } +}; + + } // local namespace using namespace yassl_int_cpp_local2; @@ -1463,8 +1569,8 @@ using namespace yassl_int_cpp_local2; SSL_SESSION* Sessions::lookup(const opaque* id, SSL_SESSION* copy) { Lock guard(mutex_); - iterator find = mySTL::find_if(list_.begin(), list_.end(), sess_match(id)); - + sess_iterator find = STL::find_if(list_.begin(), list_.end(), + sess_match(id)); if (find != list_.end()) { uint current = lowResTimer(); if ( ((*find)->GetBornOn() + (*find)->GetTimeOut()) < current) { @@ -1484,8 +1590,8 @@ SSL_SESSION* Sessions::lookup(const opaque* id, SSL_SESSION* copy) void Sessions::remove(const opaque* id) { Lock guard(mutex_); - iterator find = mySTL::find_if(list_.begin(), list_.end(), sess_match(id)); - + sess_iterator find = STL::find_if(list_.begin(), list_.end(), + sess_match(id)); if (find != list_.end()) { del_ptr_zero()(*find); list_.erase(find); @@ -1493,9 +1599,51 @@ void Sessions::remove(const opaque* id) } -SSL_METHOD::SSL_METHOD(ConnectionEnd ce, ProtocolVersion pv) +// remove a self thread error +void Errors::Remove() +{ + Lock guard(mutex_); + thr_iterator find = STL::find_if(list_.begin(), list_.end(), + thr_match()); + if (find != list_.end()) + list_.erase(find); +} + + +// lookup self error code +int Errors::Lookup(bool peek) +{ + Lock guard(mutex_); + thr_iterator find = STL::find_if(list_.begin(), list_.end(), + thr_match()); + if (find != list_.end()) { + int ret = find->errorID_; + if (!peek) + list_.erase(find); + return ret; + } + else + return 0; +} + + +// add a new error code for self +void Errors::Add(int error) +{ + ThreadError add; + add.errorID_ = error; + add.threadID_ = GetSelf(); + + Remove(); // may have old error + + Lock guard(mutex_); + list_.push_back(add); +} + + +SSL_METHOD::SSL_METHOD(ConnectionEnd ce, ProtocolVersion pv, bool multiProto) : version_(pv), side_(ce), verifyPeer_(false), verifyNone_(false), - failNoCert_(false) + failNoCert_(false), multipleProtocol_(multiProto) {} @@ -1547,8 +1695,15 @@ bool SSL_METHOD::failNoCert() const } +bool SSL_METHOD::multipleProtocol() const +{ + return multipleProtocol_; +} + + SSL_CTX::SSL_CTX(SSL_METHOD* meth) - : method_(meth), certificate_(0), privateKey_(0) + : method_(meth), certificate_(0), privateKey_(0), passwordCb_(0), + userData_(0) {} @@ -1558,7 +1713,7 @@ SSL_CTX::~SSL_CTX() ysDelete(certificate_); ysDelete(privateKey_); - mySTL::for_each(caList_.begin(), caList_.end(), del_ptr_zero()); + STL::for_each(caList_.begin(), caList_.end(), del_ptr_zero()); } @@ -1611,6 +1766,30 @@ const Stats& SSL_CTX::GetStats() const } +pem_password_cb SSL_CTX::GetPasswordCb() const +{ + return passwordCb_; +} + + +void SSL_CTX::SetPasswordCb(pem_password_cb cb) +{ + passwordCb_ = cb; +} + + +void* SSL_CTX::GetUserData() const +{ + return userData_; +} + + +void SSL_CTX::SetUserData(void* data) +{ + userData_ = data; +} + + void SSL_CTX::setVerifyPeer() { method_->setVerifyPeer(); @@ -1914,12 +2093,33 @@ Hashes& sslHashes::use_certVerify() } +Buffers::Buffers() : rawInput_(0) +{} + + Buffers::~Buffers() { - mySTL::for_each(handShakeList_.begin(), handShakeList_.end(), + STL::for_each(handShakeList_.begin(), handShakeList_.end(), del_ptr_zero()) ; - mySTL::for_each(dataList_.begin(), dataList_.end(), + STL::for_each(dataList_.begin(), dataList_.end(), del_ptr_zero()) ; + ysDelete(rawInput_); +} + + +void Buffers::SetRawInput(input_buffer* ib) +{ + assert(rawInput_ == 0); + rawInput_ = ib; +} + + +input_buffer* Buffers::TakeRawInput() +{ + input_buffer* ret = rawInput_; + rawInput_ = 0; + + return ret; } @@ -2026,12 +2226,18 @@ X509_NAME::~X509_NAME() } -char* X509_NAME::GetName() +const char* X509_NAME::GetName() const { return name_; } +size_t X509_NAME::GetLength() const +{ + return sz_; +} + + X509::X509(const char* i, size_t iSz, const char* s, size_t sSz, const char* b, int bSz, const char* a, int aSz) : issuer_(i, iSz), subject_(s, sSz), @@ -2114,10 +2320,12 @@ extern "C" void yaSSL_CleanUp() TaoCrypt::CleanUp(); yaSSL::ysDelete(yaSSL::sslFactoryInstance); yaSSL::ysDelete(yaSSL::sessionsInstance); + yaSSL::ysDelete(yaSSL::errorsInstance); // In case user calls more than once, prevent seg fault yaSSL::sslFactoryInstance = 0; yaSSL::sessionsInstance = 0; + yaSSL::errorsInstance = 0; } @@ -2126,6 +2334,7 @@ namespace mySTL { template yaSSL::yassl_int_cpp_local1::SumData for_each::iterator, yaSSL::yassl_int_cpp_local1::SumData>(mySTL::list::iterator, mySTL::list::iterator, yaSSL::yassl_int_cpp_local1::SumData); template yaSSL::yassl_int_cpp_local1::SumBuffer for_each::iterator, yaSSL::yassl_int_cpp_local1::SumBuffer>(mySTL::list::iterator, mySTL::list::iterator, yaSSL::yassl_int_cpp_local1::SumBuffer); template mySTL::list::iterator find_if::iterator, yaSSL::yassl_int_cpp_local2::sess_match>(mySTL::list::iterator, mySTL::list::iterator, yaSSL::yassl_int_cpp_local2::sess_match); +template mySTL::list::iterator find_if::iterator, yaSSL::yassl_int_cpp_local2::thr_match>(mySTL::list::iterator, mySTL::list::iterator, yaSSL::yassl_int_cpp_local2::thr_match); } #endif diff --git a/extra/yassl/taocrypt/CMakeLists.txt b/extra/yassl/taocrypt/CMakeLists.txt index 0af0a242e5d..540827954d0 100755 --- a/extra/yassl/taocrypt/CMakeLists.txt +++ b/extra/yassl/taocrypt/CMakeLists.txt @@ -1,4 +1,4 @@ -INCLUDE_DIRECTORIES(../mySTL include) +INCLUDE_DIRECTORIES(mySTL include) ADD_LIBRARY(taocrypt src/aes.cpp src/aestables.cpp src/algebra.cpp src/arc4.cpp src/asn.cpp src/coding.cpp src/des.cpp src/dh.cpp src/dsa.cpp src/file.cpp src/hash.cpp src/integer.cpp src/md2.cpp diff --git a/extra/yassl/taocrypt/COPYING b/extra/yassl/taocrypt/COPYING new file mode 100644 index 00000000000..d60c31a97a5 --- /dev/null +++ b/extra/yassl/taocrypt/COPYING @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/extra/yassl/taocrypt/INSTALL b/extra/yassl/taocrypt/INSTALL new file mode 100644 index 00000000000..54caf7c190f --- /dev/null +++ b/extra/yassl/taocrypt/INSTALL @@ -0,0 +1,229 @@ +Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002 Free Software +Foundation, Inc. + + This file is free documentation; the Free Software Foundation gives +unlimited permission to copy, distribute and modify it. + +Basic Installation +================== + + These are generic installation instructions. + + The `configure' shell script attempts to guess correct values for +various system-dependent variables used during compilation. It uses +those values to create a `Makefile' in each directory of the package. +It may also create one or more `.h' files containing system-dependent +definitions. Finally, it creates a shell script `config.status' that +you can run in the future to recreate the current configuration, and a +file `config.log' containing compiler output (useful mainly for +debugging `configure'). + + It can also use an optional file (typically called `config.cache' +and enabled with `--cache-file=config.cache' or simply `-C') that saves +the results of its tests to speed up reconfiguring. (Caching is +disabled by default to prevent problems with accidental use of stale +cache files.) + + If you need to do unusual things to compile the package, please try +to figure out how `configure' could check whether to do them, and mail +diffs or instructions to the address given in the `README' so they can +be considered for the next release. If you are using the cache, and at +some point `config.cache' contains results you don't want to keep, you +may remove or edit it. + + The file `configure.ac' (or `configure.in') is used to create +`configure' by a program called `autoconf'. You only need +`configure.ac' if you want to change it or regenerate `configure' using +a newer version of `autoconf'. + +The simplest way to compile this package is: + + 1. `cd' to the directory containing the package's source code and type + `./configure' to configure the package for your system. If you're + using `csh' on an old version of System V, you might need to type + `sh ./configure' instead to prevent `csh' from trying to execute + `configure' itself. + + Running `configure' takes awhile. While running, it prints some + messages telling which features it is checking for. + + 2. Type `make' to compile the package. + + 3. Optionally, type `make check' to run any self-tests that come with + the package. + + 4. Type `make install' to install the programs and any data files and + documentation. + + 5. You can remove the program binaries and object files from the + source code directory by typing `make clean'. To also remove the + files that `configure' created (so you can compile the package for + a different kind of computer), type `make distclean'. There is + also a `make maintainer-clean' target, but that is intended mainly + for the package's developers. If you use it, you may have to get + all sorts of other programs in order to regenerate files that came + with the distribution. + +Compilers and Options +===================== + + Some systems require unusual options for compilation or linking that +the `configure' script does not know about. Run `./configure --help' +for details on some of the pertinent environment variables. + + You can give `configure' initial values for configuration parameters +by setting variables in the command line or in the environment. Here +is an example: + + ./configure CC=c89 CFLAGS=-O2 LIBS=-lposix + + *Note Defining Variables::, for more details. + +Compiling For Multiple Architectures +==================================== + + You can compile the package for more than one kind of computer at the +same time, by placing the object files for each architecture in their +own directory. To do this, you must use a version of `make' that +supports the `VPATH' variable, such as GNU `make'. `cd' to the +directory where you want the object files and executables to go and run +the `configure' script. `configure' automatically checks for the +source code in the directory that `configure' is in and in `..'. + + If you have to use a `make' that does not support the `VPATH' +variable, you have to compile the package for one architecture at a +time in the source code directory. After you have installed the +package for one architecture, use `make distclean' before reconfiguring +for another architecture. + +Installation Names +================== + + By default, `make install' will install the package's files in +`/usr/local/bin', `/usr/local/man', etc. You can specify an +installation prefix other than `/usr/local' by giving `configure' the +option `--prefix=PATH'. + + You can specify separate installation prefixes for +architecture-specific files and architecture-independent files. If you +give `configure' the option `--exec-prefix=PATH', the package will use +PATH as the prefix for installing programs and libraries. +Documentation and other data files will still use the regular prefix. + + In addition, if you use an unusual directory layout you can give +options like `--bindir=PATH' to specify different values for particular +kinds of files. Run `configure --help' for a list of the directories +you can set and what kinds of files go in them. + + If the package supports it, you can cause programs to be installed +with an extra prefix or suffix on their names by giving `configure' the +option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'. + +Optional Features +================= + + Some packages pay attention to `--enable-FEATURE' options to +`configure', where FEATURE indicates an optional part of the package. +They may also pay attention to `--with-PACKAGE' options, where PACKAGE +is something like `gnu-as' or `x' (for the X Window System). The +`README' should mention any `--enable-' and `--with-' options that the +package recognizes. + + For packages that use the X Window System, `configure' can usually +find the X include and library files automatically, but if it doesn't, +you can use the `configure' options `--x-includes=DIR' and +`--x-libraries=DIR' to specify their locations. + +Specifying the System Type +========================== + + There may be some features `configure' cannot figure out +automatically, but needs to determine by the type of machine the package +will run on. Usually, assuming the package is built to be run on the +_same_ architectures, `configure' can figure that out, but if it prints +a message saying it cannot guess the machine type, give it the +`--build=TYPE' option. TYPE can either be a short name for the system +type, such as `sun4', or a canonical name which has the form: + + CPU-COMPANY-SYSTEM + +where SYSTEM can have one of these forms: + + OS KERNEL-OS + + See the file `config.sub' for the possible values of each field. If +`config.sub' isn't included in this package, then this package doesn't +need to know the machine type. + + If you are _building_ compiler tools for cross-compiling, you should +use the `--target=TYPE' option to select the type of system they will +produce code for. + + If you want to _use_ a cross compiler, that generates code for a +platform different from the build platform, you should specify the +"host" platform (i.e., that on which the generated programs will +eventually be run) with `--host=TYPE'. + +Sharing Defaults +================ + + If you want to set default values for `configure' scripts to share, +you can create a site shell script called `config.site' that gives +default values for variables like `CC', `cache_file', and `prefix'. +`configure' looks for `PREFIX/share/config.site' if it exists, then +`PREFIX/etc/config.site' if it exists. Or, you can set the +`CONFIG_SITE' environment variable to the location of the site script. +A warning: not all `configure' scripts look for a site script. + +Defining Variables +================== + + Variables not defined in a site shell script can be set in the +environment passed to `configure'. However, some packages may run +configure again during the build, and the customized values of these +variables may be lost. In order to avoid this problem, you should set +them in the `configure' command line, using `VAR=value'. For example: + + ./configure CC=/usr/local2/bin/gcc + +will cause the specified gcc to be used as the C compiler (unless it is +overridden in the site shell script). + +`configure' Invocation +====================== + + `configure' recognizes the following options to control how it +operates. + +`--help' +`-h' + Print a summary of the options to `configure', and exit. + +`--version' +`-V' + Print the version of Autoconf used to generate the `configure' + script, and exit. + +`--cache-file=FILE' + Enable the cache: use and save the results of the tests in FILE, + traditionally `config.cache'. FILE defaults to `/dev/null' to + disable caching. + +`--config-cache' +`-C' + Alias for `--cache-file=config.cache'. + +`--quiet' +`--silent' +`-q' + Do not print messages saying which checks are being made. To + suppress all normal output, redirect it to `/dev/null' (any error + messages will still be shown). + +`--srcdir=DIR' + Look for the package's source code in directory DIR. Usually + `configure' can determine that directory automatically. + +`configure' also accepts some other, not widely useful, options. Run +`configure --help' for more details. + diff --git a/extra/yassl/taocrypt/Makefile.am b/extra/yassl/taocrypt/Makefile.am index e232b499cc7..f1340b38437 100644 --- a/extra/yassl/taocrypt/Makefile.am +++ b/extra/yassl/taocrypt/Makefile.am @@ -1,2 +1,2 @@ SUBDIRS = src test benchmark -EXTRA_DIST = taocrypt.dsw taocrypt.dsp CMakeLists.txt +EXTRA_DIST = taocrypt.dsw taocrypt.dsp CMakeLists.txt $(wildcard mySTL/*.hpp) diff --git a/extra/yassl/taocrypt/README b/extra/yassl/taocrypt/README new file mode 100644 index 00000000000..34e1744492e --- /dev/null +++ b/extra/yassl/taocrypt/README @@ -0,0 +1,37 @@ +TaoCrypt release 0.9.0 09/18/2006 + +This is the first release of TaoCrypt, it was previously only included with +yaSSL. TaoCrypt is highly portable and fast, its features include: + +One way hash functions: SHA-1, MD2, MD4, MD5, RIPEMD-160 +Message authentication codes: HMAC +Block Ciphers: DES, Triple-DES, AES, Blowfish, Twofish +Stream Ciphers: ARC4 +Public Key Crypto: RSA, DSA, Diffie-Hellman +Password based key derivation: PBKDF2 from PKCS #5 +Pseudo Random Number Generators +Lare Integer Support +Base 16/64 encoding/decoding +DER encoding/decoding +X.509 processing +SSE2 and ia32 asm for the right processors and compilers + + +To build on Unix + + ./configure + make + + To test the build, from the ./test directory run ./test + + +On Windows + + Open the taocrypt project workspace + Choose (Re)Build All + + To test the build, run the test executable + + +Please send any questions or comments to todd@yassl.com. + diff --git a/extra/yassl/taocrypt/benchmark/Makefile.am b/extra/yassl/taocrypt/benchmark/Makefile.am index 81200ff7e6a..a5b1713427c 100644 --- a/extra/yassl/taocrypt/benchmark/Makefile.am +++ b/extra/yassl/taocrypt/benchmark/Makefile.am @@ -1,8 +1,6 @@ -INCLUDES = -I../include -I../../mySTL +INCLUDES = -I../include -I../mySTL bin_PROGRAMS = benchmark benchmark_SOURCES = benchmark.cpp -benchmark_LDFLAGS = -L../src -benchmark_LDADD = -ltaocrypt +benchmark_LDADD = $(top_builddir)/extra/yassl/taocrypt/src/libtaocrypt.la benchmark_CXXFLAGS = -DYASSL_PURE_C -benchmark_DEPENDENCIES = ../src/libtaocrypt.la EXTRA_DIST = benchmark.dsp rsa1024.der dh1024.der dsa1024.der make.bat diff --git a/extra/yassl/taocrypt/include/asn.hpp b/extra/yassl/taocrypt/include/asn.hpp index 8bea2ae780b..dbee54be6f1 100644 --- a/extra/yassl/taocrypt/include/asn.hpp +++ b/extra/yassl/taocrypt/include/asn.hpp @@ -33,10 +33,12 @@ #include "misc.hpp" #include "block.hpp" -#include "list.hpp" #include "error.hpp" +#include STL_LIST_FILE +namespace STL = STL_NAMESPACE; + namespace TaoCrypt { @@ -232,7 +234,7 @@ private: }; -typedef mySTL::list SignerList; +typedef STL::list SignerList; enum SigType { SHAwDSA = 517, MD2wRSA = 646, MD5wRSA = 648, SHAwRSA =649}; diff --git a/extra/yassl/taocrypt/include/block.hpp b/extra/yassl/taocrypt/include/block.hpp index 88cb06f62f1..a931158a83d 100644 --- a/extra/yassl/taocrypt/include/block.hpp +++ b/extra/yassl/taocrypt/include/block.hpp @@ -31,12 +31,14 @@ #ifndef TAO_CRYPT_BLOCK_HPP #define TAO_CRYPT_BLOCK_HPP -#include "algorithm.hpp" // mySTL::swap #include "misc.hpp" #include // memcpy #include // ptrdiff_t +#include STL_ALGORITHM_FILE +namespace STL = STL_NAMESPACE; + namespace TaoCrypt { @@ -80,7 +82,7 @@ typename A::pointer StdReallocate(A& a, T* p, typename A::size_type oldSize, typename A::pointer newPointer = b.allocate(newSize, 0); memcpy(newPointer, p, sizeof(T) * min(oldSize, newSize)); a.deallocate(p, oldSize); - mySTL::swap(a, b); + STL::swap(a, b); return newPointer; } else { @@ -183,9 +185,9 @@ public: } void Swap(Block& other) { - mySTL::swap(sz_, other.sz_); - mySTL::swap(buffer_, other.buffer_); - mySTL::swap(allocator_, other.allocator_); + STL::swap(sz_, other.sz_); + STL::swap(buffer_, other.buffer_); + STL::swap(allocator_, other.allocator_); } ~Block() { allocator_.deallocate(buffer_, sz_); } diff --git a/extra/yassl/taocrypt/include/blowfish.hpp b/extra/yassl/taocrypt/include/blowfish.hpp index fbc4f223702..40953624232 100644 --- a/extra/yassl/taocrypt/include/blowfish.hpp +++ b/extra/yassl/taocrypt/include/blowfish.hpp @@ -32,7 +32,11 @@ #include "misc.hpp" #include "modes.hpp" -#include "algorithm.hpp" +#include STL_ALGORITHM_FILE + + +namespace STL = STL_NAMESPACE; + namespace TaoCrypt { diff --git a/extra/yassl/taocrypt/include/error.hpp b/extra/yassl/taocrypt/include/error.hpp index b0ff9b280ba..1a93056db45 100644 --- a/extra/yassl/taocrypt/include/error.hpp +++ b/extra/yassl/taocrypt/include/error.hpp @@ -37,7 +37,7 @@ namespace TaoCrypt { enum ErrorNumber { -NO_ERROR = 0, // "not in error state" +NO_ERROR_E = 0, // "not in error state" // RandomNumberGenerator WINCRYPT_E = 1001, // "bad wincrypt acquire" @@ -78,7 +78,7 @@ SIG_OTHER_E = 1039 // "bad other signature confirmation" struct Error { ErrorNumber what_; // description number, 0 for no error - explicit Error(ErrorNumber w = NO_ERROR) : what_(w) {} + explicit Error(ErrorNumber w = NO_ERROR_E) : what_(w) {} ErrorNumber What() const { return what_; } void SetError(ErrorNumber w) { what_ = w; } diff --git a/extra/yassl/taocrypt/include/file.hpp b/extra/yassl/taocrypt/include/file.hpp index 87fc6139f8f..c12b5c73bac 100644 --- a/extra/yassl/taocrypt/include/file.hpp +++ b/extra/yassl/taocrypt/include/file.hpp @@ -83,7 +83,7 @@ private: void Swap(Source& other) { buffer_.Swap(other.buffer_); - mySTL::swap(current_, other.current_); + STL::swap(current_, other.current_); } }; diff --git a/extra/yassl/taocrypt/include/integer.hpp b/extra/yassl/taocrypt/include/integer.hpp index 7e4f6450316..70b4dc79e73 100644 --- a/extra/yassl/taocrypt/include/integer.hpp +++ b/extra/yassl/taocrypt/include/integer.hpp @@ -44,8 +44,8 @@ #include "block.hpp" #include "random.hpp" #include "file.hpp" -#include "algorithm.hpp" // mySTL::swap #include +#include STL_ALGORITHM_FILE #ifdef TAOCRYPT_X86ASM_AVAILABLE diff --git a/extra/yassl/taocrypt/include/misc.hpp b/extra/yassl/taocrypt/include/misc.hpp index 48604620706..3d2d4c62466 100644 --- a/extra/yassl/taocrypt/include/misc.hpp +++ b/extra/yassl/taocrypt/include/misc.hpp @@ -198,6 +198,23 @@ void CleanUp(); #endif +#ifdef USE_SYS_STL + // use system STL + #define STL_VECTOR_FILE + #define STL_LIST_FILE + #define STL_ALGORITHM_FILE + #define STL_MEMORY_FILE + #define STL_NAMESPACE std +#else + // use mySTL + #define STL_VECTOR_FILE "vector.hpp" + #define STL_LIST_FILE "list.hpp" + #define STL_ALGORITHM_FILE "algorithm.hpp" + #define STL_MEMORY_FILE "memory.hpp" + #define STL_NAMESPACE mySTL +#endif + + // ***************** DLL related ******************** #ifdef TAOCRYPT_WIN32_AVAILABLE diff --git a/extra/yassl/taocrypt/include/pwdbased.hpp b/extra/yassl/taocrypt/include/pwdbased.hpp index c3e916e3d83..78df7ede02e 100644 --- a/extra/yassl/taocrypt/include/pwdbased.hpp +++ b/extra/yassl/taocrypt/include/pwdbased.hpp @@ -74,7 +74,7 @@ word32 PBKDF2_HMAC::DeriveKey(byte* derived, word32 dLen, const byte* pwd, } hmac.Final(buffer.get_buffer()); - word32 segmentLen = mySTL::min(dLen, buffer.size()); + word32 segmentLen = min(dLen, buffer.size()); memcpy(derived, buffer.get_buffer(), segmentLen); for (j = 1; j < iterations; j++) { diff --git a/extra/yassl/taocrypt/include/twofish.hpp b/extra/yassl/taocrypt/include/twofish.hpp index 0529c37d6c5..ba144d2defb 100644 --- a/extra/yassl/taocrypt/include/twofish.hpp +++ b/extra/yassl/taocrypt/include/twofish.hpp @@ -32,7 +32,11 @@ #include "misc.hpp" #include "modes.hpp" -#include "algorithm.hpp" +#include STL_ALGORITHM_FILE + + +namespace STL = STL_NAMESPACE; + namespace TaoCrypt { diff --git a/extra/yassl/mySTL/algorithm.hpp b/extra/yassl/taocrypt/mySTL/algorithm.hpp similarity index 99% rename from extra/yassl/mySTL/algorithm.hpp rename to extra/yassl/taocrypt/mySTL/algorithm.hpp index efc7aa21a07..9a51d1f2281 100644 --- a/extra/yassl/mySTL/algorithm.hpp +++ b/extra/yassl/taocrypt/mySTL/algorithm.hpp @@ -8,7 +8,7 @@ * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * There are special exceptions to the terms and conditions of the GPL as it * is applied to yaSSL. View the full text of the exception in the file * FLOSS-EXCEPTIONS in the directory of this software distribution. diff --git a/extra/yassl/mySTL/helpers.hpp b/extra/yassl/taocrypt/mySTL/helpers.hpp similarity index 80% rename from extra/yassl/mySTL/helpers.hpp rename to extra/yassl/taocrypt/mySTL/helpers.hpp index c4449519db3..43381c0f6ea 100644 --- a/extra/yassl/mySTL/helpers.hpp +++ b/extra/yassl/taocrypt/mySTL/helpers.hpp @@ -113,6 +113,47 @@ PlaceIter uninit_fill_n(PlaceIter place, Size n, const T& value) } +template +T* GetArrayMemory(size_t items) +{ + unsigned char* ret; + + #ifdef YASSL_LIB + ret = NEW_YS unsigned char[sizeof(T) * items]; + #else + ret = NEW_TC unsigned char[sizeof(T) * items]; + #endif + + return reinterpret_cast(ret); +} + + +template +void FreeArrayMemory(T* ptr) +{ + unsigned char* p = reinterpret_cast(ptr); + + #ifdef YASSL_LIB + yaSSL::ysArrayDelete(p); + #else + TaoCrypt::tcArrayDelete(p); + #endif +} + + + +inline void* GetMemory(size_t bytes) +{ + return GetArrayMemory(bytes); +} + + +inline void FreeMemory(void* ptr) +{ + FreeArrayMemory(ptr); +} + + } // namespace mySTL diff --git a/extra/yassl/mySTL/list.hpp b/extra/yassl/taocrypt/mySTL/list.hpp similarity index 76% rename from extra/yassl/mySTL/list.hpp rename to extra/yassl/taocrypt/mySTL/list.hpp index 11a1a914868..831c5bbbbbd 100644 --- a/extra/yassl/mySTL/list.hpp +++ b/extra/yassl/taocrypt/mySTL/list.hpp @@ -33,7 +33,6 @@ #include "helpers.hpp" -#include namespace mySTL { @@ -75,8 +74,7 @@ public: class iterator { node* current_; public: - iterator() : current_(0) {} - explicit iterator(node* p) : current_(p) {} + explicit iterator(node* p = 0) : current_(p) {} T& operator*() const { @@ -127,11 +125,67 @@ public: friend class list; }; + + class reverse_iterator { + node* current_; + public: + explicit reverse_iterator(node* p = 0) : current_(p) {} + + T& operator*() const + { + return current_->value_; + } + + T* operator->() const + { + return &(operator*()); + } + + reverse_iterator& operator++() + { + current_ = current_->prev_; + return *this; + } + + reverse_iterator& operator--() + { + current_ = current_->next_; + return *this; + } + + reverse_iterator operator++(int) + { + reverse_iterator tmp = *this; + current_ = current_->prev_; + return tmp; + } + + reverse_iterator operator--(int) + { + reverse_iterator tmp = *this; + current_ = current_->next_; + return tmp; + } + + bool operator==(const reverse_iterator& other) const + { + return current_ == other.current_; + } + + bool operator!=(const reverse_iterator& other) const + { + return current_ != other.current_; + } + + friend class list; + }; + bool erase(iterator); - iterator begin() const { return iterator(head_); } - iterator rbegin() const { return iterator(tail_); } - iterator end() const { return iterator(); } + iterator begin() const { return iterator(head_); } + reverse_iterator rbegin() const { return reverse_iterator(tail_); } + iterator end() const { return iterator(); } + reverse_iterator rend() const { return reverse_iterator(); } typedef iterator const_iterator; // for now @@ -158,7 +212,7 @@ list::~list() for (; start; start = next_) { next_ = start->next_; destroy(start); - free(start); + FreeMemory(start); } } @@ -166,8 +220,7 @@ list::~list() template void list::push_front(T t) { - void* mem = malloc(sizeof(node)); - if (!mem) abort(); + void* mem = GetMemory(sizeof(node)); node* add = new (reinterpret_cast(mem)) node(t); if (head_) { @@ -196,7 +249,7 @@ void list::pop_front() head_->prev_ = 0; } destroy(front); - free(front); + FreeMemory(front); --sz_; } @@ -204,7 +257,7 @@ void list::pop_front() template T list::front() const { - if (head_ == 0) return 0; + if (head_ == 0) return T(); return head_->value_; } @@ -212,8 +265,7 @@ T list::front() const template void list::push_back(T t) { - void* mem = malloc(sizeof(node)); - if (!mem) abort(); + void* mem = GetMemory(sizeof(node)); node* add = new (reinterpret_cast(mem)) node(t); if (tail_) { @@ -242,7 +294,7 @@ void list::pop_back() tail_->next_ = 0; } destroy(rear); - free(rear); + FreeMemory(rear); --sz_; } @@ -250,7 +302,7 @@ void list::pop_back() template T list::back() const { - if (tail_ == 0) return 0; + if (tail_ == 0) return T(); return tail_->value_; } @@ -286,7 +338,7 @@ bool list::remove(T t) del->next_->prev_ = del->prev_; destroy(del); - free(del); + FreeMemory(del); --sz_; } return true; @@ -309,78 +361,13 @@ bool list::erase(iterator iter) del->next_->prev_ = del->prev_; destroy(del); - free(del); + FreeMemory(del); --sz_; } return true; } -/* MSVC can't handle ?? - -template -T& list::iterator::operator*() const -{ - return current_->value_; -} - - -template -T* list::iterator::operator->() const -{ - return &(operator*()); -} - - -template -typename list::iterator& list::iterator::operator++() -{ - current_ = current_->next_; - return *this; -} - - -template -typename list::iterator& list::iterator::operator--() -{ - current_ = current_->prev_; - return *this; -} - - -template -typename list::iterator& list::iterator::operator++(int) -{ - iterator tmp = *this; - current_ = current_->next_; - return tmp; -} - - -template -typename list::iterator& list::iterator::operator--(int) -{ - iterator tmp = *this; - current_ = current_->prev_; - return tmp; -} - - -template -bool list::iterator::operator==(const iterator& other) const -{ - return current_ == other.current_; -} - - -template -bool list::iterator::operator!=(const iterator& other) const -{ - return current_ != other.current_; -} -*/ // end MSVC 6 can't handle - - } // namespace mySTL diff --git a/extra/yassl/mySTL/memory.hpp b/extra/yassl/taocrypt/mySTL/memory.hpp similarity index 79% rename from extra/yassl/mySTL/memory.hpp rename to extra/yassl/taocrypt/mySTL/memory.hpp index f480af12316..5855423c6fc 100644 --- a/extra/yassl/mySTL/memory.hpp +++ b/extra/yassl/taocrypt/mySTL/memory.hpp @@ -31,6 +31,7 @@ #ifndef mySTL_MEMORY_HPP #define mySTL_MEMORY_HPP +#include "memory_array.hpp" // for auto_array #ifdef _MSC_VER // disable operator-> warning for builtins @@ -43,27 +44,25 @@ namespace mySTL { template struct auto_ptr_ref { - typedef void (*Deletor)(T*); - T* ptr_; - Deletor del_; - auto_ptr_ref(T* p, Deletor d) : ptr_(p), del_(d) {} + T* ptr_; + explicit auto_ptr_ref(T* p) : ptr_(p) {} }; template class auto_ptr { - typedef void (*Deletor)(T*); T* ptr_; - Deletor del_; void Destroy() { - del_(ptr_); + #ifdef YASSL_LIB + yaSSL::ysDelete(ptr_); + #else + TaoCrypt::tcDelete(ptr_); + #endif } public: - auto_ptr(T* p, Deletor d) : ptr_(p), del_(d) {} - - explicit auto_ptr(Deletor d) : ptr_(0), del_(d) {} + explicit auto_ptr(T* p = 0) : ptr_(p) {} ~auto_ptr() { @@ -71,14 +70,13 @@ public: } - auto_ptr(auto_ptr& other) : ptr_(other.release()), del_(other.del_) {} + auto_ptr(auto_ptr& other) : ptr_(other.release()) {} auto_ptr& operator=(auto_ptr& that) { if (this != &that) { Destroy(); ptr_ = that.release(); - del_ = that.del_; } return *this; } @@ -115,14 +113,13 @@ public: } // auto_ptr_ref conversions - auto_ptr(auto_ptr_ref ref) : ptr_(ref.ptr_), del_(ref.del_) {} + auto_ptr(auto_ptr_ref ref) : ptr_(ref.ptr_) {} auto_ptr& operator=(auto_ptr_ref ref) { if (this->ptr_ != ref.ptr_) { Destroy(); ptr_ = ref.ptr_; - del_ = ref.del_; } return *this; } @@ -130,13 +127,13 @@ public: template operator auto_ptr() { - return auto_ptr(this->release(), this->del_); + return auto_ptr(this->release()); } template operator auto_ptr_ref() { - return auto_ptr_ref(this->release(), this->del_); + return auto_ptr_ref(this->release()); } }; diff --git a/extra/yassl/taocrypt/mySTL/memory_array.hpp b/extra/yassl/taocrypt/mySTL/memory_array.hpp new file mode 100644 index 00000000000..f089c69f815 --- /dev/null +++ b/extra/yassl/taocrypt/mySTL/memory_array.hpp @@ -0,0 +1,142 @@ +/* mySTL memory_array.hpp + * + * Copyright (C) 2003 Sawtooth Consulting Ltd. + * + * This file is part of yaSSL. + * + * yaSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * There are special exceptions to the terms and conditions of the GPL as it + * is applied to yaSSL. View the full text of the exception in the file + * FLOSS-EXCEPTIONS in the directory of this software distribution. + * + * yaSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + + +/* mySTL memory_arry implements auto_array + * + */ + +#ifndef mySTL_MEMORY_ARRAY_HPP +#define mySTL_MEMORY_ARRAY_HPP + + +#ifdef _MSC_VER + // disable operator-> warning for builtins + #pragma warning(disable:4284) +#endif + + +namespace mySTL { + + +template +struct auto_array_ref { + T* ptr_; + explicit auto_array_ref(T* p) : ptr_(p) {} +}; + + +template +class auto_array { + T* ptr_; + + void Destroy() + { + #ifdef YASSL_LIB + yaSSL::ysArrayDelete(ptr_); + #else + TaoCrypt::tcArrayDelete(ptr_); + #endif + } +public: + explicit auto_array(T* p = 0) : ptr_(p) {} + + ~auto_array() + { + Destroy(); + } + + + auto_array(auto_array& other) : ptr_(other.release()) {} + + auto_array& operator=(auto_array& that) + { + if (this != &that) { + Destroy(); + ptr_ = that.release(); + } + return *this; + } + + + T* operator->() const + { + return ptr_; + } + + T& operator*() const + { + return *ptr_; + } + + T* get() const + { + return ptr_; + } + + T* release() + { + T* tmp = ptr_; + ptr_ = 0; + return tmp; + } + + void reset(T* p = 0) + { + if (ptr_ != p) { + Destroy(); + ptr_ = p; + } + } + + // auto_array_ref conversions + auto_array(auto_array_ref ref) : ptr_(ref.ptr_) {} + + auto_array& operator=(auto_array_ref ref) + { + if (this->ptr_ != ref.ptr_) { + Destroy(); + ptr_ = ref.ptr_; + } + return *this; + } + + template + operator auto_array() + { + return auto_array(this->release()); + } + + template + operator auto_array_ref() + { + return auto_array_ref(this->release()); + } +}; + + +} // namespace mySTL + +#endif // mySTL_MEMORY_ARRAY_HPP diff --git a/extra/yassl/mySTL/pair.hpp b/extra/yassl/taocrypt/mySTL/pair.hpp similarity index 100% rename from extra/yassl/mySTL/pair.hpp rename to extra/yassl/taocrypt/mySTL/pair.hpp diff --git a/extra/yassl/mySTL/stdexcept.hpp b/extra/yassl/taocrypt/mySTL/stdexcept.hpp similarity index 100% rename from extra/yassl/mySTL/stdexcept.hpp rename to extra/yassl/taocrypt/mySTL/stdexcept.hpp diff --git a/extra/yassl/mySTL/vector.hpp b/extra/yassl/taocrypt/mySTL/vector.hpp similarity index 94% rename from extra/yassl/mySTL/vector.hpp rename to extra/yassl/taocrypt/mySTL/vector.hpp index 6a412447b91..902e014f75b 100644 --- a/extra/yassl/mySTL/vector.hpp +++ b/extra/yassl/taocrypt/mySTL/vector.hpp @@ -34,7 +34,6 @@ #include "helpers.hpp" // construct, destory, fill, etc. #include "algorithm.hpp" // swap #include // assert -#include // malloc namespace mySTL { @@ -49,14 +48,15 @@ struct vector_base { vector_base() : start_(0), finish_(0), end_of_storage_(0) {} vector_base(size_t n) { - // Don't allow malloc(0), if n is 0 use 1 - start_ = static_cast(malloc((n ? n : 1) * sizeof(T))); - if (!start_) abort(); + start_ = GetArrayMemory(n); finish_ = start_; end_of_storage_ = start_ + n; } - ~vector_base() { if (start_) free(start_); } + ~vector_base() + { + FreeArrayMemory(start_); + } void Swap(vector_base& that) { @@ -71,6 +71,9 @@ struct vector_base { template class vector { public: + typedef T* iterator; + typedef const T* const_iterator; + vector() {} explicit vector(size_t n) : vec_(n) { diff --git a/extra/yassl/taocrypt/src/Makefile.am b/extra/yassl/taocrypt/src/Makefile.am index 1110ed335b8..6d02a625275 100644 --- a/extra/yassl/taocrypt/src/Makefile.am +++ b/extra/yassl/taocrypt/src/Makefile.am @@ -1,4 +1,4 @@ -INCLUDES = -I../include -I../../mySTL +INCLUDES = -I../include -I../mySTL noinst_LTLIBRARIES = libtaocrypt.la @@ -11,3 +11,7 @@ libtaocrypt_la_SOURCES = aes.cpp aestables.cpp algebra.cpp arc4.cpp \ libtaocrypt_la_CXXFLAGS = @yassl_taocrypt_extra_cxxflags@ -DYASSL_PURE_C EXTRA_DIST = $(wildcard ../include/*.hpp) + +# Don't update the files from bitkeeper +%::SCCS/s.% + diff --git a/extra/yassl/taocrypt/src/algebra.cpp b/extra/yassl/taocrypt/src/algebra.cpp index e9bc3fceac0..375cd6cd524 100644 --- a/extra/yassl/taocrypt/src/algebra.cpp +++ b/extra/yassl/taocrypt/src/algebra.cpp @@ -29,7 +29,10 @@ #include "runtime.hpp" #include "algebra.hpp" -#include "vector.hpp" // mySTL::vector (simple) +#include STL_VECTOR_FILE + + +namespace STL = STL_NAMESPACE; namespace TaoCrypt { @@ -82,7 +85,7 @@ const Integer& AbstractEuclideanDomain::Mod(const Element &a, const Integer& AbstractEuclideanDomain::Gcd(const Element &a, const Element &b) const { - mySTL::vector g(3); + STL::vector g(3); g[0]= b; g[1]= a; unsigned int i0=0, i1=1, i2=2; @@ -115,7 +118,7 @@ Integer AbstractGroup::CascadeScalarMultiply(const Element &x, const unsigned w = (expLen <= 46 ? 1 : (expLen <= 260 ? 2 : 3)); const unsigned tableSize = 1< powerTable(tableSize << w); + STL::vector powerTable(tableSize << w); powerTable[1] = x; powerTable[tableSize] = y; @@ -240,8 +243,8 @@ struct WindowSlider void AbstractGroup::SimultaneousMultiply(Integer *results, const Integer &base, const Integer *expBegin, unsigned int expCount) const { - mySTL::vector > buckets(expCount); - mySTL::vector exponents; + STL::vector > buckets(expCount); + STL::vector exponents; exponents.reserve(expCount); unsigned int i; @@ -332,6 +335,8 @@ void AbstractRing::SimultaneousExponentiate(Integer *results, namespace mySTL { template TaoCrypt::WindowSlider* uninit_copy(TaoCrypt::WindowSlider*, TaoCrypt::WindowSlider*, TaoCrypt::WindowSlider*); template void destroy(TaoCrypt::WindowSlider*, TaoCrypt::WindowSlider*); +template TaoCrypt::WindowSlider* GetArrayMemory(size_t); +template void FreeArrayMemory(TaoCrypt::WindowSlider*); } #endif diff --git a/extra/yassl/taocrypt/src/asn.cpp b/extra/yassl/taocrypt/src/asn.cpp index 45fb1e60a0c..3dc3638d85f 100644 --- a/extra/yassl/taocrypt/src/asn.cpp +++ b/extra/yassl/taocrypt/src/asn.cpp @@ -38,7 +38,8 @@ #include "sha.hpp" #include "coding.hpp" #include // gmtime(); -#include "memory.hpp" // mySTL::auto_ptr +#include "memory.hpp" // some auto_ptr don't have reset, also need auto_array + namespace TaoCrypt { @@ -202,13 +203,13 @@ void PublicKey::SetKey(const byte* k) void PublicKey::AddToEnd(const byte* data, word32 len) { - mySTL::auto_ptr tmp(NEW_TC byte[sz_ + len], tcArrayDelete); + mySTL::auto_array tmp(NEW_TC byte[sz_ + len]); memcpy(tmp.get(), key_, sz_); memcpy(tmp.get() + sz_, data, len); byte* del = 0; - mySTL::swap(del, key_); + STL::swap(del, key_); tcArrayDelete(del); key_ = tmp.release(); @@ -856,7 +857,7 @@ bool CertDecoder::ValidateSignature(SignerList* signers) bool CertDecoder::ConfirmSignature(Source& pub) { HashType ht; - mySTL::auto_ptr hasher(tcDelete); + mySTL::auto_ptr hasher; if (signatureOID_ == MD5wRSA) { hasher.reset(NEW_TC MD5); diff --git a/extra/yassl/taocrypt/src/blowfish.cpp b/extra/yassl/taocrypt/src/blowfish.cpp index cc929cd7d41..40ae1a17e6c 100644 --- a/extra/yassl/taocrypt/src/blowfish.cpp +++ b/extra/yassl/taocrypt/src/blowfish.cpp @@ -133,7 +133,7 @@ void Blowfish::SetKey(const byte* key_string, word32 keylength, CipherDir dir) if (dir==DECRYPTION) for (i=0; i<(ROUNDS+2)/2; i++) - mySTL::swap(pbox_[i], pbox_[ROUNDS+1-i]); + STL::swap(pbox_[i], pbox_[ROUNDS+1-i]); } diff --git a/extra/yassl/taocrypt/src/crypto.cpp b/extra/yassl/taocrypt/src/crypto.cpp new file mode 100644 index 00000000000..95238100f5d --- /dev/null +++ b/extra/yassl/taocrypt/src/crypto.cpp @@ -0,0 +1,39 @@ +/* crypto.cpp + * + * Copyright (C) 2003 Sawtooth Consulting Ltd. + * + * This file is part of yaSSL. + * + * yaSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * There are special exceptions to the terms and conditions of the GPL as it + * is applied to yaSSL. View the full text of the exception in the file + * FLOSS-EXCEPTIONS in the directory of this software distribution. + * + * yaSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +/* put features that other apps expect from OpenSSL type crypto */ + + + +extern "C" { + + // for libcurl configure test, these are the signatures they use + // locking handled internally by library + char CRYPTO_lock() { return 0;} + char CRYPTO_add_lock() { return 0;} +} // extern "C" + + + diff --git a/extra/yassl/taocrypt/src/des.cpp b/extra/yassl/taocrypt/src/des.cpp index 054c8c2eb78..2628e142bae 100644 --- a/extra/yassl/taocrypt/src/des.cpp +++ b/extra/yassl/taocrypt/src/des.cpp @@ -34,7 +34,10 @@ #include "runtime.hpp" #include "des.hpp" -#include "algorithm.hpp" // mySTL::swap +#include STL_ALGORITHM_FILE + + +namespace STL = STL_NAMESPACE; #if defined(TAOCRYPT_X86ASM_AVAILABLE) && defined(TAO_ASM) @@ -265,8 +268,8 @@ void BasicDES::SetKey(const byte* key, word32 /*length*/, CipherDir dir) // reverse key schedule order if (dir == DECRYPTION) for (i = 0; i < 16; i += 2) { - mySTL::swap(k_[i], k_[32 - 2 - i]); - mySTL::swap(k_[i+1], k_[32 - 1 - i]); + STL::swap(k_[i], k_[32 - 2 - i]); + STL::swap(k_[i+1], k_[32 - 1 - i]); } } diff --git a/extra/yassl/taocrypt/src/dh.cpp b/extra/yassl/taocrypt/src/dh.cpp index aec7122b70b..671a20d0d78 100644 --- a/extra/yassl/taocrypt/src/dh.cpp +++ b/extra/yassl/taocrypt/src/dh.cpp @@ -61,7 +61,7 @@ void DH::GenerateKeyPair(RandomNumberGenerator& rng, byte* priv, byte* pub) // Generate private value void DH::GeneratePrivate(RandomNumberGenerator& rng, byte* priv) { - Integer x(rng, Integer::One(), mySTL::min(p_ - 1, + Integer x(rng, Integer::One(), min(p_ - 1, Integer::Power2(2*DiscreteLogWorkFactor(p_.BitCount())) ) ); x.Encode(priv, p_.ByteCount()); } diff --git a/extra/yassl/taocrypt/src/integer.cpp b/extra/yassl/taocrypt/src/integer.cpp index 823c0c5e193..500160cfe37 100644 --- a/extra/yassl/taocrypt/src/integer.cpp +++ b/extra/yassl/taocrypt/src/integer.cpp @@ -1094,7 +1094,7 @@ static bool IsP4() word32 cpuid[4]; CpuId(0, cpuid); - mySTL::swap(cpuid[2], cpuid[3]); + STL::swap(cpuid[2], cpuid[3]); if (memcmp(cpuid+1, "GenuineIntel", 12) != 0) return false; @@ -2384,8 +2384,8 @@ void AsymmetricMultiply(word *R, word *T, const word *A, unsigned int NA, if (NA > NB) { - mySTL::swap(A, B); - mySTL::swap(NA, NB); + STL::swap(A, B); + STL::swap(NA, NB); } assert(NB % NA == 0); @@ -2521,8 +2521,8 @@ unsigned int AlmostInverse(word *R, word *T, const word *A, unsigned int NA, if (Compare(f, g, fgLen)==-1) { - mySTL::swap(f, g); - mySTL::swap(b, c); + STL::swap(f, g); + STL::swap(b, c); s++; } @@ -3162,7 +3162,7 @@ signed long Integer::ConvertToLong() const void Integer::Swap(Integer& a) { reg_.Swap(a.reg_); - mySTL::swap(sign_, a.sign_); + STL::swap(sign_, a.sign_); } diff --git a/extra/yassl/taocrypt/src/md4.cpp b/extra/yassl/taocrypt/src/md4.cpp index 6012330cba3..0dee8bf40cb 100644 --- a/extra/yassl/taocrypt/src/md4.cpp +++ b/extra/yassl/taocrypt/src/md4.cpp @@ -28,9 +28,11 @@ #include "runtime.hpp" #include "md4.hpp" -#include "algorithm.hpp" // mySTL::swap +#include STL_ALGORITHM_FILE +namespace STL = STL_NAMESPACE; + namespace TaoCrypt { @@ -69,9 +71,9 @@ MD4& MD4::operator= (const MD4& that) void MD4::Swap(MD4& other) { - mySTL::swap(loLen_, other.loLen_); - mySTL::swap(hiLen_, other.hiLen_); - mySTL::swap(buffLen_, other.buffLen_); + STL::swap(loLen_, other.loLen_); + STL::swap(hiLen_, other.hiLen_); + STL::swap(buffLen_, other.buffLen_); memcpy(digest_, other.digest_, DIGEST_SIZE); memcpy(buffer_, other.buffer_, BLOCK_SIZE); diff --git a/extra/yassl/taocrypt/src/md5.cpp b/extra/yassl/taocrypt/src/md5.cpp index f7b0b1ee2dc..2bddc7fe308 100644 --- a/extra/yassl/taocrypt/src/md5.cpp +++ b/extra/yassl/taocrypt/src/md5.cpp @@ -28,7 +28,10 @@ #include "runtime.hpp" #include "md5.hpp" -#include "algorithm.hpp" // mySTL::swap +#include STL_ALGORITHM_FILE + + +namespace STL = STL_NAMESPACE; #if defined(TAOCRYPT_X86ASM_AVAILABLE) && defined(TAO_ASM) @@ -72,9 +75,9 @@ MD5& MD5::operator= (const MD5& that) void MD5::Swap(MD5& other) { - mySTL::swap(loLen_, other.loLen_); - mySTL::swap(hiLen_, other.hiLen_); - mySTL::swap(buffLen_, other.buffLen_); + STL::swap(loLen_, other.loLen_); + STL::swap(hiLen_, other.hiLen_); + STL::swap(buffLen_, other.buffLen_); memcpy(digest_, other.digest_, DIGEST_SIZE); memcpy(buffer_, other.buffer_, BLOCK_SIZE); diff --git a/extra/yassl/taocrypt/src/misc.cpp b/extra/yassl/taocrypt/src/misc.cpp index a33ca4fa432..084a263a4ae 100644 --- a/extra/yassl/taocrypt/src/misc.cpp +++ b/extra/yassl/taocrypt/src/misc.cpp @@ -29,15 +29,6 @@ #include "runtime.hpp" #include "misc.hpp" -#if !defined(YASSL_MYSQL_COMPATIBLE) -extern "C" { - - // for libcurl configure test, these are the signatures they use - // locking handled internally by library - char CRYPTO_lock() { return 0;} - char CRYPTO_add_lock() { return 0;} -} // extern "C" -#endif #ifdef YASSL_PURE_C diff --git a/extra/yassl/taocrypt/src/random.cpp b/extra/yassl/taocrypt/src/random.cpp index 2ee1e57a663..c7bb6ae9549 100644 --- a/extra/yassl/taocrypt/src/random.cpp +++ b/extra/yassl/taocrypt/src/random.cpp @@ -31,7 +31,7 @@ #include "runtime.hpp" #include "random.hpp" #include - +#include #if defined(_WIN32) #define _WIN32_WINNT 0x0400 @@ -74,6 +74,8 @@ byte RandomNumberGenerator::GenerateByte() #if defined(_WIN32) +/* The OS_Seed implementation for windows */ + OS_Seed::OS_Seed() { if(!CryptAcquireContext(&handle_, 0, 0, PROV_RSA_FULL, @@ -95,8 +97,70 @@ void OS_Seed::GenerateSeed(byte* output, word32 sz) } -#else // _WIN32 +#elif defined(__NETWARE__) +/* The OS_Seed implementation for Netware */ + +#include +#include + +// Loop on high resulution Read Time Stamp Counter +static void NetwareSeed(byte* output, word32 sz) +{ + word32 tscResult; + + for (word32 i = 0; i < sz; i += sizeof(tscResult)) { + #if defined(__GNUC__) + asm volatile("rdtsc" : "=A" (tscResult)); + #else + #ifdef __MWERKS__ + asm { + #else + __asm { + #endif + rdtsc + mov tscResult, eax + } + #endif + + memcpy(output, &tscResult, sizeof(tscResult)); + output += sizeof(tscResult); + + NXThreadYield(); // induce more variance + } +} + + +OS_Seed::OS_Seed() +{ +} + + +OS_Seed::~OS_Seed() +{ +} + + +void OS_Seed::GenerateSeed(byte* output, word32 sz) +{ + /* + Try to use NXSeedRandom as it will generate a strong + seed using the onboard 82802 chip + + As it's not always supported, fallback to default + implementation if an error is returned + */ + + if (NXSeedRandom(sz, output) != 0) + { + NetwareSeed(output, sz); + } +} + + +#else + +/* The default OS_Seed implementation */ OS_Seed::OS_Seed() { diff --git a/extra/yassl/taocrypt/src/ripemd.cpp b/extra/yassl/taocrypt/src/ripemd.cpp index c791189544f..03c09edde84 100644 --- a/extra/yassl/taocrypt/src/ripemd.cpp +++ b/extra/yassl/taocrypt/src/ripemd.cpp @@ -28,9 +28,11 @@ #include "runtime.hpp" #include "ripemd.hpp" -#include "algorithm.hpp" // mySTL::swap +#include STL_ALGORITHM_FILE +namespace STL = STL_NAMESPACE; + #if defined(TAOCRYPT_X86ASM_AVAILABLE) && defined(TAO_ASM) #define DO_RIPEMD_ASM @@ -75,9 +77,9 @@ RIPEMD160& RIPEMD160::operator= (const RIPEMD160& that) void RIPEMD160::Swap(RIPEMD160& other) { - mySTL::swap(loLen_, other.loLen_); - mySTL::swap(hiLen_, other.hiLen_); - mySTL::swap(buffLen_, other.buffLen_); + STL::swap(loLen_, other.loLen_); + STL::swap(hiLen_, other.hiLen_); + STL::swap(buffLen_, other.buffLen_); memcpy(digest_, other.digest_, DIGEST_SIZE); memcpy(buffer_, other.buffer_, BLOCK_SIZE); diff --git a/extra/yassl/taocrypt/src/sha.cpp b/extra/yassl/taocrypt/src/sha.cpp index b877e2b7857..280d42fb3d4 100644 --- a/extra/yassl/taocrypt/src/sha.cpp +++ b/extra/yassl/taocrypt/src/sha.cpp @@ -27,8 +27,11 @@ #include "runtime.hpp" #include -#include "algorithm.hpp" // mySTL::swap #include "sha.hpp" +#include STL_ALGORITHM_FILE + + +namespace STL = STL_NAMESPACE; #if defined(TAOCRYPT_X86ASM_AVAILABLE) && defined(TAO_ASM) @@ -96,9 +99,9 @@ SHA& SHA::operator= (const SHA& that) void SHA::Swap(SHA& other) { - mySTL::swap(loLen_, other.loLen_); - mySTL::swap(hiLen_, other.hiLen_); - mySTL::swap(buffLen_, other.buffLen_); + STL::swap(loLen_, other.loLen_); + STL::swap(hiLen_, other.hiLen_); + STL::swap(buffLen_, other.buffLen_); memcpy(digest_, other.digest_, DIGEST_SIZE); memcpy(buffer_, other.buffer_, BLOCK_SIZE); diff --git a/extra/yassl/taocrypt/src/template_instnt.cpp b/extra/yassl/taocrypt/src/template_instnt.cpp index 512c5cf9dce..db1ae645e09 100644 --- a/extra/yassl/taocrypt/src/template_instnt.cpp +++ b/extra/yassl/taocrypt/src/template_instnt.cpp @@ -77,6 +77,13 @@ template void destroy*>(vector*, ve template TaoCrypt::Integer* uninit_copy(TaoCrypt::Integer*, TaoCrypt::Integer*, TaoCrypt::Integer*); template TaoCrypt::Integer* uninit_fill_n(TaoCrypt::Integer*, size_t, TaoCrypt::Integer const&); template void destroy(TaoCrypt::Integer*, TaoCrypt::Integer*); +template TaoCrypt::byte* GetArrayMemory(size_t); +template void FreeArrayMemory(TaoCrypt::byte*); +template TaoCrypt::Integer* GetArrayMemory(size_t); +template void FreeArrayMemory(TaoCrypt::Integer*); +template vector* GetArrayMemory >(size_t); +template void FreeArrayMemory >(vector*); +template void FreeArrayMemory(void*); } #endif diff --git a/extra/yassl/taocrypt/test/Makefile.am b/extra/yassl/taocrypt/test/Makefile.am index 0b238f1e057..988d00c7bef 100644 --- a/extra/yassl/taocrypt/test/Makefile.am +++ b/extra/yassl/taocrypt/test/Makefile.am @@ -1,8 +1,6 @@ -INCLUDES = -I../include -I../../mySTL +INCLUDES = -I../include -I../mySTL bin_PROGRAMS = test test_SOURCES = test.cpp -test_LDFLAGS = -L../src -test_LDADD = -ltaocrypt -test_DEPENDENCIES = ../src/libtaocrypt.la +test_LDADD = $(top_builddir)/extra/yassl/taocrypt/src/libtaocrypt.la test_CXXFLAGS = -DYASSL_PURE_C EXTRA_DIST = make.bat diff --git a/extra/yassl/testsuite/Makefile.am b/extra/yassl/testsuite/Makefile.am index 2ae46a1b409..e8abffd6bb0 100644 --- a/extra/yassl/testsuite/Makefile.am +++ b/extra/yassl/testsuite/Makefile.am @@ -1,11 +1,14 @@ -INCLUDES = -I../include -I../taocrypt/include -I../mySTL +INCLUDES = -I../include -I../taocrypt/include -I../taocrypt/mySTL bin_PROGRAMS = testsuite testsuite_SOURCES = testsuite.cpp ../taocrypt/test/test.cpp \ ../examples/client/client.cpp ../examples/server/server.cpp \ ../examples/echoclient/echoclient.cpp \ ../examples/echoserver/echoserver.cpp -testsuite_LDFLAGS = -L../src/ -L../taocrypt/src testsuite_CXXFLAGS = -DYASSL_PURE_C -DYASSL_PREFIX -DNO_MAIN_DRIVER -testsuite_LDADD = -lyassl -ltaocrypt -testsuite_DEPENDENCIES = ../src/libyassl.la ../taocrypt/src/libtaocrypt.la +testsuite_LDADD = $(top_builddir)/extra/yassl/src/libyassl.la \ + $(top_builddir)/extra/yassl/taocrypt/src/libtaocrypt.la EXTRA_DIST = testsuite.dsp test.hpp input quit make.bat + +# Don't update the files from bitkeeper +%::SCCS/s.% + diff --git a/extra/yassl/testsuite/test.hpp b/extra/yassl/testsuite/test.hpp index c80e3ad23da..0266c802657 100644 --- a/extra/yassl/testsuite/test.hpp +++ b/extra/yassl/testsuite/test.hpp @@ -27,22 +27,25 @@ #endif /* _WIN32 */ -#if !defined(_SOCKLEN_T) && (defined(__MACH__) || defined(_WIN32)) +#if !defined(_SOCKLEN_T) && (defined(_WIN32) || defined(__NETWARE__)) typedef int socklen_t; #endif +// Check type of third arg to accept +#if defined(__hpux) // HPUX doesn't use socklent_t for third parameter to accept -#if !defined(__hpux) - typedef socklen_t* ACCEPT_THIRD_T; -#else typedef int* ACCEPT_THIRD_T; - -// HPUX does not define _POSIX_THREADS as it's not _fully_ implemented -#ifndef _POSIX_THREADS -#define _POSIX_THREADS +#else + typedef socklen_t* ACCEPT_THIRD_T; #endif + +// Check if _POSIX_THREADS should be forced +#if !defined(_POSIX_THREADS) && (defined(__NETWARE__) || defined(__hpux)) +// HPUX does not define _POSIX_THREADS as it's not _fully_ implemented +// Netware supports pthreads but does not announce it +#define _POSIX_THREADS #endif @@ -148,6 +151,13 @@ inline void err_sys(const char* msg) } +static int PasswordCallBack(char* passwd, int sz, int rw, void* userdata) +{ + strncpy(passwd, "12345678", sz); + return 8; +} + + inline void store_ca(SSL_CTX* ctx) { // To allow testing from serveral dirs @@ -168,6 +178,7 @@ inline void store_ca(SSL_CTX* ctx) inline void set_certs(SSL_CTX* ctx) { store_ca(ctx); + SSL_CTX_set_default_passwd_cb(ctx, PasswordCallBack); // To allow testing from serveral dirs if (SSL_CTX_use_certificate_file(ctx, cert, SSL_FILETYPE_PEM) @@ -193,6 +204,7 @@ inline void set_certs(SSL_CTX* ctx) inline void set_serverCerts(SSL_CTX* ctx) { store_ca(ctx); + SSL_CTX_set_default_passwd_cb(ctx, PasswordCallBack); // To allow testing from serveral dirs if (SSL_CTX_use_certificate_file(ctx, svrCert, SSL_FILETYPE_PEM) @@ -258,13 +270,27 @@ inline void tcp_socket(SOCKET_T& sockfd, sockaddr_in& addr) } +inline void tcp_close(SOCKET_T& sockfd) +{ +#ifdef _WIN32 + closesocket(sockfd); +#else + close(sockfd); +#endif + sockfd = -1; +} + + inline void tcp_connect(SOCKET_T& sockfd) { sockaddr_in addr; tcp_socket(sockfd, addr); if (connect(sockfd, (const sockaddr*)&addr, sizeof(addr)) != 0) + { + tcp_close(sockfd); err_sys("tcp connect failed"); + } } @@ -274,13 +300,19 @@ inline void tcp_listen(SOCKET_T& sockfd) tcp_socket(sockfd, addr); if (bind(sockfd, (const sockaddr*)&addr, sizeof(addr)) != 0) + { + tcp_close(sockfd); err_sys("tcp bind failed"); + } if (listen(sockfd, 3) != 0) + { + tcp_close(sockfd); err_sys("tcp listen failed"); + } } -inline void tcp_accept(SOCKET_T& sockfd, int& clientfd, func_args& args) +inline void tcp_accept(SOCKET_T& sockfd, SOCKET_T& clientfd, func_args& args) { tcp_listen(sockfd); @@ -299,7 +331,10 @@ inline void tcp_accept(SOCKET_T& sockfd, int& clientfd, func_args& args) clientfd = accept(sockfd, (sockaddr*)&client, (ACCEPT_THIRD_T)&client_len); if (clientfd == -1) + { + tcp_close(sockfd); err_sys("tcp accept failed"); + } } diff --git a/include/m_ctype.h b/include/m_ctype.h index 54ae41bf2e0..0f5263e1c51 100644 --- a/include/m_ctype.h +++ b/include/m_ctype.h @@ -184,7 +184,7 @@ typedef struct my_charset_handler_st /* Charset dependant snprintf() */ int (*snprintf)(struct charset_info_st *, char *to, uint n, const char *fmt, - ...); + ...) ATTRIBUTE_FORMAT_FPTR(printf, 4, 5); int (*long10_to_str)(struct charset_info_st *, char *to, uint n, int radix, long int val); int (*longlong10_to_str)(struct charset_info_st *, char *to, uint n, @@ -205,6 +205,9 @@ typedef struct my_charset_handler_st int *err); longlong (*strtoll10)(struct charset_info_st *cs, const char *nptr, char **endptr, int *error); + ulonglong (*strntoull10rnd)(struct charset_info_st *cs, + const char *str, uint length, int unsigned_fl, + char **endptr, int *error); ulong (*scan)(struct charset_info_st *, const char *b, const char *e, int sq); } MY_CHARSET_HANDLER; @@ -319,7 +322,8 @@ int my_wc_mb_8bit(CHARSET_INFO *cs,my_wc_t wc, uchar *s, uchar *e); ulong my_scan_8bit(CHARSET_INFO *cs, const char *b, const char *e, int sq); int my_snprintf_8bit(struct charset_info_st *, char *to, uint n, - const char *fmt, ...); + const char *fmt, ...) + ATTRIBUTE_FORMAT(printf, 4, 5); long my_strntol_8bit(CHARSET_INFO *, const char *s, uint l, int base, char **e, int *err); @@ -341,6 +345,13 @@ longlong my_strtoll10_8bit(CHARSET_INFO *cs, longlong my_strtoll10_ucs2(CHARSET_INFO *cs, const char *nptr, char **endptr, int *error); +ulonglong my_strntoull10rnd_8bit(CHARSET_INFO *cs, + const char *str, uint length, int unsigned_fl, + char **endptr, int *error); +ulonglong my_strntoull10rnd_ucs2(CHARSET_INFO *cs, + const char *str, uint length, int unsigned_fl, + char **endptr, int *error); + void my_fill_8bit(CHARSET_INFO *cs, char* to, uint l, int fill); my_bool my_like_range_simple(CHARSET_INFO *cs, diff --git a/include/m_string.h b/include/m_string.h index c02ce92cd88..8a526d70d1d 100644 --- a/include/m_string.h +++ b/include/m_string.h @@ -254,7 +254,8 @@ extern ulonglong strtoull(const char *str, char **ptr, int base); extern int my_vsnprintf( char *str, size_t n, const char *format, va_list ap ); -extern int my_snprintf(char* to, size_t n, const char* fmt, ...); +extern int my_snprintf(char *to, size_t n, const char *fmt, ...) + ATTRIBUTE_FORMAT(printf, 3, 4); #if defined(__cplusplus) && !defined(OS2) } diff --git a/include/my_base.h b/include/my_base.h index d8a0e15ccbe..cffe1c3caf4 100644 --- a/include/my_base.h +++ b/include/my_base.h @@ -357,8 +357,10 @@ enum ha_base_keytype { #define HA_ERR_TABLE_DEF_CHANGED 159 /* The table changed in storage engine */ #define HA_ERR_TABLE_NEEDS_UPGRADE 160 /* The table changed in storage engine */ #define HA_ERR_TABLE_READONLY 161 /* The table is not writable */ +#define HA_ERR_AUTOINC_READ_FAILED 162/* Failed to get the next autoinc value */ +#define HA_ERR_AUTOINC_ERANGE 163 /* Failed to set the row autoinc value */ -#define HA_ERR_LAST 161 /*Copy last error nr.*/ +#define HA_ERR_LAST 163 /*Copy last error nr.*/ /* Add error numbers before HA_ERR_LAST and change it accordingly. */ #define HA_ERR_ERRORS (HA_ERR_LAST - HA_ERR_FIRST + 1) diff --git a/include/my_global.h b/include/my_global.h index 909755aef87..f94cedbc91a 100644 --- a/include/my_global.h +++ b/include/my_global.h @@ -111,7 +111,7 @@ /* Fix problem with S_ISLNK() on Linux */ -#if defined(TARGET_OS_LINUX) +#if defined(TARGET_OS_LINUX) || defined(__GLIBC__) #undef _GNU_SOURCE #define _GNU_SOURCE 1 #endif @@ -454,12 +454,50 @@ typedef unsigned short ushort; #define function_volatile volatile #define my_reinterpret_cast(A) reinterpret_cast #define my_const_cast(A) const_cast +# ifndef GCC_VERSION +# define GCC_VERSION (__GNUC__ * 1000 + __GNUC_MINOR__) +# endif #elif !defined(my_reinterpret_cast) #define my_reinterpret_cast(A) (A) #define my_const_cast(A) (A) #endif -#if !defined(__attribute__) && (defined(__cplusplus) || !defined(__GNUC__) || __GNUC__ == 2 && __GNUC_MINOR__ < 8) -#define __attribute__(A) + +/* + Disable __attribute__() on gcc < 2.7, g++ < 3.4, and non-gcc compilers. + Some forms of __attribute__ are actually supported in earlier versions of + g++, but we just disable them all because we only use them to generate + compilation warnings. +*/ +#ifndef __attribute__ +# if !defined(__GNUC__) +# define __attribute__(A) +# elif GCC_VERSION < 2008 +# define __attribute__(A) +# elif defined(__cplusplus) && GCC_VERSION < 3004 +# define __attribute__(A) +# endif +#endif + +/* + __attribute__((format(...))) is only supported in gcc >= 2.8 and g++ >= 3.4 + But that's already covered by the __attribute__ tests above, so this is + just a convenience macro. +*/ +#ifndef ATTRIBUTE_FORMAT +# define ATTRIBUTE_FORMAT(style, m, n) __attribute__((format(style, m, n))) +#endif + +/* + + __attribute__((format(...))) on a function pointer is not supported + until gcc 3.1 +*/ +#ifndef ATTRIBUTE_FORMAT_FPTR +# if (GCC_VERSION >= 3001) +# define ATTRIBUTE_FORMAT_FPTR(style, m, n) ATTRIBUTE_FORMAT(style, m, n) +# else +# define ATTRIBUTE_FORMAT_FPTR(style, m, n) +# endif /* GNUC >= 3.1 */ #endif /* diff --git a/include/my_net.h b/include/my_net.h index 71914964e46..43360b6153c 100644 --- a/include/my_net.h +++ b/include/my_net.h @@ -61,6 +61,14 @@ C_MODE_START #if defined(MSDOS) || defined(__WIN__) #define O_NONBLOCK 1 /* For emulation of fcntl() */ + +/* + SHUT_RDWR is called SD_BOTH in windows and + is defined to 2 in winsock2.h + #define SD_BOTH 0x02 +*/ +#define SHUT_RDWR 0x02 + #endif /* diff --git a/include/my_sys.h b/include/my_sys.h index 9b283ace029..2c0ef955477 100644 --- a/include/my_sys.h +++ b/include/my_sys.h @@ -632,8 +632,8 @@ extern int my_chsize(File fd,my_off_t newlength, int filler, myf MyFlags); extern int my_sync(File fd, myf my_flags); extern int my_error _VARARGS((int nr,myf MyFlags, ...)); extern int my_printf_error _VARARGS((uint my_err, const char *format, - myf MyFlags, ...) - __attribute__ ((format (printf, 2, 4)))); + myf MyFlags, ...)) + ATTRIBUTE_FORMAT(printf, 2, 4); extern int my_error_register(const char **errmsgs, int first, int last); extern const char **my_error_unregister(int first, int last); extern int my_message(uint my_err, const char *str,myf MyFlags); diff --git a/include/mysql_com.h b/include/mysql_com.h index 4c7640376a6..1bbb3cf1737 100644 --- a/include/mysql_com.h +++ b/include/mysql_com.h @@ -134,11 +134,11 @@ enum enum_server_command #define CLIENT_TRANSACTIONS 8192 /* Client knows about transactions */ #define CLIENT_RESERVED 16384 /* Old flag for 4.1 protocol */ #define CLIENT_SECURE_CONNECTION 32768 /* New 4.1 authentication */ -#define CLIENT_MULTI_STATEMENTS (((ulong) 1) << 16) /* Enable/disable multi-stmt support */ -#define CLIENT_MULTI_RESULTS (((ulong) 1) << 17) /* Enable/disable multi-results */ +#define CLIENT_MULTI_STATEMENTS (1UL << 16) /* Enable/disable multi-stmt support */ +#define CLIENT_MULTI_RESULTS (1UL << 17) /* Enable/disable multi-results */ -#define CLIENT_SSL_VERIFY_SERVER_CERT (((ulong) 1) << 30) -#define CLIENT_REMEMBER_OPTIONS (((ulong) 1) << 31) +#define CLIENT_SSL_VERIFY_SERVER_CERT (1UL << 30) +#define CLIENT_REMEMBER_OPTIONS (1UL << 31) #define SERVER_STATUS_IN_TRANS 1 /* Transaction has started */ #define SERVER_STATUS_AUTOCOMMIT 2 /* Server in auto_commit mode */ diff --git a/innobase/ibuf/ibuf0ibuf.c b/innobase/ibuf/ibuf0ibuf.c index 9c7d9c5c3da..eb10a88d1d1 100644 --- a/innobase/ibuf/ibuf0ibuf.c +++ b/innobase/ibuf/ibuf0ibuf.c @@ -1361,8 +1361,8 @@ ibuf_entry_build( index tree; NOTE that the original entry must be kept because we copy pointers to its fields */ + dict_index_t* index, /* in: non-clustered index */ dtuple_t* entry, /* in: entry for a non-clustered index */ - ibool comp, /* in: flag: TRUE=compact record format */ ulint space, /* in: space id */ ulint page_no,/* in: index page number where entry should be inserted */ @@ -1426,13 +1426,13 @@ ibuf_entry_build( dfield_set_data(field, buf, 4); - ut_ad(comp == 0 || comp == 1); + ut_ad(index->table->comp <= 1); /* Store the type info in buf2, and add the fields from entry to tuple */ buf2 = mem_heap_alloc(heap, n_fields * DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE - + comp); - if (comp) { + + index->table->comp); + if (index->table->comp) { *buf2++ = 0; /* write the compact format indicator */ } for (i = 0; i < n_fields; i++) { @@ -1445,20 +1445,22 @@ ibuf_entry_build( dtype_new_store_for_order_and_null_size( buf2 + i * DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE, - dfield_get_type(entry_field)); + dfield_get_type(entry_field), + dict_index_get_nth_field(index, i) + ->prefix_len); } /* Store the type info in buf2 to field 3 of tuple */ field = dtuple_get_nth_field(tuple, 3); - if (comp) { + if (index->table->comp) { buf2--; } dfield_set_data(field, buf2, n_fields * DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE - + comp); + + index->table->comp); /* Set all the types in the new tuple binary */ dtuple_set_types_binary(tuple, n_fields + 4); @@ -2589,8 +2591,7 @@ ibuf_insert_low( the first fields and the type information for other fields, and which will be inserted to the insert buffer. */ - ibuf_entry = ibuf_entry_build(entry, index->table->comp, - space, page_no, heap); + ibuf_entry = ibuf_entry_build(index, entry, space, page_no, heap); /* Open a cursor to the insert buffer tree to calculate if we can add the new entry to it without exceeding the free space limit for the diff --git a/innobase/include/data0type.h b/innobase/include/data0type.h index 30c0f732c34..abfbc24e336 100644 --- a/innobase/include/data0type.h +++ b/innobase/include/data0type.h @@ -366,7 +366,9 @@ dtype_new_store_for_order_and_null_size( byte* buf, /* in: buffer for DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE bytes where we store the info */ - dtype_t* type); /* in: type struct */ + dtype_t* type, /* in: type struct */ + ulint prefix_len);/* in: prefix length to + replace type->len, or 0 */ /************************************************************************** Reads to a type the stored information which determines its alphabetical ordering and the storage size of an SQL NULL value. This is the 4.1.x storage diff --git a/innobase/include/data0type.ic b/innobase/include/data0type.ic index ad0f02fa63d..032c1d7efd7 100644 --- a/innobase/include/data0type.ic +++ b/innobase/include/data0type.ic @@ -230,11 +230,14 @@ dtype_new_store_for_order_and_null_size( byte* buf, /* in: buffer for DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE bytes where we store the info */ - dtype_t* type) /* in: type struct */ + dtype_t* type, /* in: type struct */ + ulint prefix_len)/* in: prefix length to + replace type->len, or 0 */ { #if 6 != DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE #error "6 != DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE" #endif + ulint len; buf[0] = (byte)(type->mtype & 0xFFUL); @@ -249,7 +252,9 @@ dtype_new_store_for_order_and_null_size( buf[1] = (byte)(type->prtype & 0xFFUL); - mach_write_to_2(buf + 2, type->len & 0xFFFFUL); + len = prefix_len ? prefix_len : type->len; + + mach_write_to_2(buf + 2, len & 0xFFFFUL); ut_ad(dtype_get_charset_coll(type->prtype) < 256); mach_write_to_2(buf + 4, dtype_get_charset_coll(type->prtype)); diff --git a/innobase/include/univ.i b/innobase/include/univ.i index bc3bd031f0c..64a240ae8a7 100644 --- a/innobase/include/univ.i +++ b/innobase/include/univ.i @@ -39,8 +39,10 @@ if we are compiling on Windows. */ #undef PACKAGE #undef VERSION +#if !defined(__WIN__) && !defined(WIN64) && !defined(_WIN64) /* Include the header file generated by GNU autoconf */ #include "../ib_config.h" +#endif #ifdef HAVE_SCHED_H #include diff --git a/innobase/srv/srv0start.c b/innobase/srv/srv0start.c index 6e0dc720bf8..8530f117c9d 100644 --- a/innobase/srv/srv0start.c +++ b/innobase/srv/srv0start.c @@ -1140,7 +1140,7 @@ innobase_start_or_create_for_mysql(void) maximum number of threads that can wait in the 'srv_conc array' for their time to enter InnoDB. */ -#if defined(__WIN__) || defined(__NETWARE__) +#if defined(__NETWARE__) /* Create less event semaphores because Win 98/ME had difficulty creating 40000 event semaphores. diff --git a/myisam/mi_check.c b/myisam/mi_check.c index a3195ebce7f..5a81d221d2a 100644 --- a/myisam/mi_check.c +++ b/myisam/mi_check.c @@ -1370,7 +1370,8 @@ int mi_repair(MI_CHECK *param, register MI_INFO *info, param->temp_filename); goto err; } - if (filecopy(param,new_file,info->dfile,0L,new_header_length, + if (new_header_length && + filecopy(param,new_file,info->dfile,0L,new_header_length, "datafile-header")) goto err; info->s->state.dellink= HA_OFFSET_ERROR; @@ -2072,7 +2073,8 @@ int mi_repair_by_sort(MI_CHECK *param, register MI_INFO *info, param->temp_filename); goto err; } - if (filecopy(param, new_file,info->dfile,0L,new_header_length, + if (new_header_length && + filecopy(param, new_file,info->dfile,0L,new_header_length, "datafile-header")) goto err; if (param->testflag & T_UNPACK) @@ -2440,7 +2442,8 @@ int mi_repair_parallel(MI_CHECK *param, register MI_INFO *info, param->temp_filename); goto err; } - if (filecopy(param, new_file,info->dfile,0L,new_header_length, + if (new_header_length && + filecopy(param, new_file,info->dfile,0L,new_header_length, "datafile-header")) goto err; if (param->testflag & T_UNPACK) diff --git a/myisam/mi_delete.c b/myisam/mi_delete.c index 2bc99d65dd2..85cc60bdd9d 100644 --- a/myisam/mi_delete.c +++ b/myisam/mi_delete.c @@ -446,7 +446,7 @@ static int del(register MI_INFO *info, register MI_KEYDEF *keyinfo, uchar *key, else { DBUG_PRINT("test",("Inserting of key when deleting")); - if (_mi_get_last_key(info,keyinfo,leaf_buff,keybuff,endpos, + if (!_mi_get_last_key(info,keyinfo,leaf_buff,keybuff,endpos, &tmp)) goto err; ret_value=_mi_insert(info,keyinfo,key,leaf_buff,endpos,keybuff, diff --git a/myisam/mi_locking.c b/myisam/mi_locking.c index 8d48c5242e5..36b793363c5 100644 --- a/myisam/mi_locking.c +++ b/myisam/mi_locking.c @@ -224,6 +224,21 @@ int mi_lock_database(MI_INFO *info, int lock_type) break; /* Impossible */ } } +#ifdef __WIN__ + else + { + /* + Check for bad file descriptors if this table is part + of a merge union. Failing to capture this may cause + a crash on windows if the table is renamed and + later on referenced by the merge table. + */ + if( info->owned_by_merge && (info->s)->kfile < 0 ) + { + error = HA_ERR_NO_SUCH_TABLE; + } + } +#endif pthread_mutex_unlock(&share->intern_lock); #if defined(FULL_LOG) || defined(_lint) lock_type|=(int) (flag << 8); /* Set bit to set if real lock */ diff --git a/myisam/mi_packrec.c b/myisam/mi_packrec.c index 41ab71204c4..c9653eadc28 100644 --- a/myisam/mi_packrec.c +++ b/myisam/mi_packrec.c @@ -16,7 +16,7 @@ /* Functions to compressed records */ -#include "myisamdef.h" +#include "fulltext.h" #define IS_CHAR ((uint) 32768) /* Bit if char (not offset) in tree */ @@ -230,11 +230,19 @@ my_bool _mi_read_pack_info(MI_INFO *info, pbool fix_keys) { for (i=0 ; i < share->base.keys ; i++) { - share->keyinfo[i].keylength+=(uint16) diff_length; - share->keyinfo[i].minlength+=(uint16) diff_length; - share->keyinfo[i].maxlength+=(uint16) diff_length; - share->keyinfo[i].seg[share->keyinfo[i].keysegs].length= - (uint16) rec_reflength; + MI_KEYDEF *keyinfo= &share->keyinfo[i]; + keyinfo->keylength+= (uint16) diff_length; + keyinfo->minlength+= (uint16) diff_length; + keyinfo->maxlength+= (uint16) diff_length; + keyinfo->seg[keyinfo->flag & HA_FULLTEXT ? + FT_SEGS : keyinfo->keysegs].length= (uint16) rec_reflength; + } + if (share->ft2_keyinfo.seg) + { + MI_KEYDEF *ft2_keyinfo= &share->ft2_keyinfo; + ft2_keyinfo->keylength+= (uint16) diff_length; + ft2_keyinfo->minlength+= (uint16) diff_length; + ft2_keyinfo->maxlength+= (uint16) diff_length; } } diff --git a/myisam/mi_rkey.c b/myisam/mi_rkey.c index a9a8cbacb4b..43be34f6ebb 100644 --- a/myisam/mi_rkey.c +++ b/myisam/mi_rkey.c @@ -94,32 +94,45 @@ int mi_rkey(MI_INFO *info, byte *buf, int inx, const byte *key, uint key_len, myisam_read_vec[search_flag], info->s->state.key_root[inx])) { /* - If we are searching for an exact key (including the data pointer) - and this was added by an concurrent insert, - then the result is "key not found". + If we searching for a partial key (or using >, >=, < or <=) and + the data is outside of the data file, we need to continue searching + for the first key inside the data file */ - if ((search_flag == HA_READ_KEY_EXACT) && - (info->lastpos >= info->state->data_file_length)) + if (info->lastpos >= info->state->data_file_length && + (search_flag != HA_READ_KEY_EXACT || + last_used_keyseg != keyinfo->seg + keyinfo->keysegs)) { - my_errno= HA_ERR_KEY_NOT_FOUND; - info->lastpos= HA_OFFSET_ERROR; - } - else while (info->lastpos >= info->state->data_file_length) - { - /* - Skip rows that are inserted by other threads since we got a lock - Note that this can only happen if we are not searching after an - exact key, because the keys are sorted according to position - */ - if (_mi_search_next(info, keyinfo, info->lastkey, - info->lastkey_length, - myisam_readnext_vec[search_flag], - info->s->state.key_root[inx])) - break; + do + { + uint not_used[2]; + /* + Skip rows that are inserted by other threads since we got a lock + Note that this can only happen if we are not searching after an + full length exact key, because the keys are sorted + according to position + */ + if (_mi_search_next(info, keyinfo, info->lastkey, + info->lastkey_length, + myisam_readnext_vec[search_flag], + info->s->state.key_root[inx])) + break; + /* + Check that the found key does still match the search. + _mi_search_next() delivers the next key regardless of its + value. + */ + if (search_flag == HA_READ_KEY_EXACT && + ha_key_cmp(keyinfo->seg, key_buff, info->lastkey, use_key_length, + SEARCH_FIND, not_used)) + { + my_errno= HA_ERR_KEY_NOT_FOUND; + info->lastpos= HA_OFFSET_ERROR; + break; + } + } while (info->lastpos >= info->state->data_file_length); } } } - if (share->concurrent_insert) rw_unlock(&share->key_root_lock[inx]); diff --git a/myisam/mi_test_all.res b/myisam/mi_test_all.res index 16b517d3f76..4a22809b45f 100644 --- a/myisam/mi_test_all.res +++ b/myisam/mi_test_all.res @@ -8,46 +8,46 @@ myisamchk: MyISAM file test2 myisamchk: warning: Datafile is almost full, 65532 of 65534 used MyISAM-table 'test2' is usable but should be fixed Commands Used count Errors Recover errors -open 1 0 0 -write 50 0 0 -update 5 0 0 -delete 50 0 0 -close 1 0 0 -extra 6 0 0 -Total 113 0 0 +open 7 0 0 +write 350 0 0 +update 35 0 0 +delete 350 0 0 +close 7 0 0 +extra 42 0 0 +Total 791 0 0 Commands Used count Errors Recover errors -open 2 0 0 -write 100 0 0 -update 10 0 0 -delete 100 0 0 -close 2 0 0 -extra 12 0 0 -Total 226 0 0 +open 8 0 0 +write 400 0 0 +update 40 0 0 +delete 400 0 0 +close 8 0 0 +extra 48 0 0 +Total 904 0 0 -real 0m0.791s -user 0m0.137s -sys 0m0.117s +real 0m0.221s +user 0m0.120s +sys 0m0.100s -real 0m0.659s -user 0m0.252s -sys 0m0.102s +real 0m0.222s +user 0m0.140s +sys 0m0.084s -real 0m0.571s -user 0m0.188s -sys 0m0.098s +real 0m0.232s +user 0m0.112s +sys 0m0.120s -real 0m1.111s -user 0m0.236s -sys 0m0.037s +real 0m0.163s +user 0m0.116s +sys 0m0.036s -real 0m0.621s -user 0m0.242s -sys 0m0.022s +real 0m0.159s +user 0m0.136s +sys 0m0.020s -real 0m0.698s -user 0m0.248s -sys 0m0.021s +real 0m0.147s +user 0m0.132s +sys 0m0.016s -real 0m0.683s -user 0m0.265s -sys 0m0.079s +real 0m0.211s +user 0m0.124s +sys 0m0.088s diff --git a/myisam/mi_test_all.sh b/myisam/mi_test_all.sh index 07e71d65675..c1fb12d7c3b 100755 --- a/myisam/mi_test_all.sh +++ b/myisam/mi_test_all.sh @@ -79,7 +79,8 @@ myisamchk$suffix -se test1 # check of myisampack / myisamchk myisampack$suffix --force -s test1 -myisamchk$suffix -es test1 +# Ignore error for index file +myisamchk$suffix -es test1 2>&1 >& /dev/null myisamchk$suffix -rqs test1 myisamchk$suffix -es test1 myisamchk$suffix -rs test1 diff --git a/myisam/myisam_ftdump.c b/myisam/myisam_ftdump.c index 809d7bcca89..2be95d11714 100644 --- a/myisam/myisam_ftdump.c +++ b/myisam/myisam_ftdump.c @@ -126,7 +126,6 @@ int main(int argc,char *argv[]) if (count || stats) { - doc_cnt++; if (strcmp(buf, buf2)) { if (*buf2) @@ -151,6 +150,7 @@ int main(int argc,char *argv[]) keylen2=keylen; doc_cnt=0; } + doc_cnt+= (subkeys >= 0 ? 1 : -subkeys); } if (dump) { @@ -166,7 +166,6 @@ int main(int argc,char *argv[]) if (count || stats) { - doc_cnt++; if (*buf2) { uniq++; diff --git a/myisam/myisamdef.h b/myisam/myisamdef.h index d589173f0e7..ea45915a088 100644 --- a/myisam/myisamdef.h +++ b/myisam/myisamdef.h @@ -278,6 +278,9 @@ struct st_myisam_info { my_bool page_changed; /* If info->buff can't be used for rnext */ my_bool buff_used; /* If info->buff has to be reread for rnext */ my_bool once_flags; /* For MYISAMMRG */ +#ifdef __WIN__ + my_bool owned_by_merge; /* This MyISAM table is part of a merge union */ +#endif #ifdef THREAD THR_LOCK_DATA lock; #endif diff --git a/myisammrg/myrg_locking.c b/myisammrg/myrg_locking.c index e5a8d3f3d9d..98e8305b9ce 100644 --- a/myisammrg/myrg_locking.c +++ b/myisammrg/myrg_locking.c @@ -26,8 +26,19 @@ int myrg_lock_database(MYRG_INFO *info, int lock_type) MYRG_TABLE *file; error=0; - for (file=info->open_tables ; file != info->end_table ; file++) + for (file=info->open_tables ; file != info->end_table ; file++) + { +#ifdef __WIN__ + /* + Make sure this table is marked as owned by a merge table. + The semaphore is never released as long as table remains + in memory. This should be refactored into a more generic + approach (observer pattern) + */ + (file->table)->owned_by_merge = TRUE; +#endif if ((new_error=mi_lock_database(file->table,lock_type))) error=new_error; + } return(error); } diff --git a/myisammrg/myrg_open.c b/myisammrg/myrg_open.c index f9cdc2bb205..af10f0da90b 100644 --- a/myisammrg/myrg_open.c +++ b/myisammrg/myrg_open.c @@ -33,7 +33,7 @@ MYRG_INFO *myrg_open(const char *name, int mode, int handle_locking) { int save_errno,errpos=0; - uint files=0,i,dir_length,length,key_parts; + uint files= 0, i, dir_length, length, key_parts, min_keys= 0; ulonglong file_offset=0; char name_buff[FN_REFLEN*2],buff[FN_REFLEN],*end; MYRG_INFO *m_info=0; @@ -89,7 +89,10 @@ MYRG_INFO *myrg_open(const char *name, int mode, int handle_locking) else fn_format(buff, buff, "", "", 0); if (!(isam=mi_open(buff,mode,(handle_locking?HA_OPEN_WAIT_IF_LOCKED:0)))) + { + my_errno= HA_ERR_WRONG_MRG_TABLE_DEF; goto err; + } if (!m_info) /* First file */ { key_parts=isam->s->base.key_parts; @@ -106,6 +109,7 @@ MYRG_INFO *myrg_open(const char *name, int mode, int handle_locking) files= 0; } m_info->reclength=isam->s->base.reclength; + min_keys= isam->s->base.keys; errpos=3; } m_info->open_tables[files].table= isam; @@ -121,6 +125,8 @@ MYRG_INFO *myrg_open(const char *name, int mode, int handle_locking) m_info->records+= isam->state->records; m_info->del+= isam->state->del; m_info->data_file_length+= isam->state->data_file_length; + if (min_keys > isam->s->base.keys) + min_keys= isam->s->base.keys; for (i=0; i < key_parts; i++) m_info->rec_per_key_part[i]+= (isam->s->state.rec_per_key_part[i] / m_info->tables); @@ -138,7 +144,7 @@ MYRG_INFO *myrg_open(const char *name, int mode, int handle_locking) my_errno=HA_ERR_RECORD_FILE_FULL; goto err; } - m_info->keys= files ? isam->s->base.keys : 0; + m_info->keys= min_keys; bzero((char*) &m_info->by_key,sizeof(m_info->by_key)); /* this works ok if the table list is empty */ diff --git a/myisammrg/myrg_queue.c b/myisammrg/myrg_queue.c index 2e600a526c0..74fdddc7748 100644 --- a/myisammrg/myrg_queue.c +++ b/myisammrg/myrg_queue.c @@ -65,6 +65,8 @@ int _myrg_init_queue(MYRG_INFO *info,int inx,enum ha_rkey_function search_flag) error=my_errno; } } + else + my_errno= error= HA_ERR_WRONG_INDEX; return error; } diff --git a/mysql-test/include/loaddata_autocom.inc b/mysql-test/include/loaddata_autocom.inc new file mode 100644 index 00000000000..e5071c73c49 --- /dev/null +++ b/mysql-test/include/loaddata_autocom.inc @@ -0,0 +1,21 @@ +# Test if the engine does autocommit in LOAD DATA INFILE, or not +# (NDB wants to do, others don't). + +eval SET SESSION STORAGE_ENGINE = $engine_type; + +--disable_warnings +drop table if exists t1; +--enable_warnings + +create table t1 (a text, b text); +start transaction; +load data infile '../std_data_ln/loaddata2.dat' into table t1 fields terminated by ',' enclosed by ''''; +commit; +select count(*) from t1; +truncate table t1; +start transaction; +load data infile '../std_data_ln/loaddata2.dat' into table t1 fields terminated by ',' enclosed by ''''; +rollback; +select count(*) from t1; + +drop table t1; diff --git a/mysql-test/include/strict_autoinc.inc b/mysql-test/include/strict_autoinc.inc new file mode 100644 index 00000000000..6960440f3a7 --- /dev/null +++ b/mysql-test/include/strict_autoinc.inc @@ -0,0 +1,28 @@ +# +# Test for strict-mode autoincrement +# + +set @org_mode=@@sql_mode; +eval create table t1 +( + `a` tinyint(4) NOT NULL auto_increment, + primary key (`a`) +) engine = $type ; +set @@sql_mode='strict_all_tables'; +--error ER_WARN_DATA_OUT_OF_RANGE +insert into t1 values(1000); +select count(*) from t1; + +set auto_increment_increment=1000; +set auto_increment_offset=700; +--error ER_WARN_DATA_OUT_OF_RANGE +insert into t1 values(null); +select count(*) from t1; + +set @@sql_mode=@org_mode; +insert into t1 values(null); +select * from t1; + +drop table t1; + +# End of test diff --git a/mysql-test/lib/mtr_im.pl b/mysql-test/lib/mtr_im.pl new file mode 100644 index 00000000000..4a497cc7ed2 --- /dev/null +++ b/mysql-test/lib/mtr_im.pl @@ -0,0 +1,761 @@ +# -*- cperl -*- + +# This is a library file used by the Perl version of mysql-test-run, +# and is part of the translation of the Bourne shell script with the +# same name. + +use strict; + +# Private IM-related operations. + +sub mtr_im_kill_process ($$$$); +sub mtr_im_load_pids ($); +sub mtr_im_terminate ($); +sub mtr_im_check_alive ($); +sub mtr_im_check_main_alive ($); +sub mtr_im_check_angel_alive ($); +sub mtr_im_check_mysqlds_alive ($); +sub mtr_im_check_mysqld_alive ($); +sub mtr_im_cleanup ($); +sub mtr_im_rm_file ($); +sub mtr_im_errlog ($); +sub mtr_im_kill ($); +sub mtr_im_wait_for_connection ($$$); +sub mtr_im_wait_for_mysqld($$$); + +# Public IM-related operations. + +sub mtr_im_start ($$); +sub mtr_im_stop ($); + +############################################################################## +# +# Private operations. +# +############################################################################## + +sub mtr_im_kill_process ($$$$) { + my $pid_lst= shift; + my $signal= shift; + my $total_retries= shift; + my $timeout= shift; + + my %pids; + + foreach my $pid ( @{$pid_lst} ) + { + $pids{$pid}= 1; + } + + for ( my $cur_attempt= 1; $cur_attempt <= $total_retries; ++$cur_attempt ) + { + foreach my $pid ( keys %pids ) + { + mtr_debug("Sending $signal to $pid..."); + + kill($signal, $pid); + + unless ( kill (0, $pid) ) + { + mtr_debug("Process $pid died."); + delete $pids{$pid}; + } + } + + return if scalar keys %pids == 0; + + mtr_debug("Sleeping $timeout second(s) waiting for processes to die..."); + + sleep($timeout); + } + + mtr_debug("Process(es) " . + join(' ', keys %pids) . + " is still alive after $total_retries " . + "of sending signal $signal."); +} + +########################################################################### + +sub mtr_im_load_pids($) { + my $im= shift; + + mtr_debug("Loading PID files..."); + + # Obtain mysqld-process pids. + + my $instances = $im->{'instances'}; + + for ( my $idx= 0; $idx < 2; ++$idx ) + { + mtr_debug("IM-guarded mysqld[$idx] PID file: '" . + $instances->[$idx]->{'path_pid'} . "'."); + + my $mysqld_pid; + + if ( -r $instances->[$idx]->{'path_pid'} ) + { + $mysqld_pid= mtr_get_pid_from_file($instances->[$idx]->{'path_pid'}); + mtr_debug("IM-guarded mysqld[$idx] PID: $mysqld_pid."); + } + else + { + $mysqld_pid= undef; + mtr_debug("IM-guarded mysqld[$idx]: no PID file."); + } + + $instances->[$idx]->{'pid'}= $mysqld_pid; + } + + # Re-read Instance Manager PIDs from the file, since during tests Instance + # Manager could have been restarted, so its PIDs could have been changed. + + # - IM-main + + mtr_debug("IM-main PID file: '$im->{path_pid}'."); + + if ( -f $im->{'path_pid'} ) + { + $im->{'pid'} = + mtr_get_pid_from_file($im->{'path_pid'}); + + mtr_debug("IM-main PID: $im->{pid}."); + } + else + { + mtr_debug("IM-main: no PID file."); + $im->{'pid'}= undef; + } + + # - IM-angel + + mtr_debug("IM-angel PID file: '$im->{path_angel_pid}'."); + + if ( -f $im->{'path_angel_pid'} ) + { + $im->{'angel_pid'} = + mtr_get_pid_from_file($im->{'path_angel_pid'}); + + mtr_debug("IM-angel PID: $im->{'angel_pid'}."); + } + else + { + mtr_debug("IM-angel: no PID file."); + $im->{'angel_pid'} = undef; + } +} + +########################################################################### + +sub mtr_im_terminate($) { + my $im= shift; + + # Load pids from pid-files. We should do it first of all, because IM deletes + # them on shutdown. + + mtr_im_load_pids($im); + + mtr_debug("Shutting Instance Manager down..."); + + # Ignoring SIGCHLD so that all children could rest in peace. + + start_reap_all(); + + # Send SIGTERM to IM-main. + + if ( defined $im->{'pid'} ) + { + mtr_debug("IM-main pid: $im->{pid}."); + mtr_debug("Stopping IM-main..."); + + mtr_im_kill_process([ $im->{'pid'} ], 'TERM', 10, 1); + } + else + { + mtr_debug("IM-main pid: n/a."); + } + + # If IM-angel was alive, wait for it to die. + + if ( defined $im->{'angel_pid'} ) + { + mtr_debug("IM-angel pid: $im->{'angel_pid'}."); + mtr_debug("Waiting for IM-angel to die..."); + + my $total_attempts= 10; + + for ( my $cur_attempt=1; $cur_attempt <= $total_attempts; ++$cur_attempt ) + { + unless ( kill (0, $im->{'angel_pid'}) ) + { + mtr_debug("IM-angel died."); + last; + } + + sleep(1); + } + } + else + { + mtr_debug("IM-angel pid: n/a."); + } + + stop_reap_all(); + + # Re-load PIDs. + + mtr_im_load_pids($im); +} + +########################################################################### + +sub mtr_im_check_alive($) { + my $im= shift; + + mtr_debug("Checking whether IM-components are alive..."); + + return 1 if mtr_im_check_main_alive($im); + + return 1 if mtr_im_check_angel_alive($im); + + return 1 if mtr_im_check_mysqlds_alive($im); + + return 0; +} + +########################################################################### + +sub mtr_im_check_main_alive($) { + my $im= shift; + + # Check that the process, that we know to be IM's, is dead. + + if ( defined $im->{'pid'} ) + { + if ( kill (0, $im->{'pid'}) ) + { + mtr_debug("IM-main (PID: $im->{pid}) is alive."); + return 1; + } + else + { + mtr_debug("IM-main (PID: $im->{pid}) is dead."); + } + } + else + { + mtr_debug("No PID file for IM-main."); + } + + # Check that IM does not accept client connections. + + if ( mtr_ping_mysqld_server($im->{'port'}) ) + { + mtr_debug("IM-main (port: $im->{port}) " . + "is accepting connections."); + + mtr_im_errlog("IM-main is accepting connections on port " . + "$im->{port}, but there is no " . + "process information."); + return 1; + } + else + { + mtr_debug("IM-main (port: $im->{port}) " . + "does not accept connections."); + return 0; + } +} + +########################################################################### + +sub mtr_im_check_angel_alive($) { + my $im= shift; + + # Check that the process, that we know to be the Angel, is dead. + + if ( defined $im->{'angel_pid'} ) + { + if ( kill (0, $im->{'angel_pid'}) ) + { + mtr_debug("IM-angel (PID: $im->{angel_pid}) is alive."); + return 1; + } + else + { + mtr_debug("IM-angel (PID: $im->{angel_pid}) is dead."); + return 0; + } + } + else + { + mtr_debug("No PID file for IM-angel."); + return 0; + } +} + +########################################################################### + +sub mtr_im_check_mysqlds_alive($) { + my $im= shift; + + mtr_debug("Checking for IM-guarded mysqld instances..."); + + my $instances = $im->{'instances'}; + + for ( my $idx= 0; $idx < 2; ++$idx ) + { + mtr_debug("Checking mysqld[$idx]..."); + + return 1 + if mtr_im_check_mysqld_alive($instances->[$idx]); + } +} + +########################################################################### + +sub mtr_im_check_mysqld_alive($) { + my $mysqld_instance= shift; + + # Check that the process is dead. + + if ( defined $mysqld_instance->{'pid'} ) + { + if ( kill (0, $mysqld_instance->{'pid'}) ) + { + mtr_debug("Mysqld instance (PID: $mysqld_instance->{pid}) is alive."); + return 1; + } + else + { + mtr_debug("Mysqld instance (PID: $mysqld_instance->{pid}) is dead."); + } + } + else + { + mtr_debug("No PID file for mysqld instance."); + } + + # Check that mysqld does not accept client connections. + + if ( mtr_ping_mysqld_server($mysqld_instance->{'port'}) ) + { + mtr_debug("Mysqld instance (port: $mysqld_instance->{port}) " . + "is accepting connections."); + + mtr_im_errlog("Mysqld is accepting connections on port " . + "$mysqld_instance->{port}, but there is no " . + "process information."); + return 1; + } + else + { + mtr_debug("Mysqld instance (port: $mysqld_instance->{port}) " . + "does not accept connections."); + return 0; + } +} + +########################################################################### + +sub mtr_im_cleanup($) { + my $im= shift; + + mtr_im_rm_file($im->{'path_pid'}); + mtr_im_rm_file($im->{'path_sock'}); + + mtr_im_rm_file($im->{'path_angel_pid'}); + + for ( my $idx= 0; $idx < 2; ++$idx ) + { + mtr_im_rm_file($im->{'instances'}->[$idx]->{'path_pid'}); + mtr_im_rm_file($im->{'instances'}->[$idx]->{'path_sock'}); + } +} + +########################################################################### + +sub mtr_im_rm_file($) +{ + my $file_path= shift; + + if ( -f $file_path ) + { + mtr_debug("Removing '$file_path'..."); + + unless ( unlink($file_path) ) + { + mtr_warning("Can not remove '$file_path'.") + } + } + else + { + mtr_debug("File '$file_path' does not exist already."); + } +} + +########################################################################### + +sub mtr_im_errlog($) { + my $msg= shift; + + # Complain in error log so that a warning will be shown. + # + # TODO: unless BUG#20761 is fixed, we will print the warning to stdout, so + # that it can be seen on console and does not produce pushbuild error. + + # my $errlog= "$opt_vardir/log/mysql-test-run.pl.err"; + # + # open (ERRLOG, ">>$errlog") || + # mtr_error("Can not open error log ($errlog)"); + # + # my $ts= localtime(); + # print ERRLOG + # "Warning: [$ts] $msg\n"; + # + # close ERRLOG; + + my $ts= localtime(); + print "Warning: [$ts] $msg\n"; +} + +########################################################################### + +sub mtr_im_kill($) { + my $im= shift; + + # Re-load PIDs. That can be useful because some processes could have been + # restarted. + + mtr_im_load_pids($im); + + # Ignoring SIGCHLD so that all children could rest in peace. + + start_reap_all(); + + # Kill IM-angel first of all. + + if ( defined $im->{'angel_pid'} ) + { + mtr_debug("Killing IM-angel (PID: $im->{angel_pid})..."); + mtr_im_kill_process([ $im->{'angel_pid'} ], 'KILL', 10, 1) + } + else + { + mtr_debug("IM-angel is dead."); + } + + # Re-load PIDs again. + + mtr_im_load_pids($im); + + # Kill IM-main. + + if ( defined $im->{'pid'} ) + { + mtr_debug("Killing IM-main (PID: $im->pid})..."); + mtr_im_kill_process([ $im->{'pid'} ], 'KILL', 10, 1); + } + else + { + mtr_debug("IM-main is dead."); + } + + # Re-load PIDs again. + + mtr_im_load_pids($im); + + # Kill guarded mysqld instances. + + my @mysqld_pids; + + mtr_debug("Collecting PIDs of mysqld instances to kill..."); + + for ( my $idx= 0; $idx < 2; ++$idx ) + { + my $pid= $im->{'instances'}->[$idx]->{'pid'}; + + unless ( defined $pid ) + { + next; + } + + mtr_debug(" - IM-guarded mysqld[$idx] PID: $pid."); + + push (@mysqld_pids, $pid); + } + + if ( scalar @mysqld_pids > 0 ) + { + mtr_debug("Killing IM-guarded mysqld instances..."); + mtr_im_kill_process(\@mysqld_pids, 'KILL', 10, 1); + } + + # That's all. + + stop_reap_all(); +} + +############################################################################## + +sub mtr_im_wait_for_connection($$$) { + my $im= shift; + my $total_attempts= shift; + my $connect_timeout= shift; + + mtr_debug("Waiting for IM on port $im->{port} " . + "to start accepting connections..."); + + for ( my $cur_attempt= 1; $cur_attempt <= $total_attempts; ++$cur_attempt ) + { + mtr_debug("Trying to connect to IM ($cur_attempt of $total_attempts)..."); + + if ( mtr_ping_mysqld_server($im->{'port'}) ) + { + mtr_debug("IM is accepting connections " . + "on port $im->{port}."); + return 1; + } + + mtr_debug("Sleeping $connect_timeout..."); + sleep($connect_timeout); + } + + mtr_debug("IM does not accept connections " . + "on port $im->{port} after " . + ($total_attempts * $connect_timeout) . " seconds."); + + return 0; +} + +############################################################################## + +sub mtr_im_wait_for_mysqld($$$) { + my $mysqld= shift; + my $total_attempts= shift; + my $connect_timeout= shift; + + mtr_debug("Waiting for IM-guarded mysqld on port $mysqld->{port} " . + "to start accepting connections..."); + + for ( my $cur_attempt= 1; $cur_attempt <= $total_attempts; ++$cur_attempt ) + { + mtr_debug("Trying to connect to mysqld " . + "($cur_attempt of $total_attempts)..."); + + if ( mtr_ping_mysqld_server($mysqld->{'port'}) ) + { + mtr_debug("Mysqld is accepting connections " . + "on port $mysqld->{port}."); + return 1; + } + + mtr_debug("Sleeping $connect_timeout..."); + sleep($connect_timeout); + } + + mtr_debug("Mysqld does not accept connections " . + "on port $mysqld->{port} after " . + ($total_attempts * $connect_timeout) . " seconds."); + + return 0; +} + +############################################################################## +# +# Public operations. +# +############################################################################## + +sub mtr_im_start($$) { + my $im = shift; + my $opts = shift; + + mtr_debug("Starting Instance Manager..."); + + my $args; + mtr_init_args(\$args); + mtr_add_arg($args, "--defaults-file=%s", $im->{'defaults_file'}); + + foreach my $opt ( @{$opts} ) + { + mtr_add_arg($args, $opt); + } + + $im->{'pid'} = + mtr_spawn( + $::exe_im, # path to the executable + $args, # cmd-line args + '', # stdin + $im->{'path_log'}, # stdout + $im->{'path_err'}, # stderr + '', # pid file path (not used) + { append_log_file => 1 } # append log files + ); + + unless ( $im->{'pid'} ) + { + mtr_error('Could not start Instance Manager.') + } + + # Instance Manager can be run in daemon mode. In this case, it creates + # several processes and the parent process, created by mtr_spawn(), exits just + # after start. So, we have to obtain Instance Manager PID from the PID file. + + mtr_debug("Waiting for IM to create PID file (" . + "path: '$im->{path_pid}'; " . + "timeout: $im->{start_timeout})..."); + + unless ( sleep_until_file_created($im->{'path_pid'}, + $im->{'start_timeout'}, + -1) ) # real PID is still unknown + { + mtr_debug("IM has not created PID file in $im->{start_timeout} secs."); + mtr_debug("Aborting test suite..."); + + mtr_kill_leftovers(); + + mtr_report("IM has not created PID file in $im->{start_timeout} secs."); + return 0; + } + + $im->{'pid'}= mtr_get_pid_from_file($im->{'path_pid'}); + + mtr_debug("Instance Manager started. PID: $im->{pid}."); + + # Wait until we can connect to IM. + + my $IM_CONNECT_TIMEOUT= 30; + + unless ( mtr_im_wait_for_connection($im, + $IM_CONNECT_TIMEOUT, 1) ) + { + mtr_debug("Can not connect to Instance Manager " . + "in $IM_CONNECT_TIMEOUT seconds after start."); + mtr_debug("Aborting test suite..."); + + mtr_kill_leftovers(); + + mtr_report("Can not connect to Instance Manager " . + "in $IM_CONNECT_TIMEOUT seconds after start."); + return 0; + } + + # Wait for IM to start guarded instances: + # - wait for PID files; + + mtr_debug("Waiting for guarded mysqlds instances to create PID files..."); + + for ( my $idx= 0; $idx < 2; ++$idx ) + { + my $mysqld= $im->{'instances'}->[$idx]; + + if ( exists $mysqld->{'nonguarded'} ) + { + next; + } + + mtr_debug("Waiting for mysqld[$idx] to create PID file (" . + "path: '$mysqld->{path_pid}'; " . + "timeout: $mysqld->{start_timeout})..."); + + unless ( sleep_until_file_created($mysqld->{'path_pid'}, + $mysqld->{'start_timeout'}, + -1) ) # real PID is still unknown + { + mtr_debug("mysqld[$idx] has not created PID file in " . + "$mysqld->{start_timeout} secs."); + mtr_debug("Aborting test suite..."); + + mtr_kill_leftovers(); + + mtr_report("mysqld[$idx] has not created PID file in " . + "$mysqld->{start_timeout} secs."); + return 0; + } + + mtr_debug("PID file for mysqld[$idx] ($mysqld->{path_pid} created."); + } + + # Wait until we can connect to guarded mysqld-instances + # (in other words -- wait for IM to start guarded instances). + + mtr_debug("Waiting for guarded mysqlds to start accepting connections..."); + + for ( my $idx= 0; $idx < 2; ++$idx ) + { + my $mysqld= $im->{'instances'}->[$idx]; + + if ( exists $mysqld->{'nonguarded'} ) + { + next; + } + + mtr_debug("Waiting for mysqld[$idx] to accept connection..."); + + unless ( mtr_im_wait_for_mysqld($mysqld, 30, 1) ) + { + mtr_debug("Can not connect to mysqld[$idx] " . + "in $IM_CONNECT_TIMEOUT seconds after start."); + mtr_debug("Aborting test suite..."); + + mtr_kill_leftovers(); + + mtr_report("Can not connect to mysqld[$idx] " . + "in $IM_CONNECT_TIMEOUT seconds after start."); + return 0; + } + + mtr_debug("mysqld[$idx] started."); + } + + mtr_debug("Instance Manager and its components are up and running."); + + return 1; +} + +############################################################################## + +sub mtr_im_stop($) { + my $im= shift; + + mtr_debug("Stopping Instance Manager..."); + + # Try graceful shutdown. + + mtr_im_terminate($im); + + # Check that all processes died. + + unless ( mtr_im_check_alive($im) ) + { + mtr_debug("Instance Manager has been stopped successfully."); + mtr_im_cleanup($im); + return 1; + } + + # Instance Manager don't want to die. We should kill it. + + mtr_im_errlog("Instance Manager did not shutdown gracefully."); + + mtr_im_kill($im); + + # Check again that all IM-related processes have been killed. + + my $im_is_alive= mtr_im_check_alive($im); + + mtr_im_cleanup($im); + + if ( $im_is_alive ) + { + mtr_debug("Can not kill Instance Manager or its children."); + return 0; + } + + mtr_debug("Instance Manager has been killed successfully."); + return 1; +} + +########################################################################### + +1; diff --git a/mysql-test/lib/mtr_process.pl b/mysql-test/lib/mtr_process.pl index bf869ca91c4..00b12ba5fb5 100644 --- a/mysql-test/lib/mtr_process.pl +++ b/mysql-test/lib/mtr_process.pl @@ -22,28 +22,6 @@ sub sleep_until_file_created ($$$); sub mtr_kill_processes ($); sub mtr_ping_mysqld_server ($); -# Private IM-related operations. - -sub mtr_im_kill_process ($$$$); -sub mtr_im_load_pids ($); -sub mtr_im_terminate ($); -sub mtr_im_check_alive ($); -sub mtr_im_check_main_alive ($); -sub mtr_im_check_angel_alive ($); -sub mtr_im_check_mysqlds_alive ($); -sub mtr_im_check_mysqld_alive ($$); -sub mtr_im_cleanup ($); -sub mtr_im_rm_file ($); -sub mtr_im_errlog ($); -sub mtr_im_kill ($); -sub mtr_im_wait_for_connection ($$$); -sub mtr_im_wait_for_mysqld($$$); - -# Public IM-related operations. - -sub mtr_im_start ($$); -sub mtr_im_stop ($); - # static in C sub spawn_impl ($$$$$$$$); @@ -381,9 +359,16 @@ sub mtr_process_exit_status { sub mtr_kill_leftovers () { + mtr_report("Killing Possible Leftover Processes"); mtr_debug("mtr_kill_leftovers(): started."); - mtr_im_stop($::instance_manager); + mkpath("$::opt_vardir/log"); # Needed for mysqladmin log + + # Stop or kill Instance Manager and all its children. If we failed to do + # that, we can only abort -- there is nothing left to do. + + mtr_error("Failed to stop Instance Manager.") + unless mtr_im_stop($::instance_manager); # Kill mysqld servers (masters and slaves) that would conflict with this # run. Make sure to remove the PID file, if any. @@ -470,14 +455,6 @@ sub mtr_kill_leftovers () { mtr_debug("Got pid: $pid from file '$pidfile'"); - # Race, could have been removed between I tested with -f - # and the unlink() below, so I better check again with -f - - if ( ! unlink($pidfile) and -f $pidfile ) - { - mtr_error("can't remove $pidfile"); - } - if ( $::glob_cygwin_perl or kill(0, $pid) ) { mtr_debug("There is process with pid $pid -- scheduling for kill."); @@ -1002,676 +979,6 @@ sub mtr_exit ($) { exit($code); } -############################################################################## -# -# Instance Manager management routines. -# -############################################################################## - -sub mtr_im_kill_process ($$$$) { - my $pid_lst= shift; - my $signal= shift; - my $total_retries= shift; - my $timeout= shift; - - my %pids; - - foreach my $pid (@{$pid_lst}) - { - $pids{$pid}= 1; - } - - for (my $cur_attempt= 1; $cur_attempt <= $total_retries; ++$cur_attempt) - { - foreach my $pid (keys %pids) - { - mtr_debug("Sending $signal to $pid..."); - - kill($signal, $pid); - - unless (kill (0, $pid)) - { - mtr_debug("Process $pid died."); - delete $pids{$pid}; - } - } - - return if scalar keys %pids == 0; - - mtr_debug("Sleeping $timeout second(s) waiting for processes to die..."); - - sleep($timeout); - } - - mtr_debug("Process(es) " . - join(' ', keys %pids) . - " is still alive after $total_retries " . - "of sending signal $signal."); -} - -########################################################################### - -sub mtr_im_load_pids($) { - my $instance_manager= shift; - - mtr_debug("Loading PID files..."); - - # Obtain mysqld-process pids. - - my $instances = $instance_manager->{'instances'}; - - for (my $idx= 0; $idx < 2; ++$idx) - { - mtr_debug("IM-guarded mysqld[$idx] PID file: '" . - $instances->[$idx]->{'path_pid'} . "'."); - - my $mysqld_pid; - - if (-r $instances->[$idx]->{'path_pid'}) - { - $mysqld_pid= mtr_get_pid_from_file($instances->[$idx]->{'path_pid'}); - mtr_debug("IM-guarded mysqld[$idx] PID: $mysqld_pid."); - } - else - { - $mysqld_pid= undef; - mtr_debug("IM-guarded mysqld[$idx]: no PID file."); - } - - $instances->[$idx]->{'pid'}= $mysqld_pid; - } - - # Re-read Instance Manager PIDs from the file, since during tests Instance - # Manager could have been restarted, so its PIDs could have been changed. - - # - IM-main - - mtr_debug("IM-main PID file: '$instance_manager->{path_pid}'."); - - if (-f $instance_manager->{'path_pid'}) - { - $instance_manager->{'pid'} = - mtr_get_pid_from_file($instance_manager->{'path_pid'}); - - mtr_debug("IM-main PID: $instance_manager->{pid}."); - } - else - { - mtr_debug("IM-main: no PID file."); - $instance_manager->{'pid'}= undef; - } - - # - IM-angel - - mtr_debug("IM-angel PID file: '$instance_manager->{path_angel_pid}'."); - - if (-f $instance_manager->{'path_angel_pid'}) - { - $instance_manager->{'angel_pid'} = - mtr_get_pid_from_file($instance_manager->{'path_angel_pid'}); - - mtr_debug("IM-angel PID: $instance_manager->{'angel_pid'}."); - } - else - { - mtr_debug("IM-angel: no PID file."); - $instance_manager->{'angel_pid'} = undef; - } -} - -########################################################################### - -sub mtr_im_terminate($) { - my $instance_manager= shift; - - # Load pids from pid-files. We should do it first of all, because IM deletes - # them on shutdown. - - mtr_im_load_pids($instance_manager); - - mtr_debug("Shutting Instance Manager down..."); - - # Ignoring SIGCHLD so that all children could rest in peace. - - start_reap_all(); - - # Send SIGTERM to IM-main. - - if (defined $instance_manager->{'pid'}) - { - mtr_debug("IM-main pid: $instance_manager->{pid}."); - mtr_debug("Stopping IM-main..."); - - mtr_im_kill_process([ $instance_manager->{'pid'} ], 'TERM', 10, 1); - } - else - { - mtr_debug("IM-main pid: n/a."); - } - - # If IM-angel was alive, wait for it to die. - - if (defined $instance_manager->{'angel_pid'}) - { - mtr_debug("IM-angel pid: $instance_manager->{'angel_pid'}."); - mtr_debug("Waiting for IM-angel to die..."); - - my $total_attempts= 10; - - for (my $cur_attempt=1; $cur_attempt <= $total_attempts; ++$cur_attempt) - { - unless (kill (0, $instance_manager->{'angel_pid'})) - { - mtr_debug("IM-angel died."); - last; - } - - sleep(1); - } - } - else - { - mtr_debug("IM-angel pid: n/a."); - } - - stop_reap_all(); - - # Re-load PIDs. - - mtr_im_load_pids($instance_manager); -} - -########################################################################### - -sub mtr_im_check_alive($) { - my $instance_manager= shift; - - mtr_debug("Checking whether IM-components are alive..."); - - return 1 if mtr_im_check_main_alive($instance_manager); - - return 1 if mtr_im_check_angel_alive($instance_manager); - - return 1 if mtr_im_check_mysqlds_alive($instance_manager); - - return 0; -} - -########################################################################### - -sub mtr_im_check_main_alive($) { - my $instance_manager= shift; - - # Check that the process, that we know to be IM's, is dead. - - if (defined $instance_manager->{'pid'}) - { - if (kill (0, $instance_manager->{'pid'})) - { - mtr_debug("IM-main (PID: $instance_manager->{pid}) is alive."); - return 1; - } - else - { - mtr_debug("IM-main (PID: $instance_manager->{pid}) is dead."); - } - } - else - { - mtr_debug("No PID file for IM-main."); - } - - # Check that IM does not accept client connections. - - if (mtr_ping_mysqld_server($instance_manager->{'port'})) - { - mtr_debug("IM-main (port: $instance_manager->{port}) " . - "is accepting connections."); - - mtr_im_errlog("IM-main is accepting connections on port " . - "$instance_manager->{port}, but there is no " . - "process information."); - return 1; - } - else - { - mtr_debug("IM-main (port: $instance_manager->{port}) " . - "does not accept connections."); - return 0; - } -} - -########################################################################### - -sub mtr_im_check_angel_alive($) { - my $instance_manager= shift; - - # Check that the process, that we know to be the Angel, is dead. - - if (defined $instance_manager->{'angel_pid'}) - { - if (kill (0, $instance_manager->{'angel_pid'})) - { - mtr_debug("IM-angel (PID: $instance_manager->{angel_pid}) is alive."); - return 1; - } - else - { - mtr_debug("IM-angel (PID: $instance_manager->{angel_pid}) is dead."); - return 0; - } - } - else - { - mtr_debug("No PID file for IM-angel."); - return 0; - } -} - -########################################################################### - -sub mtr_im_check_mysqlds_alive($) { - my $instance_manager= shift; - - mtr_debug("Checking for IM-guarded mysqld instances..."); - - my $instances = $instance_manager->{'instances'}; - - for (my $idx= 0; $idx < 2; ++$idx) - { - mtr_debug("Checking mysqld[$idx]..."); - - return 1 - if mtr_im_check_mysqld_alive($instance_manager, $instances->[$idx]); - } -} - -########################################################################### - -sub mtr_im_check_mysqld_alive($$) { - my $instance_manager= shift; - my $mysqld_instance= shift; - - # Check that the process is dead. - - if (defined $instance_manager->{'pid'}) - { - if (kill (0, $instance_manager->{'pid'})) - { - mtr_debug("Mysqld instance (PID: $mysqld_instance->{pid}) is alive."); - return 1; - } - else - { - mtr_debug("Mysqld instance (PID: $mysqld_instance->{pid}) is dead."); - } - } - else - { - mtr_debug("No PID file for mysqld instance."); - } - - # Check that mysqld does not accept client connections. - - if (mtr_ping_mysqld_server($mysqld_instance->{'port'})) - { - mtr_debug("Mysqld instance (port: $mysqld_instance->{port}) " . - "is accepting connections."); - - mtr_im_errlog("Mysqld is accepting connections on port " . - "$mysqld_instance->{port}, but there is no " . - "process information."); - return 1; - } - else - { - mtr_debug("Mysqld instance (port: $mysqld_instance->{port}) " . - "does not accept connections."); - return 0; - } -} - -########################################################################### - -sub mtr_im_cleanup($) { - my $instance_manager= shift; - - mtr_im_rm_file($instance_manager->{'path_pid'}); - mtr_im_rm_file($instance_manager->{'path_sock'}); - - mtr_im_rm_file($instance_manager->{'path_angel_pid'}); - - for (my $idx= 0; $idx < 2; ++$idx) - { - mtr_im_rm_file($instance_manager->{'instances'}->[$idx]->{'path_pid'}); - mtr_im_rm_file($instance_manager->{'instances'}->[$idx]->{'path_sock'}); - } -} - -########################################################################### - -sub mtr_im_rm_file($) -{ - my $file_path= shift; - - if (-f $file_path) - { - mtr_debug("Removing '$file_path'..."); - - mtr_warning("Can not remove '$file_path'.") - unless unlink($file_path); - } - else - { - mtr_debug("File '$file_path' does not exist already."); - } -} - -########################################################################### - -sub mtr_im_errlog($) { - my $msg= shift; - - # Complain in error log so that a warning will be shown. - # - # TODO: unless BUG#20761 is fixed, we will print the warning to stdout, so - # that it can be seen on console and does not produce pushbuild error. - - # my $errlog= "$opt_vardir/log/mysql-test-run.pl.err"; - # - # open (ERRLOG, ">>$errlog") || - # mtr_error("Can not open error log ($errlog)"); - # - # my $ts= localtime(); - # print ERRLOG - # "Warning: [$ts] $msg\n"; - # - # close ERRLOG; - - my $ts= localtime(); - print "Warning: [$ts] $msg\n"; -} - -########################################################################### - -sub mtr_im_kill($) { - my $instance_manager= shift; - - # Re-load PIDs. That can be useful because some processes could have been - # restarted. - - mtr_im_load_pids($instance_manager); - - # Ignoring SIGCHLD so that all children could rest in peace. - - start_reap_all(); - - # Kill IM-angel first of all. - - if (defined $instance_manager->{'angel_pid'}) - { - mtr_debug("Killing IM-angel (PID: $instance_manager->{angel_pid})..."); - mtr_im_kill_process([ $instance_manager->{'angel_pid'} ], 'KILL', 10, 1) - } - else - { - mtr_debug("IM-angel is dead."); - } - - # Re-load PIDs again. - - mtr_im_load_pids($instance_manager); - - # Kill IM-main. - - if (defined $instance_manager->{'pid'}) - { - mtr_debug("Killing IM-main (PID: $instance_manager->pid})..."); - mtr_im_kill_process([ $instance_manager->{'pid'} ], 'KILL', 10, 1); - } - else - { - mtr_debug("IM-main is dead."); - } - - # Re-load PIDs again. - - mtr_im_load_pids($instance_manager); - - # Kill guarded mysqld instances. - - my @mysqld_pids; - - mtr_debug("Collecting PIDs of mysqld instances to kill..."); - - for (my $idx= 0; $idx < 2; ++$idx) - { - my $pid= $instance_manager->{'instances'}->[$idx]->{'pid'}; - - next unless defined $pid; - - mtr_debug(" - IM-guarded mysqld[$idx] PID: $pid."); - - push (@mysqld_pids, $pid); - } - - if (scalar @mysqld_pids > 0) - { - mtr_debug("Killing IM-guarded mysqld instances..."); - mtr_im_kill_process(\@mysqld_pids, 'KILL', 10, 1); - } - - # That's all. - - stop_reap_all(); -} - -############################################################################## - -sub mtr_im_wait_for_connection($$$) { - my $instance_manager= shift; - my $total_attempts= shift; - my $connect_timeout= shift; - - mtr_debug("Waiting for IM on port $instance_manager->{port} " . - "to start accepting connections..."); - - for (my $cur_attempt= 1; $cur_attempt <= $total_attempts; ++$cur_attempt) - { - mtr_debug("Trying to connect to IM ($cur_attempt of $total_attempts)..."); - - if (mtr_ping_mysqld_server($instance_manager->{'port'})) - { - mtr_debug("IM is accepting connections " . - "on port $instance_manager->{port}."); - return 1; - } - - mtr_debug("Sleeping $connect_timeout..."); - sleep($connect_timeout); - } - - mtr_debug("IM does not accept connections " . - "on port $instance_manager->{port} after " . - ($total_attempts * $connect_timeout) . " seconds."); - - return 0; -} - -############################################################################## - -sub mtr_im_wait_for_mysqld($$$) { - my $mysqld= shift; - my $total_attempts= shift; - my $connect_timeout= shift; - - mtr_debug("Waiting for IM-guarded mysqld on port $mysqld->{port} " . - "to start accepting connections..."); - - for (my $cur_attempt= 1; $cur_attempt <= $total_attempts; ++$cur_attempt) - { - mtr_debug("Trying to connect to mysqld " . - "($cur_attempt of $total_attempts)..."); - - if (mtr_ping_mysqld_server($mysqld->{'port'})) - { - mtr_debug("Mysqld is accepting connections " . - "on port $mysqld->{port}."); - return 1; - } - - mtr_debug("Sleeping $connect_timeout..."); - sleep($connect_timeout); - } - - mtr_debug("Mysqld does not accept connections " . - "on port $mysqld->{port} after " . - ($total_attempts * $connect_timeout) . " seconds."); - - return 0; -} - -############################################################################## - -sub mtr_im_start($$) { - my $instance_manager = shift; - my $opts = shift; - - mtr_debug("Starting Instance Manager..."); - - my $args; - mtr_init_args(\$args); - mtr_add_arg($args, "--defaults-file=%s", - $instance_manager->{'defaults_file'}); - - foreach my $opt (@{$opts}) - { - mtr_add_arg($args, $opt); - } - - $instance_manager->{'pid'} = - mtr_spawn( - $::exe_im, # path to the executable - $args, # cmd-line args - '', # stdin - $instance_manager->{'path_log'}, # stdout - $instance_manager->{'path_err'}, # stderr - '', # pid file path (not used) - { append_log_file => 1 } # append log files - ); - - if ( ! $instance_manager->{'pid'} ) - { - mtr_report('Could not start Instance Manager'); - return; - } - - # Instance Manager can be run in daemon mode. In this case, it creates - # several processes and the parent process, created by mtr_spawn(), exits just - # after start. So, we have to obtain Instance Manager PID from the PID file. - - if ( ! sleep_until_file_created( - $instance_manager->{'path_pid'}, - $instance_manager->{'start_timeout'}, - -1)) # real PID is still unknown - { - mtr_report("Instance Manager PID file is missing"); - return; - } - - $instance_manager->{'pid'} = - mtr_get_pid_from_file($instance_manager->{'path_pid'}); - - mtr_debug("Instance Manager started. PID: $instance_manager->{pid}."); - - # Wait until we can connect to IM. - - my $IM_CONNECT_TIMEOUT= 30; - - unless (mtr_im_wait_for_connection($instance_manager, - $IM_CONNECT_TIMEOUT, 1)) - { - mtr_debug("Can not connect to Instance Manager " . - "in $IM_CONNECT_TIMEOUT seconds after start."); - mtr_debug("Aborting test suite..."); - - mtr_kill_leftovers(); - - mtr_error("Can not connect to Instance Manager " . - "in $IM_CONNECT_TIMEOUT seconds after start."); - } - - # Wait until we can connect to guarded mysqld-instances - # (in other words -- wait for IM to start guarded instances). - - for (my $idx= 0; $idx < 2; ++$idx) - { - my $mysqld= $instance_manager->{'instances'}->[$idx]; - - next if exists $mysqld->{'nonguarded'}; - - mtr_debug("Waiting for mysqld[$idx] to start..."); - - unless (mtr_im_wait_for_mysqld($mysqld, 30, 1)) - { - mtr_debug("Can not connect to mysqld[$idx] " . - "in $IM_CONNECT_TIMEOUT seconds after start."); - mtr_debug("Aborting test suite..."); - - mtr_kill_leftovers(); - - mtr_error("Can not connect to mysqld[$idx] " . - "in $IM_CONNECT_TIMEOUT seconds after start."); - } - - mtr_debug("mysqld[$idx] started."); - } - - mtr_debug("Instance Manager started."); -} - -############################################################################## - -sub mtr_im_stop($) { - my $instance_manager= shift; - - mtr_debug("Stopping Instance Manager..."); - - # Try graceful shutdown. - - mtr_im_terminate($instance_manager); - - # Check that all processes died. - - unless (mtr_im_check_alive($instance_manager)) - { - mtr_debug("Instance Manager has been stopped successfully."); - mtr_im_cleanup($instance_manager); - return 1; - } - - # Instance Manager don't want to die. We should kill it. - - mtr_im_errlog("Instance Manager did not shutdown gracefully."); - - mtr_im_kill($instance_manager); - - # Check again that all IM-related processes have been killed. - - my $im_is_alive= mtr_im_check_alive($instance_manager); - - mtr_im_cleanup($instance_manager); - - if ($im_is_alive) - { - mtr_error("Can not kill Instance Manager or its children."); - return 0; - } - - mtr_debug("Instance Manager has been killed successfully."); - return 1; -} - ########################################################################### 1; diff --git a/mysql-test/lib/mtr_stress.pl b/mysql-test/lib/mtr_stress.pl index 77c3d8bb030..92bb220461b 100644 --- a/mysql-test/lib/mtr_stress.pl +++ b/mysql-test/lib/mtr_stress.pl @@ -21,7 +21,6 @@ sub run_stress_test () { my $args; - my $stress_basedir; my $stress_suitedir; mtr_report("Starting stress testing\n"); diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl index 7bca21e3ff6..13ce7ccc66e 100755 --- a/mysql-test/mysql-test-run.pl +++ b/mysql-test/mysql-test-run.pl @@ -88,6 +88,7 @@ use strict; #use diagnostics; require "lib/mtr_cases.pl"; +require "lib/mtr_im.pl"; require "lib/mtr_process.pl"; require "lib/mtr_timer.pl"; require "lib/mtr_io.pl"; @@ -133,7 +134,6 @@ our @mysqld_src_dirs= our $glob_win32= 0; # OS and native Win32 executables our $glob_win32_perl= 0; # ActiveState Win32 Perl our $glob_cygwin_perl= 0; # Cygwin Perl -our $glob_cygwin_shell= undef; our $glob_mysql_test_dir= undef; our $glob_mysql_bench_dir= undef; our $glob_hostname= undef; @@ -256,7 +256,7 @@ our $opt_result_ext; our $opt_skip; our $opt_skip_rpl; -our $use_slaves; +our $max_slave_num= 0; our $opt_skip_test; our $opt_skip_im; @@ -267,7 +267,7 @@ our $opt_sleep_time_for_delete= 10; our $opt_testcase_timeout; our $opt_suite_timeout; my $default_testcase_timeout= 15; # 15 min max -my $default_suite_timeout= 120; # 2 hours max +my $default_suite_timeout= 180; # 3 hours max our $opt_socket; @@ -410,7 +410,13 @@ sub main () { { $need_ndbcluster||= $test->{ndb_test}; $need_im||= $test->{component_id} eq 'im'; - $use_slaves||= $test->{slave_num}; + + # Count max number of slaves used by a test case + if ( $test->{slave_num} > $max_slave_num) + { + $max_slave_num= $test->{slave_num}; + mtr_error("Too many slaves") if $max_slave_num > 3; + } } $opt_with_ndbcluster= 0 unless $need_ndbcluster; $opt_skip_im= 1 unless $need_im; @@ -464,10 +470,7 @@ sub initial_setup () { { # Windows programs like 'mysqld' needs Windows paths $glob_mysql_test_dir= `cygpath -m "$glob_mysql_test_dir"`; - my $shell= $ENV{'SHELL'} || "/bin/bash"; - $glob_cygwin_shell= `cygpath -w "$shell"`; # The Windows path c:\... chomp($glob_mysql_test_dir); - chomp($glob_cygwin_shell); } $glob_basedir= dirname($glob_mysql_test_dir); $glob_mysql_bench_dir= "$glob_basedir/mysql-bench"; # FIXME make configurable @@ -848,13 +851,13 @@ sub command_line_setup () { if ( ! $opt_testcase_timeout ) { $opt_testcase_timeout= $default_testcase_timeout; - $opt_testcase_timeout*= 10 if defined $opt_valgrind; + $opt_testcase_timeout*= 10 if $opt_valgrind; } if ( ! $opt_suite_timeout ) { $opt_suite_timeout= $default_suite_timeout; - $opt_suite_timeout*= 4 if defined $opt_valgrind; + $opt_suite_timeout*= 6 if $opt_valgrind; } # Increase times to wait for executables to start if using valgrind @@ -964,6 +967,7 @@ sub command_line_setup () { path_datadir => "$opt_vardir/im_mysqld_1.data", path_sock => "$sockdir/mysqld_1.sock", path_pid => "$opt_vardir/run/mysqld_1.pid", + start_timeout => 400, # enough time create innodb tables }; $instance_manager->{'instances'}->[1]= @@ -974,6 +978,7 @@ sub command_line_setup () { path_sock => "$sockdir/mysqld_2.sock", path_pid => "$opt_vardir/run/mysqld_2.pid", nonguarded => 1, + start_timeout => 400, # enough time create innodb tables }; if ( $opt_extern ) @@ -997,11 +1002,9 @@ sub snapshot_setup () { $master->[0]->{'path_myddir'}, $master->[1]->{'path_myddir'}); - if ($use_slaves) + for (my $idx= 0; $idx < $max_slave_num; $idx++) { - push @data_dir_lst, ($slave->[0]->{'path_myddir'}, - $slave->[1]->{'path_myddir'}, - $slave->[2]->{'path_myddir'}); + push(@data_dir_lst, $slave->[$idx]->{'path_myddir'}); } unless ($opt_skip_im) @@ -1114,7 +1117,9 @@ sub executable_setup () { $path_ndb_tools_dir= mtr_path_exists("$glob_basedir/ndb/tools"); $exe_ndb_mgm= "$glob_basedir/ndb/src/mgmclient/ndb_mgm"; $lib_udf_example= - mtr_file_exists("$glob_basedir/sql/.libs/udf_example.so"); + mtr_file_exists("$glob_basedir/sql/.libs/udf_example.so", + "$glob_basedir/sql/release/udf_example.dll", + "$glob_basedir/sql/debug/udf_example.dll"); } else { @@ -1193,7 +1198,7 @@ sub executable_setup () { sub environment_setup () { - my $extra_ld_library_paths; + my @ld_library_paths; # -------------------------------------------------------------------------- # Setup LD_LIBRARY_PATH so the libraries from this distro/clone @@ -1201,25 +1206,40 @@ sub environment_setup () { # -------------------------------------------------------------------------- if ( $opt_source_dist ) { - $extra_ld_library_paths= "$glob_basedir/libmysql/.libs/"; + push(@ld_library_paths, "$glob_basedir/libmysql/.libs/") } else { - $extra_ld_library_paths= "$glob_basedir/lib"; + push(@ld_library_paths, "$glob_basedir/lib") } # -------------------------------------------------------------------------- # Add the path where mysqld will find udf_example.so # -------------------------------------------------------------------------- - $extra_ld_library_paths .= ":" . - ($lib_udf_example ? dirname($lib_udf_example) : ""); + if ( $lib_udf_example ) + { + push(@ld_library_paths, dirname($lib_udf_example)); + } - $ENV{'LD_LIBRARY_PATH'}= - "$extra_ld_library_paths" . - ($ENV{'LD_LIBRARY_PATH'} ? ":$ENV{'LD_LIBRARY_PATH'}" : ""); - $ENV{'DYLD_LIBRARY_PATH'}= - "$extra_ld_library_paths" . - ($ENV{'DYLD_LIBRARY_PATH'} ? ":$ENV{'DYLD_LIBRARY_PATH'}" : ""); + # -------------------------------------------------------------------------- + #Valgrind need to be run with debug libraries otherwise it's almost + # impossible to add correct supressions, that means if "/usr/lib/debug" + # is available, it should be added to + # LD_LIBRARY_PATH + # -------------------------------------------------------------------------- + my $debug_libraries_path= "/usr/lib/debug"; + if ( $opt_valgrind and -d $debug_libraries_path ) + { + push(@ld_library_paths, $debug_libraries_path); + } + + $ENV{'LD_LIBRARY_PATH'}= join(":", @ld_library_paths, + split(':', $ENV{'LD_LIBRARY_PATH'})); + mtr_debug("LD_LIBRARY_PATH: $ENV{'LD_LIBRARY_PATH'}"); + + $ENV{'DYLD_LIBRARY_PATH'}= join(":", @ld_library_paths, + split(':', $ENV{'DYLD_LIBRARY_PATH'})); + mtr_debug("DYLD_LIBRARY_PATH: $ENV{'DYLD_LIBRARY_PATH'}"); # -------------------------------------------------------------------------- # Also command lines in .opt files may contain env vars @@ -1313,12 +1333,9 @@ sub kill_running_server () { { # Ensure that no old mysqld test servers are running # This is different from terminating processes we have - # started from ths run of the script, this is terminating + # started from this run of the script, this is terminating # leftovers from previous runs. - mtr_report("Killing Possible Leftover Processes"); - mkpath("$opt_vardir/log"); # Needed for mysqladmin log - mtr_kill_leftovers(); $using_ndbcluster_master= $opt_with_ndbcluster; @@ -1723,15 +1740,13 @@ sub initialize_servers () { sub mysql_install_db () { - # FIXME not exactly true I think, needs improvements - install_db('master', $master->[0]->{'path_myddir'}); - install_db('master', $master->[1]->{'path_myddir'}); + install_db('master1', $master->[0]->{'path_myddir'}); + copy_install_db('master2', $master->[1]->{'path_myddir'}); - if ( $use_slaves ) + # Install the number of slave databses needed + for (my $idx= 0; $idx < $max_slave_num; $idx++) { - install_db('slave', $slave->[0]->{'path_myddir'}); - install_db('slave', $slave->[1]->{'path_myddir'}); - install_db('slave', $slave->[2]->{'path_myddir'}); + copy_install_db("slave".($idx+1), $slave->[$idx]->{'path_myddir'}); } if ( ! $opt_skip_im ) @@ -1761,6 +1776,17 @@ sub mysql_install_db () { } +sub copy_install_db ($$) { + my $type= shift; + my $data_dir= shift; + + mtr_report("Installing \u$type Database"); + + # Just copy the installed db from first master + mtr_copy_dir($master->[0]->{'path_myddir'}, $data_dir); + +} + sub install_db ($$) { my $type= shift; my $data_dir= shift; @@ -1807,6 +1833,12 @@ sub install_db ($$) { mtr_add_arg($args, "--skip-ndbcluster"); mtr_add_arg($args, "--skip-bdb"); + if ( $opt_debug ) + { + mtr_add_arg($args, "--debug=d:t:i:A,%s/log/bootstrap_%s.trace", + $opt_vardir_trace, $type); + } + if ( ! $opt_netware ) { mtr_add_arg($args, "--language=%s", $path_language); @@ -1915,13 +1947,33 @@ sub im_prepare_data_dir($) { foreach my $instance (@{$instance_manager->{'instances'}}) { - install_db( + copy_install_db( 'im_mysqld_' . $instance->{'server_id'}, $instance->{'path_datadir'}); } } +# +# Restore snapshot of the installed slave databases +# if the snapshot exists +# +sub restore_slave_databases () { + + if ( -d $path_snapshot) + { + # Restore the number of slave databases being used + for (my $idx= 0; $idx < $max_slave_num; $idx++) + { + my $data_dir= $slave->[$idx]->{'path_myddir'}; + my $name= basename($data_dir); + rmtree($data_dir); + mtr_copy_dir("$path_snapshot/$name", $data_dir); + } + } +} + + ############################################################################## # # Run a single test case @@ -2022,6 +2074,7 @@ sub run_testcase ($) { # ---------------------------------------------------------------------- stop_slaves(); + restore_slave_databases(); } # ---------------------------------------------------------------------- @@ -2112,7 +2165,13 @@ sub run_testcase ($) { im_create_defaults_file($instance_manager); - mtr_im_start($instance_manager, $tinfo->{im_opts}); + unless ( mtr_im_start($instance_manager, $tinfo->{im_opts}) ) + { + report_failure_and_restart($tinfo); + mtr_report("Failed to start Instance Manager. " . + "The test '$tname' is marked as failed."); + return; + } } # ---------------------------------------------------------------------- @@ -2209,7 +2268,10 @@ sub run_testcase ($) { if ( ! $glob_use_running_server and $tinfo->{'component_id'} eq 'im' ) { - mtr_im_stop($instance_manager); + unless ( mtr_im_stop($instance_manager) ) + { + mtr_error("Failed to stop Instance Manager.") + } } } @@ -2403,7 +2465,7 @@ sub do_before_start_slave ($$) { sub mysqld_arguments ($$$$$$) { my $args= shift; - my $type= shift; # master/slave/bootstrap + my $type= shift; # master/slave my $idx= shift; my $extra_opt= shift; my $slave_master_info= shift; @@ -2632,7 +2694,7 @@ sub mysqld_arguments ($$$$$$) { ############################################################################## sub mysqld_start ($$$$$) { - my $type= shift; # master/slave/bootstrap + my $type= shift; # master/slave my $idx= shift; my $extra_opt= shift; my $slave_master_info= shift; @@ -2653,7 +2715,7 @@ sub mysqld_start ($$$$$) { } else { - $exe= $exe_mysqld; + mtr_error("Unknown 'type' passed to mysqld_start"); } mtr_init_args(\$args); @@ -2738,7 +2800,10 @@ sub stop_masters_slaves () { print "Ending Tests\n"; print "Shutting-down Instance Manager\n"; - mtr_im_stop($instance_manager); + unless ( mtr_im_stop($instance_manager) ) + { + mtr_error("Failed to stop Instance Manager.") + } print "Shutting-down MySQL daemon\n\n"; stop_masters(); @@ -2752,7 +2817,7 @@ sub stop_masters () { my @args; - for ( my $idx; $idx < 2; $idx++ ) + for ( my $idx= 0; $idx < 2; $idx++ ) { # FIXME if we hit ^C before fully started, this test will prevent # the mysqld process from being killed @@ -2783,7 +2848,7 @@ sub stop_slaves () { my @args; - for ( my $idx; $idx < 3; $idx++ ) + for ( my $idx= 0; $idx < $max_slave_num; $idx++ ) { if ( $slave->[$idx]->{'pid'} ) { @@ -2901,7 +2966,8 @@ sub run_mysqltest ($) { my $cmdline_mysql= "$exe_mysql --host=localhost --user=root --password= " . "--port=$master->[0]->{'path_myport'} " . - "--socket=$master->[0]->{'path_mysock'}"; + "--socket=$master->[0]->{'path_mysock'} ". + "--character-sets-dir=$path_charsetsdir"; my $cmdline_mysql_client_test= "$exe_mysql_client_test --no-defaults --testcase --user=root --silent " . diff --git a/mysql-test/r/analyse.result b/mysql-test/r/analyse.result index 56f67cce4d6..0ecc462fb70 100644 --- a/mysql-test/r/analyse.result +++ b/mysql-test/r/analyse.result @@ -141,3 +141,16 @@ test.t1.product Computer TV 2 8 0 0 4.2500 NULL ENUM('Computer','Phone','TV') NO sum(profit) 10 6900 11 11 0 0 1946.2500 2867.6719 ENUM('10','275','600','6900') NOT NULL avg(profit) 10.0000 1380.0000 16 16 0 0 394.68750000 570.20033144 ENUM('10.0000','68.7500','120.0000','1380.0000') NOT NULL drop table t1,t2; +create table t1 (f1 double(10,5), f2 char(10), f3 double(10,5)); +insert into t1 values (5.999, "5.9999", 5.99999), (9.555, "9.5555", 9.55555); +select f1 from t1 procedure analyse(1, 1); +Field_name Min_value Max_value Min_length Max_length Empties_or_zeros Nulls Avg_value_or_avg_length Std Optimal_fieldtype +test.t1.f1 5.99900 9.55500 7 7 0 0 7.77700 1.77800 FLOAT(4,3) NOT NULL +select f2 from t1 procedure analyse(1, 1); +Field_name Min_value Max_value Min_length Max_length Empties_or_zeros Nulls Avg_value_or_avg_length Std Optimal_fieldtype +test.t1.f2 5.9999 9.5555 6 6 0 0 6.0000 NULL FLOAT(5,4) UNSIGNED NOT NULL +select f3 from t1 procedure analyse(1, 1); +Field_name Min_value Max_value Min_length Max_length Empties_or_zeros Nulls Avg_value_or_avg_length Std Optimal_fieldtype +test.t1.f3 5.99999 9.55555 7 7 0 0 7.77777 1.77778 FLOAT(6,5) NOT NULL +drop table t1; +End of 4.1 tests diff --git a/mysql-test/r/client_xml.result b/mysql-test/r/client_xml.result index 24c05c7f9d6..7395b2433e8 100644 --- a/mysql-test/r/client_xml.result +++ b/mysql-test/r/client_xml.result @@ -68,7 +68,7 @@ insert into t1 values (1, 2, 'a&b ab'); - NULL + drop table t1; diff --git a/mysql-test/r/create.result b/mysql-test/r/create.result index 3f8083a0e20..5f885ad199b 100644 --- a/mysql-test/r/create.result +++ b/mysql-test/r/create.result @@ -773,3 +773,5 @@ Warnings: Warning 1071 Specified key was too long; max key length is 765 bytes insert into t1 values('aaa'); drop table t1; +create table t1 (upgrade int); +drop table t1; diff --git a/mysql-test/r/ctype_gbk.result b/mysql-test/r/ctype_gbk.result index 241539ecf42..3f5d8b0d8c6 100644 --- a/mysql-test/r/ctype_gbk.result +++ b/mysql-test/r/ctype_gbk.result @@ -168,3 +168,13 @@ DROP TABLE t1; select hex(convert(_gbk 0xA14041 using ucs2)); hex(convert(_gbk 0xA14041 using ucs2)) 003F0041 +create table t1 (c1 text not null, c2 text not null) character set gbk; +alter table t1 change c1 c1 mediumtext character set gbk not null; +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `c1` mediumtext NOT NULL, + `c2` text NOT NULL +) ENGINE=MyISAM DEFAULT CHARSET=gbk +drop table t1; +End of 5.0 tests diff --git a/mysql-test/r/ctype_ucs.result b/mysql-test/r/ctype_ucs.result index 3b6bfa6d776..76fcbbeb9f8 100644 --- a/mysql-test/r/ctype_ucs.result +++ b/mysql-test/r/ctype_ucs.result @@ -755,6 +755,27 @@ select export_set(5, name, upper(name), ",", 5) from bug20536; export_set(5, name, upper(name), ",", 5) test1,TEST1,test1,TEST1,TEST1 'test\_2','TEST\_2','test\_2','TEST\_2','TEST\_2' +CREATE TABLE t1 ( +status enum('active','passive') collate latin1_general_ci +NOT NULL default 'passive' +); +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `status` enum('active','passive') character set latin1 collate latin1_general_ci NOT NULL default 'passive' +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +ALTER TABLE t1 ADD a int NOT NULL AFTER status; +CREATE TABLE t2 ( +status enum('active','passive') collate ucs2_turkish_ci +NOT NULL default 'passive' +); +SHOW CREATE TABLE t2; +Table Create Table +t2 CREATE TABLE `t2` ( + `status` enum('active','passive') character set ucs2 collate ucs2_turkish_ci NOT NULL default 'passive' +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +ALTER TABLE t2 ADD a int NOT NULL AFTER status; +DROP TABLE t1,t2; select password(name) from bug20536; password(name) ???????????????????? diff --git a/mysql-test/r/ctype_utf8.result b/mysql-test/r/ctype_utf8.result index bf271437fac..fd46f36227b 100644 --- a/mysql-test/r/ctype_utf8.result +++ b/mysql-test/r/ctype_utf8.result @@ -1340,6 +1340,18 @@ select a from t1 group by a; a e drop table t1; +create table t1(a char(10)) default charset utf8; +insert into t1 values ('123'), ('456'); +explain +select substr(Z.a,-1), Z.a from t1 as Y join t1 as Z on Y.a=Z.a order by 1; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE Y ALL NULL NULL NULL NULL 2 Using temporary; Using filesort +1 SIMPLE Z ALL NULL NULL NULL NULL 2 Using where +select substr(Z.a,-1), Z.a from t1 as Y join t1 as Z on Y.a=Z.a order by 1; +substr(Z.a,-1) a +3 123 +6 456 +drop table t1; CREATE TABLE t1(id varchar(20) NOT NULL) DEFAULT CHARSET=utf8; INSERT INTO t1 VALUES ('xxx'), ('aa'), ('yyy'), ('aa'); SELECT id FROM t1; @@ -1449,3 +1461,21 @@ set @a:=null; execute my_stmt using @a; a b drop table if exists t1; +CREATE TABLE t1 ( +colA int(11) NOT NULL, +colB varchar(255) character set utf8 NOT NULL, +PRIMARY KEY (colA) +) ENGINE=InnoDB DEFAULT CHARSET=latin1; +INSERT INTO t1 (colA, colB) VALUES (1, 'foo'), (2, 'foo bar'); +CREATE TABLE t2 ( +colA int(11) NOT NULL, +colB varchar(255) character set utf8 NOT NULL, +KEY bad (colA,colB(3)) +) ENGINE=InnoDB DEFAULT CHARSET=latin1; +INSERT INTO t2 (colA, colB) VALUES (1, 'foo'),(2, 'foo bar'); +SELECT * FROM t1 JOIN t2 ON t1.colA=t2.colA AND t1.colB=t2.colB +WHERE t1.colA < 3; +colA colB colA colB +1 foo 1 foo +2 foo bar 2 foo bar +DROP TABLE t1, t2; diff --git a/mysql-test/r/delayed.result b/mysql-test/r/delayed.result index a336f3b4108..6295fceec2b 100644 --- a/mysql-test/r/delayed.result +++ b/mysql-test/r/delayed.result @@ -7,6 +7,7 @@ insert delayed into t1 set a = 4; insert delayed into t1 set a = 5, tmsp = 19711006010203; insert delayed into t1 (a, tmsp) values (6, 19711006010203); insert delayed into t1 (a, tmsp) values (7, NULL); +FLUSH TABLE t1; insert into t1 set a = 8,tmsp=19711006010203; select * from t1 where tmsp=0; a tmsp @@ -22,6 +23,7 @@ insert delayed into t1 values (null,"c"); insert delayed into t1 values (3,"d"),(null,"e"); insert delayed into t1 values (3,"this will give an","error"); ERROR 21S01: Column count doesn't match value count at row 1 +FLUSH TABLE t1; show status like 'not_flushed_delayed_rows'; Variable_name Value Not_flushed_delayed_rows 0 @@ -54,6 +56,7 @@ insert delayed into t1 values(null); insert delayed into t1 values(null); insert delayed into t1 values(null); insert delayed into t1 values(null); +FLUSH TABLE t1; select * from t1 order by a; a 1 @@ -69,3 +72,174 @@ a 12 13 DROP TABLE t1; +SET @bug20627_old_auto_increment_offset= +@@auto_increment_offset= 2; +SET @bug20627_old_auto_increment_increment= +@@auto_increment_increment= 3; +SET @bug20627_old_session_auto_increment_offset= +@@session.auto_increment_offset= 4; +SET @bug20627_old_session_auto_increment_increment= +@@session.auto_increment_increment= 5; +SET @@auto_increment_offset= 2; +SET @@auto_increment_increment= 3; +SET @@session.auto_increment_offset= 4; +SET @@session.auto_increment_increment= 5; +CREATE TABLE t1 ( +c1 INT NOT NULL AUTO_INCREMENT, +PRIMARY KEY (c1) +); +INSERT INTO t1 VALUES (NULL),(NULL),(NULL); +SELECT * FROM t1; +c1 +4 +9 +14 +DROP TABLE t1; +CREATE TABLE t1 ( +c1 INT NOT NULL AUTO_INCREMENT, +PRIMARY KEY (c1) +); +INSERT DELAYED INTO t1 VALUES (NULL),(NULL),(NULL); +FLUSH TABLE t1; +SELECT * FROM t1; +c1 +4 +9 +14 +DROP TABLE t1; +SET @@auto_increment_offset= +@bug20627_old_auto_increment_offset; +SET @@auto_increment_increment= +@bug20627_old_auto_increment_increment; +SET @@session.auto_increment_offset= +@bug20627_old_session_auto_increment_offset; +SET @@session.auto_increment_increment= +@bug20627_old_session_auto_increment_increment; +SET @bug20830_old_auto_increment_offset= +@@auto_increment_offset= 2; +SET @bug20830_old_auto_increment_increment= +@@auto_increment_increment= 3; +SET @bug20830_old_session_auto_increment_offset= +@@session.auto_increment_offset= 4; +SET @bug20830_old_session_auto_increment_increment= +@@session.auto_increment_increment= 5; +SET @@auto_increment_offset= 2; +SET @@auto_increment_increment= 3; +SET @@session.auto_increment_offset= 4; +SET @@session.auto_increment_increment= 5; +CREATE TABLE t1 ( +c1 INT(11) NOT NULL AUTO_INCREMENT, +c2 INT(11) DEFAULT NULL, +PRIMARY KEY (c1) +); +SET insert_id= 14; +INSERT INTO t1 VALUES(NULL, 11), (NULL, 12), (NULL, 13); +INSERT INTO t1 VALUES(NULL, 21), (NULL, 22), (NULL, 23); +INSERT INTO t1 VALUES( 69, 31), (NULL, 32), (NULL, 33); +INSERT INTO t1 VALUES(NULL, 41), (NULL, 42), (NULL, 43); +SET insert_id= 114; +INSERT INTO t1 VALUES(NULL, 51), (NULL, 52), (NULL, 53); +INSERT INTO t1 VALUES(NULL, 61), (NULL, 62), (NULL, 63); +INSERT INTO t1 VALUES( 49, 71), (NULL, 72), (NULL, 73); +INSERT INTO t1 VALUES(NULL, 81), (NULL, 82), (NULL, 83); +SET insert_id= 114; +INSERT INTO t1 VALUES(NULL, 91); +ERROR 23000: Duplicate entry '114' for key 1 +INSERT INTO t1 VALUES (NULL, 92), (NULL, 93); +SELECT * FROM t1; +c1 c2 +14 11 +19 12 +24 13 +29 21 +34 22 +39 23 +69 31 +74 32 +79 33 +84 41 +89 42 +94 43 +114 51 +119 52 +124 53 +129 61 +134 62 +139 63 +49 71 +144 72 +149 73 +154 81 +159 82 +164 83 +169 92 +174 93 +SELECT COUNT(*) FROM t1; +COUNT(*) +26 +SELECT SUM(c1) FROM t1; +SUM(c1) +2569 +DROP TABLE t1; +CREATE TABLE t1 ( +c1 INT(11) NOT NULL AUTO_INCREMENT, +c2 INT(11) DEFAULT NULL, +PRIMARY KEY (c1) +); +SET insert_id= 14; +INSERT DELAYED INTO t1 VALUES(NULL, 11), (NULL, 12), (NULL, 13); +INSERT DELAYED INTO t1 VALUES(NULL, 21), (NULL, 22), (NULL, 23); +INSERT DELAYED INTO t1 VALUES( 69, 31), (NULL, 32), (NULL, 33); +INSERT DELAYED INTO t1 VALUES(NULL, 41), (NULL, 42), (NULL, 43); +SET insert_id= 114; +INSERT DELAYED INTO t1 VALUES(NULL, 51), (NULL, 52), (NULL, 53); +INSERT DELAYED INTO t1 VALUES(NULL, 61), (NULL, 62), (NULL, 63); +INSERT DELAYED INTO t1 VALUES( 49, 71), (NULL, 72), (NULL, 73); +INSERT DELAYED INTO t1 VALUES(NULL, 81), (NULL, 82), (NULL, 83); +SET insert_id= 114; +INSERT DELAYED INTO t1 VALUES(NULL, 91); +INSERT DELAYED INTO t1 VALUES (NULL, 92), (NULL, 93); +FLUSH TABLE t1; +SELECT * FROM t1; +c1 c2 +14 11 +19 12 +24 13 +29 21 +34 22 +39 23 +69 31 +74 32 +79 33 +84 41 +89 42 +94 43 +114 51 +119 52 +124 53 +129 61 +134 62 +139 63 +49 71 +144 72 +149 73 +154 81 +159 82 +164 83 +169 92 +174 93 +SELECT COUNT(*) FROM t1; +COUNT(*) +26 +SELECT SUM(c1) FROM t1; +SUM(c1) +2569 +DROP TABLE t1; +SET @@auto_increment_offset= +@bug20830_old_auto_increment_offset; +SET @@auto_increment_increment= +@bug20830_old_auto_increment_increment; +SET @@session.auto_increment_offset= +@bug20830_old_session_auto_increment_offset; +SET @@session.auto_increment_increment= +@bug20830_old_session_auto_increment_increment; diff --git a/mysql-test/r/delete.result b/mysql-test/r/delete.result index 0946dc8f809..9d337a1ed34 100644 --- a/mysql-test/r/delete.result +++ b/mysql-test/r/delete.result @@ -172,6 +172,10 @@ a 0 2 DROP TABLE t1; +create table t1 (a int); +delete `4.t1` from t1 as `4.t1` where `4.t1`.a = 5; +delete FROM `4.t1` USING t1 as `4.t1` where `4.t1`.a = 5; +drop table t1; CREATE TABLE t1 (a int not null,b int not null); CREATE TABLE t2 (a int not null, b int not null, primary key (a,b)); CREATE TABLE t3 (a int not null, b int not null, primary key (a,b)); diff --git a/mysql-test/r/execution_constants.result b/mysql-test/r/execution_constants.result new file mode 100644 index 00000000000..293c88dc506 --- /dev/null +++ b/mysql-test/r/execution_constants.result @@ -0,0 +1,12 @@ +CREATE TABLE `t_bug21476` ( +`ID_BOARD` smallint(5) unsigned NOT NULL default '0', +`ID_MEMBER` mediumint(8) unsigned NOT NULL default '0', +`logTime` int(10) unsigned NOT NULL default '0', +`ID_MSG` mediumint(8) unsigned NOT NULL default '0', +PRIMARY KEY (`ID_MEMBER`,`ID_BOARD`), +KEY `logTime` (`logTime`) +) ENGINE=MyISAM DEFAULT CHARSET=cp1251 COLLATE=cp1251_bulgarian_ci; +INSERT INTO `t_bug21476` VALUES (2,2,1154870939,0),(1,2,1154870957,0),(2,183,1154941362,0),(2,84,1154904301,0),(1,84,1154905867,0),(2,13,1154947484,10271),(3,84,1154880549,0),(1,6,1154892183,0),(2,25,1154947581,10271),(3,25,1154904760,0),(1,25,1154947373,10271),(1,179,1154899992,0),(2,179,1154899410,0),(5,25,1154901666,0),(2,329,1154902026,0),(3,329,1154902040,0),(1,329,1154902058,0),(1,13,1154930841,0),(3,85,1154904987,0),(1,183,1154929665,0),(3,13,1154931268,0),(1,85,1154936888,0),(1,169,1154937959,0),(2,169,1154941717,0),(3,183,1154939810,0),(3,169,1154941734,0); +Assertion: mysql_errno 1436 == 1436 +DROP TABLE `t_bug21476`; +End of 5.0 tests. diff --git a/mysql-test/r/func_gconcat.result b/mysql-test/r/func_gconcat.result index dc09a68682c..93925670d01 100644 --- a/mysql-test/r/func_gconcat.result +++ b/mysql-test/r/func_gconcat.result @@ -566,14 +566,14 @@ COUNT(*) GROUP_CONCAT(DISTINCT t2.somename SEPARATOR ' |') DROP TABLE t1,t2; select * from (select group_concat('c') from DUAL) t; group_concat('c') -NULL +c create table t1 ( a int not null default 0); select * from (select group_concat(a) from t1) t2; group_concat(a) NULL select group_concat('x') UNION ALL select 1; group_concat('x') -NULL +x 1 drop table t1; CREATE TABLE t1 (id int, a varchar(9)); @@ -654,3 +654,12 @@ CHAR_LENGTH( GROUP_CONCAT(b) ) 240001 SET GROUP_CONCAT_MAX_LEN = 1024; DROP TABLE t1; +CREATE TABLE t1 (a int, b int); +INSERT INTO t1 VALUES (2,1), (1,2), (2,2), (1,3); +SELECT GROUP_CONCAT(a), x +FROM (SELECT a, GROUP_CONCAT(b) x FROM t1 GROUP BY a) AS s +GROUP BY x; +GROUP_CONCAT(a) x +2 1,2 +1 2,3 +DROP TABLE t1; diff --git a/mysql-test/r/func_group.result b/mysql-test/r/func_group.result index f57b4ad6ce9..c6117053a60 100644 --- a/mysql-test/r/func_group.result +++ b/mysql-test/r/func_group.result @@ -856,6 +856,22 @@ EXPLAIN SELECT MAX(b) FROM t1; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 ALL NULL NULL NULL NULL 4 DROP TABLE t1; +CREATE TABLE t1 (a INT, b INT); +INSERT INTO t1 VALUES (1,1),(1,2),(2,3); +SELECT (SELECT COUNT(DISTINCT t1.b)) FROM t1 GROUP BY t1.a; +(SELECT COUNT(DISTINCT t1.b)) +2 +1 +SELECT (SELECT COUNT(DISTINCT 12)) FROM t1 GROUP BY t1.a; +(SELECT COUNT(DISTINCT 12)) +1 +1 +SELECT AVG(2), BIT_AND(2), BIT_OR(2), BIT_XOR(2), COUNT(*), COUNT(12), +COUNT(DISTINCT 12), MIN(2),MAX(2),STD(2), VARIANCE(2),SUM(2), +GROUP_CONCAT(2),GROUP_CONCAT(DISTINCT 2); +AVG(2) BIT_AND(2) BIT_OR(2) BIT_XOR(2) COUNT(*) COUNT(12) COUNT(DISTINCT 12) MIN(2) MAX(2) STD(2) VARIANCE(2) SUM(2) GROUP_CONCAT(2) GROUP_CONCAT(DISTINCT 2) +2.00000 2 2 2 1 1 1 2 2 0.00000 0.00000 2 2 2 +DROP TABLE t1; create table t2 (ff double); insert into t2 values (2.2); select cast(sum(distinct ff) as decimal(5,2)) from t2; @@ -997,7 +1013,7 @@ SELECT SQL_NO_CACHE WHERE ttt.a = ccc.b AND ttt.a = t.a GROUP BY ttt.a) AS minid FROM t1 t, t2 c WHERE t.a = c.b; minid -NULL +1 DROP TABLE t1,t2; create table t1 select variance(0); show create table t1; diff --git a/mysql-test/r/func_str.result b/mysql-test/r/func_str.result index 14da630f61e..00642e1a570 100644 --- a/mysql-test/r/func_str.result +++ b/mysql-test/r/func_str.result @@ -1113,4 +1113,39 @@ conv("18383815659218730760",10,10) + 0 select "18383815659218730760" + 0; "18383815659218730760" + 0 1.8383815659219e+19 +CREATE TABLE t1 (code varchar(10)); +INSERT INTO t1 VALUES ('a12'), ('A12'), ('a13'); +SELECT ASCII(code), code FROM t1 WHERE code='A12'; +ASCII(code) code +97 a12 +65 A12 +SELECT ASCII(code), code FROM t1 WHERE code='A12' AND ASCII(code)=65; +ASCII(code) code +65 A12 +INSERT INTO t1 VALUES ('a12 '), ('A12 '); +SELECT LENGTH(code), code FROM t1 WHERE code='A12'; +LENGTH(code) code +3 a12 +3 A12 +4 a12 +5 A12 +SELECT LENGTH(code), code FROM t1 WHERE code='A12' AND LENGTH(code)=5; +LENGTH(code) code +5 A12 +ALTER TABLE t1 ADD INDEX (code); +CREATE TABLE t2 (id varchar(10) PRIMARY KEY); +INSERT INTO t2 VALUES ('a11'), ('a12'), ('a13'), ('a14'); +SELECT * FROM t1 INNER JOIN t2 ON t1.code=t2.id +WHERE t2.id='a12' AND (LENGTH(code)=5 OR code < 'a00'); +code id +A12 a12 +EXPLAIN EXTENDED +SELECT * FROM t1 INNER JOIN t2 ON code=id +WHERE id='a12' AND (LENGTH(code)=5 OR code < 'a00'); +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ref code code 13 const 3 Using where; Using index +1 SIMPLE t2 ref PRIMARY PRIMARY 12 const 1 Using where; Using index +Warnings: +Note 1003 select `test`.`t1`.`code` AS `code`,`test`.`t2`.`id` AS `id` from `test`.`t1` join `test`.`t2` where ((`test`.`t1`.`code` = _latin1'a12') and (`test`.`t2`.`id` = _latin1'a12') and (length(`test`.`t1`.`code`) = 5)) +DROP TABLE t1,t2; End of 5.0 tests diff --git a/mysql-test/r/func_time.result b/mysql-test/r/func_time.result index dc6a4561531..25c910a711a 100644 --- a/mysql-test/r/func_time.result +++ b/mysql-test/r/func_time.result @@ -840,39 +840,38 @@ drop table t1; create table t1(f1 date, f2 time, f3 datetime); insert into t1 values ("2006-01-01", "12:01:01", "2006-01-01 12:01:01"); insert into t1 values ("2006-01-02", "12:01:02", "2006-01-02 12:01:02"); -select f1 from t1 where f1 between "2006-1-1" and 20060101; +select f1 from t1 where f1 between CAST("2006-1-1" as date) and CAST(20060101 as date); f1 2006-01-01 -select f1 from t1 where f1 between "2006-1-1" and "2006.1.1"; +select f1 from t1 where f1 between cast("2006-1-1" as date) and cast("2006.1.1" as date); f1 2006-01-01 -select f1 from t1 where date(f1) between "2006-1-1" and "2006.1.1"; +select f1 from t1 where date(f1) between cast("2006-1-1" as date) and cast("2006.1.1" as date); f1 2006-01-01 -select f2 from t1 where f2 between "12:1:2" and "12:2:2"; +select f2 from t1 where f2 between cast("12:1:2" as time) and cast("12:2:2" as time); f2 12:01:02 -select f2 from t1 where time(f2) between "12:1:2" and "12:2:2"; +select f2 from t1 where time(f2) between cast("12:1:2" as time) and cast("12:2:2" as time); f2 12:01:02 -select f3 from t1 where f3 between "2006-1-1 12:1:1" and "2006-1-1 12:1:2"; +select f3 from t1 where f3 between cast("2006-1-1 12:1:1" as datetime) and cast("2006-1-1 12:1:2" as datetime); f3 2006-01-01 12:01:01 -select f3 from t1 where timestamp(f3) between "2006-1-1 12:1:1" and "2006-1-1 12:1:2"; +select f3 from t1 where timestamp(f3) between cast("2006-1-1 12:1:1" as datetime) and cast("2006-1-1 12:1:2" as datetime); f3 2006-01-01 12:01:01 -select f1 from t1 where "2006-1-1" between f1 and f3; +select f1 from t1 where cast("2006-1-1" as date) between f1 and f3; f1 2006-01-01 -select f1 from t1 where "2006-1-1" between date(f1) and date(f3); +select f1 from t1 where cast("2006-1-1" as date) between date(f1) and date(f3); f1 2006-01-01 -select f1 from t1 where "2006-1-1" between f1 and 'zzz'; +select f1 from t1 where cast("2006-1-1" as date) between f1 and cast('zzz' as date); f1 Warnings: -Warning 1292 Incorrect date value: 'zzz' for column 'f1' at row 1 -Warning 1292 Truncated incorrect DOUBLE value: 'zzz' -Warning 1292 Truncated incorrect DOUBLE value: 'zzz' +Warning 1292 Truncated incorrect datetime value: 'zzz' +Warning 1292 Truncated incorrect datetime value: 'zzz' select f1 from t1 where makedate(2006,1) between date(f1) and date(f3); f1 2006-01-01 @@ -891,6 +890,18 @@ t1 CREATE TABLE `t1` ( `from_unixtime(1) + 0` double(23,6) default NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 drop table t1; +SET NAMES latin1; +SET character_set_results = NULL; +SHOW VARIABLES LIKE 'character_set_results'; +Variable_name Value +character_set_results +CREATE TABLE testBug8868 (field1 DATE, field2 VARCHAR(32) CHARACTER SET BINARY); +INSERT INTO testBug8868 VALUES ('2006-09-04', 'abcd'); +SELECT DATE_FORMAT(field1,'%b-%e %l:%i%p') as fmtddate, field2 FROM testBug8868; +fmtddate field2 +Sep-4 12:00AM abcd +DROP TABLE testBug8868; +SET NAMES DEFAULT; (select time_format(timediff(now(), DATE_SUB(now(),INTERVAL 5 DAY)),'%H') As H) union (select time_format(timediff(now(), DATE_SUB(now(),INTERVAL 5 DAY)),'%H') As H); diff --git a/mysql-test/r/group_by.result b/mysql-test/r/group_by.result index 57cb09fe44c..5eb2e5744c1 100644 --- a/mysql-test/r/group_by.result +++ b/mysql-test/r/group_by.result @@ -807,8 +807,8 @@ explain SELECT straight_join sql_no_cache v1.a, v1.b, v1.real_b from t2, v1 where t2.b=v1.a GROUP BY t2.b; id select_type table type possible_keys key key_len ref rows Extra -1 PRIMARY t2 index b b 2 NULL 10 Using index -1 PRIMARY t1 eq_ref PRIMARY PRIMARY 1 test.t2.b 1 +1 SIMPLE t2 index b b 2 NULL 10 Using index +1 SIMPLE t1 eq_ref PRIMARY PRIMARY 1 test.t2.b 1 SELECT straight_join sql_no_cache v1.a, v1.b, v1.real_b from t2, v1 where t2.b=v1.a GROUP BY t2.b; a b real_b @@ -821,12 +821,3 @@ a b real_b 68 France France DROP VIEW v1; DROP TABLE t1,t2; -CREATE TABLE t1 (a INT, b INT, KEY(a)); -INSERT INTO t1 VALUES (1, 1), (2, 2), (3,3), (4,4); -EXPLAIN SELECT a, SUM(b) FROM t1 GROUP BY a LIMIT 2; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 index NULL a 5 NULL 4 -EXPLAIN SELECT a, SUM(b) FROM t1 IGNORE INDEX (a) GROUP BY a LIMIT 2; -id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 ALL NULL NULL NULL NULL 4 Using temporary; Using filesort -DROP TABLE t1; diff --git a/mysql-test/r/heap_hash.result b/mysql-test/r/heap_hash.result index e0835bbf8d6..80abcebbfea 100644 --- a/mysql-test/r/heap_hash.result +++ b/mysql-test/r/heap_hash.result @@ -354,7 +354,7 @@ t3 1 a 2 b NULL 13 NULL NULL HASH explain select * from t1 ignore key(btree_idx), t3 where t1.name='matt' and t3.a = concat('',t1.name) and t3.b=t1.name; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 ref heap_idx heap_idx 22 const 7 Using where -1 SIMPLE t3 ref a a 44 const,const 7 Using where +1 SIMPLE t3 ref a a 44 func,const 7 Using where drop table t1, t2, t3; create temporary table t1 ( a int, index (a) ) engine=memory; insert into t1 values (1),(2),(3),(4),(5); diff --git a/mysql-test/r/im_daemon_life_cycle.result b/mysql-test/r/im_daemon_life_cycle.result index b805bdc9166..52a69d98fcf 100644 --- a/mysql-test/r/im_daemon_life_cycle.result +++ b/mysql-test/r/im_daemon_life_cycle.result @@ -8,3 +8,17 @@ mysqld2 offline Killing the process... Sleeping... Success: the process was restarted. + +-------------------------------------------------------------------- +-- Test for BUG#12751 +-------------------------------------------------------------------- +START INSTANCE mysqld2; +Success: the process has been started. +Killing the process... +Sleeping... +Success: the process was restarted. +SHOW INSTANCE STATUS mysqld1; +instance_name status version +mysqld1 online VERSION +STOP INSTANCE mysqld2; +Success: the process has been stopped. diff --git a/mysql-test/r/index_merge.result b/mysql-test/r/index_merge.result index 3a69f56cbd3..3f3360e2da0 100644 --- a/mysql-test/r/index_merge.result +++ b/mysql-test/r/index_merge.result @@ -424,3 +424,34 @@ id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t3 index_merge a,b a,b 5,5 NULL # Using intersect(a,b); Using where drop table t3; drop table t0, t1, t2; +CREATE TABLE t1(a INT); +INSERT INTO t1 VALUES(1); +CREATE TABLE t2(a INT, b INT, dummy CHAR(16) DEFAULT '', KEY(a), KEY(b)); +INSERT INTO t2(a,b) VALUES +(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0), +(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0), +(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0), +(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0), +(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0), +(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0), +(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0), +(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0), +(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0), +(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0), +(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0), +(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0), +(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0), +(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0), +(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0), +(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0), +(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0), +(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0), +(1,2); +LOCK TABLES t1 WRITE, t2 WRITE; +INSERT INTO t2(a,b) VALUES(1,2); +SELECT t2.a FROM t1,t2 WHERE t2.b=2 AND t2.a=1; +a +1 +1 +UNLOCK TABLES; +DROP TABLE t1, t2; diff --git a/mysql-test/r/information_schema.result b/mysql-test/r/information_schema.result index 652af1c8387..407f8a040b7 100644 --- a/mysql-test/r/information_schema.result +++ b/mysql-test/r/information_schema.result @@ -337,7 +337,7 @@ mysql test explain select * from v0; id select_type table type possible_keys key key_len ref rows Extra -1 PRIMARY # ALL NULL NULL NULL NULL 2 +1 SIMPLE # ALL NULL NULL NULL NULL 2 create view v1 (c) as select table_name from information_schema.tables where table_name="v1"; select * from v1; diff --git a/mysql-test/r/innodb_mysql.result b/mysql-test/r/innodb_mysql.result index e7d097a1d2f..b4101e037f2 100644 --- a/mysql-test/r/innodb_mysql.result +++ b/mysql-test/r/innodb_mysql.result @@ -118,7 +118,7 @@ min(7) NULL select min(7) from DUAL; min(7) -NULL +7 explain select min(7) from t2m join t1m; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Select tables optimized away @@ -133,7 +133,7 @@ max(7) NULL select max(7) from DUAL; max(7) -NULL +7 explain select max(7) from t2m join t1m; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Select tables optimized away @@ -172,7 +172,7 @@ min(7) NULL select min(7) from DUAL; min(7) -NULL +7 explain select min(7) from t2i join t1i; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t2i ALL NULL NULL NULL NULL 1 @@ -188,7 +188,7 @@ max(7) NULL select max(7) from DUAL; max(7) -NULL +7 explain select max(7) from t2i join t1i; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t2i ALL NULL NULL NULL NULL 1 diff --git a/mysql-test/r/insert_select.result b/mysql-test/r/insert_select.result index 89ac863b8d2..0af48d27cd5 100644 --- a/mysql-test/r/insert_select.result +++ b/mysql-test/r/insert_select.result @@ -695,6 +695,16 @@ CREATE TABLE t2 (z int, y int); CREATE TABLE t3 (a int, b int); INSERT INTO t3 (SELECT x, y FROM t1 JOIN t2 USING (y) WHERE z = 1); DROP TABLE IF EXISTS t1,t2,t3; +CREATE DATABASE bug21774_1; +CREATE DATABASE bug21774_2; +CREATE TABLE bug21774_1.t1(id VARCHAR(10) NOT NULL,label VARCHAR(255)); +CREATE TABLE bug21774_2.t1(id VARCHAR(10) NOT NULL,label VARCHAR(255)); +CREATE TABLE bug21774_1.t2(id VARCHAR(10) NOT NULL,label VARCHAR(255)); +INSERT INTO bug21774_2.t1 SELECT t1.* FROM bug21774_1.t1; +use bug21774_1; +INSERT INTO bug21774_2.t1 SELECT t1.* FROM t1; +DROP DATABASE bug21774_1; +DROP DATABASE bug21774_2; CREATE DATABASE meow; CREATE TABLE table_target ( mexs_id CHAR(8), messzeit TIMESTAMP, PRIMARY KEY (mexs_id)); CREATE TABLE table_target2 ( mexs_id CHAR(8), messzeit TIMESTAMP, PRIMARY KEY (mexs_id)); diff --git a/mysql-test/r/insert_update.result b/mysql-test/r/insert_update.result index dbe5d600a95..6be37450835 100644 --- a/mysql-test/r/insert_update.result +++ b/mysql-test/r/insert_update.result @@ -63,9 +63,9 @@ Warnings: Note 1003 select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b`,`test`.`t1`.`c` AS `c`,values(`test`.`t1`.`a`) AS `VALUES(a)` from `test`.`t1` explain extended select * from t1 where values(a); id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE +1 SIMPLE t1 ALL NULL NULL NULL NULL 5 Using where Warnings: -Note 1003 select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b`,`test`.`t1`.`c` AS `c` from `test`.`t1` +Note 1003 select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b`,`test`.`t1`.`c` AS `c` from `test`.`t1` where values(`test`.`t1`.`a`) DROP TABLE t1; create table t1(a int primary key, b int); insert into t1 values(1,1),(2,2),(3,3),(4,4),(5,5); @@ -197,3 +197,25 @@ PRIMARY KEY (a) ) ENGINE=MyISAM; INSERT INTO t1 ( a ) SELECT 0 ON DUPLICATE KEY UPDATE a = a + VALUES (a) ; DROP TABLE t1; +CREATE TABLE t1 +( +a BIGINT UNSIGNED, +b BIGINT UNSIGNED, +PRIMARY KEY (a) +); +INSERT INTO t1 VALUES (45, 1) ON DUPLICATE KEY UPDATE b = +IF(VALUES(b) > t1.b, VALUES(b), t1.b); +SELECT * FROM t1; +a b +45 1 +INSERT INTO t1 VALUES (45, 2) ON DUPLICATE KEY UPDATE b = +IF(VALUES(b) > t1.b, VALUES(b), t1.b); +SELECT * FROM t1; +a b +45 2 +INSERT INTO t1 VALUES (45, 1) ON DUPLICATE KEY UPDATE b = +IF(VALUES(b) > t1.b, VALUES(b), t1.b); +SELECT * FROM t1; +a b +45 2 +DROP TABLE t1; diff --git a/mysql-test/r/join_outer.result b/mysql-test/r/join_outer.result index 2d9652ff0e3..89bb26c4b3f 100644 --- a/mysql-test/r/join_outer.result +++ b/mysql-test/r/join_outer.result @@ -1126,7 +1126,7 @@ a b a b 7 8 7 5 EXPLAIN SELECT * FROM t1 LEFT JOIN t2 ON t1.a = t2.a WHERE t1.a = t2.a OR t1.a = t2.b; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t2 ALL PRIMARY NULL NULL NULL 4 Using where +1 SIMPLE t2 ALL PRIMARY NULL NULL NULL 4 1 SIMPLE t1 eq_ref PRIMARY PRIMARY 4 test.t2.a 1 EXPLAIN SELECT * FROM t1 LEFT JOIN t2 ON t1.a = t2.a WHERE t1.a IN(t2.a, t2.b); id select_type table type possible_keys key key_len ref rows Extra diff --git a/mysql-test/r/loaddata.result b/mysql-test/r/loaddata.result index 17e1966dbc9..d415bd468e0 100644 --- a/mysql-test/r/loaddata.result +++ b/mysql-test/r/loaddata.result @@ -43,9 +43,9 @@ drop table t1; create table t1 (a int, b char(10)); load data infile '../std_data_ln/loaddata3.dat' into table t1 fields terminated by '' enclosed by '' ignore 1 lines; Warnings: -Warning 1264 Out of range value adjusted for column 'a' at row 3 +Warning 1366 Incorrect integer value: 'error ' for column 'a' at row 3 Warning 1262 Row 3 was truncated; it contained more data than there were input columns -Warning 1264 Out of range value adjusted for column 'a' at row 5 +Warning 1366 Incorrect integer value: 'wrong end ' for column 'a' at row 5 Warning 1262 Row 5 was truncated; it contained more data than there were input columns select * from t1; a b @@ -57,7 +57,8 @@ a b truncate table t1; load data infile '../std_data_ln/loaddata4.dat' into table t1 fields terminated by '' enclosed by '' lines terminated by '' ignore 1 lines; Warnings: -Warning 1264 Out of range value adjusted for column 'a' at row 4 +Warning 1366 Incorrect integer value: ' +' for column 'a' at row 4 Warning 1261 Row 4 doesn't contain data for all columns select * from t1; a b diff --git a/mysql-test/r/loaddata_autocom_innodb.result b/mysql-test/r/loaddata_autocom_innodb.result new file mode 100644 index 00000000000..10da6b5dde7 --- /dev/null +++ b/mysql-test/r/loaddata_autocom_innodb.result @@ -0,0 +1,21 @@ +SET SESSION STORAGE_ENGINE = InnoDB; +drop table if exists t1; +create table t1 (a text, b text); +start transaction; +load data infile '../std_data_ln/loaddata2.dat' into table t1 fields terminated by ',' enclosed by ''''; +Warnings: +Warning 1261 Row 3 doesn't contain data for all columns +commit; +select count(*) from t1; +count(*) +4 +truncate table t1; +start transaction; +load data infile '../std_data_ln/loaddata2.dat' into table t1 fields terminated by ',' enclosed by ''''; +Warnings: +Warning 1261 Row 3 doesn't contain data for all columns +rollback; +select count(*) from t1; +count(*) +0 +drop table t1; diff --git a/mysql-test/r/loaddata_autocom_ndb.result b/mysql-test/r/loaddata_autocom_ndb.result new file mode 100644 index 00000000000..94e5f825fa2 --- /dev/null +++ b/mysql-test/r/loaddata_autocom_ndb.result @@ -0,0 +1,23 @@ +SET SESSION STORAGE_ENGINE = ndbcluster; +drop table if exists t1; +create table t1 (a text, b text); +start transaction; +load data infile '../std_data_ln/loaddata2.dat' into table t1 fields terminated by ',' enclosed by ''''; +Warnings: +Warning 1261 Row 3 doesn't contain data for all columns +commit; +select count(*) from t1; +count(*) +4 +truncate table t1; +start transaction; +load data infile '../std_data_ln/loaddata2.dat' into table t1 fields terminated by ',' enclosed by ''''; +Warnings: +Warning 1261 Row 3 doesn't contain data for all columns +rollback; +Warnings: +Warning 1196 Some non-transactional changed tables couldn't be rolled back +select count(*) from t1; +count(*) +4 +drop table t1; diff --git a/mysql-test/r/merge.result b/mysql-test/r/merge.result index b8fdd24be74..6a065bd7332 100644 --- a/mysql-test/r/merge.result +++ b/mysql-test/r/merge.result @@ -178,9 +178,9 @@ t3 CREATE TABLE `t3` ( ) ENGINE=MRG_MyISAM DEFAULT CHARSET=latin1 UNION=(`t1`,`t2`) create table t4 (a int not null, b char(10), key(a)) engine=MERGE UNION=(t1,t2); select * from t4; -ERROR HY000: All tables in the MERGE table are not identically defined +ERROR HY000: Unable to open underlying table which is differently defined or of non-MyISAM type or doesn't exist alter table t4 add column c int; -ERROR HY000: All tables in the MERGE table are not identically defined +ERROR HY000: Unable to open underlying table which is differently defined or of non-MyISAM type or doesn't exist create database mysqltest; create table mysqltest.t6 (a int not null primary key auto_increment, message char(20)); create table t5 (a int not null, b char(20), key(a)) engine=MERGE UNION=(test.t1,mysqltest.t6); @@ -768,6 +768,21 @@ Table Op Msg_type Msg_text test.t1 check status OK test.t2 check status OK drop table t1, t2, t3; +CREATE TABLE t1(a INT); +INSERT INTO t1 VALUES(2),(1); +CREATE TABLE t2(a INT, KEY(a)) ENGINE=MERGE UNION=(t1); +SELECT * FROM t2 WHERE a=2; +ERROR HY000: Got error 124 from storage engine +DROP TABLE t1, t2; +CREATE TABLE t1(a INT) ENGINE=MEMORY; +CREATE TABLE t2(a INT) ENGINE=MERGE UNION=(t1); +SELECT * FROM t2; +ERROR HY000: Unable to open underlying table which is differently defined or of non-MyISAM type or doesn't exist +DROP TABLE t1, t2; +CREATE TABLE t2(a INT) ENGINE=MERGE UNION=(t3); +SELECT * FROM t2; +ERROR HY000: Unable to open underlying table which is differently defined or of non-MyISAM type or doesn't exist +DROP TABLE t2; create table t1 (b bit(1)); create table t2 (b bit(1)); create table tm (b bit(1)) engine = merge union = (t1,t2); diff --git a/mysql-test/r/myisam.result b/mysql-test/r/myisam.result index c7d8f5c128d..0021e6717ee 100644 --- a/mysql-test/r/myisam.result +++ b/mysql-test/r/myisam.result @@ -515,6 +515,34 @@ select c1 from t1 order by c1 limit 1; c1 a drop table t1; +create table t1 (a int not null, primary key(a)); +create table t2 (a int not null, b int not null, primary key(a,b)); +insert into t1 values (1),(2),(3),(4),(5),(6); +insert into t2 values (1,1),(2,1); +lock tables t1 read local, t2 read local; +select straight_join * from t1,t2 force index (primary) where t1.a=t2.a; +a a b +1 1 1 +2 2 1 +insert into t2 values(2,0); +select straight_join * from t1,t2 force index (primary) where t1.a=t2.a; +a a b +1 1 1 +2 2 1 +drop table t1,t2; +CREATE TABLE t1 (c1 varchar(250) NOT NULL); +CREATE TABLE t2 (c1 varchar(250) NOT NULL, PRIMARY KEY (c1)); +INSERT INTO t1 VALUES ('test000001'), ('test000002'), ('test000003'); +INSERT INTO t2 VALUES ('test000002'), ('test000003'), ('test000004'); +LOCK TABLES t1 READ LOCAL, t2 READ LOCAL; +SELECT t1.c1 AS t1c1, t2.c1 AS t2c1 FROM t1, t2 +WHERE t1.c1 = t2.c1 HAVING t1c1 != t2c1; +t1c1 t2c1 +INSERT INTO t2 VALUES ('test000001'), ('test000005'); +SELECT t1.c1 AS t1c1, t2.c1 AS t2c1 FROM t1, t2 +WHERE t1.c1 = t2.c1 HAVING t1c1 != t2c1; +t1c1 t2c1 +DROP TABLE t1,t2; CREATE TABLE t1 (`a` int(11) NOT NULL default '0', `b` int(11) NOT NULL default '0', UNIQUE KEY `a` USING RTREE (`a`,`b`)) ENGINE=MyISAM; Got one of the listed errors create table t1 (a int, b varchar(200), c text not null) checksum=1; diff --git a/mysql-test/r/mysql.result b/mysql-test/r/mysql.result index 99633f5e12a..1053b1918fb 100644 --- a/mysql-test/r/mysql.result +++ b/mysql-test/r/mysql.result @@ -76,6 +76,16 @@ c_cp932 | >a < | 0123456789 | 4 | | >abcd< | | 4 | +----------------------+------------+--------+ ++-------------------+ +| __tañgè Ñãmé | ++-------------------+ +| John Doe | ++-------------------+ ++-------------------+ +| John Doe | ++-------------------+ +| __tañgè Ñãmé | ++-------------------+ +------+------+---------------------------+ | i | j | k | +------+------+---------------------------+ @@ -85,6 +95,12 @@ c_cp932 | NULL | NULL | Τη γλώσσα | | NULL | NULL | á›–áš´ áš·á›–á› | +------+------+---------------------------+ +i j k +NULL 1 NULL +Field Type Null Key Default Extra +i int(11) YES NULL +j int(11) NO +k int(11) YES NULL +------+---+------+ | i | j | k | +------+---+------+ @@ -97,6 +113,10 @@ c_cp932 | j | int(11) | NO | | | | | k | int(11) | YES | | NULL | | +-------+---------+------+-----+---------+-------+ +i s1 +1 x +2 NULL +3 +------+------+ | i | s1 | +------+------+ @@ -104,6 +124,13 @@ c_cp932 | 2 | NULL | | 3 | | +------+------+ +unhex('zz') +NULL ++-------------+ +| unhex('zz') | ++-------------+ +| NULL | ++-------------+ create table t1(a int, b varchar(255), c int); Field Type Null Key Default Extra a int(11) YES NULL diff --git a/mysql-test/r/mysqldump.result b/mysql-test/r/mysqldump.result index 1d131c67c73..ee50fc42203 100644 --- a/mysql-test/r/mysqldump.result +++ b/mysql-test/r/mysqldump.result @@ -22,6 +22,9 @@ INSERT INTO t1 VALUES (1), (2); DROP TABLE t1; +# +# Bug #2005 +# CREATE TABLE t1 (a decimal(64, 20)); INSERT INTO t1 VALUES ("1234567890123456789012345678901234567890"), ("0987654321098765432109876543210987654321"); @@ -30,6 +33,9 @@ CREATE TABLE `t1` ( ) ENGINE=MyISAM DEFAULT CHARSET=latin1; INSERT INTO `t1` VALUES ('1234567890123456789012345678901234567890.00000000000000000000'),('987654321098765432109876543210987654321.00000000000000000000'); DROP TABLE t1; +# +# Bug #2055 +# CREATE TABLE t1 (a double); INSERT INTO t1 VALUES ('-9e999999'); Warnings: @@ -39,6 +45,9 @@ CREATE TABLE `t1` ( ) ENGINE=MyISAM DEFAULT CHARSET=latin1; INSERT INTO `t1` VALUES (RES); DROP TABLE t1; +# +# Bug #3361 mysqldump quotes DECIMAL values inconsistently +# CREATE TABLE t1 (a DECIMAL(10,5), b FLOAT); INSERT INTO t1 VALUES (1.2345, 2.3456); INSERT INTO t1 VALUES ('1.2345', 2.3456); @@ -136,6 +145,9 @@ INSERT INTO t1 VALUES (1, "test", "tes"), (2, "TEST", "TES"); DROP TABLE t1; +# +# Bug #1707 +# CREATE TABLE t1 (`a"b"` char(2)); INSERT INTO t1 VALUES ("1\""), ("\"2"); @@ -155,6 +167,10 @@ INSERT INTO t1 VALUES ("1\""), ("\"2"); DROP TABLE t1; +# +# Bug #1994 +# Bug #4261 +# CREATE TABLE t1 (a VARCHAR(255)) DEFAULT CHARSET koi8r; INSERT INTO t1 VALUES (_koi8r x'C1C2C3C4C5'), (NULL); @@ -190,6 +206,9 @@ UNLOCK TABLES; /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; DROP TABLE t1; +# +# Bug #2634 +# CREATE TABLE t1 (a int) ENGINE=MYISAM; INSERT INTO t1 VALUES (1), (2); /*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */; @@ -239,11 +258,17 @@ UNLOCK TABLES; /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; DROP TABLE t1; +# +# Bug #2592 'mysqldump doesn't quote "tricky" names correctly' +# create table ```a` (i int); CREATE TABLE ```a` ( `i` int(11) default NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1; drop table ```a`; +# +# Bug #2591 "mysqldump quotes names inconsistently" +# create table t1(a int); /*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; @@ -352,6 +377,9 @@ UNLOCK TABLES; set global sql_mode=''; drop table t1; +# +# Bug #2705 'mysqldump --tab extra output' +# create table t1(a int); insert into t1 values (1),(2),(3); @@ -380,6 +408,9 @@ CREATE TABLE `t1` ( 2 3 drop table t1; +# +# Bug #6101: create database problem +# /*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; /*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; @@ -432,6 +463,12 @@ USE `mysqldump_test_db`; /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; drop database mysqldump_test_db; +# +# Bug #7020 +# Check that we don't dump in UTF8 in compatible mode by default, +# but use the default compiled values, or the values given in +# --default-character-set=xxx. However, we should dump in UTF8 +# if it is explicitely set. CREATE TABLE t1 (a CHAR(10)); INSERT INTO t1 VALUES (_latin1 'ÄÖÜß'); @@ -465,6 +502,13 @@ UNLOCK TABLES; /*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; +# +# Bug#8063: make test mysqldump [ fail ] +# We cannot tes this command because its output depends +# on --default-character-set incompiled into "mysqldump" program. +# If the future we can move this command into a separate test with +# checking that "mysqldump" is compiled with "latin1" +# /*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */; /*!40103 SET TIME_ZONE='+00:00' */; /*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; @@ -535,6 +579,9 @@ UNLOCK TABLES; /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; DROP TABLE t1; +# +# WL #2319: Exclude Tables from dump +# CREATE TABLE t1 (a int); CREATE TABLE t2 (a int); INSERT INTO t1 VALUES (1),(2),(3); @@ -572,6 +619,9 @@ UNLOCK TABLES; DROP TABLE t1; DROP TABLE t2; +# +# Bug #8830 +# CREATE TABLE t1 (`b` blob); INSERT INTO `t1` VALUES (0x602010000280100005E71A); @@ -606,6 +656,9 @@ UNLOCK TABLES; /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; DROP TABLE t1; +# +# Test for --insert-ignore +# CREATE TABLE t1 (a int); INSERT INTO t1 VALUES (1),(2),(3); INSERT INTO t1 VALUES (4),(5),(6); @@ -670,6 +723,10 @@ INSERT DELAYED IGNORE INTO `t1` VALUES (1),(2),(3),(4),(5),(6); /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; DROP TABLE t1; +# +# Bug #10286: mysqldump -c crashes on table that has many fields with long +# names +# create table t1 ( F_c4ca4238a0b923820dcc509a6f75849b int, F_c81e728d9d4c2f636f067f89cc14862c int, @@ -1363,6 +1420,9 @@ UNLOCK TABLES; /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; drop table t1; +# +# Test for --add-drop-database +# CREATE TABLE t1 (a int); INSERT INTO t1 VALUES (1),(2),(3); @@ -1403,6 +1463,9 @@ UNLOCK TABLES; /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; DROP TABLE t1; +# +# Bug #9558 mysqldump --no-data db t1 t2 format still dumps data +# CREATE DATABASE mysqldump_test_db; USE mysqldump_test_db; CREATE TABLE t1 ( a INT ); @@ -1491,6 +1554,11 @@ CREATE TABLE `t2` ( DROP TABLE t1, t2; DROP DATABASE mysqldump_test_db; +# +# Testing with tables and databases that don't exists +# or contains illegal characters +# (Bug #9358 mysqldump crashes if tablename starts with \) +# create database mysqldump_test_db; use mysqldump_test_db; create table t1(a varchar(30) primary key, b int not null); @@ -1529,6 +1597,9 @@ mysqldump: Got error: 1102: Incorrect database name 'mysqld\ump_test_db' when se drop table t1, t2, t3; drop database mysqldump_test_db; use test; +# +# Bug #9657 mysqldump xml ( -x ) does not format NULL fields correctly +# create table t1 (a int(10)); create table t2 (pk int primary key auto_increment, a int(10), b varchar(30), c datetime, d blob, e text); @@ -1585,6 +1656,9 @@ insert into t2 (a, b) values (NULL, NULL),(10, NULL),(NULL, "twenty"),(30, "thir drop table t1, t2; +# +# BUG #12123 +# create table t1 (a text character set utf8, b text character set latin1); insert t1 values (0x4F736E616272C3BC636B, 0x4BF66C6E); select * from t1; @@ -1595,7 +1669,13 @@ select * from t1; a b Osnabrück Köln drop table t1; +# +# BUG#15328 Segmentation fault occured if my.cnf is invalid for escape sequence +# --fields-optionally-enclosed-by=" +# +# BUG #19025 mysqldump doesn't correctly dump "auto_increment = [int]" +# create table `t1` ( t1_name varchar(255) default null, t1_id int(10) unsigned not null auto_increment, @@ -1633,6 +1713,9 @@ t1 CREATE TABLE `t1` ( KEY `t1_name` (`t1_name`) ) ENGINE=MyISAM AUTO_INCREMENT=1003 DEFAULT CHARSET=latin1 drop table `t1`; +# +# Bug #18536: wrong table order +# create table t1(a int); create table t2(a int); create table t3(a int); @@ -1670,6 +1753,9 @@ CREATE TABLE `t2` ( /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; drop table t1, t2, t3; +# +# Bug #21288: mysqldump segmentation fault when using --where +# create table t1 (a int); mysqldump: Couldn't execute 'SELECT /*!40001 SQL_NO_CACHE */ * FROM `t1` WHERE xx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx': You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' at line 1 (1064) mysqldump: Got error: 1064: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' at line 1 when retrieving data from server @@ -1701,6 +1787,9 @@ CREATE TABLE `t1` ( drop table t1; End of 4.1 tests +# +# Bug #10213 mysqldump crashes when dumping VIEWs(on MacOS X) +# create database db1; use db1; CREATE TABLE t2 ( @@ -1760,6 +1849,9 @@ drop table t2; drop view v2; drop database db1; use test; +# +# Bug 10713 mysqldump includes database in create view and referenced tables +# create database db2; use db2; create table t1 (a int); @@ -1833,6 +1925,9 @@ DROP TABLE IF EXISTS `v1`; drop view v1; drop table t1; +# +# Bug #10213 mysqldump crashes when dumping VIEWs(on MacOS X) +# create database mysqldump_test_db; use mysqldump_test_db; CREATE TABLE t2 ( @@ -1892,6 +1987,9 @@ drop table t2; drop view v2; drop database mysqldump_test_db; use test; +# +# Bug #9756 +# CREATE TABLE t1 (a char(10)); INSERT INTO t1 VALUES ('\''); @@ -1926,6 +2024,9 @@ UNLOCK TABLES; /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; DROP TABLE t1; +# +# Bug #10927 mysqldump: Can't reload dump with view that consist of other view +# create table t1(a int, b int, c varchar(30)); insert into t1 values(1, 2, "one"), (2, 4, "two"), (3, 6, "three"); create view v3 as @@ -2003,6 +2104,9 @@ DROP TABLE IF EXISTS `v3`; drop view v1, v2, v3; drop table t1; +# +# Test for dumping triggers +# CREATE TABLE t1 (a int, b bigint default NULL); CREATE TABLE t2 (a int); create trigger trg1 before insert on t1 for each row @@ -2201,8 +2305,14 @@ set @fired:= "No"; end if; end BEFORE # STRICT_TRANS_TABLES,STRICT_ALL_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,TRADITIONAL,NO_AUTO_CREATE_USER root@localhost DROP TABLE t1, t2; +# +# Bugs #9136, #12917: problems with --defaults-extra-file option +# --port=1234 --port=1234 +# +# Test of fix to BUG 12597 +# DROP TABLE IF EXISTS `test1`; Warnings: Note 1051 Unknown table 'test1' @@ -2234,6 +2344,9 @@ a2 DROP TRIGGER testref; DROP TABLE test1; DROP TABLE test2; +# +# BUG#9056 - mysqldump does not dump routines +# DROP TABLE IF EXISTS t1; DROP FUNCTION IF EXISTS bug9056_func1; DROP FUNCTION IF EXISTS bug9056_func2; @@ -2330,6 +2443,9 @@ DROP PROCEDURE bug9056_proc1; DROP PROCEDURE bug9056_proc2; DROP PROCEDURE `a'b`; drop table t1; +# +# BUG# 13052 - mysqldump timestamp reloads broken +# drop table if exists t1; create table t1 (`d` timestamp, unique (`d`)); set time_zone='+00:00'; @@ -2416,6 +2532,9 @@ UNLOCK TABLES; drop table t1; set global time_zone=default; set time_zone=default; +# +# Test of fix to BUG 13146 - ansi quotes break loading of triggers +# DROP TABLE IF EXISTS `t1 test`; DROP TABLE IF EXISTS `t2 test`; CREATE TABLE `t1 test` ( @@ -2479,6 +2598,9 @@ UNLOCK TABLES; DROP TRIGGER `test trig`; DROP TABLE `t1 test`; DROP TABLE `t2 test`; +# +# BUG# 12838 mysqldump -x with views exits with error +# drop table if exists t1; create table t1 (a int, b varchar(32), c varchar(32)); insert into t1 values (1, 'first value', 'xxxx'); @@ -2571,6 +2693,10 @@ drop view v2; drop view v0; drop view v1; drop table t1; +# +# BUG#14554 - mysqldump does not separate words "ROW" and "BEGIN" +# for tables with trigger created in the IGNORE_SPACE sql mode. +# SET @old_sql_mode = @@SQL_MODE; SET SQL_MODE = IGNORE_SPACE; CREATE TABLE t1 (a INT); @@ -2626,6 +2752,9 @@ DELIMITER ; DROP TRIGGER tr1; DROP TABLE t1; +# +# Bug #13318: Bad result with empty field and --hex-blob +# create table t1 (a binary(1), b blob); insert into t1 values ('',''); @@ -2693,6 +2822,9 @@ UNLOCK TABLES; /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; drop table t1; +# +# Bug 14871 Invalid view dump output +# create table t1 (a int); insert into t1 values (289), (298), (234), (456), (789); create definer = CURRENT_USER view v1 as select * from t1; @@ -2719,6 +2851,9 @@ a 789 drop table t1; drop view v1, v2, v3, v4, v5; +# +# Bug #16878 dump of trigger +# create table t1 (a int, created datetime); create table t2 (b int, created datetime); create trigger tr1 before insert on t1 for each row set @@ -2741,6 +2876,9 @@ end AFTER # root@localhost drop trigger tr1; drop trigger tr2; drop table t1, t2; +# +# Bug#18462 mysqldump does not dump view structures correctly +# create table t (qty int, price int); insert into t values(3, 50); insert into t values(5, 51); @@ -2760,6 +2898,10 @@ mysqldump { drop view v1; drop view v2; drop table t; +# +# Bug#14857 Reading dump files with single statement stored routines fails. +# fixed by patch for bug#16878 +# /*!50003 CREATE FUNCTION `f`() RETURNS bigint(20) return 42 */| /*!50003 CREATE PROCEDURE `p`() @@ -2774,6 +2916,9 @@ p CREATE DEFINER=`root`@`localhost` PROCEDURE `p`() select 42 drop function f; drop procedure p; +# +# Bug #17371 Unable to dump a schema with invalid views +# create table t1 ( id serial ); create view v1 as select * from t1; drop table t1; @@ -2783,6 +2928,9 @@ mysqldump { } mysqldump drop view v1; +# BUG#17201 Spurious 'DROP DATABASE' in output, +# also confusion between tables and views. +# Example code from Markus Popp create database mysqldump_test_db; use mysqldump_test_db; create table t1 (id int); @@ -2843,6 +2991,9 @@ USE `mysqldump_test_db`; drop view v1; drop table t1; drop database mysqldump_test_db; +# +# Bug21014 Segmentation fault of mysqldump on view +# create database mysqldump_tables; use mysqldump_tables; create table basetable ( id serial, tag varchar(64) ); @@ -2876,6 +3027,9 @@ drop view nasishnasifu; drop database mysqldump_views; drop table mysqldump_tables.basetable; drop database mysqldump_tables; +# +# Bug20221 Dumping of multiple databases containing view(s) yields maleformed dumps +# create database mysqldump_dba; use mysqldump_dba; create table t1 (f1 int, f2 int); @@ -2908,6 +3062,9 @@ drop view v1; drop table t1; drop database mysqldump_dbb; use test; +# +# Bug#21215 mysqldump creating incomplete backups without warning +# create user mysqltest_1@localhost; create table t1(a int, b varchar(34)); reset master; @@ -2924,19 +3081,120 @@ CREATE TABLE `t1` ( ) ENGINE=MyISAM DEFAULT CHARSET=latin1; drop table t1; drop user mysqltest_1@localhost; +# +# Bug #21527 mysqldump incorrectly tries to LOCK TABLES on the +# information_schema database. +# +# Bug #21424 mysqldump failing to export/import views +# create database mysqldump_myDB; use mysqldump_myDB; create user myDB_User; -grant create view, select on mysqldump_myDB.* to myDB_User@localhost; +grant create, create view, select, insert on mysqldump_myDB.* to myDB_User@localhost; create table t1 (c1 int); insert into t1 values (3); use mysqldump_myDB; +create table u1 (f1 int); +insert into u1 values (4); create view v1 (c1) as select * from t1; use mysqldump_myDB; drop view v1; drop table t1; +drop table u1; +revoke all privileges on mysqldump_myDB.* from myDB_User@localhost; +drop user myDB_User; +drop database mysqldump_myDB; +flush privileges; +# Bug #21424 continues from here. +# Restore. Flush Privileges test ends. +# +use mysqldump_myDB; +select * from mysqldump_myDB.v1; +c1 +3 +select * from mysqldump_myDB.u1; +f1 +4 +use mysqldump_myDB; +drop view v1; +drop table t1; +drop table u1; revoke all privileges on mysqldump_myDB.* from myDB_User@localhost; drop user myDB_User; drop database mysqldump_myDB; use test; -End of 5.0 tests +# +# BUG#13926: --order-by-primary fails if PKEY contains quote character +# +DROP TABLE IF EXISTS `t1`; +CREATE TABLE `t1` ( +`a b` INT, +`c"d` INT, +`e``f` INT, +PRIMARY KEY (`a b`, `c"d`, `e``f`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1; +insert into t1 values (0815, 4711, 2006); +/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */; +/*!40103 SET TIME_ZONE='+00:00' */; +/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; +/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; +/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO,ANSI' */; +/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; +DROP TABLE IF EXISTS "t1"; +CREATE TABLE "t1" ( + "a b" int(11) NOT NULL default '0', + "c""d" int(11) NOT NULL default '0', + "e`f" int(11) NOT NULL default '0', + PRIMARY KEY ("a b","c""d","e`f") +); + +LOCK TABLES "t1" WRITE; +/*!40000 ALTER TABLE "t1" DISABLE KEYS */; +INSERT INTO "t1" VALUES (815,4711,2006); +/*!40000 ALTER TABLE "t1" ENABLE KEYS */; +UNLOCK TABLES; +/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */; + +/*!40101 SET SQL_MODE=@OLD_SQL_MODE */; +/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */; +/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; +/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; + + +/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; +/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; +/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; +/*!40101 SET NAMES utf8 */; +/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */; +/*!40103 SET TIME_ZONE='+00:00' */; +/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; +/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; +/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; +/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; +DROP TABLE IF EXISTS `t1`; +CREATE TABLE `t1` ( + `a b` int(11) NOT NULL default '0', + `c"d` int(11) NOT NULL default '0', + `e``f` int(11) NOT NULL default '0', + PRIMARY KEY (`a b`,`c"d`,`e``f`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1; + +LOCK TABLES `t1` WRITE; +/*!40000 ALTER TABLE `t1` DISABLE KEYS */; +INSERT INTO `t1` VALUES (815,4711,2006); +/*!40000 ALTER TABLE `t1` ENABLE KEYS */; +UNLOCK TABLES; +/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */; + +/*!40101 SET SQL_MODE=@OLD_SQL_MODE */; +/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */; +/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; +/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; +/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; +/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; +/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; + +DROP TABLE `t1`; +# +# End of 5.0 tests +# diff --git a/mysql-test/r/mysqltest.result b/mysql-test/r/mysqltest.result index d9ca863b6bc..123091841df 100644 --- a/mysql-test/r/mysqltest.result +++ b/mysql-test/r/mysqltest.result @@ -217,8 +217,11 @@ hej a long variable content a long variable content -a long $where variable content +a long a long variable content variable content +a long \$where variable content +banana = banana +Not a banana: ba\$cat\$cat mysqltest: At line 1: Missing arguments to let mysqltest: At line 1: Missing variable name in let mysqltest: At line 1: Variable name in hi=hi does not start with '$' diff --git a/mysql-test/r/olap.result b/mysql-test/r/olap.result index 28c1dc59540..7cdd5e1b152 100644 --- a/mysql-test/r/olap.result +++ b/mysql-test/r/olap.result @@ -611,7 +611,7 @@ C NULL EXPLAIN SELECT type FROM v1 GROUP BY type WITH ROLLUP; id select_type table type possible_keys key key_len ref rows Extra -1 PRIMARY t1 ALL NULL NULL NULL NULL 10 Using filesort +1 SIMPLE t1 ALL NULL NULL NULL NULL 10 Using filesort DROP VIEW v1; DROP TABLE t1; CREATE TABLE t1 (a int(11) NOT NULL); diff --git a/mysql-test/r/ps.result b/mysql-test/r/ps.result index 080187cfa7b..048c3ae46d3 100644 --- a/mysql-test/r/ps.result +++ b/mysql-test/r/ps.result @@ -909,6 +909,53 @@ create temporary table if not exists t1 (a1 int); execute stmt; drop temporary table t1; deallocate prepare stmt; +CREATE TABLE t1( +ID int(10) unsigned NOT NULL auto_increment, +Member_ID varchar(15) NOT NULL default '', +Action varchar(12) NOT NULL, +Action_Date datetime NOT NULL, +Track varchar(15) default NULL, +User varchar(12) default NULL, +Date_Updated timestamp NOT NULL default CURRENT_TIMESTAMP on update +CURRENT_TIMESTAMP, +PRIMARY KEY (ID), +KEY Action (Action), +KEY Action_Date (Action_Date) +); +INSERT INTO t1(Member_ID, Action, Action_Date, Track) VALUES +('111111', 'Disenrolled', '2006-03-01', 'CAD' ), +('111111', 'Enrolled', '2006-03-01', 'CAD' ), +('111111', 'Disenrolled', '2006-07-03', 'CAD' ), +('222222', 'Enrolled', '2006-03-07', 'CAD' ), +('222222', 'Enrolled', '2006-03-07', 'CHF' ), +('222222', 'Disenrolled', '2006-08-02', 'CHF' ), +('333333', 'Enrolled', '2006-03-01', 'CAD' ), +('333333', 'Disenrolled', '2006-03-01', 'CAD' ), +('444444', 'Enrolled', '2006-03-01', 'CAD' ), +('555555', 'Disenrolled', '2006-03-01', 'CAD' ), +('555555', 'Enrolled', '2006-07-21', 'CAD' ), +('555555', 'Disenrolled', '2006-03-01', 'CHF' ), +('666666', 'Enrolled', '2006-02-09', 'CAD' ), +('666666', 'Enrolled', '2006-05-12', 'CHF' ), +('666666', 'Disenrolled', '2006-06-01', 'CAD' ); +PREPARE STMT FROM +"SELECT GROUP_CONCAT(Track SEPARATOR ', ') FROM t1 + WHERE Member_ID=? AND Action='Enrolled' AND + (Track,Action_Date) IN (SELECT Track, MAX(Action_Date) FROM t1 + WHERE Member_ID=? + GROUP BY Track + HAVING Track>='CAD' AND + MAX(Action_Date)>'2006-03-01')"; +SET @id='111111'; +EXECUTE STMT USING @id,@id; +GROUP_CONCAT(Track SEPARATOR ', ') +NULL +SET @id='222222'; +EXECUTE STMT USING @id,@id; +GROUP_CONCAT(Track SEPARATOR ', ') +CAD +DEALLOCATE PREPARE STMT; +DROP TABLE t1; End of 4.1 tests create table t1 (a varchar(20)); insert into t1 values ('foo'); @@ -1311,4 +1358,25 @@ EXECUTE stmt USING @a; i j i i j DEALLOCATE PREPARE stmt; DROP TABLE IF EXISTS t1, t2, t3; +DROP TABLE IF EXISTS t1, t2; +CREATE TABLE t1 (i INT KEY); +CREATE TABLE t2 (i INT); +INSERT INTO t1 VALUES (1), (2); +INSERT INTO t2 VALUES (1); +PREPARE stmt FROM "SELECT t2.i FROM t1 LEFT JOIN t2 ON t2.i = t1.i + WHERE t1.i = ?"; +SET @arg= 1; +EXECUTE stmt USING @arg; +i +1 +SET @arg= 2; +EXECUTE stmt USING @arg; +i +NULL +SET @arg= 1; +EXECUTE stmt USING @arg; +i +1 +DEALLOCATE PREPARE stmt; +DROP TABLE t1, t2; End of 5.0 tests. diff --git a/mysql-test/r/ps_2myisam.result b/mysql-test/r/ps_2myisam.result index 205c084b71f..2a7b0e959af 100644 --- a/mysql-test/r/ps_2myisam.result +++ b/mysql-test/r/ps_2myisam.result @@ -2689,21 +2689,21 @@ set @arg00= '1.11111111111111111111e+50' ; execute my_insert using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00 ; Warnings: -Warning 1265 Data truncated for column 'c1' at row 1 -Warning 1265 Data truncated for column 'c2' at row 1 -Warning 1265 Data truncated for column 'c3' at row 1 -Warning 1265 Data truncated for column 'c4' at row 1 -Warning 1265 Data truncated for column 'c5' at row 1 -Warning 1265 Data truncated for column 'c6' at row 1 +Warning 1264 Out of range value adjusted for column 'c1' at row 1 +Warning 1264 Out of range value adjusted for column 'c2' at row 1 +Warning 1264 Out of range value adjusted for column 'c3' at row 1 +Warning 1264 Out of range value adjusted for column 'c4' at row 1 +Warning 1264 Out of range value adjusted for column 'c5' at row 1 +Warning 1264 Out of range value adjusted for column 'c6' at row 1 Warning 1264 Out of range value adjusted for column 'c7' at row 1 Warning 1264 Out of range value adjusted for column 'c12' at row 1 execute my_select ; -c1 1 -c2 1 -c3 1 -c4 1 -c5 1 -c6 1 +c1 127 +c2 32767 +c3 8388607 +c4 2147483647 +c5 2147483647 +c6 9223372036854775807 c7 3.40282e+38 c8 1.11111111111111e+50 c9 1.11111111111111e+50 @@ -2739,21 +2739,21 @@ set @arg00= '-1.11111111111111111111e+50' ; execute my_insert using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00 ; Warnings: -Warning 1265 Data truncated for column 'c1' at row 1 -Warning 1265 Data truncated for column 'c2' at row 1 -Warning 1265 Data truncated for column 'c3' at row 1 -Warning 1265 Data truncated for column 'c4' at row 1 -Warning 1265 Data truncated for column 'c5' at row 1 -Warning 1265 Data truncated for column 'c6' at row 1 +Warning 1264 Out of range value adjusted for column 'c1' at row 1 +Warning 1264 Out of range value adjusted for column 'c2' at row 1 +Warning 1264 Out of range value adjusted for column 'c3' at row 1 +Warning 1264 Out of range value adjusted for column 'c4' at row 1 +Warning 1264 Out of range value adjusted for column 'c5' at row 1 +Warning 1264 Out of range value adjusted for column 'c6' at row 1 Warning 1264 Out of range value adjusted for column 'c7' at row 1 Warning 1264 Out of range value adjusted for column 'c12' at row 1 execute my_select ; -c1 -1 -c2 -1 -c3 -1 -c4 -1 -c5 -1 -c6 -1 +c1 -128 +c2 -32768 +c3 -8388608 +c4 -2147483648 +c5 -2147483648 +c6 -9223372036854775808 c7 -3.40282e+38 c8 -1.11111111111111e+50 c9 -1.11111111111111e+50 diff --git a/mysql-test/r/ps_3innodb.result b/mysql-test/r/ps_3innodb.result index 2e7c4785542..88e8bf3ce04 100644 --- a/mysql-test/r/ps_3innodb.result +++ b/mysql-test/r/ps_3innodb.result @@ -2672,21 +2672,21 @@ set @arg00= '1.11111111111111111111e+50' ; execute my_insert using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00 ; Warnings: -Warning 1265 Data truncated for column 'c1' at row 1 -Warning 1265 Data truncated for column 'c2' at row 1 -Warning 1265 Data truncated for column 'c3' at row 1 -Warning 1265 Data truncated for column 'c4' at row 1 -Warning 1265 Data truncated for column 'c5' at row 1 -Warning 1265 Data truncated for column 'c6' at row 1 +Warning 1264 Out of range value adjusted for column 'c1' at row 1 +Warning 1264 Out of range value adjusted for column 'c2' at row 1 +Warning 1264 Out of range value adjusted for column 'c3' at row 1 +Warning 1264 Out of range value adjusted for column 'c4' at row 1 +Warning 1264 Out of range value adjusted for column 'c5' at row 1 +Warning 1264 Out of range value adjusted for column 'c6' at row 1 Warning 1264 Out of range value adjusted for column 'c7' at row 1 Warning 1264 Out of range value adjusted for column 'c12' at row 1 execute my_select ; -c1 1 -c2 1 -c3 1 -c4 1 -c5 1 -c6 1 +c1 127 +c2 32767 +c3 8388607 +c4 2147483647 +c5 2147483647 +c6 9223372036854775807 c7 3.40282e+38 c8 1.11111111111111e+50 c9 1.11111111111111e+50 @@ -2722,21 +2722,21 @@ set @arg00= '-1.11111111111111111111e+50' ; execute my_insert using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00 ; Warnings: -Warning 1265 Data truncated for column 'c1' at row 1 -Warning 1265 Data truncated for column 'c2' at row 1 -Warning 1265 Data truncated for column 'c3' at row 1 -Warning 1265 Data truncated for column 'c4' at row 1 -Warning 1265 Data truncated for column 'c5' at row 1 -Warning 1265 Data truncated for column 'c6' at row 1 +Warning 1264 Out of range value adjusted for column 'c1' at row 1 +Warning 1264 Out of range value adjusted for column 'c2' at row 1 +Warning 1264 Out of range value adjusted for column 'c3' at row 1 +Warning 1264 Out of range value adjusted for column 'c4' at row 1 +Warning 1264 Out of range value adjusted for column 'c5' at row 1 +Warning 1264 Out of range value adjusted for column 'c6' at row 1 Warning 1264 Out of range value adjusted for column 'c7' at row 1 Warning 1264 Out of range value adjusted for column 'c12' at row 1 execute my_select ; -c1 -1 -c2 -1 -c3 -1 -c4 -1 -c5 -1 -c6 -1 +c1 -128 +c2 -32768 +c3 -8388608 +c4 -2147483648 +c5 -2147483648 +c6 -9223372036854775808 c7 -3.40282e+38 c8 -1.11111111111111e+50 c9 -1.11111111111111e+50 diff --git a/mysql-test/r/ps_4heap.result b/mysql-test/r/ps_4heap.result index 8a0da364598..0e4c6fc3077 100644 --- a/mysql-test/r/ps_4heap.result +++ b/mysql-test/r/ps_4heap.result @@ -2673,21 +2673,21 @@ set @arg00= '1.11111111111111111111e+50' ; execute my_insert using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00 ; Warnings: -Warning 1265 Data truncated for column 'c1' at row 1 -Warning 1265 Data truncated for column 'c2' at row 1 -Warning 1265 Data truncated for column 'c3' at row 1 -Warning 1265 Data truncated for column 'c4' at row 1 -Warning 1265 Data truncated for column 'c5' at row 1 -Warning 1265 Data truncated for column 'c6' at row 1 +Warning 1264 Out of range value adjusted for column 'c1' at row 1 +Warning 1264 Out of range value adjusted for column 'c2' at row 1 +Warning 1264 Out of range value adjusted for column 'c3' at row 1 +Warning 1264 Out of range value adjusted for column 'c4' at row 1 +Warning 1264 Out of range value adjusted for column 'c5' at row 1 +Warning 1264 Out of range value adjusted for column 'c6' at row 1 Warning 1264 Out of range value adjusted for column 'c7' at row 1 Warning 1264 Out of range value adjusted for column 'c12' at row 1 execute my_select ; -c1 1 -c2 1 -c3 1 -c4 1 -c5 1 -c6 1 +c1 127 +c2 32767 +c3 8388607 +c4 2147483647 +c5 2147483647 +c6 9223372036854775807 c7 3.40282e+38 c8 1.11111111111111e+50 c9 1.11111111111111e+50 @@ -2723,21 +2723,21 @@ set @arg00= '-1.11111111111111111111e+50' ; execute my_insert using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00 ; Warnings: -Warning 1265 Data truncated for column 'c1' at row 1 -Warning 1265 Data truncated for column 'c2' at row 1 -Warning 1265 Data truncated for column 'c3' at row 1 -Warning 1265 Data truncated for column 'c4' at row 1 -Warning 1265 Data truncated for column 'c5' at row 1 -Warning 1265 Data truncated for column 'c6' at row 1 +Warning 1264 Out of range value adjusted for column 'c1' at row 1 +Warning 1264 Out of range value adjusted for column 'c2' at row 1 +Warning 1264 Out of range value adjusted for column 'c3' at row 1 +Warning 1264 Out of range value adjusted for column 'c4' at row 1 +Warning 1264 Out of range value adjusted for column 'c5' at row 1 +Warning 1264 Out of range value adjusted for column 'c6' at row 1 Warning 1264 Out of range value adjusted for column 'c7' at row 1 Warning 1264 Out of range value adjusted for column 'c12' at row 1 execute my_select ; -c1 -1 -c2 -1 -c3 -1 -c4 -1 -c5 -1 -c6 -1 +c1 -128 +c2 -32768 +c3 -8388608 +c4 -2147483648 +c5 -2147483648 +c6 -9223372036854775808 c7 -3.40282e+38 c8 -1.11111111111111e+50 c9 -1.11111111111111e+50 diff --git a/mysql-test/r/ps_5merge.result b/mysql-test/r/ps_5merge.result index 1c6e11f203c..1e337072ecb 100644 --- a/mysql-test/r/ps_5merge.result +++ b/mysql-test/r/ps_5merge.result @@ -2609,21 +2609,21 @@ set @arg00= '1.11111111111111111111e+50' ; execute my_insert using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00 ; Warnings: -Warning 1265 Data truncated for column 'c1' at row 1 -Warning 1265 Data truncated for column 'c2' at row 1 -Warning 1265 Data truncated for column 'c3' at row 1 -Warning 1265 Data truncated for column 'c4' at row 1 -Warning 1265 Data truncated for column 'c5' at row 1 -Warning 1265 Data truncated for column 'c6' at row 1 +Warning 1264 Out of range value adjusted for column 'c1' at row 1 +Warning 1264 Out of range value adjusted for column 'c2' at row 1 +Warning 1264 Out of range value adjusted for column 'c3' at row 1 +Warning 1264 Out of range value adjusted for column 'c4' at row 1 +Warning 1264 Out of range value adjusted for column 'c5' at row 1 +Warning 1264 Out of range value adjusted for column 'c6' at row 1 Warning 1264 Out of range value adjusted for column 'c7' at row 1 Warning 1264 Out of range value adjusted for column 'c12' at row 1 execute my_select ; -c1 1 -c2 1 -c3 1 -c4 1 -c5 1 -c6 1 +c1 127 +c2 32767 +c3 8388607 +c4 2147483647 +c5 2147483647 +c6 9223372036854775807 c7 3.40282e+38 c8 1.11111111111111e+50 c9 1.11111111111111e+50 @@ -2659,21 +2659,21 @@ set @arg00= '-1.11111111111111111111e+50' ; execute my_insert using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00 ; Warnings: -Warning 1265 Data truncated for column 'c1' at row 1 -Warning 1265 Data truncated for column 'c2' at row 1 -Warning 1265 Data truncated for column 'c3' at row 1 -Warning 1265 Data truncated for column 'c4' at row 1 -Warning 1265 Data truncated for column 'c5' at row 1 -Warning 1265 Data truncated for column 'c6' at row 1 +Warning 1264 Out of range value adjusted for column 'c1' at row 1 +Warning 1264 Out of range value adjusted for column 'c2' at row 1 +Warning 1264 Out of range value adjusted for column 'c3' at row 1 +Warning 1264 Out of range value adjusted for column 'c4' at row 1 +Warning 1264 Out of range value adjusted for column 'c5' at row 1 +Warning 1264 Out of range value adjusted for column 'c6' at row 1 Warning 1264 Out of range value adjusted for column 'c7' at row 1 Warning 1264 Out of range value adjusted for column 'c12' at row 1 execute my_select ; -c1 -1 -c2 -1 -c3 -1 -c4 -1 -c5 -1 -c6 -1 +c1 -128 +c2 -32768 +c3 -8388608 +c4 -2147483648 +c5 -2147483648 +c6 -9223372036854775808 c7 -3.40282e+38 c8 -1.11111111111111e+50 c9 -1.11111111111111e+50 @@ -5623,21 +5623,21 @@ set @arg00= '1.11111111111111111111e+50' ; execute my_insert using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00 ; Warnings: -Warning 1265 Data truncated for column 'c1' at row 1 -Warning 1265 Data truncated for column 'c2' at row 1 -Warning 1265 Data truncated for column 'c3' at row 1 -Warning 1265 Data truncated for column 'c4' at row 1 -Warning 1265 Data truncated for column 'c5' at row 1 -Warning 1265 Data truncated for column 'c6' at row 1 +Warning 1264 Out of range value adjusted for column 'c1' at row 1 +Warning 1264 Out of range value adjusted for column 'c2' at row 1 +Warning 1264 Out of range value adjusted for column 'c3' at row 1 +Warning 1264 Out of range value adjusted for column 'c4' at row 1 +Warning 1264 Out of range value adjusted for column 'c5' at row 1 +Warning 1264 Out of range value adjusted for column 'c6' at row 1 Warning 1264 Out of range value adjusted for column 'c7' at row 1 Warning 1264 Out of range value adjusted for column 'c12' at row 1 execute my_select ; -c1 1 -c2 1 -c3 1 -c4 1 -c5 1 -c6 1 +c1 127 +c2 32767 +c3 8388607 +c4 2147483647 +c5 2147483647 +c6 9223372036854775807 c7 3.40282e+38 c8 1.11111111111111e+50 c9 1.11111111111111e+50 @@ -5673,21 +5673,21 @@ set @arg00= '-1.11111111111111111111e+50' ; execute my_insert using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00 ; Warnings: -Warning 1265 Data truncated for column 'c1' at row 1 -Warning 1265 Data truncated for column 'c2' at row 1 -Warning 1265 Data truncated for column 'c3' at row 1 -Warning 1265 Data truncated for column 'c4' at row 1 -Warning 1265 Data truncated for column 'c5' at row 1 -Warning 1265 Data truncated for column 'c6' at row 1 +Warning 1264 Out of range value adjusted for column 'c1' at row 1 +Warning 1264 Out of range value adjusted for column 'c2' at row 1 +Warning 1264 Out of range value adjusted for column 'c3' at row 1 +Warning 1264 Out of range value adjusted for column 'c4' at row 1 +Warning 1264 Out of range value adjusted for column 'c5' at row 1 +Warning 1264 Out of range value adjusted for column 'c6' at row 1 Warning 1264 Out of range value adjusted for column 'c7' at row 1 Warning 1264 Out of range value adjusted for column 'c12' at row 1 execute my_select ; -c1 -1 -c2 -1 -c3 -1 -c4 -1 -c5 -1 -c6 -1 +c1 -128 +c2 -32768 +c3 -8388608 +c4 -2147483648 +c5 -2147483648 +c6 -9223372036854775808 c7 -3.40282e+38 c8 -1.11111111111111e+50 c9 -1.11111111111111e+50 diff --git a/mysql-test/r/ps_6bdb.result b/mysql-test/r/ps_6bdb.result index 3546b05870a..49e3f9d9bb7 100644 --- a/mysql-test/r/ps_6bdb.result +++ b/mysql-test/r/ps_6bdb.result @@ -2672,21 +2672,21 @@ set @arg00= '1.11111111111111111111e+50' ; execute my_insert using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00 ; Warnings: -Warning 1265 Data truncated for column 'c1' at row 1 -Warning 1265 Data truncated for column 'c2' at row 1 -Warning 1265 Data truncated for column 'c3' at row 1 -Warning 1265 Data truncated for column 'c4' at row 1 -Warning 1265 Data truncated for column 'c5' at row 1 -Warning 1265 Data truncated for column 'c6' at row 1 +Warning 1264 Out of range value adjusted for column 'c1' at row 1 +Warning 1264 Out of range value adjusted for column 'c2' at row 1 +Warning 1264 Out of range value adjusted for column 'c3' at row 1 +Warning 1264 Out of range value adjusted for column 'c4' at row 1 +Warning 1264 Out of range value adjusted for column 'c5' at row 1 +Warning 1264 Out of range value adjusted for column 'c6' at row 1 Warning 1264 Out of range value adjusted for column 'c7' at row 1 Warning 1264 Out of range value adjusted for column 'c12' at row 1 execute my_select ; -c1 1 -c2 1 -c3 1 -c4 1 -c5 1 -c6 1 +c1 127 +c2 32767 +c3 8388607 +c4 2147483647 +c5 2147483647 +c6 9223372036854775807 c7 3.40282e+38 c8 1.11111111111111e+50 c9 1.11111111111111e+50 @@ -2722,21 +2722,21 @@ set @arg00= '-1.11111111111111111111e+50' ; execute my_insert using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00 ; Warnings: -Warning 1265 Data truncated for column 'c1' at row 1 -Warning 1265 Data truncated for column 'c2' at row 1 -Warning 1265 Data truncated for column 'c3' at row 1 -Warning 1265 Data truncated for column 'c4' at row 1 -Warning 1265 Data truncated for column 'c5' at row 1 -Warning 1265 Data truncated for column 'c6' at row 1 +Warning 1264 Out of range value adjusted for column 'c1' at row 1 +Warning 1264 Out of range value adjusted for column 'c2' at row 1 +Warning 1264 Out of range value adjusted for column 'c3' at row 1 +Warning 1264 Out of range value adjusted for column 'c4' at row 1 +Warning 1264 Out of range value adjusted for column 'c5' at row 1 +Warning 1264 Out of range value adjusted for column 'c6' at row 1 Warning 1264 Out of range value adjusted for column 'c7' at row 1 Warning 1264 Out of range value adjusted for column 'c12' at row 1 execute my_select ; -c1 -1 -c2 -1 -c3 -1 -c4 -1 -c5 -1 -c6 -1 +c1 -128 +c2 -32768 +c3 -8388608 +c4 -2147483648 +c5 -2147483648 +c6 -9223372036854775808 c7 -3.40282e+38 c8 -1.11111111111111e+50 c9 -1.11111111111111e+50 diff --git a/mysql-test/r/ps_7ndb.result b/mysql-test/r/ps_7ndb.result index b1986ca62dc..c84cced15f5 100644 --- a/mysql-test/r/ps_7ndb.result +++ b/mysql-test/r/ps_7ndb.result @@ -2672,21 +2672,21 @@ set @arg00= '1.11111111111111111111e+50' ; execute my_insert using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00 ; Warnings: -Warning 1265 Data truncated for column 'c1' at row 1 -Warning 1265 Data truncated for column 'c2' at row 1 -Warning 1265 Data truncated for column 'c3' at row 1 -Warning 1265 Data truncated for column 'c4' at row 1 -Warning 1265 Data truncated for column 'c5' at row 1 -Warning 1265 Data truncated for column 'c6' at row 1 +Warning 1264 Out of range value adjusted for column 'c1' at row 1 +Warning 1264 Out of range value adjusted for column 'c2' at row 1 +Warning 1264 Out of range value adjusted for column 'c3' at row 1 +Warning 1264 Out of range value adjusted for column 'c4' at row 1 +Warning 1264 Out of range value adjusted for column 'c5' at row 1 +Warning 1264 Out of range value adjusted for column 'c6' at row 1 Warning 1264 Out of range value adjusted for column 'c7' at row 1 Warning 1264 Out of range value adjusted for column 'c12' at row 1 execute my_select ; -c1 1 -c2 1 -c3 1 -c4 1 -c5 1 -c6 1 +c1 127 +c2 32767 +c3 8388607 +c4 2147483647 +c5 2147483647 +c6 9223372036854775807 c7 3.40282e+38 c8 1.11111111111111e+50 c9 1.11111111111111e+50 @@ -2722,21 +2722,21 @@ set @arg00= '-1.11111111111111111111e+50' ; execute my_insert using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00 ; Warnings: -Warning 1265 Data truncated for column 'c1' at row 1 -Warning 1265 Data truncated for column 'c2' at row 1 -Warning 1265 Data truncated for column 'c3' at row 1 -Warning 1265 Data truncated for column 'c4' at row 1 -Warning 1265 Data truncated for column 'c5' at row 1 -Warning 1265 Data truncated for column 'c6' at row 1 +Warning 1264 Out of range value adjusted for column 'c1' at row 1 +Warning 1264 Out of range value adjusted for column 'c2' at row 1 +Warning 1264 Out of range value adjusted for column 'c3' at row 1 +Warning 1264 Out of range value adjusted for column 'c4' at row 1 +Warning 1264 Out of range value adjusted for column 'c5' at row 1 +Warning 1264 Out of range value adjusted for column 'c6' at row 1 Warning 1264 Out of range value adjusted for column 'c7' at row 1 Warning 1264 Out of range value adjusted for column 'c12' at row 1 execute my_select ; -c1 -1 -c2 -1 -c3 -1 -c4 -1 -c5 -1 -c6 -1 +c1 -128 +c2 -32768 +c3 -8388608 +c4 -2147483648 +c5 -2147483648 +c6 -9223372036854775808 c7 -3.40282e+38 c8 -1.11111111111111e+50 c9 -1.11111111111111e+50 diff --git a/mysql-test/r/query_cache.result b/mysql-test/r/query_cache.result index a735b52a26f..5224280e134 100644 --- a/mysql-test/r/query_cache.result +++ b/mysql-test/r/query_cache.result @@ -947,24 +947,24 @@ COUNT(*) Warnings: Warning 1292 Incorrect datetime value: '20050327 invalid' for column 'date' at row 1 Warning 1292 Incorrect datetime value: '20050327 invalid' for column 'date' at row 1 -Warning 1292 Truncated incorrect DOUBLE value: '20050327 invalid' -Warning 1292 Truncated incorrect DOUBLE value: '20050327 invalid' +Warning 1292 Truncated incorrect INTEGER value: '20050327 invalid' +Warning 1292 Truncated incorrect INTEGER value: '20050327 invalid' SELECT COUNT(*) FROM t1 WHERE date BETWEEN '20050326' AND '20050328 invalid'; COUNT(*) 0 Warnings: Warning 1292 Incorrect datetime value: '20050328 invalid' for column 'date' at row 1 Warning 1292 Incorrect datetime value: '20050328 invalid' for column 'date' at row 1 -Warning 1292 Truncated incorrect DOUBLE value: '20050328 invalid' -Warning 1292 Truncated incorrect DOUBLE value: '20050328 invalid' +Warning 1292 Truncated incorrect INTEGER value: '20050328 invalid' +Warning 1292 Truncated incorrect INTEGER value: '20050328 invalid' SELECT COUNT(*) FROM t1 WHERE date BETWEEN '20050326' AND '20050327 invalid'; COUNT(*) 0 Warnings: Warning 1292 Incorrect datetime value: '20050327 invalid' for column 'date' at row 1 Warning 1292 Incorrect datetime value: '20050327 invalid' for column 'date' at row 1 -Warning 1292 Truncated incorrect DOUBLE value: '20050327 invalid' -Warning 1292 Truncated incorrect DOUBLE value: '20050327 invalid' +Warning 1292 Truncated incorrect INTEGER value: '20050327 invalid' +Warning 1292 Truncated incorrect INTEGER value: '20050327 invalid' show status like "Qcache_queries_in_cache"; Variable_name Value Qcache_queries_in_cache 0 diff --git a/mysql-test/r/range.result b/mysql-test/r/range.result index 3edf56496fe..add95613d62 100644 --- a/mysql-test/r/range.result +++ b/mysql-test/r/range.result @@ -750,13 +750,13 @@ id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 range PRIMARY PRIMARY 4 NULL 4 Using where; Using index EXPLAIN SELECT a,b FROM v1 WHERE a < 2 and b=3; id select_type table type possible_keys key key_len ref rows Extra -1 PRIMARY t1 range PRIMARY PRIMARY 4 NULL 4 Using where; Using index +1 SIMPLE t1 range PRIMARY PRIMARY 4 NULL 4 Using where; Using index EXPLAIN SELECT a,b FROM t1 WHERE a < 2; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 range PRIMARY PRIMARY 4 NULL 4 Using where; Using index EXPLAIN SELECT a,b FROM v1 WHERE a < 2; id select_type table type possible_keys key key_len ref rows Extra -1 PRIMARY t1 range PRIMARY PRIMARY 4 NULL 4 Using where; Using index +1 SIMPLE t1 range PRIMARY PRIMARY 4 NULL 4 Using where; Using index SELECT a,b FROM t1 WHERE a < 2 and b=3; a b 1 3 @@ -799,13 +799,13 @@ id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 range PRIMARY PRIMARY 8 NULL # Using where; Using index explain select * from v1 where a in (3,4) and b in (1,2,3); id select_type table type possible_keys key key_len ref rows Extra -1 PRIMARY t1 range PRIMARY PRIMARY 8 NULL # Using where; Using index +1 SIMPLE t1 range PRIMARY PRIMARY 8 NULL # Using where; Using index explain select * from t1 where a between 3 and 4 and b between 1 and 2; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 range PRIMARY PRIMARY 8 NULL # Using where; Using index explain select * from v1 where a between 3 and 4 and b between 1 and 2; id select_type table type possible_keys key key_len ref rows Extra -1 PRIMARY t1 range PRIMARY PRIMARY 8 NULL # Using where; Using index +1 SIMPLE t1 range PRIMARY PRIMARY 8 NULL # Using where; Using index drop view v1; drop table t1; create table t3 (a int); diff --git a/mysql-test/r/round.result b/mysql-test/r/round.result new file mode 100644 index 00000000000..e9a80df0f49 --- /dev/null +++ b/mysql-test/r/round.result @@ -0,0 +1,272 @@ +DROP TABLE IF EXISTS t1; +CREATE TABLE t1 (sint8 tinyint not null); +INSERT INTO t1 VALUES ('0.1'); +INSERT INTO t1 VALUES ('0.5'); +INSERT INTO t1 VALUES ('127.4'); +INSERT INTO t1 VALUES ('127.5'); +Warnings: +Warning 1264 Out of range value adjusted for column 'sint8' at row 1 +INSERT INTO t1 VALUES ('-0.1'); +INSERT INTO t1 VALUES ('-0.5'); +INSERT INTO t1 VALUES ('-127.4'); +INSERT INTO t1 VALUES ('-127.5'); +INSERT INTO t1 VALUES ('-128.4'); +INSERT INTO t1 VALUES ('-128.5'); +Warnings: +Warning 1264 Out of range value adjusted for column 'sint8' at row 1 +SELECT * FROM t1; +sint8 +0 +1 +127 +127 +0 +-1 +-127 +-128 +-128 +-128 +DROP TABLE t1; +CREATE TABLE t1 (uint8 tinyint unsigned not null); +INSERT INTO t1 VALUES ('0.1'); +INSERT INTO t1 VALUES ('0.5'); +INSERT INTO t1 VALUES ('127.4'); +INSERT INTO t1 VALUES ('127.5'); +INSERT INTO t1 VALUES ('-0.1'); +INSERT INTO t1 VALUES ('-0.5'); +Warnings: +Warning 1264 Out of range value adjusted for column 'uint8' at row 1 +INSERT INTO t1 VALUES ('255.4'); +INSERT INTO t1 VALUES ('255.5'); +Warnings: +Warning 1264 Out of range value adjusted for column 'uint8' at row 1 +SELECT * FROM t1; +uint8 +0 +1 +127 +128 +0 +0 +255 +255 +DROP TABLE t1; +CREATE TABLE t1 (sint16 smallint not null); +INSERT INTO t1 VALUES ('0.1'); +INSERT INTO t1 VALUES ('0.5'); +INSERT INTO t1 VALUES ('32767.4'); +INSERT INTO t1 VALUES ('32767.5'); +Warnings: +Warning 1264 Out of range value adjusted for column 'sint16' at row 1 +INSERT INTO t1 VALUES ('-0.1'); +INSERT INTO t1 VALUES ('-0.5'); +INSERT INTO t1 VALUES ('-32767.4'); +INSERT INTO t1 VALUES ('-32767.5'); +INSERT INTO t1 VALUES ('-32768.4'); +INSERT INTO t1 VALUES ('-32768.5'); +Warnings: +Warning 1264 Out of range value adjusted for column 'sint16' at row 1 +SELECT * FROM t1; +sint16 +0 +1 +32767 +32767 +0 +-1 +-32767 +-32768 +-32768 +-32768 +DROP TABLE t1; +CREATE TABLE t1 (uint16 smallint unsigned not null); +INSERT INTO t1 VALUES ('0.1'); +INSERT INTO t1 VALUES ('0.5'); +INSERT INTO t1 VALUES ('32767.4'); +INSERT INTO t1 VALUES ('32767.5'); +INSERT INTO t1 VALUES ('-0.1'); +INSERT INTO t1 VALUES ('-0.5'); +Warnings: +Warning 1264 Out of range value adjusted for column 'uint16' at row 1 +INSERT INTO t1 VALUES ('65535.4'); +INSERT INTO t1 VALUES ('65535.5'); +Warnings: +Warning 1264 Out of range value adjusted for column 'uint16' at row 1 +SELECT * FROM t1; +uint16 +0 +1 +32767 +32768 +0 +0 +65535 +65535 +DROP TABLE t1; +CREATE TABLE t1 (sint24 mediumint not null); +INSERT INTO t1 VALUES ('0.1'); +INSERT INTO t1 VALUES ('0.5'); +INSERT INTO t1 VALUES ('8388607.4'); +INSERT INTO t1 VALUES ('8388607.5'); +Warnings: +Warning 1264 Out of range value adjusted for column 'sint24' at row 1 +INSERT INTO t1 VALUES ('-0.1'); +INSERT INTO t1 VALUES ('-0.5'); +INSERT INTO t1 VALUES ('-8388607.4'); +INSERT INTO t1 VALUES ('-8388607.5'); +INSERT INTO t1 VALUES ('-8388608.4'); +INSERT INTO t1 VALUES ('-8388608.5'); +Warnings: +Warning 1264 Out of range value adjusted for column 'sint24' at row 1 +SELECT * FROM t1; +sint24 +0 +1 +8388607 +8388607 +0 +-1 +-8388607 +-8388608 +-8388608 +-8388608 +DROP TABLE t1; +CREATE TABLE t1 (uint24 mediumint unsigned not null); +INSERT INTO t1 VALUES ('0.1'); +INSERT INTO t1 VALUES ('0.5'); +INSERT INTO t1 VALUES ('8388607.4'); +INSERT INTO t1 VALUES ('8388607.5'); +INSERT INTO t1 VALUES ('-0.1'); +INSERT INTO t1 VALUES ('-0.5'); +Warnings: +Warning 1264 Out of range value adjusted for column 'uint24' at row 1 +INSERT INTO t1 VALUES ('16777215.4'); +INSERT INTO t1 VALUES ('16777215.5'); +Warnings: +Warning 1264 Out of range value adjusted for column 'uint24' at row 1 +SELECT * FROM t1; +uint24 +0 +1 +8388607 +8388608 +0 +0 +16777215 +16777215 +DROP TABLE t1; +CREATE TABLE t1 (sint64 bigint not null); +INSERT INTO t1 VALUES ('0.1'); +INSERT INTO t1 VALUES ('0.5'); +INSERT INTO t1 VALUES ('9223372036854775807.4'); +INSERT INTO t1 VALUES ('9223372036854775807.5'); +Warnings: +Warning 1264 Out of range value adjusted for column 'sint64' at row 1 +INSERT INTO t1 VALUES ('-0.1'); +INSERT INTO t1 VALUES ('-0.5'); +INSERT INTO t1 VALUES ('-9223372036854775807.4'); +INSERT INTO t1 VALUES ('-9223372036854775807.5'); +INSERT INTO t1 VALUES ('-9223372036854775808.4'); +INSERT INTO t1 VALUES ('-9223372036854775808.5'); +Warnings: +Warning 1264 Out of range value adjusted for column 'sint64' at row 1 +SELECT * FROM t1; +sint64 +0 +1 +9223372036854775807 +9223372036854775807 +0 +-1 +-9223372036854775807 +-9223372036854775808 +-9223372036854775808 +-9223372036854775808 +DROP TABLE t1; +CREATE TABLE t1 (uint64 bigint unsigned not null); +INSERT INTO t1 VALUES ('0.1'); +INSERT INTO t1 VALUES ('0.5'); +INSERT INTO t1 VALUES ('9223372036854775807.4'); +INSERT INTO t1 VALUES ('9223372036854775807.5'); +INSERT INTO t1 VALUES ('-0.1'); +INSERT INTO t1 VALUES ('-0.5'); +Warnings: +Warning 1264 Out of range value adjusted for column 'uint64' at row 1 +INSERT INTO t1 VALUES ('18446744073709551615.4'); +INSERT INTO t1 VALUES ('18446744073709551615.5'); +Warnings: +Warning 1264 Out of range value adjusted for column 'uint64' at row 1 +INSERT INTO t1 VALUES ('1844674407370955161.0'); +INSERT INTO t1 VALUES ('1844674407370955161.1'); +INSERT INTO t1 VALUES ('1844674407370955161.2'); +INSERT INTO t1 VALUES ('1844674407370955161.3'); +INSERT INTO t1 VALUES ('1844674407370955161.4'); +INSERT INTO t1 VALUES ('1844674407370955161.5'); +INSERT INTO t1 VALUES ('1844674407370955161.0e1'); +INSERT INTO t1 VALUES ('1844674407370955161.1e1'); +INSERT INTO t1 VALUES ('1844674407370955161.2e1'); +INSERT INTO t1 VALUES ('1844674407370955161.3e1'); +INSERT INTO t1 VALUES ('1844674407370955161.4e1'); +INSERT INTO t1 VALUES ('1844674407370955161.5e1'); +INSERT INTO t1 VALUES ('18446744073709551610e-1'); +INSERT INTO t1 VALUES ('18446744073709551611e-1'); +INSERT INTO t1 VALUES ('18446744073709551612e-1'); +INSERT INTO t1 VALUES ('18446744073709551613e-1'); +INSERT INTO t1 VALUES ('18446744073709551614e-1'); +INSERT INTO t1 VALUES ('18446744073709551615e-1'); +SELECT * FROM t1; +uint64 +0 +1 +9223372036854775807 +9223372036854775808 +0 +0 +18446744073709551615 +18446744073709551615 +1844674407370955161 +1844674407370955161 +1844674407370955161 +1844674407370955161 +1844674407370955161 +1844674407370955162 +18446744073709551610 +18446744073709551611 +18446744073709551612 +18446744073709551613 +18446744073709551614 +18446744073709551615 +1844674407370955161 +1844674407370955161 +1844674407370955161 +1844674407370955161 +1844674407370955161 +1844674407370955162 +DROP TABLE t1; +CREATE TABLE t1 (str varchar(128), sint64 bigint not null default 0); +INSERT INTO t1 (str) VALUES ('1.5'); +INSERT INTO t1 (str) VALUES ('1.00005e4'); +INSERT INTO t1 (str) VALUES ('1.0005e3'); +INSERT INTO t1 (str) VALUES ('1.005e2'); +INSERT INTO t1 (str) VALUES ('1.05e1'); +INSERT INTO t1 (str) VALUES ('1.5e0'); +INSERT INTO t1 (str) VALUES ('100005e-1'); +INSERT INTO t1 (str) VALUES ('100050e-2'); +INSERT INTO t1 (str) VALUES ('100500e-3'); +INSERT INTO t1 (str) VALUES ('105000e-4'); +INSERT INTO t1 (str) VALUES ('150000e-5'); +UPDATE t1 SET sint64=str; +SELECT * FROM t1; +str sint64 +1.5 2 +1.00005e4 10001 +1.0005e3 1001 +1.005e2 101 +1.05e1 11 +1.5e0 2 +100005e-1 10001 +100050e-2 1001 +100500e-3 101 +105000e-4 11 +150000e-5 2 +DROP TABLE t1; diff --git a/mysql-test/r/row.result b/mysql-test/r/row.result index 1762587415d..5b5f8b7b954 100644 --- a/mysql-test/r/row.result +++ b/mysql-test/r/row.result @@ -181,3 +181,128 @@ SELECT ROW(1,1,1) = ROW(1,1,1) as `1`, ROW(1,1,1) = ROW(1,2,1) as `0`, ROW(1,NUL select row(NULL,1)=(2,0); row(NULL,1)=(2,0) 0 +CREATE TABLE t1 (a int, b int, PRIMARY KEY (a,b)); +INSERT INTO t1 VALUES (1,1), (2,1), (3,1), (1,2), (3,2), (3,3); +EXPLAIN SELECT * FROM t1 WHERE a=3 AND b=2; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 const PRIMARY PRIMARY 8 const,const 1 Using index +EXPLAIN SELECT * FROM t1 WHERE (a,b)=(3,2); +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 const PRIMARY PRIMARY 8 const,const 1 Using index +SELECT * FROM t1 WHERE a=3 and b=2; +a b +3 2 +SELECT * FROM t1 WHERE (a,b)=(3,2); +a b +3 2 +CREATE TABLE t2 (a int, b int, c int, PRIMARY KEY (a,b,c)); +INSERT INTO t2 VALUES +(1,1,2), (3,1,3), (1,2,2), (4,4,2), +(1,1,1), (3,1,1), (1,2,1); +EXPLAIN SELECT * FROM t1,t2 WHERE t1.a=t2.a AND t1.b=t2.b; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 index PRIMARY PRIMARY 8 NULL 6 Using index +1 SIMPLE t2 ref PRIMARY PRIMARY 8 test.t1.a,test.t1.b 1 Using index +EXPLAIN SELECT * FROM t1,t2 WHERE (t1.a,t1.b)=(t2.a,t2.b); +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 index PRIMARY PRIMARY 8 NULL 6 Using index +1 SIMPLE t2 ref PRIMARY PRIMARY 8 test.t1.a,test.t1.b 1 Using index +SELECT * FROM t1,t2 WHERE t1.a=t2.a and t1.b=t2.b; +a b a b c +1 1 1 1 1 +1 1 1 1 2 +1 2 1 2 1 +1 2 1 2 2 +3 1 3 1 1 +3 1 3 1 3 +SELECT * FROM t1,t2 WHERE (t1.a,t1.b)=(t2.a,t2.b); +a b a b c +1 1 1 1 1 +1 1 1 1 2 +1 2 1 2 1 +1 2 1 2 2 +3 1 3 1 1 +3 1 3 1 3 +EXPLAIN SELECT * FROM t1,t2 WHERE t1.a=t2.a AND t1.b=2; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 index PRIMARY PRIMARY 8 NULL 5 Using where; Using index +1 SIMPLE t2 ref PRIMARY PRIMARY 4 test.t1.a 1 Using index +EXPLAIN SELECT * FROM t1,t2 WHERE (t1.a,t1.b)=(t2.a,2); +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 index PRIMARY PRIMARY 8 NULL 5 Using where; Using index +1 SIMPLE t2 ref PRIMARY PRIMARY 4 test.t1.a 1 Using index +SELECT * FROM t1,t2 WHERE t1.a=1 and t1.b=t2.b; +a b a b c +1 1 1 1 2 +1 1 3 1 3 +1 2 1 2 2 +1 1 1 1 1 +1 1 3 1 1 +1 2 1 2 1 +SELECT * FROM t1,t2 WHERE (t1.a,t1.b)=(t2.a,2); +a b a b c +1 2 1 1 1 +1 2 1 1 2 +1 2 1 2 1 +1 2 1 2 2 +3 2 3 1 1 +3 2 3 1 3 +EXPLAIN EXTENDED SELECT * FROM t1,t2 WHERE (t1.a,t1.b)=(t2.a,t2.b+1); +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 index PRIMARY PRIMARY 8 NULL 6 Using index +1 SIMPLE t2 ref PRIMARY PRIMARY 4 test.t1.a 1 Using where; Using index +Warnings: +Note 1003 select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b`,`test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b`,`test`.`t2`.`c` AS `c` from `test`.`t1` join `test`.`t2` where ((`test`.`t2`.`a` = `test`.`t1`.`a`) and (`test`.`t1`.`b` = (`test`.`t2`.`b` + 1))) +SELECT * FROM t1,t2 WHERE (t1.a,t1.b)=(t2.a,t2.b+1); +a b a b c +1 2 1 1 1 +1 2 1 1 2 +3 2 3 1 1 +3 2 3 1 3 +EXPLAIN EXTENDED SELECT * FROM t1,t2 WHERE (t1.a-1,t1.b)=(t2.a-1,t2.b+1); +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 index NULL PRIMARY 8 NULL 6 Using index +1 SIMPLE t2 index NULL PRIMARY 12 NULL 7 Using where; Using index +Warnings: +Note 1003 select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b`,`test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b`,`test`.`t2`.`c` AS `c` from `test`.`t1` join `test`.`t2` where (((`test`.`t1`.`a` - 1) = (`test`.`t2`.`a` - 1)) and (`test`.`t1`.`b` = (`test`.`t2`.`b` + 1))) +SELECT * FROM t1,t2 WHERE (t1.a-1,t1.b)=(t2.a-1,t2.b+1); +a b a b c +1 2 1 1 2 +3 2 3 1 3 +1 2 1 1 1 +3 2 3 1 1 +EXPLAIN SELECT * FROM t2 WHERE a=3 AND b=2; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t2 ref PRIMARY PRIMARY 8 const,const 1 Using index +EXPLAIN SELECT * FROM t2 WHERE (a,b)=(3,2); +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t2 ref PRIMARY PRIMARY 8 const,const 1 Using index +SELECT * FROM t2 WHERE a=3 and b=2; +a b c +SELECT * FROM t2 WHERE (a,b)=(3,2); +a b c +EXPLAIN SELECT * FROM t1,t2 WHERE t2.a=t1.a AND t2.b=2 AND t2.c=1; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 index PRIMARY PRIMARY 8 NULL 6 Using index +1 SIMPLE t2 eq_ref PRIMARY PRIMARY 12 test.t1.a,const,const 1 Using index +EXPLAIN EXTENDED SELECT * FROM t1,t2 WHERE (t2.a,(t2.b,t2.c))=(t1.a,(2,1)); +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 index PRIMARY PRIMARY 8 NULL 6 Using index +1 SIMPLE t2 eq_ref PRIMARY PRIMARY 12 test.t1.a,const,const 1 Using index +Warnings: +Note 1003 select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b`,`test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b`,`test`.`t2`.`c` AS `c` from `test`.`t1` join `test`.`t2` where ((`test`.`t2`.`c` = 1) and (`test`.`t2`.`b` = 2) and (`test`.`t2`.`a` = `test`.`t1`.`a`)) +SELECT * FROM t1,t2 WHERE (t2.a,(t2.b,t2.c))=(t1.a,(2,1)); +a b a b c +1 1 1 2 1 +1 2 1 2 1 +EXPLAIN EXTENDED SELECT * FROM t1,t2 WHERE t2.a=t1.a AND (t2.b,t2.c)=(2,1); +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 index PRIMARY PRIMARY 8 NULL 6 Using index +1 SIMPLE t2 eq_ref PRIMARY PRIMARY 12 test.t1.a,const,const 1 Using index +Warnings: +Note 1003 select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b`,`test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b`,`test`.`t2`.`c` AS `c` from `test`.`t1` join `test`.`t2` where ((`test`.`t2`.`c` = 1) and (`test`.`t2`.`b` = 2) and (`test`.`t2`.`a` = `test`.`t1`.`a`)) +SELECT * FROM t1,t2 WHERE t2.a=t1.a AND (t2.b,t2.c)=(2,1); +a b a b c +1 1 1 2 1 +1 2 1 2 1 +DROP TABLE t1,t2; diff --git a/mysql-test/r/rpl_insert_id.result b/mysql-test/r/rpl_insert_id.result index 3aa82bf1d63..d133a2ae8ed 100644 --- a/mysql-test/r/rpl_insert_id.result +++ b/mysql-test/r/rpl_insert_id.result @@ -1,9 +1,20 @@ +# +# Setup +# stop slave; drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; reset master; reset slave; drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; start slave; +use test; +drop table if exists t1, t2, t3; +# +# See if queries that use both auto_increment and LAST_INSERT_ID() +# are replicated well +# +# We also check how the foreign_key_check variable is replicated +# create table t1(a int auto_increment, key(a)); create table t2(b int auto_increment, c int, key(b)); insert into t1 values (1),(2),(3); @@ -38,6 +49,9 @@ select * from t2; b c 5 0 6 11 +# +# check if INSERT SELECT in auto_increment is well replicated (bug #490) +# drop table t2; drop table t1; create table t1(a int auto_increment, key(a)); @@ -68,12 +82,19 @@ b c 9 13 drop table t1; drop table t2; +# +# Bug#8412: Error codes reported in binary log for CHARACTER SET, +# FOREIGN_KEY_CHECKS +# SET TIMESTAMP=1000000000; CREATE TABLE t1 ( a INT UNIQUE ); SET FOREIGN_KEY_CHECKS=0; INSERT INTO t1 VALUES (1),(1); ERROR 23000: Duplicate entry '1' for key 1 drop table t1; +# +# Bug#14553: NULL in WHERE resets LAST_INSERT_ID +# create table t1(a int auto_increment, key(a)); create table t2(a int); insert into t1 (a) values (null); @@ -87,6 +108,9 @@ a 1 drop table t1; drop table t2; +# +# End of 4.1 tests +# drop function if exists bug15728; drop function if exists bug15728_insert; drop table if exists t1, t2; @@ -210,3 +234,153 @@ n b 2 100 3 350 drop table t1; +DROP PROCEDURE IF EXISTS p1; +DROP TABLE IF EXISTS t1, t2; +SELECT LAST_INSERT_ID(0); +LAST_INSERT_ID(0) +0 +CREATE TABLE t1 ( +id INT NOT NULL DEFAULT 0, +last_id INT, +PRIMARY KEY (id) +); +CREATE TABLE t2 ( +id INT NOT NULL AUTO_INCREMENT, +last_id INT, +PRIMARY KEY (id) +); +CREATE PROCEDURE p1() +BEGIN +INSERT INTO t2 (last_id) VALUES (LAST_INSERT_ID()); +INSERT INTO t1 (last_id) VALUES (LAST_INSERT_ID()); +END| +CALL p1(); +SELECT * FROM t1; +id last_id +0 1 +SELECT * FROM t2; +id last_id +1 0 +SELECT * FROM t1; +id last_id +0 1 +SELECT * FROM t2; +id last_id +1 0 +DROP PROCEDURE p1; +DROP TABLE t1, t2; +DROP PROCEDURE IF EXISTS p1; +DROP FUNCTION IF EXISTS f1; +DROP FUNCTION IF EXISTS f2; +DROP FUNCTION IF EXISTS f3; +DROP TABLE IF EXISTS t1, t2; +CREATE TABLE t1 ( +i INT NOT NULL AUTO_INCREMENT PRIMARY KEY, +j INT DEFAULT 0 +); +CREATE TABLE t2 (i INT); +CREATE PROCEDURE p1() +BEGIN +INSERT INTO t1 (i) VALUES (NULL); +INSERT INTO t2 (i) VALUES (LAST_INSERT_ID()); +INSERT INTO t1 (i) VALUES (NULL), (NULL); +INSERT INTO t2 (i) VALUES (LAST_INSERT_ID()); +END | +CREATE FUNCTION f1() RETURNS INT MODIFIES SQL DATA +BEGIN +INSERT INTO t1 (i) VALUES (NULL); +INSERT INTO t2 (i) VALUES (LAST_INSERT_ID()); +INSERT INTO t1 (i) VALUES (NULL), (NULL); +INSERT INTO t2 (i) VALUES (LAST_INSERT_ID()); +RETURN 0; +END | +CREATE FUNCTION f2() RETURNS INT NOT DETERMINISTIC +RETURN LAST_INSERT_ID() | +CREATE FUNCTION f3() RETURNS INT MODIFIES SQL DATA +BEGIN +INSERT INTO t2 (i) VALUES (LAST_INSERT_ID()); +RETURN 0; +END | +INSERT INTO t1 VALUES (NULL, -1); +CALL p1(); +SELECT f1(); +f1() +0 +INSERT INTO t1 VALUES (NULL, f2()), (NULL, LAST_INSERT_ID()), +(NULL, LAST_INSERT_ID()), (NULL, f2()), (NULL, f2()); +INSERT INTO t1 VALUES (NULL, f2()); +INSERT INTO t1 VALUES (NULL, LAST_INSERT_ID()), (NULL, LAST_INSERT_ID(5)), +(NULL, @@LAST_INSERT_ID); +INSERT INTO t1 VALUES (NULL, 0), (NULL, LAST_INSERT_ID()); +UPDATE t1 SET j= -1 WHERE i IS NULL; +INSERT INTO t1 (i) VALUES (NULL); +INSERT INTO t1 (i) VALUES (NULL); +SELECT f3(); +f3() +0 +SELECT * FROM t1; +i j +1 -1 +2 0 +3 0 +4 0 +5 0 +6 0 +7 0 +8 3 +9 3 +10 3 +11 3 +12 3 +13 8 +14 13 +15 5 +16 13 +17 -1 +18 14 +19 0 +20 0 +SELECT * FROM t2; +i +2 +3 +5 +6 +19 +SELECT * FROM t1; +i j +1 -1 +2 0 +3 0 +4 0 +5 0 +6 0 +7 0 +8 3 +9 3 +10 3 +11 3 +12 3 +13 8 +14 13 +15 5 +16 13 +17 -1 +18 14 +19 0 +20 0 +SELECT * FROM t2; +i +2 +3 +5 +6 +19 +DROP PROCEDURE p1; +DROP FUNCTION f1; +DROP FUNCTION f2; +DROP FUNCTION f3; +DROP TABLE t1, t2; + +# End of 5.0 tests + diff --git a/mysql-test/r/rpl_max_relay_size.result b/mysql-test/r/rpl_max_relay_size.result index fbe3b89828a..1fa49db6013 100644 --- a/mysql-test/r/rpl_max_relay_size.result +++ b/mysql-test/r/rpl_max_relay_size.result @@ -5,9 +5,15 @@ reset slave; drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; start slave; stop slave; +# +# Generate a big enough master's binlog to cause relay log rotations +# create table t1 (a int); drop table t1; reset slave; +# +# Test 1 +# set global max_binlog_size=8192; set global max_relay_log_size=8192-1; select @@global.max_relay_log_size; @@ -15,47 +21,251 @@ select @@global.max_relay_log_size; 4096 start slave; 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_PORT 1 master-bin.000001 72952 # # master-bin.000001 Yes Yes 0 0 72952 # None 0 No # +Slave_IO_State # +Master_Host 127.0.0.1 +Master_User root +Master_Port MASTER_PORT +Connect_Retry 1 +Master_Log_File master-bin.000001 +Read_Master_Log_Pos 72952 +Relay_Log_File # +Relay_Log_Pos # +Relay_Master_Log_File master-bin.000001 +Slave_IO_Running Yes +Slave_SQL_Running Yes +Replicate_Do_DB +Replicate_Ignore_DB +Replicate_Do_Table +Replicate_Ignore_Table +Replicate_Wild_Do_Table +Replicate_Wild_Ignore_Table +Last_Errno 0 +Last_Error +Skip_Counter 0 +Exec_Master_Log_Pos 72952 +Relay_Log_Space # +Until_Condition None +Until_Log_File +Until_Log_Pos 0 +Master_SSL_Allowed No +Master_SSL_CA_File +Master_SSL_CA_Path +Master_SSL_Cert +Master_SSL_Cipher +Master_SSL_Key +Seconds_Behind_Master # +# +# Test 2 +# stop slave; reset slave; set global max_relay_log_size=(5*4096); select @@global.max_relay_log_size; -@@global.max_relay_log_size -20480 +@@global.max_relay_log_size 20480 start slave; 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_PORT 1 master-bin.000001 72952 # # master-bin.000001 Yes Yes 0 0 72952 # None 0 No # +Slave_IO_State # +Master_Host 127.0.0.1 +Master_User root +Master_Port MASTER_PORT +Connect_Retry 1 +Master_Log_File master-bin.000001 +Read_Master_Log_Pos 72952 +Relay_Log_File # +Relay_Log_Pos # +Relay_Master_Log_File master-bin.000001 +Slave_IO_Running Yes +Slave_SQL_Running Yes +Replicate_Do_DB +Replicate_Ignore_DB +Replicate_Do_Table +Replicate_Ignore_Table +Replicate_Wild_Do_Table +Replicate_Wild_Ignore_Table +Last_Errno 0 +Last_Error +Skip_Counter 0 +Exec_Master_Log_Pos 72952 +Relay_Log_Space # +Until_Condition None +Until_Log_File +Until_Log_Pos 0 +Master_SSL_Allowed No +Master_SSL_CA_File +Master_SSL_CA_Path +Master_SSL_Cert +Master_SSL_Cipher +Master_SSL_Key +Seconds_Behind_Master # +# +# Test 3: max_relay_log_size = 0 +# stop slave; reset slave; set global max_relay_log_size=0; select @@global.max_relay_log_size; -@@global.max_relay_log_size -0 +@@global.max_relay_log_size 0 start slave; 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_PORT 1 master-bin.000001 72952 # # master-bin.000001 Yes Yes 0 0 72952 # None 0 No # +Slave_IO_State # +Master_Host 127.0.0.1 +Master_User root +Master_Port MASTER_PORT +Connect_Retry 1 +Master_Log_File master-bin.000001 +Read_Master_Log_Pos 72952 +Relay_Log_File # +Relay_Log_Pos # +Relay_Master_Log_File master-bin.000001 +Slave_IO_Running Yes +Slave_SQL_Running Yes +Replicate_Do_DB +Replicate_Ignore_DB +Replicate_Do_Table +Replicate_Ignore_Table +Replicate_Wild_Do_Table +Replicate_Wild_Ignore_Table +Last_Errno 0 +Last_Error +Skip_Counter 0 +Exec_Master_Log_Pos 72952 +Relay_Log_Space # +Until_Condition None +Until_Log_File +Until_Log_Pos 0 +Master_SSL_Allowed No +Master_SSL_CA_File +Master_SSL_CA_Path +Master_SSL_Cert +Master_SSL_Cipher +Master_SSL_Key +Seconds_Behind_Master # +# +# Test 4: Tests below are mainly to ensure that we have not coded with wrong assumptions +# stop slave; reset slave; flush logs; 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_PORT 1 4 # # No No 0 0 0 # None 0 No # +Slave_IO_State # +Master_Host 127.0.0.1 +Master_User root +Master_Port MASTER_PORT +Connect_Retry 1 +Master_Log_File +Read_Master_Log_Pos 4 +Relay_Log_File # +Relay_Log_Pos # +Relay_Master_Log_File +Slave_IO_Running No +Slave_SQL_Running No +Replicate_Do_DB +Replicate_Ignore_DB +Replicate_Do_Table +Replicate_Ignore_Table +Replicate_Wild_Do_Table +Replicate_Wild_Ignore_Table +Last_Errno 0 +Last_Error +Skip_Counter 0 +Exec_Master_Log_Pos 0 +Relay_Log_Space # +Until_Condition None +Until_Log_File +Until_Log_Pos 0 +Master_SSL_Allowed No +Master_SSL_CA_File +Master_SSL_CA_Path +Master_SSL_Cert +Master_SSL_Cipher +Master_SSL_Key +Seconds_Behind_Master # +# +# Test 5 +# reset slave; start slave; flush logs; create table t1 (a int); 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_PORT 1 master-bin.000001 73038 # # master-bin.000001 Yes Yes 0 0 73038 # None 0 No # +Slave_IO_State # +Master_Host 127.0.0.1 +Master_User root +Master_Port MASTER_PORT +Connect_Retry 1 +Master_Log_File master-bin.000001 +Read_Master_Log_Pos 73038 +Relay_Log_File # +Relay_Log_Pos # +Relay_Master_Log_File master-bin.000001 +Slave_IO_Running Yes +Slave_SQL_Running Yes +Replicate_Do_DB +Replicate_Ignore_DB +Replicate_Do_Table +Replicate_Ignore_Table +Replicate_Wild_Do_Table +Replicate_Wild_Ignore_Table +Last_Errno 0 +Last_Error +Skip_Counter 0 +Exec_Master_Log_Pos 73038 +Relay_Log_Space # +Until_Condition None +Until_Log_File +Until_Log_Pos 0 +Master_SSL_Allowed No +Master_SSL_CA_File +Master_SSL_CA_Path +Master_SSL_Cert +Master_SSL_Cipher +Master_SSL_Key +Seconds_Behind_Master # +# +# Test 6: one more rotation, to be sure Relay_Log_Space is correctly updated +# flush logs; drop table t1; 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_PORT 1 master-bin.000001 73114 # # master-bin.000001 Yes Yes 0 0 73114 # None 0 No # +Slave_IO_State # +Master_Host 127.0.0.1 +Master_User root +Master_Port MASTER_PORT +Connect_Retry 1 +Master_Log_File master-bin.000001 +Read_Master_Log_Pos 73114 +Relay_Log_File # +Relay_Log_Pos # +Relay_Master_Log_File master-bin.000001 +Slave_IO_Running Yes +Slave_SQL_Running Yes +Replicate_Do_DB +Replicate_Ignore_DB +Replicate_Do_Table +Replicate_Ignore_Table +Replicate_Wild_Do_Table +Replicate_Wild_Ignore_Table +Last_Errno 0 +Last_Error +Skip_Counter 0 +Exec_Master_Log_Pos 73114 +Relay_Log_Space # +Until_Condition None +Until_Log_File +Until_Log_Pos 0 +Master_SSL_Allowed No +Master_SSL_CA_File +Master_SSL_CA_Path +Master_SSL_Cert +Master_SSL_Cipher +Master_SSL_Key +Seconds_Behind_Master # flush logs; show master status; -File Position Binlog_Do_DB Binlog_Ignore_DB -master-bin.000002 98 +File master-bin.000002 +Position 98 +Binlog_Do_DB +Binlog_Ignore_DB +# +# End of 4.1 tests +# diff --git a/mysql-test/r/rpl_ndb_innodb_trans.result b/mysql-test/r/rpl_ndb_innodb_trans.result new file mode 100644 index 00000000000..148e6247b03 --- /dev/null +++ b/mysql-test/r/rpl_ndb_innodb_trans.result @@ -0,0 +1,103 @@ +stop slave; +drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; +reset master; +reset slave; +drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; +start slave; +create table t1 (a int, unique(a)) engine=ndbcluster; +create table t2 (a int, unique(a)) engine=innodb; +begin; +insert into t1 values(1); +insert into t2 values(1); +rollback; +select count(*) from t1; +count(*) +0 +select count(*) from t2; +count(*) +0 +select count(*) from t1; +count(*) +0 +select count(*) from t2; +count(*) +0 +begin; +load data infile '../std_data_ln/rpl_loaddata.dat' into table t2; +Warnings: +Warning 1262 Row 1 was truncated; it contained more data than there were input columns +Warning 1262 Row 2 was truncated; it contained more data than there were input columns +load data infile '../std_data_ln/rpl_loaddata.dat' into table t1; +Warnings: +Warning 1262 Row 1 was truncated; it contained more data than there were input columns +Warning 1262 Row 2 was truncated; it contained more data than there were input columns +rollback; +Warnings: +Warning 1196 Some non-transactional changed tables couldn't be rolled back +select count(*) from t1; +count(*) +2 +select count(*) from t2; +count(*) +0 +select count(*) from t1; +count(*) +2 +select count(*) from t2; +count(*) +0 +delete from t1; +delete from t2; +begin; +load data infile '../std_data_ln/rpl_loaddata.dat' into table t2; +Warnings: +Warning 1262 Row 1 was truncated; it contained more data than there were input columns +Warning 1262 Row 2 was truncated; it contained more data than there were input columns +load data infile '../std_data_ln/rpl_loaddata.dat' into table t1; +Warnings: +Warning 1262 Row 1 was truncated; it contained more data than there were input columns +Warning 1262 Row 2 was truncated; it contained more data than there were input columns +rollback; +Warnings: +Warning 1196 Some non-transactional changed tables couldn't be rolled back +select count(*) from t1; +count(*) +2 +select count(*) from t2; +count(*) +0 +select count(*) from t1; +count(*) +2 +select count(*) from t2; +count(*) +0 +delete from t1; +delete from t2; +begin; +insert into t2 values(3),(4); +insert into t1 values(3),(4); +load data infile '../std_data_ln/rpl_loaddata.dat' into table t2; +Warnings: +Warning 1262 Row 1 was truncated; it contained more data than there were input columns +Warning 1262 Row 2 was truncated; it contained more data than there were input columns +load data infile '../std_data_ln/rpl_loaddata.dat' into table t1; +Warnings: +Warning 1262 Row 1 was truncated; it contained more data than there were input columns +Warning 1262 Row 2 was truncated; it contained more data than there were input columns +rollback; +Warnings: +Warning 1196 Some non-transactional changed tables couldn't be rolled back +select count(*) from t1; +count(*) +4 +select count(*) from t2; +count(*) +0 +select count(*) from t1; +count(*) +4 +select count(*) from t2; +count(*) +0 +drop table t1,t2; diff --git a/mysql-test/r/rpl_rewrite_db.result b/mysql-test/r/rpl_rewrite_db.result index 71ac39010b5..1b843bffdca 100644 --- a/mysql-test/r/rpl_rewrite_db.result +++ b/mysql-test/r/rpl_rewrite_db.result @@ -67,9 +67,9 @@ drop table t1; create table t1 (a int, b char(10)); load data infile '../std_data_ln/loaddata3.dat' into table t1 fields terminated by '' enclosed by '' ignore 1 lines; Warnings: -Warning 1264 Out of range value adjusted for column 'a' at row 3 +Warning 1366 Incorrect integer value: 'error ' for column 'a' at row 3 Warning 1262 Row 3 was truncated; it contained more data than there were input columns -Warning 1264 Out of range value adjusted for column 'a' at row 5 +Warning 1366 Incorrect integer value: 'wrong end ' for column 'a' at row 5 Warning 1262 Row 5 was truncated; it contained more data than there were input columns select * from rewrite.t1; a b @@ -81,7 +81,8 @@ a b truncate table t1; load data infile '../std_data_ln/loaddata4.dat' into table t1 fields terminated by '' enclosed by '' lines terminated by '' ignore 1 lines; Warnings: -Warning 1264 Out of range value adjusted for column 'a' at row 4 +Warning 1366 Incorrect integer value: ' +' for column 'a' at row 4 Warning 1261 Row 4 doesn't contain data for all columns select * from rewrite.t1; a b diff --git a/mysql-test/r/rpl_view.result b/mysql-test/r/rpl_view.result index 5a101defe38..601f3d9cd14 100644 --- a/mysql-test/r/rpl_view.result +++ b/mysql-test/r/rpl_view.result @@ -91,3 +91,19 @@ c ---> Cleaning up... DROP VIEW v1; DROP TABLE t1; +create table t1(a int, b int); +insert into t1 values (1, 1), (1, 2), (1, 3); +create view v1(a, b) as select a, sum(b) from t1 group by a; +explain v1; +Field Type Null Key Default Extra +a int(11) YES NULL +b decimal(32,0) YES NULL +show create table v1; +View Create View +v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select `t1`.`a` AS `a`,sum(`t1`.`b`) AS `b` from `t1` group by `t1`.`a` +select * from v1; +a b +1 6 +drop table t1; +drop view v1; +End of 5.0 tests diff --git a/mysql-test/r/select.result b/mysql-test/r/select.result index 0c62d3f570f..543dfd82eae 100644 --- a/mysql-test/r/select.result +++ b/mysql-test/r/select.result @@ -2734,7 +2734,7 @@ CREATE TABLE t1 (i BIGINT UNSIGNED NOT NULL); INSERT INTO t1 VALUES (10); SELECT i='1e+01',i=1e+01, i in (1e+01,1e+01), i in ('1e+01','1e+01') FROM t1; i='1e+01' i=1e+01 i in (1e+01,1e+01) i in ('1e+01','1e+01') -0 1 1 1 +1 1 1 1 DROP TABLE t1; CREATE TABLE t1 (a int, b int); INSERT INTO t1 VALUES (1,1), (2,1), (4,10); diff --git a/mysql-test/r/sp-vars.result b/mysql-test/r/sp-vars.result index 83ee188bfa4..14040f8420e 100644 --- a/mysql-test/r/sp-vars.result +++ b/mysql-test/r/sp-vars.result @@ -896,7 +896,7 @@ sp_var @user_var 0 Warnings: -Warning 1264 Out of range value adjusted for column 'sp_var' at row 1 +Warning 1366 Incorrect integer value: 'Hello, world!' for column 'sp_var' at row 1 DROP PROCEDURE p1; DROP TABLE t1; diff --git a/mysql-test/r/sp.result b/mysql-test/r/sp.result index 854935b071b..31aa96ab05d 100644 --- a/mysql-test/r/sp.result +++ b/mysql-test/r/sp.result @@ -5394,4 +5394,81 @@ Procedure sql_mode Create Procedure bug21416 CREATE DEFINER=`root`@`localhost` PROCEDURE `bug21416`() show create procedure bug21416 drop procedure bug21416| +DROP PROCEDURE IF EXISTS bug21414| +CREATE PROCEDURE bug21414() SELECT 1| +FLUSH TABLES WITH READ LOCK| +DROP PROCEDURE bug21414| +ERROR HY000: Can't execute the query because you have a conflicting read lock +UNLOCK TABLES| +The following should succeed. +DROP PROCEDURE bug21414| +set names utf8| +drop database if exists това_е_дълго_име_за_база_данни_нали| +create database това_е_дълго_име_за_база_данни_нали| +INSERT INTO mysql.proc VALUES ('това_е_дълго_име_за_база_данни_нали','това_е_процедура_Ñ_доÑта_дълго_име_нали_и_още_по_дълго','PROCEDURE','това_е_процедура_Ñ_доÑта_дълго_име_нали_и_още_по_дълго','SQL','CONTAINS_SQL','NO','DEFINER','','','bad_body','root@localhost',now(), now(),'','')| +call това_е_дълго_име_за_база_данни_нали.това_е_процедура_Ñ_доÑта_дълго_име_нали_и_още_по_дълго()| +ERROR HY000: Failed to load routine това_е_дълго_име_за_база_данни_нали.това_е_процедура_Ñ_доÑта_дълго_име_нали_и_още_по_дълго. The table mysql.proc is missing, corrupt, or contains bad data (internal code -6) +drop database това_е_дълго_име_за_база_данни_нали| +CREATE TABLE t3 ( +Member_ID varchar(15) NOT NULL, +PRIMARY KEY (Member_ID) +)| +CREATE TABLE t4 ( +ID int(10) unsigned NOT NULL auto_increment, +Member_ID varchar(15) NOT NULL default '', +Action varchar(12) NOT NULL, +Action_Date datetime NOT NULL, +Track varchar(15) default NULL, +User varchar(12) default NULL, +Date_Updated timestamp NOT NULL default CURRENT_TIMESTAMP on update +CURRENT_TIMESTAMP, +PRIMARY KEY (ID), +KEY Action (Action), +KEY Action_Date (Action_Date) +)| +INSERT INTO t3(Member_ID) VALUES +('111111'), ('222222'), ('333333'), ('444444'), ('555555'), ('666666')| +INSERT INTO t4(Member_ID, Action, Action_Date, Track) VALUES +('111111', 'Disenrolled', '2006-03-01', 'CAD' ), +('111111', 'Enrolled', '2006-03-01', 'CAD' ), +('111111', 'Disenrolled', '2006-07-03', 'CAD' ), +('222222', 'Enrolled', '2006-03-07', 'CAD' ), +('222222', 'Enrolled', '2006-03-07', 'CHF' ), +('222222', 'Disenrolled', '2006-08-02', 'CHF' ), +('333333', 'Enrolled', '2006-03-01', 'CAD' ), +('333333', 'Disenrolled', '2006-03-01', 'CAD' ), +('444444', 'Enrolled', '2006-03-01', 'CAD' ), +('555555', 'Disenrolled', '2006-03-01', 'CAD' ), +('555555', 'Enrolled', '2006-07-21', 'CAD' ), +('555555', 'Disenrolled', '2006-03-01', 'CHF' ), +('666666', 'Enrolled', '2006-02-09', 'CAD' ), +('666666', 'Enrolled', '2006-05-12', 'CHF' ), +('666666', 'Disenrolled', '2006-06-01', 'CAD' )| +DROP FUNCTION IF EXISTS bug21493| +CREATE FUNCTION bug21493(paramMember VARCHAR(15)) RETURNS varchar(45) +BEGIN +DECLARE tracks VARCHAR(45); +SELECT GROUP_CONCAT(Track SEPARATOR ', ') INTO tracks FROM t4 +WHERE Member_ID=paramMember AND Action='Enrolled' AND +(Track,Action_Date) IN (SELECT Track, MAX(Action_Date) FROM t4 +WHERE Member_ID=paramMember GROUP BY Track); +RETURN tracks; +END| +SELECT bug21493('111111')| +bug21493('111111') +NULL +SELECT bug21493('222222')| +bug21493('222222') +CAD +SELECT bug21493(Member_ID) FROM t3| +bug21493(Member_ID) +NULL +CAD +CAD +CAD +CAD +CHF +DROP FUNCTION bug21493| +DROP TABLE t3,t4| +End of 5.0 tests drop table t1,t2; diff --git a/mysql-test/r/strict.result b/mysql-test/r/strict.result index e144eed92f5..702fc68bb25 100644 --- a/mysql-test/r/strict.result +++ b/mysql-test/r/strict.result @@ -619,9 +619,9 @@ ERROR 22012: Division by 0 UPDATE t1 SET col1= MOD(col1,0) WHERE col1 > 0; ERROR 22012: Division by 0 INSERT INTO t1 (col1) VALUES (''); -ERROR 22003: Out of range value adjusted for column 'col1' at row 1 +ERROR HY000: Incorrect integer value: '' for column 'col1' at row 1 INSERT INTO t1 (col1) VALUES ('a59b'); -ERROR 22003: Out of range value adjusted for column 'col1' at row 1 +ERROR HY000: Incorrect integer value: 'a59b' for column 'col1' at row 1 INSERT INTO t1 (col1) VALUES ('1a'); ERROR 01000: Data truncated for column 'col1' at row 1 INSERT IGNORE INTO t1 (col1) VALUES ('2a'); @@ -701,9 +701,9 @@ ERROR 22012: Division by 0 UPDATE t1 SET col1= MOD(col1,0) WHERE col1 > 0; ERROR 22012: Division by 0 INSERT INTO t1 (col1) VALUES (''); -ERROR 22003: Out of range value adjusted for column 'col1' at row 1 +ERROR HY000: Incorrect integer value: '' for column 'col1' at row 1 INSERT INTO t1 (col1) VALUES ('a59b'); -ERROR 22003: Out of range value adjusted for column 'col1' at row 1 +ERROR HY000: Incorrect integer value: 'a59b' for column 'col1' at row 1 INSERT INTO t1 (col1) VALUES ('1a'); ERROR 01000: Data truncated for column 'col1' at row 1 INSERT IGNORE INTO t1 (col1) VALUES ('2a'); @@ -925,10 +925,10 @@ Warning 1264 Out of range value adjusted for column 'col2' at row 1 Warning 1264 Out of range value adjusted for column 'col2' at row 1 SELECT * FROM t1; col1 col2 -0 0 +-2.2e-307 0 1e-303 0 1.7e+308 1.7e+308 -0 0 +-2.2e-307 0 -2e-307 0 1.7e+308 1.7e+308 0 NULL diff --git a/mysql-test/r/strict_autoinc_1myisam.result b/mysql-test/r/strict_autoinc_1myisam.result new file mode 100644 index 00000000000..5d3c2698cda --- /dev/null +++ b/mysql-test/r/strict_autoinc_1myisam.result @@ -0,0 +1,27 @@ +set @org_mode=@@sql_mode; +create table t1 +( +`a` tinyint(4) NOT NULL auto_increment, +primary key (`a`) +) engine = 'MYISAM' ; +set @@sql_mode='strict_all_tables'; +insert into t1 values(1000); +ERROR 22003: Out of range value adjusted for column 'a' at row 1 +select count(*) from t1; +count(*) +0 +set auto_increment_increment=1000; +set auto_increment_offset=700; +insert into t1 values(null); +ERROR 22003: Out of range value adjusted for column 'a' at row 1 +select count(*) from t1; +count(*) +0 +set @@sql_mode=@org_mode; +insert into t1 values(null); +Warnings: +Warning 1264 Out of range value adjusted for column 'a' at row 1 +select * from t1; +a +127 +drop table t1; diff --git a/mysql-test/r/strict_autoinc_2innodb.result b/mysql-test/r/strict_autoinc_2innodb.result new file mode 100644 index 00000000000..f1936ff4de3 --- /dev/null +++ b/mysql-test/r/strict_autoinc_2innodb.result @@ -0,0 +1,27 @@ +set @org_mode=@@sql_mode; +create table t1 +( +`a` tinyint(4) NOT NULL auto_increment, +primary key (`a`) +) engine = 'InnoDB' ; +set @@sql_mode='strict_all_tables'; +insert into t1 values(1000); +ERROR 22003: Out of range value adjusted for column 'a' at row 1 +select count(*) from t1; +count(*) +0 +set auto_increment_increment=1000; +set auto_increment_offset=700; +insert into t1 values(null); +ERROR 22003: Out of range value adjusted for column 'a' at row 1 +select count(*) from t1; +count(*) +0 +set @@sql_mode=@org_mode; +insert into t1 values(null); +Warnings: +Warning 1264 Out of range value adjusted for column 'a' at row 1 +select * from t1; +a +127 +drop table t1; diff --git a/mysql-test/r/strict_autoinc_3heap.result b/mysql-test/r/strict_autoinc_3heap.result new file mode 100644 index 00000000000..aa0be270ac5 --- /dev/null +++ b/mysql-test/r/strict_autoinc_3heap.result @@ -0,0 +1,27 @@ +set @org_mode=@@sql_mode; +create table t1 +( +`a` tinyint(4) NOT NULL auto_increment, +primary key (`a`) +) engine = 'MEMORY' ; +set @@sql_mode='strict_all_tables'; +insert into t1 values(1000); +ERROR 22003: Out of range value adjusted for column 'a' at row 1 +select count(*) from t1; +count(*) +0 +set auto_increment_increment=1000; +set auto_increment_offset=700; +insert into t1 values(null); +ERROR 22003: Out of range value adjusted for column 'a' at row 1 +select count(*) from t1; +count(*) +0 +set @@sql_mode=@org_mode; +insert into t1 values(null); +Warnings: +Warning 1264 Out of range value adjusted for column 'a' at row 1 +select * from t1; +a +127 +drop table t1; diff --git a/mysql-test/r/strict_autoinc_4bdb.result b/mysql-test/r/strict_autoinc_4bdb.result new file mode 100644 index 00000000000..73683b645e2 --- /dev/null +++ b/mysql-test/r/strict_autoinc_4bdb.result @@ -0,0 +1,27 @@ +set @org_mode=@@sql_mode; +create table t1 +( +`a` tinyint(4) NOT NULL auto_increment, +primary key (`a`) +) engine = 'BDB' ; +set @@sql_mode='strict_all_tables'; +insert into t1 values(1000); +ERROR 22003: Out of range value adjusted for column 'a' at row 1 +select count(*) from t1; +count(*) +0 +set auto_increment_increment=1000; +set auto_increment_offset=700; +insert into t1 values(null); +ERROR 22003: Out of range value adjusted for column 'a' at row 1 +select count(*) from t1; +count(*) +0 +set @@sql_mode=@org_mode; +insert into t1 values(null); +Warnings: +Warning 1264 Out of range value adjusted for column 'a' at row 1 +select * from t1; +a +127 +drop table t1; diff --git a/mysql-test/r/strict_autoinc_5ndb.result b/mysql-test/r/strict_autoinc_5ndb.result new file mode 100644 index 00000000000..d0d62d05b32 --- /dev/null +++ b/mysql-test/r/strict_autoinc_5ndb.result @@ -0,0 +1,27 @@ +set @org_mode=@@sql_mode; +create table t1 +( +`a` tinyint(4) NOT NULL auto_increment, +primary key (`a`) +) engine = 'NDB' ; +set @@sql_mode='strict_all_tables'; +insert into t1 values(1000); +ERROR 22003: Out of range value adjusted for column 'a' at row 1 +select count(*) from t1; +count(*) +0 +set auto_increment_increment=1000; +set auto_increment_offset=700; +insert into t1 values(null); +ERROR 22003: Out of range value adjusted for column 'a' at row 1 +select count(*) from t1; +count(*) +0 +set @@sql_mode=@org_mode; +insert into t1 values(null); +Warnings: +Warning 1264 Out of range value adjusted for column 'a' at row 1 +select * from t1; +a +127 +drop table t1; diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result index 4ee6d3088a5..6bf85979002 100644 --- a/mysql-test/r/subselect.result +++ b/mysql-test/r/subselect.result @@ -1011,7 +1011,7 @@ INSERT INTO t1 VALUES (1); UPDATE t1 SET i=i+1 WHERE i=(SELECT MAX(i)); select * from t1; i -1 +2 drop table t1; CREATE TABLE t1 (a int(1)); EXPLAIN EXTENDED SELECT (SELECT RAND() FROM t1) FROM t1; @@ -1160,7 +1160,7 @@ Code2 char(2) NOT NULL default '', PRIMARY KEY (Code) ) ENGINE=MyISAM; INSERT INTO t2 VALUES ('AUS','Australia','Oceania','Australia and New Zealand',7741220.00,1901,18886000,79.8,351182.00,392911.00,'Australia','Constitutional Monarchy, Federation','Elisabeth II',135,'AU'); -INSERT INTO t2 VALUES ('AZE','Azerbaijan','Asia','Middle East',86600.00,1991,7734000,62.9,4127.00,4100.00,'Azärbaycan','Federal Republic','Heydär Äliyev',144,'AZ'); +INSERT INTO t2 VALUES ('AZE','Azerbaijan','Asia','Middle East',86600.00,1991,7734000,62.9,4127.00,4100.00,'Azärbaycan','Federal Republic','Heydär Äliyev',144,'AZ'); select t2.Continent, t1.Name, t1.Population from t2 LEFT JOIN t1 ON t2.Code = t1.t2 where t1.Population IN (select max(t1.Population) AS Population from t1, t2 where t1.t2 = t2.Code group by Continent); Continent Name Population Oceania Sydney 3276207 @@ -1203,7 +1203,7 @@ UPDATE t1 SET t.i=i+(SELECT MAX(i) FROM (SELECT 1) t); ERROR 42S22: Unknown column 't.i' in 'field list' select * from t1; i -1 +3 drop table t1; CREATE TABLE t1 ( id int(11) default NULL @@ -2512,7 +2512,7 @@ Code2 char(2) NOT NULL default '' ) ENGINE=MyISAM; INSERT INTO t1 VALUES ('XXX','Xxxxx','Oceania','Xxxxxx',26.00,0,0,0,0,0,'Xxxxx','Xxxxx','Xxxxx',NULL,'XX'); INSERT INTO t1 VALUES ('ASM','American Samoa','Oceania','Polynesia',199.00,0,68000,75.1,334.00,NULL,'Amerika Samoa','US Territory','George W. Bush',54,'AS'); -INSERT INTO t1 VALUES ('ATF','French Southern territories','Antarctica','Antarctica',7780.00,0,0,NULL,0.00,NULL,'Terres australes françaises','Nonmetropolitan Territory of France','Jacques Chirac',NULL,'TF'); +INSERT INTO t1 VALUES ('ATF','French Southern territories','Antarctica','Antarctica',7780.00,0,0,NULL,0.00,NULL,'Terres australes françaises','Nonmetropolitan Territory of France','Jacques Chirac',NULL,'TF'); INSERT INTO t1 VALUES ('UMI','United States Minor Outlying Islands','Oceania','Micronesia/Caribbean',16.00,0,0,NULL,0.00,NULL,'United States Minor Outlying Islands','Dependent Territory of the US','George W. Bush',NULL,'UM'); /*!40000 ALTER TABLE t1 ENABLE KEYS */; SELECT DISTINCT Continent AS c FROM t1 WHERE Code <> SOME ( SELECT Code FROM t1 WHERE Continent = c AND Population < 200); @@ -2937,6 +2937,71 @@ retailerID statusID changed 0048 1 2006-01-06 12:37:50 0059 1 2006-01-06 12:37:50 drop table t1; +create table t1(a int, primary key (a)); +insert into t1 values (10); +create table t2 (a int primary key, b varchar(32), c int, unique key b(c, b)); +insert into t2(a, c, b) values (1,10,'359'), (2,10,'35988'), (3,10,'35989'); +explain SELECT sql_no_cache t1.a, r.a, r.b FROM t1 LEFT JOIN t2 r +ON r.a = (SELECT t2.a FROM t2 WHERE t2.c = t1.a AND t2.b <= '359899' +ORDER BY t2.c DESC, t2.b DESC LIMIT 1) WHERE t1.a = 10; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 system PRIMARY NULL NULL NULL 1 +1 PRIMARY r const PRIMARY PRIMARY 4 const 1 +2 DEPENDENT SUBQUERY t2 range b b 40 NULL 2 Using where +SELECT sql_no_cache t1.a, r.a, r.b FROM t1 LEFT JOIN t2 r +ON r.a = (SELECT t2.a FROM t2 WHERE t2.c = t1.a AND t2.b <= '359899' +ORDER BY t2.c DESC, t2.b DESC LIMIT 1) WHERE t1.a = 10; +a a b +10 3 35989 +explain SELECT sql_no_cache t1.a, r.a, r.b FROM t1 LEFT JOIN t2 r +ON r.a = (SELECT t2.a FROM t2 WHERE t2.c = t1.a AND t2.b <= '359899' +ORDER BY t2.c, t2.b LIMIT 1) WHERE t1.a = 10; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 system PRIMARY NULL NULL NULL 1 +1 PRIMARY r const PRIMARY PRIMARY 4 const 1 +2 DEPENDENT SUBQUERY t2 range b b 40 NULL 2 Using where +SELECT sql_no_cache t1.a, r.a, r.b FROM t1 LEFT JOIN t2 r +ON r.a = (SELECT t2.a FROM t2 WHERE t2.c = t1.a AND t2.b <= '359899' +ORDER BY t2.c, t2.b LIMIT 1) WHERE t1.a = 10; +a a b +10 1 359 +drop table t1,t2; +CREATE TABLE t1 ( +field1 int NOT NULL, +field2 int NOT NULL, +field3 int NOT NULL, +PRIMARY KEY (field1,field2,field3) +); +CREATE TABLE t2 ( +fieldA int NOT NULL, +fieldB int NOT NULL, +PRIMARY KEY (fieldA,fieldB) +); +INSERT INTO t1 VALUES +(1,1,1), (1,1,2), (1,2,1), (1,2,2), (1,2,3), (1,3,1); +INSERT INTO t2 VALUES (1,1), (1,2), (1,3); +SELECT field1, field2, COUNT(*) +FROM t1 GROUP BY field1, field2; +field1 field2 COUNT(*) +1 1 2 +1 2 3 +1 3 1 +SELECT field1, field2 +FROM t1 +GROUP BY field1, field2 +HAVING COUNT(*) >= ALL (SELECT fieldB +FROM t2 WHERE fieldA = field1); +field1 field2 +1 2 +SELECT field1, field2 +FROM t1 +GROUP BY field1, field2 +HAVING COUNT(*) < ANY (SELECT fieldB +FROM t2 WHERE fieldA = field1); +field1 field2 +1 1 +1 3 +DROP TABLE t1, t2; create table t1 (df decimal(5,1)); insert into t1 values(1.1); insert into t1 values(2.2); @@ -3368,3 +3433,89 @@ ORDER BY t1.t DESC LIMIT 1); i1 i2 t i1 i2 t 24 1 2005-05-27 12:40:30 24 1 2006-06-20 12:29:40 DROP TABLE t1, t2; +CREATE TABLE t1 (i INT); +(SELECT i FROM t1) UNION (SELECT i FROM t1); +i +SELECT sql_no_cache * FROM t1 WHERE NOT EXISTS +( +(SELECT i FROM t1) UNION +(SELECT i FROM t1) +); +i +SELECT * FROM t1 +WHERE NOT EXISTS (((SELECT i FROM t1) UNION (SELECT i FROM t1))); +i +explain select ((select t11.i from t1 t11) union (select t12.i from t1 t12)) +from t1; +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'union (select t12.i from t1 t12)) +from t1' at line 1 +explain select * from t1 where not exists +((select t11.i from t1 t11) union (select t12.i from t1 t12)); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 system NULL NULL NULL NULL 0 const row not found +2 SUBQUERY NULL NULL NULL NULL NULL NULL NULL No tables used +3 SUBQUERY NULL NULL NULL NULL NULL NULL NULL no matching row in const table +4 UNION t12 system NULL NULL NULL NULL 0 const row not found +NULL UNION RESULT ALL NULL NULL NULL NULL NULL +DROP TABLE t1; +CREATE TABLE t1 (a INT, b INT); +CREATE TABLE t2 (a INT); +INSERT INTO t2 values (1); +INSERT INTO t1 VALUES (1,1),(1,2),(2,3),(3,4); +SELECT (SELECT COUNT(DISTINCT t1.b) from t2) FROM t1 GROUP BY t1.a; +(SELECT COUNT(DISTINCT t1.b) from t2) +2 +1 +1 +SELECT (SELECT COUNT(DISTINCT t1.b) from t2 union select 1 from t2 where 12 < 3) +FROM t1 GROUP BY t1.a; +(SELECT COUNT(DISTINCT t1.b) from t2 union select 1 from t2 where 12 < 3) +2 +1 +1 +SELECT COUNT(DISTINCT t1.b), (SELECT COUNT(DISTINCT t1.b)) FROM t1 GROUP BY t1.a; +COUNT(DISTINCT t1.b) (SELECT COUNT(DISTINCT t1.b)) +2 2 +1 1 +1 1 +SELECT COUNT(DISTINCT t1.b), +(SELECT COUNT(DISTINCT t1.b) union select 1 from DUAL where 12 < 3) +FROM t1 GROUP BY t1.a; +COUNT(DISTINCT t1.b) (SELECT COUNT(DISTINCT t1.b) union select 1 from DUAL where 12 < 3) +2 2 +1 1 +1 1 +SELECT ( +SELECT ( +SELECT COUNT(DISTINCT t1.b) +) +) +FROM t1 GROUP BY t1.a; +( +SELECT ( +SELECT COUNT(DISTINCT t1.b) +) +) +2 +1 +1 +SELECT ( +SELECT ( +SELECT ( +SELECT COUNT(DISTINCT t1.b) +) +) +FROM t1 GROUP BY t1.a LIMIT 1) +FROM t1 t2 +GROUP BY t2.a; +( +SELECT ( +SELECT ( +SELECT COUNT(DISTINCT t1.b) +) +) +FROM t1 GROUP BY t1.a LIMIT 1) +2 +2 +2 +DROP TABLE t1,t2; diff --git a/mysql-test/r/temp_table.result b/mysql-test/r/temp_table.result index 82479504b10..139a7da77de 100644 --- a/mysql-test/r/temp_table.result +++ b/mysql-test/r/temp_table.result @@ -135,3 +135,20 @@ d c bar 2 foo 1 drop table t1, t2; +DROP TABLE IF EXISTS t1; +CREATE TABLE t1 (i INT); +LOCK TABLE t1 WRITE; +CREATE TEMPORARY TABLE t1 (i INT); +The following command should not block +DROP TEMPORARY TABLE t1; +DROP TABLE t1; +CREATE TABLE t1 (i INT); +CREATE TEMPORARY TABLE t2 (i INT); +DROP TEMPORARY TABLE t2, t1; +ERROR 42S02: Unknown table 't1' +SELECT * FROM t2; +ERROR 42S02: Table 'test.t2' doesn't exist +SELECT * FROM t1; +i +DROP TABLE t1; +End of 4.1 tests. diff --git a/mysql-test/r/trigger.result b/mysql-test/r/trigger.result index c687d4c49c8..0b0bf1086db 100644 --- a/mysql-test/r/trigger.result +++ b/mysql-test/r/trigger.result @@ -1173,4 +1173,16 @@ TRIGGER t2_bi BEFORE INSERT ON t2 FOR EACH ROW SET @a = 2; ERROR HY000: String '1234567890abcdefghij1234567890abcdefghij1234567890abcdefghijQWERTY' is too long for host name (should be no longer than 60) DROP TABLE t1; DROP TABLE t2; +drop table if exists t1; +create table t1 (i int, j int key); +insert into t1 values (1,1), (2,2), (3,3); +create trigger t1_bu before update on t1 for each row +set new.j = new.j + 10; +update t1 set i= i+ 10 where j > 2; +select * from t1; +i j +1 1 +2 2 +13 13 +drop table t1; End of 5.0 tests diff --git a/mysql-test/r/type_bit.result b/mysql-test/r/type_bit.result index 2281ed44e3f..bd58e83bb3f 100644 --- a/mysql-test/r/type_bit.result +++ b/mysql-test/r/type_bit.result @@ -572,4 +572,42 @@ def test t1 t1 a a 16 7 1 Y 0 0 63 a ` drop table t1; +create table bug15583(b BIT(8), n INT); +insert into bug15583 values(128, 128); +insert into bug15583 values(null, null); +insert into bug15583 values(0, 0); +insert into bug15583 values(255, 255); +select hex(b), bin(b), oct(b), hex(n), bin(n), oct(n) from bug15583; +hex(b) bin(b) oct(b) hex(n) bin(n) oct(n) +80 10000000 200 80 10000000 200 +NULL NULL NULL NULL NULL NULL +0 0 0 0 0 0 +FF 11111111 377 FF 11111111 377 +select hex(b)=hex(n) as should_be_onetrue, bin(b)=bin(n) as should_be_onetrue, oct(b)=oct(n) as should_be_onetrue from bug15583; +should_be_onetrue should_be_onetrue should_be_onetrue +1 1 1 +NULL NULL NULL +1 1 1 +1 1 1 +select hex(b + 0), bin(b + 0), oct(b + 0), hex(n), bin(n), oct(n) from bug15583; +hex(b + 0) bin(b + 0) oct(b + 0) hex(n) bin(n) oct(n) +80 10000000 200 80 10000000 200 +NULL NULL NULL NULL NULL NULL +0 0 0 0 0 0 +FF 11111111 377 FF 11111111 377 +select conv(b, 10, 2), conv(b + 0, 10, 2) from bug15583; +conv(b, 10, 2) conv(b + 0, 10, 2) +10000000 10000000 +NULL NULL +0 0 +11111111 11111111 +drop table bug15583; +create table t1(a bit(1), b smallint unsigned); +insert into t1 (b, a) values ('2', '1'); +Warnings: +Warning 1264 Out of range value adjusted for column 'a' at row 1 +select hex(a), b from t1; +hex(a) b +1 2 +drop table t1; End of 5.0 tests diff --git a/mysql-test/r/type_date.result b/mysql-test/r/type_date.result index e88eebffb55..ed15293bb45 100644 --- a/mysql-test/r/type_date.result +++ b/mysql-test/r/type_date.result @@ -27,12 +27,12 @@ INSERT INTO t1 VALUES ( "2000-1-2" ); INSERT INTO t1 VALUES ( "2000-1-3" ); INSERT INTO t1 VALUES ( "2000-1-4" ); INSERT INTO t1 VALUES ( "2000-1-5" ); -SELECT * FROM t1 WHERE datum BETWEEN "2000-1-2" AND "2000-1-4"; +SELECT * FROM t1 WHERE datum BETWEEN cast("2000-1-2" as date) AND cast("2000-1-4" as date); datum 2000-01-02 2000-01-03 2000-01-04 -SELECT * FROM t1 WHERE datum BETWEEN "2000-1-2" AND datum - INTERVAL 100 DAY; +SELECT * FROM t1 WHERE datum BETWEEN cast("2000-1-2" as date) AND datum - INTERVAL 100 DAY; datum DROP TABLE t1; CREATE TABLE t1 ( @@ -104,3 +104,9 @@ SELECT * FROM t1; y 0000 DROP TABLE t1; +create table t1(start_date date, end_date date); +insert into t1 values ('2000-01-01','2000-01-02'); +select 1 from t1 where cast('2000-01-01 12:01:01' as datetime) between start_date and end_date; +1 +1 +drop table t1; diff --git a/mysql-test/r/type_float.result b/mysql-test/r/type_float.result index 61482ab282c..6790ae2c67d 100644 --- a/mysql-test/r/type_float.result +++ b/mysql-test/r/type_float.result @@ -262,6 +262,13 @@ desc t3; Field Type Null Key Default Extra a decimal(21,2) NO 0.00 drop table t1,t2,t3; +select 1e-308, 1.00000001e-300, 100000000e-300; +1e-308 1.00000001e-300 100000000e-300 +0 1.00000001e-300 1e-292 +select 10e307; +10e307 +1e+308 +End of 4.1 tests create table t1 (s1 float(0,2)); ERROR 42000: For float(M,D), double(M,D) or decimal(M,D), M must be >= D (column 's1'). create table t1 (s1 float(1,2)); diff --git a/mysql-test/r/union.result b/mysql-test/r/union.result index 42a3874db08..12463658bf9 100644 --- a/mysql-test/r/union.result +++ b/mysql-test/r/union.result @@ -1365,7 +1365,7 @@ drop table t1, t2; (select avg(1)) union (select avg(1)) union (select avg(1)) union (select avg(1)) union (select avg(1)) union (select avg(1)); avg(1) -NULL +1.0000 select _utf8'12' union select _latin1'12345'; 12 12 diff --git a/mysql-test/r/view.result b/mysql-test/r/view.result index f70547cd4a8..213a1dcde20 100644 --- a/mysql-test/r/view.result +++ b/mysql-test/r/view.result @@ -49,7 +49,7 @@ select v1.b from v1; ERROR 42S22: Unknown column 'v1.b' in 'field list' explain extended select c from v1; id select_type table type possible_keys key key_len ref rows Extra -1 PRIMARY t1 ALL NULL NULL NULL NULL 5 +1 SIMPLE t1 ALL NULL NULL NULL NULL 5 Warnings: Note 1003 select (`test`.`t1`.`b` + 1) AS `c` from `test`.`t1` create algorithm=temptable view v2 (c) as select b+1 from t1; @@ -83,7 +83,7 @@ c 12 explain extended select c from v3; id select_type table type possible_keys key key_len ref rows Extra -1 PRIMARY t1 ALL NULL NULL NULL NULL 5 +1 SIMPLE t1 ALL NULL NULL NULL NULL 5 Warnings: Note 1003 select ((`test`.`t1`.`b` + 1) + 1) AS `c` from `test`.`t1` create algorithm=temptable view v4 (c) as select c+1 from v2; @@ -376,7 +376,7 @@ c 30 explain extended select * from v1; id select_type table type possible_keys key key_len ref rows Extra -1 PRIMARY t1 ALL NULL NULL NULL NULL 5 Using where +1 SIMPLE t1 ALL NULL NULL NULL NULL 5 Using where Warnings: Note 1003 select `test`.`t1`.`b` AS `c` from `test`.`t1` where (`test`.`t1`.`a` < 3) update v1 set c=c+1; @@ -472,11 +472,11 @@ create view v3 (x,y,z) as select b, a, b from t1; create view v4 (x,y,z) as select c+1, b, a from t1; create algorithm=temptable view v5 (x,y,z) as select c, b, a from t1; insert into v3 values (-60,4,30); -ERROR HY000: The target table v3 of the INSERT is not updatable +ERROR HY000: The target table v3 of the INSERT is not insertable-into insert into v4 values (-60,4,30); -ERROR HY000: The target table v4 of the INSERT is not updatable +ERROR HY000: The target table v4 of the INSERT is not insertable-into insert into v5 values (-60,4,30); -ERROR HY000: The target table v5 of the INSERT is not updatable +ERROR HY000: The target table v5 of the INSERT is not insertable-into insert into v1 values (-60,4,30); insert into v1 (z,y,x) values (50,6,-100); insert into v2 values (5,40); @@ -499,11 +499,11 @@ create view v3 (x,y,z) as select b, a, b from t1; create view v4 (x,y,z) as select c+1, b, a from t1; create algorithm=temptable view v5 (x,y,z) as select c, b, a from t1; insert into v3 select c, b, a from t2; -ERROR HY000: The target table v3 of the INSERT is not updatable +ERROR HY000: The target table v3 of the INSERT is not insertable-into insert into v4 select c, b, a from t2; -ERROR HY000: The target table v4 of the INSERT is not updatable +ERROR HY000: The target table v4 of the INSERT is not insertable-into insert into v5 select c, b, a from t2; -ERROR HY000: The target table v5 of the INSERT is not updatable +ERROR HY000: The target table v5 of the INSERT is not insertable-into insert into v1 select c, b, a from t2; insert into v1 (z,y,x) select a+20,b+2,-100 from t2; insert into v2 select b+1, a+10 from t2; @@ -1306,9 +1306,9 @@ a b delete from t1; load data infile '../std_data_ln/loaddata3.dat' ignore into table v1 fields terminated by '' enclosed by '' ignore 1 lines; Warnings: -Warning 1264 Out of range value adjusted for column 'a' at row 3 +Warning 1366 Incorrect integer value: 'error ' for column 'a' at row 3 Error 1369 CHECK OPTION failed 'test.v1' -Warning 1264 Out of range value adjusted for column 'a' at row 4 +Warning 1366 Incorrect integer value: 'wrong end ' for column 'a' at row 4 Error 1369 CHECK OPTION failed 'test.v1' select * from t1; a b @@ -1352,14 +1352,14 @@ drop table t1; create table t1 (s1 smallint); create view v1 as select * from t1 where 20 < (select (s1) from t1); insert into v1 values (30); -ERROR HY000: The target table v1 of the INSERT is not updatable +ERROR HY000: The target table v1 of the INSERT is not insertable-into create view v2 as select * from t1; create view v3 as select * from t1 where 20 < (select (s1) from v2); insert into v3 values (30); -ERROR HY000: The target table v3 of the INSERT is not updatable +ERROR HY000: The target table v3 of the INSERT is not insertable-into create view v4 as select * from v2 where 20 < (select (s1) from t1); insert into v4 values (30); -ERROR HY000: The target table v4 of the INSERT is not updatable +ERROR HY000: The target table v4 of the INSERT is not insertable-into drop view v4, v3, v2, v1; drop table t1; create table t1 (a int); @@ -1391,9 +1391,9 @@ a a b 4 NULL NULL explain extended select * from t3 left join v3 on (t3.a = v3.a); id select_type table type possible_keys key key_len ref rows Extra -1 PRIMARY t3 ALL NULL NULL NULL NULL 3 -1 PRIMARY t1 ALL NULL NULL NULL NULL 3 -1 PRIMARY t2 ALL NULL NULL NULL NULL 2 +1 SIMPLE t3 ALL NULL NULL NULL NULL 3 +1 SIMPLE t1 ALL NULL NULL NULL NULL 3 +1 SIMPLE t2 ALL NULL NULL NULL NULL 2 Warnings: Note 1003 select `test`.`t3`.`a` AS `a`,`test`.`t1`.`a` AS `a`,`test`.`t2`.`a` AS `b` from `test`.`t3` left join (`test`.`t1` left join `test`.`t2` on((`test`.`t1`.`a` = `test`.`t2`.`a`))) on((`test`.`t3`.`a` = `test`.`t1`.`a`)) where 1 create view v1 (a) as select a from t1; @@ -1406,9 +1406,9 @@ a a b 4 NULL NULL explain extended select * from t3 left join v4 on (t3.a = v4.a); id select_type table type possible_keys key key_len ref rows Extra -1 PRIMARY t3 ALL NULL NULL NULL NULL 3 -1 PRIMARY t1 ALL NULL NULL NULL NULL 3 -1 PRIMARY t2 ALL NULL NULL NULL NULL 2 +1 SIMPLE t3 ALL NULL NULL NULL NULL 3 +1 SIMPLE t1 ALL NULL NULL NULL NULL 3 +1 SIMPLE t2 ALL NULL NULL NULL NULL 2 Warnings: Note 1003 select `test`.`t3`.`a` AS `a`,`test`.`t1`.`a` AS `a`,`test`.`t2`.`a` AS `b` from `test`.`t3` left join (`test`.`t1` left join (`test`.`t2`) on((`test`.`t1`.`a` = `test`.`t2`.`a`))) on((`test`.`t3`.`a` = `test`.`t1`.`a`)) where 1 prepare stmt1 from "select * from t3 left join v4 on (t3.a = v4.a);"; @@ -2321,12 +2321,12 @@ id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t2 ref a a 10 const,test.t1.b 2 Using where; Using index EXPLAIN SELECT * FROM v1 WHERE a=1; id select_type table type possible_keys key key_len ref rows Extra -1 PRIMARY t1 ref a a 5 const 1 Using where; Using index -1 PRIMARY t2 ref a a 10 const,test.t1.b 2 Using where; Using index +1 SIMPLE t1 ref a a 5 const 1 Using where; Using index +1 SIMPLE t2 ref a a 10 const,test.t1.b 2 Using where; Using index EXPLAIN SELECT * FROM v2 WHERE a=1; id select_type table type possible_keys key key_len ref rows Extra -1 PRIMARY t1 ref a a 5 const 1 Using where; Using index -1 PRIMARY t3 ALL NULL NULL NULL NULL 3 Using where +1 SIMPLE t1 ref a a 5 const 1 Using where; Using index +1 SIMPLE t3 ALL NULL NULL NULL NULL 3 Using where DROP VIEW v1,v2; DROP TABLE t1,t2,t3; create table t1 (f1 int); @@ -2409,7 +2409,7 @@ insert into t1 values (1),(2); create view v1 as select * from t1; explain select id from v1 order by id; id select_type table type possible_keys key key_len ref rows Extra -1 PRIMARY t1 index NULL PRIMARY 4 NULL 2 Using index +1 SIMPLE t1 index NULL PRIMARY 4 NULL 2 Using index drop view v1; drop table t1; create table t1(f1 int, f2 int); @@ -2480,7 +2480,7 @@ id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Select tables optimized away EXPLAIN SELECT MAX(a) FROM v1; id select_type table type possible_keys key key_len ref rows Extra -1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Select tables optimized away +1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Select tables optimized away SELECT MIN(a) FROM t1; MIN(a) 0 @@ -2492,7 +2492,7 @@ id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Select tables optimized away EXPLAIN SELECT MIN(a) FROM v1; id select_type table type possible_keys key key_len ref rows Extra -1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Select tables optimized away +1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Select tables optimized away DROP VIEW v1; DROP TABLE t1; CREATE TABLE t1 (x varchar(10)); @@ -2586,13 +2586,13 @@ INSERT INTO t1 VALUES (4, '2005-01-03'), (5, '2005-01-04'), (6, '2005-01-05'), (7, '2005-01-05'), (8, '2005-01-05'), (9, '2005-01-06'); CREATE VIEW v1 AS SELECT * FROM t1; -SELECT * FROM t1 WHERE td BETWEEN '2005.01.02' AND '2005.01.04'; +SELECT * FROM t1 WHERE td BETWEEN CAST('2005.01.02' AS DATE) AND CAST('2005.01.04' AS DATE); id td 2 2005-01-02 3 2005-01-02 4 2005-01-03 5 2005-01-04 -SELECT * FROM v1 WHERE td BETWEEN '2005.01.02' AND '2005.01.04'; +SELECT * FROM v1 WHERE td BETWEEN CAST('2005.01.02' AS DATE) AND CAST('2005.01.04' AS DATE); id td 2 2005-01-02 3 2005-01-02 @@ -2911,9 +2911,49 @@ INSERT INTO v2 VALUES (0); RETURN 0; END | SELECT f2(); -ERROR HY000: The target table v2 of the INSERT is not updatable +ERROR HY000: The target table v2 of the INSERT is not insertable-into DROP FUNCTION f1; DROP FUNCTION f2; DROP VIEW v1, v2; DROP TABLE t1; +CREATE TABLE t1 (s1 int); +CREATE VIEW v1 AS SELECT * FROM t1; +EXPLAIN SELECT * FROM t1; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 system NULL NULL NULL NULL 0 const row not found +EXPLAIN SELECT * FROM v1; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 system NULL NULL NULL NULL 0 const row not found +INSERT INTO t1 VALUES (1), (3), (2); +EXPLAIN SELECT * FROM t1 t WHERE t.s1+1 < (SELECT MAX(t1.s1) FROM t1); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t ALL NULL NULL NULL NULL 3 Using where +2 SUBQUERY t1 ALL NULL NULL NULL NULL 3 +EXPLAIN SELECT * FROM v1 t WHERE t.s1+1 < (SELECT MAX(t1.s1) FROM t1); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 3 Using where +2 SUBQUERY t1 ALL NULL NULL NULL NULL 3 +DROP VIEW v1; +DROP TABLE t1; +create table t1 (s1 int); +create view v1 as select s1 as a, s1 as b from t1; +insert into v1 values (1,1); +ERROR HY000: The target table v1 of the INSERT is not insertable-into +update v1 set a = 5; +drop view v1; +drop table t1; +CREATE TABLE t1(pk int PRIMARY KEY); +CREATE TABLE t2(pk int PRIMARY KEY, fk int, ver int, org int); +CREATE ALGORITHM=MERGE VIEW v1 AS +SELECT t1.* +FROM t1 JOIN t2 +ON t2.fk = t1.pk AND +t2.ver = (SELECT MAX(t.ver) FROM t2 t WHERE t.org = t2.org); +SHOW WARNINGS; +Level Code Message +SHOW CREATE VIEW v1; +View Create View +v1 CREATE ALGORITHM=MERGE DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select `t1`.`pk` AS `pk` from (`t1` join `t2` on(((`t2`.`fk` = `t1`.`pk`) and (`t2`.`ver` = (select max(`t`.`ver`) AS `MAX(t.ver)` from `t2` `t` where (`t`.`org` = `t2`.`org`)))))) +DROP VIEW v1; +DROP TABLE t1, t2; End of 5.0 tests. diff --git a/mysql-test/r/view_grant.result b/mysql-test/r/view_grant.result index 7f63d790fb8..35e7afc0a7b 100644 --- a/mysql-test/r/view_grant.result +++ b/mysql-test/r/view_grant.result @@ -103,7 +103,7 @@ ERROR 42000: SHOW VIEW command denied to user 'mysqltest_1'@'localhost' for tabl grant select on mysqltest.t1 to mysqltest_1@localhost; explain select c from mysqltest.v1; id select_type table type possible_keys key key_len ref rows Extra -1 PRIMARY t1 system NULL NULL NULL NULL 0 const row not found +1 SIMPLE t1 system NULL NULL NULL NULL 0 const row not found show create view mysqltest.v1; ERROR 42000: SHOW VIEW command denied to user 'mysqltest_1'@'localhost' for table 'v1' explain select c from mysqltest.v2; @@ -123,7 +123,7 @@ ERROR 42000: SHOW VIEW command denied to user 'mysqltest_1'@'localhost' for tabl grant show view on mysqltest.* to mysqltest_1@localhost; explain select c from mysqltest.v1; id select_type table type possible_keys key key_len ref rows Extra -1 PRIMARY t1 system NULL NULL NULL NULL 0 const row not found +1 SIMPLE t1 system NULL NULL NULL NULL 0 const row not found show create view mysqltest.v1; View Create View v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `mysqltest`.`v1` AS select (`mysqltest`.`t1`.`a` + 1) AS `c`,(`mysqltest`.`t1`.`b` + 1) AS `d` from `mysqltest`.`t1` @@ -136,7 +136,7 @@ View Create View v2 CREATE ALGORITHM=TEMPTABLE DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `mysqltest`.`v2` AS select (`mysqltest`.`t1`.`a` + 1) AS `c`,(`mysqltest`.`t1`.`b` + 1) AS `d` from `mysqltest`.`t1` explain select c from mysqltest.v3; id select_type table type possible_keys key key_len ref rows Extra -1 PRIMARY t2 system NULL NULL NULL NULL 0 const row not found +1 SIMPLE t2 system NULL NULL NULL NULL 0 const row not found show create view mysqltest.v3; View Create View v3 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `mysqltest`.`v3` AS select (`mysqltest`.`t2`.`a` + 1) AS `c`,(`mysqltest`.`t2`.`b` + 1) AS `d` from `mysqltest`.`t2` diff --git a/mysql-test/r/warnings.result b/mysql-test/r/warnings.result index 283a0661721..d0ad4ca6648 100644 --- a/mysql-test/r/warnings.result +++ b/mysql-test/r/warnings.result @@ -31,19 +31,19 @@ Error 1064 You have an error in your SQL syntax; check the manual that correspon insert into t1 values (1); insert into t1 values ("hej"); Warnings: -Warning 1264 Out of range value adjusted for column 'a' at row 1 +Warning 1366 Incorrect integer value: 'hej' for column 'a' at row 1 insert into t1 values ("hej"),("då"); Warnings: -Warning 1264 Out of range value adjusted for column 'a' at row 1 -Warning 1264 Out of range value adjusted for column 'a' at row 2 +Warning 1366 Incorrect integer value: 'hej' for column 'a' at row 1 +Warning 1366 Incorrect integer value: 'd?' for column 'a' at row 2 set SQL_WARNINGS=1; insert into t1 values ("hej"); Warnings: -Warning 1264 Out of range value adjusted for column 'a' at row 1 +Warning 1366 Incorrect integer value: 'hej' for column 'a' at row 1 insert into t1 values ("hej"),("då"); Warnings: -Warning 1264 Out of range value adjusted for column 'a' at row 1 -Warning 1264 Out of range value adjusted for column 'a' at row 2 +Warning 1366 Incorrect integer value: 'hej' for column 'a' at row 1 +Warning 1366 Incorrect integer value: 'd?' for column 'a' at row 2 drop table t1; set SQL_WARNINGS=0; drop temporary table if exists not_exists; @@ -194,44 +194,44 @@ create table t1 (a int); insert into t1 (a) values (1), (2), (3), (4), (5), (6), (7), (8), (9), (10); update t1 set a='abc'; Warnings: -Warning 1264 Out of range value adjusted for column 'a' at row 1 -Warning 1264 Out of range value adjusted for column 'a' at row 2 -Warning 1264 Out of range value adjusted for column 'a' at row 3 -Warning 1264 Out of range value adjusted for column 'a' at row 4 -Warning 1264 Out of range value adjusted for column 'a' at row 5 -Warning 1264 Out of range value adjusted for column 'a' at row 6 -Warning 1264 Out of range value adjusted for column 'a' at row 7 -Warning 1264 Out of range value adjusted for column 'a' at row 8 -Warning 1264 Out of range value adjusted for column 'a' at row 9 -Warning 1264 Out of range value adjusted for column 'a' at row 10 +Warning 1366 Incorrect integer value: 'abc' for column 'a' at row 1 +Warning 1366 Incorrect integer value: 'abc' for column 'a' at row 2 +Warning 1366 Incorrect integer value: 'abc' for column 'a' at row 3 +Warning 1366 Incorrect integer value: 'abc' for column 'a' at row 4 +Warning 1366 Incorrect integer value: 'abc' for column 'a' at row 5 +Warning 1366 Incorrect integer value: 'abc' for column 'a' at row 6 +Warning 1366 Incorrect integer value: 'abc' for column 'a' at row 7 +Warning 1366 Incorrect integer value: 'abc' for column 'a' at row 8 +Warning 1366 Incorrect integer value: 'abc' for column 'a' at row 9 +Warning 1366 Incorrect integer value: 'abc' for column 'a' at row 10 show warnings limit 2, 1; Level Code Message -Warning 1264 Out of range value adjusted for column 'a' at row 3 +Warning 1366 Incorrect integer value: 'abc' for column 'a' at row 3 show warnings limit 0, 10; Level Code Message -Warning 1264 Out of range value adjusted for column 'a' at row 1 -Warning 1264 Out of range value adjusted for column 'a' at row 2 -Warning 1264 Out of range value adjusted for column 'a' at row 3 -Warning 1264 Out of range value adjusted for column 'a' at row 4 -Warning 1264 Out of range value adjusted for column 'a' at row 5 -Warning 1264 Out of range value adjusted for column 'a' at row 6 -Warning 1264 Out of range value adjusted for column 'a' at row 7 -Warning 1264 Out of range value adjusted for column 'a' at row 8 -Warning 1264 Out of range value adjusted for column 'a' at row 9 -Warning 1264 Out of range value adjusted for column 'a' at row 10 +Warning 1366 Incorrect integer value: 'abc' for column 'a' at row 1 +Warning 1366 Incorrect integer value: 'abc' for column 'a' at row 2 +Warning 1366 Incorrect integer value: 'abc' for column 'a' at row 3 +Warning 1366 Incorrect integer value: 'abc' for column 'a' at row 4 +Warning 1366 Incorrect integer value: 'abc' for column 'a' at row 5 +Warning 1366 Incorrect integer value: 'abc' for column 'a' at row 6 +Warning 1366 Incorrect integer value: 'abc' for column 'a' at row 7 +Warning 1366 Incorrect integer value: 'abc' for column 'a' at row 8 +Warning 1366 Incorrect integer value: 'abc' for column 'a' at row 9 +Warning 1366 Incorrect integer value: 'abc' for column 'a' at row 10 show warnings limit 9, 1; Level Code Message -Warning 1264 Out of range value adjusted for column 'a' at row 10 +Warning 1366 Incorrect integer value: 'abc' for column 'a' at row 10 show warnings limit 10, 1; Level Code Message show warnings limit 9, 2; Level Code Message -Warning 1264 Out of range value adjusted for column 'a' at row 10 +Warning 1366 Incorrect integer value: 'abc' for column 'a' at row 10 show warnings limit 0, 0; Level Code Message show warnings limit 1; Level Code Message -Warning 1264 Out of range value adjusted for column 'a' at row 1 +Warning 1366 Incorrect integer value: 'abc' for column 'a' at row 1 show warnings limit 0; Level Code Message show warnings limit 1, 0; @@ -243,3 +243,59 @@ a select * from t1 limit 0, 0; a drop table t1; +End of 4.1 tests +CREATE TABLE t1( f1 CHAR(20) ); +CREATE TABLE t2( f1 CHAR(20), f2 CHAR(25) ); +CREATE TABLE t3( f1 CHAR(20), f2 CHAR(25), f3 DATE ); +INSERT INTO t1 VALUES ( 'a`' ); +INSERT INTO t2 VALUES ( 'a`', 'a`' ); +INSERT INTO t3 VALUES ( 'a`', 'a`', '1000-01-1' ); +DROP PROCEDURE IF EXISTS sp1; +Warnings: +Note 1305 PROCEDURE sp1 does not exist +DROP PROCEDURE IF EXISTS sp2; +Warnings: +Note 1305 PROCEDURE sp2 does not exist +DROP PROCEDURE IF EXISTS sp3; +Warnings: +Note 1305 PROCEDURE sp3 does not exist +CREATE PROCEDURE sp1() +BEGIN +DECLARE x NUMERIC ZEROFILL; +SELECT f1 INTO x FROM t1 LIMIT 1; +END// +CREATE PROCEDURE sp2() +BEGIN +DECLARE x NUMERIC ZEROFILL; +SELECT f1 INTO x FROM t2 LIMIT 1; +END// +CREATE PROCEDURE sp3() +BEGIN +DECLARE x NUMERIC ZEROFILL; +SELECT f1 INTO x FROM t3 LIMIT 1; +END// +CALL sp1(); +Warnings: +Warning 1366 Incorrect decimal value: 'a`' for column 'x' at row 1 +CALL sp2(); +Warnings: +Warning 1366 Incorrect decimal value: 'a`' for column 'x' at row 1 +CALL sp3(); +Warnings: +Warning 1366 Incorrect decimal value: 'a`' for column 'x' at row 1 +DROP PROCEDURE IF EXISTS sp1; +CREATE PROCEDURE sp1() +BEGIN +declare x numeric unsigned zerofill; +SELECT f1 into x from t2 limit 1; +END// +CALL sp1(); +Warnings: +Warning 1366 Incorrect decimal value: 'a`' for column 'x' at row 1 +DROP TABLE t1; +DROP TABLE t2; +DROP TABLE t3; +DROP PROCEDURE sp1; +DROP PROCEDURE sp2; +DROP PROCEDURE sp3; +End of 5.0 tests diff --git a/mysql-test/t/analyse.test b/mysql-test/t/analyse.test index a248c671c18..efcf5f6421c 100644 --- a/mysql-test/t/analyse.test +++ b/mysql-test/t/analyse.test @@ -90,5 +90,16 @@ create table t2 (country_id int primary key, country char(20) not null); insert into t2 values (1, 'USA'),(2,'India'), (3,'Finland'); select product, sum(profit),avg(profit) from t1 group by product with rollup procedure analyse(); drop table t1,t2; -# End of 4.1 tests +# +# Bug #20305 PROCEDURE ANALYSE() returns wrong M for FLOAT(M, D) and DOUBLE(M, D) +# + +create table t1 (f1 double(10,5), f2 char(10), f3 double(10,5)); +insert into t1 values (5.999, "5.9999", 5.99999), (9.555, "9.5555", 9.55555); +select f1 from t1 procedure analyse(1, 1); +select f2 from t1 procedure analyse(1, 1); +select f3 from t1 procedure analyse(1, 1); +drop table t1; + +--echo End of 4.1 tests diff --git a/mysql-test/t/case.test b/mysql-test/t/case.test index fbe1ee2b8c8..0e9e141f6d8 100644 --- a/mysql-test/t/case.test +++ b/mysql-test/t/case.test @@ -133,8 +133,6 @@ select min(a), min(case when 1=1 then a else NULL end), from t1 where b=3 group by b; drop table t1; -# End of 4.1 tests - # # Tests for bug #9939: conversion of the arguments for COALESCE and IFNULL @@ -154,3 +152,4 @@ SELECT IFNULL(t2.EMPNUM,t1.EMPNUM) AS CEMPNUM, FROM t1 LEFT JOIN t2 ON t1.EMPNUM=t2.EMPNUM; DROP TABLE t1,t2; +# End of 4.1 tests diff --git a/mysql-test/t/create.test b/mysql-test/t/create.test index 07edbf206fe..db73782fdbf 100644 --- a/mysql-test/t/create.test +++ b/mysql-test/t/create.test @@ -674,4 +674,10 @@ create table t1(f1 varchar(800) binary not null, key(f1)) engine = innodb insert into t1 values('aaa'); drop table t1; +# +# Bug#21772: can not name a column 'upgrade' when create a table +# +create table t1 (upgrade int); +drop table t1; + # End of 5.0 tests diff --git a/mysql-test/t/ctype_gbk.test b/mysql-test/t/ctype_gbk.test index 7aec48586d8..5ff138fa97b 100644 --- a/mysql-test/t/ctype_gbk.test +++ b/mysql-test/t/ctype_gbk.test @@ -42,3 +42,13 @@ DROP TABLE t1; select hex(convert(_gbk 0xA14041 using ucs2)); # End of 4.1 tests + +# +# Bug#21620 ALTER TABLE affects other columns +# +create table t1 (c1 text not null, c2 text not null) character set gbk; +alter table t1 change c1 c1 mediumtext character set gbk not null; +show create table t1; +drop table t1; + +--echo End of 5.0 tests diff --git a/mysql-test/t/ctype_ucs.test b/mysql-test/t/ctype_ucs.test index 8116d39e3db..6c814368c88 100644 --- a/mysql-test/t/ctype_ucs.test +++ b/mysql-test/t/ctype_ucs.test @@ -484,6 +484,27 @@ select make_set(3, name, upper(name)) from bug20536; select export_set(5, name, upper(name)) from bug20536; select export_set(5, name, upper(name), ",", 5) from bug20536; +# +# Bug #20108: corrupted default enum value for a ucs2 field +# + +CREATE TABLE t1 ( + status enum('active','passive') collate latin1_general_ci + NOT NULL default 'passive' +); +SHOW CREATE TABLE t1; +ALTER TABLE t1 ADD a int NOT NULL AFTER status; + +CREATE TABLE t2 ( + status enum('active','passive') collate ucs2_turkish_ci + NOT NULL default 'passive' +); +SHOW CREATE TABLE t2; +ALTER TABLE t2 ADD a int NOT NULL AFTER status; + +DROP TABLE t1,t2; + + # Some broken functions: add these tests just to document current behavior. # PASSWORD and OLD_PASSWORD don't work with UCS2 strings, but to fix it would diff --git a/mysql-test/t/ctype_utf8.test b/mysql-test/t/ctype_utf8.test index 39928f18f2e..5dc3e6d5eb2 100644 --- a/mysql-test/t/ctype_utf8.test +++ b/mysql-test/t/ctype_utf8.test @@ -1069,6 +1069,16 @@ explain select a from t1 group by a; select a from t1 group by a; drop table t1; +# +# Bug #20204: "order by" changes the results returned +# + +create table t1(a char(10)) default charset utf8; +insert into t1 values ('123'), ('456'); +explain + select substr(Z.a,-1), Z.a from t1 as Y join t1 as Z on Y.a=Z.a order by 1; +select substr(Z.a,-1), Z.a from t1 as Y join t1 as Z on Y.a=Z.a order by 1; +drop table t1; # End of 4.1 tests # @@ -1147,3 +1157,23 @@ execute my_stmt using @a; set @a:=null; execute my_stmt using @a; drop table if exists t1; + +# +# Bug#19960: Inconsistent results when joining +# InnoDB tables using partial UTF8 indexes +# +CREATE TABLE t1 ( + colA int(11) NOT NULL, + colB varchar(255) character set utf8 NOT NULL, + PRIMARY KEY (colA) +) ENGINE=InnoDB DEFAULT CHARSET=latin1; +INSERT INTO t1 (colA, colB) VALUES (1, 'foo'), (2, 'foo bar'); +CREATE TABLE t2 ( + colA int(11) NOT NULL, + colB varchar(255) character set utf8 NOT NULL, + KEY bad (colA,colB(3)) +) ENGINE=InnoDB DEFAULT CHARSET=latin1; +INSERT INTO t2 (colA, colB) VALUES (1, 'foo'),(2, 'foo bar'); +SELECT * FROM t1 JOIN t2 ON t1.colA=t2.colA AND t1.colB=t2.colB +WHERE t1.colA < 3; +DROP TABLE t1, t2; diff --git a/mysql-test/t/delayed.test b/mysql-test/t/delayed.test index 55e8f81f763..03d8e20dd8f 100644 --- a/mysql-test/t/delayed.test +++ b/mysql-test/t/delayed.test @@ -17,7 +17,8 @@ insert delayed into t1 set a = 4; insert delayed into t1 set a = 5, tmsp = 19711006010203; insert delayed into t1 (a, tmsp) values (6, 19711006010203); insert delayed into t1 (a, tmsp) values (7, NULL); ---sleep 2 +# Wait until the rows are flushed to the table files. +FLUSH TABLE t1; insert into t1 set a = 8,tmsp=19711006010203; select * from t1 where tmsp=0; select * from t1 where tmsp=19711006010203; @@ -34,8 +35,8 @@ insert delayed into t1 values (null,"c"); insert delayed into t1 values (3,"d"),(null,"e"); --error 1136 insert delayed into t1 values (3,"this will give an","error"); -# 2 was not enough for --ps-protocol ---sleep 4 +# Wait until the rows are flushed to the table files. +FLUSH TABLE t1; show status like 'not_flushed_delayed_rows'; select * from t1; drop table t1; @@ -92,10 +93,145 @@ insert delayed into t1 values(null); # Works, since the delayed-counter is 8, which is unused insert delayed into t1 values(null); +# Wait until the rows are flushed to the table files. +FLUSH TABLE t1; # Check what we have now -# must wait so that the delayed thread finishes -# Note: this must be increased if the test fails ---sleep 1 select * from t1 order by a; DROP TABLE t1; + +# +# Bug#20627 - INSERT DELAYED does not honour auto_increment_* variables +# +SET @bug20627_old_auto_increment_offset= + @@auto_increment_offset= 2; +SET @bug20627_old_auto_increment_increment= + @@auto_increment_increment= 3; +SET @bug20627_old_session_auto_increment_offset= + @@session.auto_increment_offset= 4; +SET @bug20627_old_session_auto_increment_increment= + @@session.auto_increment_increment= 5; +SET @@auto_increment_offset= 2; +SET @@auto_increment_increment= 3; +SET @@session.auto_increment_offset= 4; +SET @@session.auto_increment_increment= 5; +# +# Normal insert as reference. +CREATE TABLE t1 ( + c1 INT NOT NULL AUTO_INCREMENT, + PRIMARY KEY (c1) + ); +INSERT INTO t1 VALUES (NULL),(NULL),(NULL); +# Check what we have now +SELECT * FROM t1; +DROP TABLE t1; +# +# Delayed insert. +CREATE TABLE t1 ( + c1 INT NOT NULL AUTO_INCREMENT, + PRIMARY KEY (c1) + ); +INSERT DELAYED INTO t1 VALUES (NULL),(NULL),(NULL); +# Wait until the rows are flushed to the table files. +FLUSH TABLE t1; +# Check what we have now +SELECT * FROM t1; +DROP TABLE t1; +# +# Cleanup +SET @@auto_increment_offset= + @bug20627_old_auto_increment_offset; +SET @@auto_increment_increment= + @bug20627_old_auto_increment_increment; +SET @@session.auto_increment_offset= + @bug20627_old_session_auto_increment_offset; +SET @@session.auto_increment_increment= + @bug20627_old_session_auto_increment_increment; + +# +# Bug#20830 - INSERT DELAYED does not honour SET INSERT_ID +# +SET @bug20830_old_auto_increment_offset= + @@auto_increment_offset= 2; +SET @bug20830_old_auto_increment_increment= + @@auto_increment_increment= 3; +SET @bug20830_old_session_auto_increment_offset= + @@session.auto_increment_offset= 4; +SET @bug20830_old_session_auto_increment_increment= + @@session.auto_increment_increment= 5; +SET @@auto_increment_offset= 2; +SET @@auto_increment_increment= 3; +SET @@session.auto_increment_offset= 4; +SET @@session.auto_increment_increment= 5; +# +# Normal insert as reference. +CREATE TABLE t1 ( + c1 INT(11) NOT NULL AUTO_INCREMENT, + c2 INT(11) DEFAULT NULL, + PRIMARY KEY (c1) + ); +SET insert_id= 14; +INSERT INTO t1 VALUES(NULL, 11), (NULL, 12), (NULL, 13); +INSERT INTO t1 VALUES(NULL, 21), (NULL, 22), (NULL, 23); +# Restart sequence at a different value. +INSERT INTO t1 VALUES( 69, 31), (NULL, 32), (NULL, 33); +INSERT INTO t1 VALUES(NULL, 41), (NULL, 42), (NULL, 43); +# Restart sequence at a different value. +SET insert_id= 114; +INSERT INTO t1 VALUES(NULL, 51), (NULL, 52), (NULL, 53); +INSERT INTO t1 VALUES(NULL, 61), (NULL, 62), (NULL, 63); +# Set one value below the maximum value. +INSERT INTO t1 VALUES( 49, 71), (NULL, 72), (NULL, 73); +INSERT INTO t1 VALUES(NULL, 81), (NULL, 82), (NULL, 83); +# Create a duplicate value. +SET insert_id= 114; +--error 1062 +INSERT INTO t1 VALUES(NULL, 91); +INSERT INTO t1 VALUES (NULL, 92), (NULL, 93); +# Check what we have now +SELECT * FROM t1; +SELECT COUNT(*) FROM t1; +SELECT SUM(c1) FROM t1; +DROP TABLE t1; +# +# Delayed insert. +CREATE TABLE t1 ( + c1 INT(11) NOT NULL AUTO_INCREMENT, + c2 INT(11) DEFAULT NULL, + PRIMARY KEY (c1) + ); +SET insert_id= 14; +INSERT DELAYED INTO t1 VALUES(NULL, 11), (NULL, 12), (NULL, 13); +INSERT DELAYED INTO t1 VALUES(NULL, 21), (NULL, 22), (NULL, 23); +# Restart sequence at a different value. +INSERT DELAYED INTO t1 VALUES( 69, 31), (NULL, 32), (NULL, 33); +INSERT DELAYED INTO t1 VALUES(NULL, 41), (NULL, 42), (NULL, 43); +# Restart sequence at a different value. +SET insert_id= 114; +INSERT DELAYED INTO t1 VALUES(NULL, 51), (NULL, 52), (NULL, 53); +INSERT DELAYED INTO t1 VALUES(NULL, 61), (NULL, 62), (NULL, 63); +# Set one value below the maximum value. +INSERT DELAYED INTO t1 VALUES( 49, 71), (NULL, 72), (NULL, 73); +INSERT DELAYED INTO t1 VALUES(NULL, 81), (NULL, 82), (NULL, 83); +# Create a duplicate value. +SET insert_id= 114; +INSERT DELAYED INTO t1 VALUES(NULL, 91); +INSERT DELAYED INTO t1 VALUES (NULL, 92), (NULL, 93); +# Wait until the rows are flushed to the table files. +FLUSH TABLE t1; +# Check what we have now +SELECT * FROM t1; +SELECT COUNT(*) FROM t1; +SELECT SUM(c1) FROM t1; +DROP TABLE t1; +# +# Cleanup +SET @@auto_increment_offset= + @bug20830_old_auto_increment_offset; +SET @@auto_increment_increment= + @bug20830_old_auto_increment_increment; +SET @@session.auto_increment_offset= + @bug20830_old_session_auto_increment_offset; +SET @@session.auto_increment_increment= + @bug20830_old_session_auto_increment_increment; + diff --git a/mysql-test/t/delete.test b/mysql-test/t/delete.test index 677ffaa2860..865e1746fd3 100644 --- a/mysql-test/t/delete.test +++ b/mysql-test/t/delete.test @@ -153,6 +153,16 @@ DELETE FROM t1 WHERE t1.a > 0 ORDER BY t1.a LIMIT 1; SELECT * FROM t1; DROP TABLE t1; +# +# Bug #21392: multi-table delete with alias table name fails with +# 1003: Incorrect table name +# + +create table t1 (a int); +delete `4.t1` from t1 as `4.t1` where `4.t1`.a = 5; +delete FROM `4.t1` USING t1 as `4.t1` where `4.t1`.a = 5; +drop table t1; + # End of 4.1 tests # diff --git a/mysql-test/t/execution_constants.test b/mysql-test/t/execution_constants.test new file mode 100644 index 00000000000..00967b2eeba --- /dev/null +++ b/mysql-test/t/execution_constants.test @@ -0,0 +1,74 @@ +# +# Bug#21476: Lost Database Connection During Query +# +# When the amount of stack space we think we need to report an error is +# actually too small, then we can get SEGVs. But, we don't want to reserve +# space that we could use to get real work done. So, we want the reserved +# space small, and this test verifies that the reservation is not too small. + +CREATE TABLE `t_bug21476` ( + `ID_BOARD` smallint(5) unsigned NOT NULL default '0', + `ID_MEMBER` mediumint(8) unsigned NOT NULL default '0', + `logTime` int(10) unsigned NOT NULL default '0', + `ID_MSG` mediumint(8) unsigned NOT NULL default '0', + PRIMARY KEY (`ID_MEMBER`,`ID_BOARD`), + KEY `logTime` (`logTime`) +) ENGINE=MyISAM DEFAULT CHARSET=cp1251 COLLATE=cp1251_bulgarian_ci; + +INSERT INTO `t_bug21476` VALUES (2,2,1154870939,0),(1,2,1154870957,0),(2,183,1154941362,0),(2,84,1154904301,0),(1,84,1154905867,0),(2,13,1154947484,10271),(3,84,1154880549,0),(1,6,1154892183,0),(2,25,1154947581,10271),(3,25,1154904760,0),(1,25,1154947373,10271),(1,179,1154899992,0),(2,179,1154899410,0),(5,25,1154901666,0),(2,329,1154902026,0),(3,329,1154902040,0),(1,329,1154902058,0),(1,13,1154930841,0),(3,85,1154904987,0),(1,183,1154929665,0),(3,13,1154931268,0),(1,85,1154936888,0),(1,169,1154937959,0),(2,169,1154941717,0),(3,183,1154939810,0),(3,169,1154941734,0); + +delimiter //; +let $query_head=UPDATE t_bug21476 SET ID_MSG = IF(logTime BETWEEN 1 AND 1101770053, 2, // +let $query_tail =) WHERE logTime BETWEEN 1 AND 1104091539 AND ID_MSG = 0// + +# Scan over the possible stack heights, trying to recurse to exactly that +# depth. Eventually, we will reach our imposed limit on height and try to +# raise an error. If the remaining stack space is enough to raise that error, +# we will get an error-number of 1436 and quit the loop. If it's not enough +# space, we should get a SEGV + +# Well more than enough recursions to find the end of our stack. +let $i = 100000// +disable_query_log// +disable_result_log// +while ($i) +{ + # If we SEGV because the min stack size is exceeded, this would return error + # 2013 . + error 0,1436 // + eval $query_head 0 $query_tail// + + if ($mysql_errno != 1436) + { + # We reached the place where we reported an error about the stack limit, + # and we successfully returned the error. That means that at the stack + # limit, we still have enough space reserved to report an error. + let $i = 1// + } + + # Multiplying by three stack frames should be fine enough resolution. + # Trading exactness for speed. + + # go one more level deep + let $query_head = $query_head IF(logTime <= 1104091$i, $i, // + let $query_tail =) $query_tail// + + # go one more level deep + let $query_head = $query_head IF(logTime <= 1105091$i, $i, // + let $query_tail =) $query_tail// + + # go one more level deep + let $query_head = $query_head IF(logTime <= 1106091$i, $i, // + let $query_tail =) $query_tail// + + dec $i// +} +enable_result_log// +enable_query_log// + +echo Assertion: mysql_errno 1436 == $mysql_errno// + +delimiter ;// +DROP TABLE `t_bug21476`; + +--echo End of 5.0 tests. diff --git a/mysql-test/t/func_gconcat.test b/mysql-test/t/func_gconcat.test index 98c21986aa9..b5c468e1638 100644 --- a/mysql-test/t/func_gconcat.test +++ b/mysql-test/t/func_gconcat.test @@ -447,3 +447,18 @@ SELECT a, CHAR_LENGTH(b) FROM t1; SELECT CHAR_LENGTH( GROUP_CONCAT(b) ) FROM t1; SET GROUP_CONCAT_MAX_LEN = 1024; DROP TABLE t1; + +# +# Bug #22015: crash with GROUP_CONCAT over a derived table that +# returns the results of aggregation by GROUP_CONCAT +# + +CREATE TABLE t1 (a int, b int); + +INSERT INTO t1 VALUES (2,1), (1,2), (2,2), (1,3); + +SELECT GROUP_CONCAT(a), x + FROM (SELECT a, GROUP_CONCAT(b) x FROM t1 GROUP BY a) AS s + GROUP BY x; + +DROP TABLE t1; diff --git a/mysql-test/t/func_group.test b/mysql-test/t/func_group.test index c2dd77e662a..079d107fad8 100644 --- a/mysql-test/t/func_group.test +++ b/mysql-test/t/func_group.test @@ -566,6 +566,19 @@ INSERT INTO t1 VALUES SELECT MAX(b) FROM t1; EXPLAIN SELECT MAX(b) FROM t1; DROP TABLE t1; +# +# Bug #16792 query with subselect, join, and group not returning proper values +# +CREATE TABLE t1 (a INT, b INT); +INSERT INTO t1 VALUES (1,1),(1,2),(2,3); + +SELECT (SELECT COUNT(DISTINCT t1.b)) FROM t1 GROUP BY t1.a; +SELECT (SELECT COUNT(DISTINCT 12)) FROM t1 GROUP BY t1.a; +# an attempt to test all aggregate function with no table. +SELECT AVG(2), BIT_AND(2), BIT_OR(2), BIT_XOR(2), COUNT(*), COUNT(12), + COUNT(DISTINCT 12), MIN(2),MAX(2),STD(2), VARIANCE(2),SUM(2), + GROUP_CONCAT(2),GROUP_CONCAT(DISTINCT 2); +DROP TABLE t1; # End of 4.1 tests diff --git a/mysql-test/t/func_str.test b/mysql-test/t/func_str.test index 8753db0ebe1..45415882ac7 100644 --- a/mysql-test/t/func_str.test +++ b/mysql-test/t/func_str.test @@ -753,4 +753,31 @@ select cast(rtrim(ltrim(' 20.06 ')) as decimal(19,2)); select conv("18383815659218730760",10,10) + 0; select "18383815659218730760" + 0; +# +# Bug #21698: substitution of a string field for a constant under a function +# + +CREATE TABLE t1 (code varchar(10)); +INSERT INTO t1 VALUES ('a12'), ('A12'), ('a13'); + +SELECT ASCII(code), code FROM t1 WHERE code='A12'; +SELECT ASCII(code), code FROM t1 WHERE code='A12' AND ASCII(code)=65; + +INSERT INTO t1 VALUES ('a12 '), ('A12 '); + +SELECT LENGTH(code), code FROM t1 WHERE code='A12'; +SELECT LENGTH(code), code FROM t1 WHERE code='A12' AND LENGTH(code)=5; + +ALTER TABLE t1 ADD INDEX (code); +CREATE TABLE t2 (id varchar(10) PRIMARY KEY); +INSERT INTO t2 VALUES ('a11'), ('a12'), ('a13'), ('a14'); + +SELECT * FROM t1 INNER JOIN t2 ON t1.code=t2.id + WHERE t2.id='a12' AND (LENGTH(code)=5 OR code < 'a00'); +EXPLAIN EXTENDED +SELECT * FROM t1 INNER JOIN t2 ON code=id + WHERE id='a12' AND (LENGTH(code)=5 OR code < 'a00'); + +DROP TABLE t1,t2; + --echo End of 5.0 tests diff --git a/mysql-test/t/func_test.test b/mysql-test/t/func_test.test index f2ff47704c9..0ea89cd0913 100644 --- a/mysql-test/t/func_test.test +++ b/mysql-test/t/func_test.test @@ -108,9 +108,6 @@ select 5.1 mod 3, 5.1 mod -3, -5.1 mod 3, -5.1 mod -3; select 5 mod 3, 5 mod -3, -5 mod 3, -5 mod -3; -# End of 4.1 tests - -# # Bug#6726: NOT BETWEEN parse failure # create table t1 (a int, b int); @@ -127,3 +124,5 @@ SELECT GREATEST(1,NULL) FROM DUAL; SELECT LEAST('xxx','aaa',NULL,'yyy') FROM DUAL; SELECT LEAST(1.1,1.2,NULL,1.0) FROM DUAL; SELECT GREATEST(1.5E+2,1.3E+2,NULL) FROM DUAL; + +# End of 4.1 tests diff --git a/mysql-test/t/func_time.test b/mysql-test/t/func_time.test index be09b00ad46..2b3fb86829d 100644 --- a/mysql-test/t/func_time.test +++ b/mysql-test/t/func_time.test @@ -419,20 +419,20 @@ drop table t1; # # Bug#16377 result of DATE/TIME functions were compared as strings which # can lead to a wrong result. -# +# Now wrong dates should be compared only with CAST() create table t1(f1 date, f2 time, f3 datetime); insert into t1 values ("2006-01-01", "12:01:01", "2006-01-01 12:01:01"); insert into t1 values ("2006-01-02", "12:01:02", "2006-01-02 12:01:02"); -select f1 from t1 where f1 between "2006-1-1" and 20060101; -select f1 from t1 where f1 between "2006-1-1" and "2006.1.1"; -select f1 from t1 where date(f1) between "2006-1-1" and "2006.1.1"; -select f2 from t1 where f2 between "12:1:2" and "12:2:2"; -select f2 from t1 where time(f2) between "12:1:2" and "12:2:2"; -select f3 from t1 where f3 between "2006-1-1 12:1:1" and "2006-1-1 12:1:2"; -select f3 from t1 where timestamp(f3) between "2006-1-1 12:1:1" and "2006-1-1 12:1:2"; -select f1 from t1 where "2006-1-1" between f1 and f3; -select f1 from t1 where "2006-1-1" between date(f1) and date(f3); -select f1 from t1 where "2006-1-1" between f1 and 'zzz'; +select f1 from t1 where f1 between CAST("2006-1-1" as date) and CAST(20060101 as date); +select f1 from t1 where f1 between cast("2006-1-1" as date) and cast("2006.1.1" as date); +select f1 from t1 where date(f1) between cast("2006-1-1" as date) and cast("2006.1.1" as date); +select f2 from t1 where f2 between cast("12:1:2" as time) and cast("12:2:2" as time); +select f2 from t1 where time(f2) between cast("12:1:2" as time) and cast("12:2:2" as time); +select f3 from t1 where f3 between cast("2006-1-1 12:1:1" as datetime) and cast("2006-1-1 12:1:2" as datetime); +select f3 from t1 where timestamp(f3) between cast("2006-1-1 12:1:1" as datetime) and cast("2006-1-1 12:1:2" as datetime); +select f1 from t1 where cast("2006-1-1" as date) between f1 and f3; +select f1 from t1 where cast("2006-1-1" as date) between date(f1) and date(f3); +select f1 from t1 where cast("2006-1-1" as date) between f1 and cast('zzz' as date); select f1 from t1 where makedate(2006,1) between date(f1) and date(f3); select f1 from t1 where makedate(2006,2) between date(f1) and date(f3); drop table t1; @@ -446,6 +446,25 @@ create table t1 select now() - now(), curtime() - curtime(), show create table t1; drop table t1; +# +# 21913: DATE_FORMAT() Crashes mysql server if I use it through +# mysql-connector-j driver. +# + +SET NAMES latin1; +SET character_set_results = NULL; +SHOW VARIABLES LIKE 'character_set_results'; + +CREATE TABLE testBug8868 (field1 DATE, field2 VARCHAR(32) CHARACTER SET BINARY); +INSERT INTO testBug8868 VALUES ('2006-09-04', 'abcd'); + +SELECT DATE_FORMAT(field1,'%b-%e %l:%i%p') as fmtddate, field2 FROM testBug8868; + +DROP TABLE testBug8868; + +SET NAMES DEFAULT; + + # # Bug #19844 time_format in Union truncates values # diff --git a/mysql-test/t/group_by.test b/mysql-test/t/group_by.test index 8a514108dc3..ce1e4e59600 100644 --- a/mysql-test/t/group_by.test +++ b/mysql-test/t/group_by.test @@ -655,15 +655,3 @@ where t2.b=v1.a GROUP BY t2.b; DROP VIEW v1; DROP TABLE t1,t2; - -# -# Bug #21174: Index degrades sort performance and -# optimizer does not honor IGNORE INDEX -# -CREATE TABLE t1 (a INT, b INT, KEY(a)); -INSERT INTO t1 VALUES (1, 1), (2, 2), (3,3), (4,4); - -EXPLAIN SELECT a, SUM(b) FROM t1 GROUP BY a LIMIT 2; -EXPLAIN SELECT a, SUM(b) FROM t1 IGNORE INDEX (a) GROUP BY a LIMIT 2; - -DROP TABLE t1; diff --git a/mysql-test/t/im_daemon_life_cycle.imtest b/mysql-test/t/im_daemon_life_cycle.imtest index a07da161279..acd1f0d887b 100644 --- a/mysql-test/t/im_daemon_life_cycle.imtest +++ b/mysql-test/t/im_daemon_life_cycle.imtest @@ -14,3 +14,47 @@ # process. --exec $MYSQL_TEST_DIR/t/kill_n_check.sh $IM_PATH_PID restarted 30 + +########################################################################### + +# +# BUG#12751: Instance Manager: client hangs +# + +--echo +--echo -------------------------------------------------------------------- +--echo -- Test for BUG#12751 +--echo -------------------------------------------------------------------- + +# Give some time to begin accepting connections after restart. +# FIXME: race condition here. + +--sleep 3 + +# 1. Start mysqld; + +START INSTANCE mysqld2; +# FIXME: START INSTANCE should be synchronous. +--exec $MYSQL_TEST_DIR/t/wait_for_process.sh $IM_MYSQLD2_PATH_PID 30 started + +# 2. Restart IM-main: kill it and IM-angel will restart it. + +--exec $MYSQL_TEST_DIR/t/kill_n_check.sh $IM_PATH_PID restarted 30 + +# 3. Issue some statement -- connection should be re-established. + +# Give some time to begin accepting connections after restart. +# FIXME: race condition here. + +--sleep 3 + +--replace_column 3 VERSION +SHOW INSTANCE STATUS mysqld1; + +# 4. Stop mysqld2, because it will not be stopped by IM, as it is nonguarded. +# So, if it we do not stop it, it will be stopped by mysql-test-run.pl with +# warning. + +STOP INSTANCE mysqld2; +# FIXME: STOP INSTANCE should be synchronous. +--exec $MYSQL_TEST_DIR/t/wait_for_process.sh $IM_MYSQLD2_PATH_PID 30 stopped diff --git a/mysql-test/t/index_merge.test b/mysql-test/t/index_merge.test index 3da5711bf7a..30eb0b40fca 100644 --- a/mysql-test/t/index_merge.test +++ b/mysql-test/t/index_merge.test @@ -383,3 +383,35 @@ explain select * from t3 where a=1 and b=1; drop table t3; drop table t0, t1, t2; + +# +# BUG#20256 - LOCK WRITE - MyISAM +# +CREATE TABLE t1(a INT); +INSERT INTO t1 VALUES(1); +CREATE TABLE t2(a INT, b INT, dummy CHAR(16) DEFAULT '', KEY(a), KEY(b)); +INSERT INTO t2(a,b) VALUES +(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0), +(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0), +(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0), +(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0), +(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0), +(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0), +(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0), +(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0), +(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0), +(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0), +(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0), +(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0), +(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0), +(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0), +(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0), +(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0), +(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0), +(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0), +(1,2); +LOCK TABLES t1 WRITE, t2 WRITE; +INSERT INTO t2(a,b) VALUES(1,2); +SELECT t2.a FROM t1,t2 WHERE t2.b=2 AND t2.a=1; +UNLOCK TABLES; +DROP TABLE t1, t2; diff --git a/mysql-test/t/insert_select.test b/mysql-test/t/insert_select.test index b6b94d07e87..6f86ed897ac 100644 --- a/mysql-test/t/insert_select.test +++ b/mysql-test/t/insert_select.test @@ -248,6 +248,24 @@ CREATE TABLE t3 (a int, b int); INSERT INTO t3 (SELECT x, y FROM t1 JOIN t2 USING (y) WHERE z = 1); DROP TABLE IF EXISTS t1,t2,t3; +# +# Bug #21774: Column count doesn't match value count at row x +# +CREATE DATABASE bug21774_1; +CREATE DATABASE bug21774_2; + +CREATE TABLE bug21774_1.t1(id VARCHAR(10) NOT NULL,label VARCHAR(255)); +CREATE TABLE bug21774_2.t1(id VARCHAR(10) NOT NULL,label VARCHAR(255)); +CREATE TABLE bug21774_1.t2(id VARCHAR(10) NOT NULL,label VARCHAR(255)); + +INSERT INTO bug21774_2.t1 SELECT t1.* FROM bug21774_1.t1; + +use bug21774_1; +INSERT INTO bug21774_2.t1 SELECT t1.* FROM t1; + +DROP DATABASE bug21774_1; +DROP DATABASE bug21774_2; + # # Bug #20989: View '(null).(null)' references invalid table(s)... on # SQL SECURITY INVOKER diff --git a/mysql-test/t/insert_update.test b/mysql-test/t/insert_update.test index eda768be1bc..b3813864464 100644 --- a/mysql-test/t/insert_update.test +++ b/mysql-test/t/insert_update.test @@ -115,4 +115,27 @@ INSERT INTO t1 ( a ) SELECT 0 ON DUPLICATE KEY UPDATE a = a + VALUES (a) ; DROP TABLE t1; +# +# Bug#21555: incorrect behavior with INSERT ... ON DUPL KEY UPDATE and VALUES +# + + # End of 4.1 tests +CREATE TABLE t1 +( + a BIGINT UNSIGNED, + b BIGINT UNSIGNED, + PRIMARY KEY (a) +); + +INSERT INTO t1 VALUES (45, 1) ON DUPLICATE KEY UPDATE b = + IF(VALUES(b) > t1.b, VALUES(b), t1.b); +SELECT * FROM t1; +INSERT INTO t1 VALUES (45, 2) ON DUPLICATE KEY UPDATE b = + IF(VALUES(b) > t1.b, VALUES(b), t1.b); +SELECT * FROM t1; +INSERT INTO t1 VALUES (45, 1) ON DUPLICATE KEY UPDATE b = + IF(VALUES(b) > t1.b, VALUES(b), t1.b); +SELECT * FROM t1; + +DROP TABLE t1; diff --git a/mysql-test/t/kill_n_check.sh b/mysql-test/t/kill_n_check.sh index 64cc869d1ec..a54fb6ef8bb 100755 --- a/mysql-test/t/kill_n_check.sh +++ b/mysql-test/t/kill_n_check.sh @@ -49,7 +49,7 @@ if [ -z "$pid_path" ]; then exit 0 fi -if [ $expected_result = 'killed' -a ! -r "$pid_path" ]; then +if [ ! -r "$pid_path" ]; then echo "Error: PID file ($pid_path) does not exist." exit 0 fi diff --git a/mysql-test/t/loaddata_autocom_innodb.test b/mysql-test/t/loaddata_autocom_innodb.test new file mode 100644 index 00000000000..d7f152cb286 --- /dev/null +++ b/mysql-test/t/loaddata_autocom_innodb.test @@ -0,0 +1,4 @@ +--source include/have_innodb.inc +let $engine_type= InnoDB; + +--source include/loaddata_autocom.inc diff --git a/mysql-test/t/loaddata_autocom_ndb.test b/mysql-test/t/loaddata_autocom_ndb.test new file mode 100644 index 00000000000..f4a6743aabe --- /dev/null +++ b/mysql-test/t/loaddata_autocom_ndb.test @@ -0,0 +1,4 @@ +--source include/have_ndb.inc +let $engine_type=ndbcluster; + +--source include/loaddata_autocom.inc diff --git a/mysql-test/t/lowercase_fs_off.test b/mysql-test/t/lowercase_fs_off.test index 7f7b573e7ee..883315994fe 100644 --- a/mysql-test/t/lowercase_fs_off.test +++ b/mysql-test/t/lowercase_fs_off.test @@ -3,6 +3,7 @@ # i.e. lower_case_filesystem=OFF # -- source include/have_case_sensitive_file_system.inc +-- source include/not_embedded.inc connect (master,localhost,root,,); connection master; diff --git a/mysql-test/t/merge.test b/mysql-test/t/merge.test index 93fbc631680..1308b0b83a4 100644 --- a/mysql-test/t/merge.test +++ b/mysql-test/t/merge.test @@ -378,6 +378,31 @@ select * from t3; check table t1, t2; drop table t1, t2, t3; +# +# BUG#21617 - crash when selecting from merge table with inconsistent +# indexes +# +CREATE TABLE t1(a INT); +INSERT INTO t1 VALUES(2),(1); +CREATE TABLE t2(a INT, KEY(a)) ENGINE=MERGE UNION=(t1); +--error 1030 +SELECT * FROM t2 WHERE a=2; +DROP TABLE t1, t2; + +# +# BUG#10974 - No error message if merge table based on union of innodb, +# memory +# +CREATE TABLE t1(a INT) ENGINE=MEMORY; +CREATE TABLE t2(a INT) ENGINE=MERGE UNION=(t1); +--error 1168 +SELECT * FROM t2; +DROP TABLE t1, t2; +CREATE TABLE t2(a INT) ENGINE=MERGE UNION=(t3); +--error 1168 +SELECT * FROM t2; +DROP TABLE t2; + # End of 4.1 tests # diff --git a/mysql-test/t/myisam.test b/mysql-test/t/myisam.test index 7dee5ebdf41..5ec4edea8c7 100644 --- a/mysql-test/t/myisam.test +++ b/mysql-test/t/myisam.test @@ -488,6 +488,42 @@ insert into t1 values ('a'), ('b'); select c1 from t1 order by c1 limit 1; drop table t1; +# +# Bug #14400 Join could miss concurrently inserted row +# +# Partial key. +create table t1 (a int not null, primary key(a)); +create table t2 (a int not null, b int not null, primary key(a,b)); +insert into t1 values (1),(2),(3),(4),(5),(6); +insert into t2 values (1,1),(2,1); +lock tables t1 read local, t2 read local; +select straight_join * from t1,t2 force index (primary) where t1.a=t2.a; +connect (root,localhost,root,,test,$MASTER_MYPORT,master.sock); +insert into t2 values(2,0); +disconnect root; +connection default; +select straight_join * from t1,t2 force index (primary) where t1.a=t2.a; +drop table t1,t2; +# +# Full key. +CREATE TABLE t1 (c1 varchar(250) NOT NULL); +CREATE TABLE t2 (c1 varchar(250) NOT NULL, PRIMARY KEY (c1)); +INSERT INTO t1 VALUES ('test000001'), ('test000002'), ('test000003'); +INSERT INTO t2 VALUES ('test000002'), ('test000003'), ('test000004'); +LOCK TABLES t1 READ LOCAL, t2 READ LOCAL; +SELECT t1.c1 AS t1c1, t2.c1 AS t2c1 FROM t1, t2 + WHERE t1.c1 = t2.c1 HAVING t1c1 != t2c1; +connect (con1,localhost,root,,); +connection con1; +INSERT INTO t2 VALUES ('test000001'), ('test000005'); +disconnect con1; +connection default; +SELECT t1.c1 AS t1c1, t2.c1 AS t2c1 FROM t1, t2 + WHERE t1.c1 = t2.c1 HAVING t1c1 != t2c1; +DROP TABLE t1,t2; + +# End of 4.0 tests + # # Test RTREE index # diff --git a/mysql-test/t/mysql.test b/mysql-test/t/mysql.test index cf4e6f4047c..f3296e6f706 100644 --- a/mysql-test/t/mysql.test +++ b/mysql-test/t/mysql.test @@ -62,6 +62,12 @@ drop table t1; # --exec $MYSQL -t test -e "create table t1 (col1 binary(4), col2 varchar(10), col3 int); insert into t1 values ('a', 'b', 123421),('a ', '0123456789', 4), ('abcd', '', 4); select concat('>',col1,'<'), col2, col3 from t1; drop table t1;" 2>&1 +# +# Bug#17939 Wrong table format when using UTF8 strings +# +--exec $MYSQL --default-character-set=utf8 --table -e "SELECT 'John Doe' as '__tañgè Ñãmé'" 2>&1 +--exec $MYSQL --default-character-set=utf8 --table -e "SELECT '__tañgè Ñãmé' as 'John Doe'" 2>&1 + # # Bug#18265 -- mysql client: No longer right-justifies numeric columns # @@ -70,14 +76,21 @@ drop table t1; # # "DESCRIBE" commands may return strange NULLness flags. # +--exec $MYSQL --default-character-set utf8 test -e "create table t1 (i int, j int not null, k int); insert into t1 values (null, 1, null); select * from t1; describe t1; drop table t1;" --exec $MYSQL -t --default-character-set utf8 test -e "create table t1 (i int, j int not null, k int); insert into t1 values (null, 1, null); select * from t1; describe t1; drop table t1;" # # Bug#19564: mysql displays NULL instead of space # +--exec $MYSQL test -e "create table b19564 (i int, s1 char(1)); insert into b19564 values (1, 'x'); insert into b19564 values (2, NULL); insert into b19564 values (3, ' '); select * from b19564 order by i; drop table b19564;" --exec $MYSQL -t test -e "create table b19564 (i int, s1 char(1)); insert into b19564 values (1, 'x'); insert into b19564 values (2, NULL); insert into b19564 values (3, ' '); select * from b19564 order by i; drop table b19564;" # +# Bug#21618: NULL shown as empty string in client +# +--exec $MYSQL test -e "select unhex('zz');" +--exec $MYSQL -t test -e "select unhex('zz');" + # Bug#19265 describe command does not work from mysql prompt # diff --git a/mysql-test/t/mysqldump.test b/mysql-test/t/mysqldump.test index 9766ee8d9c8..6dfb24c2e75 100644 --- a/mysql-test/t/mysqldump.test +++ b/mysql-test/t/mysqldump.test @@ -16,9 +16,9 @@ INSERT INTO t1 VALUES (1), (2); --exec $MYSQL_DUMP --skip-create --skip-comments -X test t1 DROP TABLE t1; -# -# Bug #2005 -# +--echo # +--echo # Bug #2005 +--echo # CREATE TABLE t1 (a decimal(64, 20)); INSERT INTO t1 VALUES ("1234567890123456789012345678901234567890"), @@ -26,9 +26,9 @@ INSERT INTO t1 VALUES ("1234567890123456789012345678901234567890"), --exec $MYSQL_DUMP --compact test t1 DROP TABLE t1; -# -# Bug #2055 -# +--echo # +--echo # Bug #2055 +--echo # CREATE TABLE t1 (a double); INSERT INTO t1 VALUES ('-9e999999'); @@ -38,9 +38,9 @@ INSERT INTO t1 VALUES ('-9e999999'); --exec $MYSQL_DUMP --compact test t1 DROP TABLE t1; -# -# Bug #3361 mysqldump quotes DECIMAL values inconsistently -# +--echo # +--echo # Bug #3361 mysqldump quotes DECIMAL values inconsistently +--echo # CREATE TABLE t1 (a DECIMAL(10,5), b FLOAT); @@ -69,28 +69,28 @@ INSERT INTO t1 VALUES (1, "test", "tes"), (2, "TEST", "TES"); --exec $MYSQL_DUMP --skip-create --compact -X test t1 DROP TABLE t1; -# -# Bug #1707 -# +--echo # +--echo # Bug #1707 +--echo # CREATE TABLE t1 (`a"b"` char(2)); INSERT INTO t1 VALUES ("1\""), ("\"2"); --exec $MYSQL_DUMP --compact --skip-create -X test t1 DROP TABLE t1; -# -# Bug #1994 -# Bug #4261 -# +--echo # +--echo # Bug #1994 +--echo # Bug #4261 +--echo # CREATE TABLE t1 (a VARCHAR(255)) DEFAULT CHARSET koi8r; INSERT INTO t1 VALUES (_koi8r x'C1C2C3C4C5'), (NULL); --exec $MYSQL_DUMP --skip-comments --skip-extended-insert test t1 DROP TABLE t1; -# -# Bug #2634 -# +--echo # +--echo # Bug #2634 +--echo # CREATE TABLE t1 (a int) ENGINE=MYISAM; INSERT INTO t1 VALUES (1), (2); @@ -98,17 +98,17 @@ INSERT INTO t1 VALUES (1), (2); --exec $MYSQL_DUMP --skip-comments --compatible=mysql323 test t1 DROP TABLE t1; -# -# Bug #2592 'mysqldump doesn't quote "tricky" names correctly' -# +--echo # +--echo # Bug #2592 'mysqldump doesn't quote "tricky" names correctly' +--echo # create table ```a` (i int); --exec $MYSQL_DUMP --compact test drop table ```a`; -# -# Bug #2591 "mysqldump quotes names inconsistently" -# +--echo # +--echo # Bug #2591 "mysqldump quotes names inconsistently" +--echo # create table t1(a int); --exec $MYSQL_DUMP --comments=0 test @@ -119,9 +119,9 @@ set global sql_mode='ANSI_QUOTES'; set global sql_mode=''; drop table t1; -# -# Bug #2705 'mysqldump --tab extra output' -# +--echo # +--echo # Bug #2705 'mysqldump --tab extra output' +--echo # create table t1(a int); insert into t1 values (1),(2),(3); @@ -135,9 +135,9 @@ insert into t1 values (1),(2),(3); --exec rm $MYSQLTEST_VARDIR/tmp/t1.txt drop table t1; -# -# Bug #6101: create database problem -# +--echo # +--echo # Bug #6101: create database problem +--echo # --exec $MYSQL_DUMP --skip-comments --databases test @@ -145,32 +145,34 @@ create database mysqldump_test_db character set latin2 collate latin2_bin; --exec $MYSQL_DUMP --skip-comments --databases mysqldump_test_db drop database mysqldump_test_db; -# -# Bug #7020 -# Check that we don't dump in UTF8 in compatible mode by default, -# but use the default compiled values, or the values given in -# --default-character-set=xxx. However, we should dump in UTF8 -# if it is explicitely set. +--echo # +--echo # Bug #7020 +--echo # Check that we don't dump in UTF8 in compatible mode by default, +--echo # but use the default compiled values, or the values given in +--echo # --default-character-set=xxx. However, we should dump in UTF8 +--echo # if it is explicitely set. CREATE TABLE t1 (a CHAR(10)); INSERT INTO t1 VALUES (_latin1 'ÄÖÜß'); --exec $MYSQL_DUMP --character-sets-dir=$CHARSETSDIR --skip-comments test t1 -# -# Bug#8063: make test mysqldump [ fail ] -# We cannot tes this command because its output depends -# on --default-character-set incompiled into "mysqldump" program. -# If the future we can move this command into a separate test with -# checking that "mysqldump" is compiled with "latin1" -# + +--echo # +--echo # Bug#8063: make test mysqldump [ fail ] +--echo # We cannot tes this command because its output depends +--echo # on --default-character-set incompiled into "mysqldump" program. +--echo # If the future we can move this command into a separate test with +--echo # checking that "mysqldump" is compiled with "latin1" +--echo # + #--exec $MYSQL_DUMP --character-sets-dir=$CHARSETSDIR --skip-comments --compatible=mysql323 test t1 --exec $MYSQL_DUMP --character-sets-dir=$CHARSETSDIR --skip-comments --compatible=mysql323 --default-character-set=cp850 test t1 --exec $MYSQL_DUMP --character-sets-dir=$CHARSETSDIR --skip-comments --default-character-set=cp850 --compatible=mysql323 test t1 --exec $MYSQL_DUMP --character-sets-dir=$CHARSETSDIR --skip-comments --default-character-set=utf8 --compatible=mysql323 test t1 DROP TABLE t1; -# -# WL #2319: Exclude Tables from dump -# +--echo # +--echo # WL #2319: Exclude Tables from dump +--echo # CREATE TABLE t1 (a int); CREATE TABLE t2 (a int); @@ -180,18 +182,18 @@ INSERT INTO t2 VALUES (4),(5),(6); DROP TABLE t1; DROP TABLE t2; -# -# Bug #8830 -# +--echo # +--echo # Bug #8830 +--echo # CREATE TABLE t1 (`b` blob); INSERT INTO `t1` VALUES (0x602010000280100005E71A); --exec $MYSQL_DUMP --skip-extended-insert --hex-blob test --skip-comments t1 DROP TABLE t1; -# -# Test for --insert-ignore -# +--echo # +--echo # Test for --insert-ignore +--echo # CREATE TABLE t1 (a int); INSERT INTO t1 VALUES (1),(2),(3); @@ -200,10 +202,10 @@ INSERT INTO t1 VALUES (4),(5),(6); --exec $MYSQL_DUMP --skip-comments --insert-ignore --delayed-insert test t1 DROP TABLE t1; -# -# Bug #10286: mysqldump -c crashes on table that has many fields with long -# names -# +--echo # +--echo # Bug #10286: mysqldump -c crashes on table that has many fields with long +--echo # names +--echo # create table t1 ( F_c4ca4238a0b923820dcc509a6f75849b int, F_c81e728d9d4c2f636f067f89cc14862c int, @@ -539,18 +541,18 @@ insert into t1 (F_8d3bba7425e7c98c50f52ca1b52d3735) values (1); --exec $MYSQL_DUMP --skip-comments -c test drop table t1; -# -# Test for --add-drop-database -# +--echo # +--echo # Test for --add-drop-database +--echo # CREATE TABLE t1 (a int); INSERT INTO t1 VALUES (1),(2),(3); --exec $MYSQL_DUMP --add-drop-database --skip-comments --databases test DROP TABLE t1; -# -# Bug #9558 mysqldump --no-data db t1 t2 format still dumps data -# +--echo # +--echo # Bug #9558 mysqldump --no-data db t1 t2 format still dumps data +--echo # CREATE DATABASE mysqldump_test_db; USE mysqldump_test_db; @@ -565,11 +567,11 @@ INSERT INTO t2 VALUES (1), (2); DROP TABLE t1, t2; DROP DATABASE mysqldump_test_db; -# -# Testing with tables and databases that don't exists -# or contains illegal characters -# (Bug #9358 mysqldump crashes if tablename starts with \) -# +--echo # +--echo # Testing with tables and databases that don't exists +--echo # or contains illegal characters +--echo # (Bug #9358 mysqldump crashes if tablename starts with \) +--echo # create database mysqldump_test_db; use mysqldump_test_db; create table t1(a varchar(30) primary key, b int not null); @@ -629,9 +631,9 @@ drop database mysqldump_test_db; use test; -# -# Bug #9657 mysqldump xml ( -x ) does not format NULL fields correctly -# +--echo # +--echo # Bug #9657 mysqldump xml ( -x ) does not format NULL fields correctly +--echo # create table t1 (a int(10)); create table t2 (pk int primary key auto_increment, @@ -641,9 +643,10 @@ insert into t2 (a, b) values (NULL, NULL),(10, NULL),(NULL, "twenty"),(30, "thir --exec $MYSQL_DUMP --skip-comments --xml --no-create-info test drop table t1, t2; -# -# BUG #12123 -# +--echo # +--echo # BUG #12123 +--echo # + create table t1 (a text character set utf8, b text character set latin1); insert t1 values (0x4F736E616272C3BC636B, 0x4BF66C6E); select * from t1; @@ -654,15 +657,16 @@ select * from t1; drop table t1; -# -# BUG#15328 Segmentation fault occured if my.cnf is invalid for escape sequence -# +--echo # +--echo # BUG#15328 Segmentation fault occured if my.cnf is invalid for escape sequence +--echo # --exec $MYSQL_MY_PRINT_DEFAULTS --config-file=$MYSQL_TEST_DIR/std_data/bug15328.cnf mysqldump -# -# BUG #19025 mysqldump doesn't correctly dump "auto_increment = [int]" -# +--echo # +--echo # BUG #19025 mysqldump doesn't correctly dump "auto_increment = [int]" +--echo # + create table `t1` ( t1_name varchar(255) default null, t1_id int(10) unsigned not null auto_increment, @@ -689,9 +693,9 @@ show create table `t1`; drop table `t1`; -# -# Bug #18536: wrong table order -# +--echo # +--echo # Bug #18536: wrong table order +--echo # create table t1(a int); create table t2(a int); @@ -700,9 +704,10 @@ create table t3(a int); --exec $MYSQL_DUMP --skip-comments --force --no-data test t3 t1 non_existing t2 drop table t1, t2, t3; -# -# Bug #21288: mysqldump segmentation fault when using --where -# +--echo # +--echo # Bug #21288: mysqldump segmentation fault when using --where +--echo # + create table t1 (a int); --error 2 --exec $MYSQL_DUMP --skip-comments --force test t1 --where='xx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' 2>&1 @@ -710,9 +715,9 @@ drop table t1; --echo End of 4.1 tests -# -# Bug #10213 mysqldump crashes when dumping VIEWs(on MacOS X) -# +--echo # +--echo # Bug #10213 mysqldump crashes when dumping VIEWs(on MacOS X) +--echo # create database db1; use db1; @@ -734,9 +739,9 @@ drop view v2; drop database db1; use test; -# -# Bug 10713 mysqldump includes database in create view and referenced tables -# +--echo # +--echo # Bug 10713 mysqldump includes database in create view and referenced tables +--echo # # create table and views in db2 create database db2; @@ -779,9 +784,9 @@ create view v1 as select * from t1; drop view v1; drop table t1; -# -# Bug #10213 mysqldump crashes when dumping VIEWs(on MacOS X) -# +--echo # +--echo # Bug #10213 mysqldump crashes when dumping VIEWs(on MacOS X) +--echo # create database mysqldump_test_db; use mysqldump_test_db; @@ -803,18 +808,18 @@ drop view v2; drop database mysqldump_test_db; use test; -# -# Bug #9756 -# +--echo # +--echo # Bug #9756 +--echo # CREATE TABLE t1 (a char(10)); INSERT INTO t1 VALUES ('\''); --exec $MYSQL_DUMP --skip-comments test t1 DROP TABLE t1; -# -# Bug #10927 mysqldump: Can't reload dump with view that consist of other view -# +--echo # +--echo # Bug #10927 mysqldump: Can't reload dump with view that consist of other view +--echo # create table t1(a int, b int, c varchar(30)); @@ -834,9 +839,9 @@ select v3.a from v3, v1 where v1.a=v3.a and v3.b=3 limit 1; drop view v1, v2, v3; drop table t1; -# -# Test for dumping triggers -# +--echo # +--echo # Test for dumping triggers +--echo # CREATE TABLE t1 (a int, b bigint default NULL); CREATE TABLE t2 (a int); @@ -884,9 +889,9 @@ show tables; show triggers; DROP TABLE t1, t2; -# -# Bugs #9136, #12917: problems with --defaults-extra-file option -# +--echo # +--echo # Bugs #9136, #12917: problems with --defaults-extra-file option +--echo # --system echo '[mysqltest1]' > $MYSQLTEST_VARDIR/tmp/tmp.cnf --system echo 'port=1234' >> $MYSQLTEST_VARDIR/tmp/tmp.cnf @@ -894,9 +899,9 @@ DROP TABLE t1, t2; --exec $MYSQL_MY_PRINT_DEFAULTS -e $MYSQLTEST_VARDIR/tmp/tmp.cnf mysqltest1 mysqltest1 --system rm $MYSQLTEST_VARDIR/tmp/tmp.cnf -# -# Test of fix to BUG 12597 -# +--echo # +--echo # Test of fix to BUG 12597 +--echo # DROP TABLE IF EXISTS `test1`; CREATE TABLE `test1` ( @@ -932,9 +937,9 @@ DROP TRIGGER testref; DROP TABLE test1; DROP TABLE test2; -# -# BUG#9056 - mysqldump does not dump routines -# +--echo # +--echo # BUG#9056 - mysqldump does not dump routines +--echo # --disable_warnings DROP TABLE IF EXISTS t1; @@ -981,9 +986,10 @@ DROP PROCEDURE bug9056_proc2; DROP PROCEDURE `a'b`; drop table t1; -# -# BUG# 13052 - mysqldump timestamp reloads broken -# +--echo # +--echo # BUG# 13052 - mysqldump timestamp reloads broken +--echo # + --disable_warnings drop table if exists t1; --enable_warnings @@ -1003,9 +1009,10 @@ drop table t1; set global time_zone=default; set time_zone=default; -# -# Test of fix to BUG 13146 - ansi quotes break loading of triggers -# +--echo # +--echo # Test of fix to BUG 13146 - ansi quotes break loading of triggers +--echo # + --disable_warnings DROP TABLE IF EXISTS `t1 test`; DROP TABLE IF EXISTS `t2 test`; @@ -1036,9 +1043,9 @@ DROP TRIGGER `test trig`; DROP TABLE `t1 test`; DROP TABLE `t2 test`; -# -# BUG# 12838 mysqldump -x with views exits with error -# +--echo # +--echo # BUG# 12838 mysqldump -x with views exits with error +--echo # --disable_warnings drop table if exists t1; @@ -1060,10 +1067,10 @@ drop view v0; drop view v1; drop table t1; -# -# BUG#14554 - mysqldump does not separate words "ROW" and "BEGIN" -# for tables with trigger created in the IGNORE_SPACE sql mode. -# +--echo # +--echo # BUG#14554 - mysqldump does not separate words "ROW" and "BEGIN" +--echo # for tables with trigger created in the IGNORE_SPACE sql mode. +--echo # SET @old_sql_mode = @@SQL_MODE; SET SQL_MODE = IGNORE_SPACE; @@ -1084,18 +1091,19 @@ SET SQL_MODE = @old_sql_mode; DROP TRIGGER tr1; DROP TABLE t1; -# -# Bug #13318: Bad result with empty field and --hex-blob -# +--echo # +--echo # Bug #13318: Bad result with empty field and --hex-blob +--echo # + create table t1 (a binary(1), b blob); insert into t1 values ('',''); --exec $MYSQL_DUMP --skip-comments --skip-extended-insert --hex-blob test t1 --exec $MYSQL_DUMP --skip-comments --hex-blob test t1 drop table t1; -# -# Bug 14871 Invalid view dump output -# +--echo # +--echo # Bug 14871 Invalid view dump output +--echo # create table t1 (a int); insert into t1 values (289), (298), (234), (456), (789); @@ -1122,9 +1130,9 @@ select * from v3 order by a; drop table t1; drop view v1, v2, v3, v4, v5; -# -# Bug #16878 dump of trigger -# +--echo # +--echo # Bug #16878 dump of trigger +--echo # create table t1 (a int, created datetime); create table t2 (b int, created datetime); @@ -1152,11 +1160,10 @@ drop trigger tr1; drop trigger tr2; drop table t1, t2; +--echo # +--echo # Bug#18462 mysqldump does not dump view structures correctly +--echo # -# -# Bug#18462 mysqldump does not dump view structures correctly -# -# create table t (qty int, price int); insert into t values(3, 50); insert into t values(5, 51); @@ -1173,11 +1180,11 @@ drop view v2; drop table t; -# -# Bug#14857 Reading dump files with single statement stored routines fails. -# fixed by patch for bug#16878 -# -# +--echo # +--echo # Bug#14857 Reading dump files with single statement stored routines fails. +--echo # fixed by patch for bug#16878 +--echo # + DELIMITER |; /*!50003 CREATE FUNCTION `f`() RETURNS bigint(20) return 42 */| @@ -1189,10 +1196,10 @@ show create procedure p; drop function f; drop procedure p; -# -# Bug #17371 Unable to dump a schema with invalid views -# -# +--echo # +--echo # Bug #17371 Unable to dump a schema with invalid views +--echo # + create table t1 ( id serial ); create view v1 as select * from t1; drop table t1; @@ -1203,9 +1210,9 @@ drop table t1; --echo } mysqldump drop view v1; -# BUG#17201 Spurious 'DROP DATABASE' in output, -# also confusion between tables and views. -# Example code from Markus Popp +--echo # BUG#17201 Spurious 'DROP DATABASE' in output, +--echo # also confusion between tables and views. +--echo # Example code from Markus Popp create database mysqldump_test_db; use mysqldump_test_db; @@ -1220,7 +1227,9 @@ drop view v1; drop table t1; drop database mysqldump_test_db; -# Bug21014 Segmentation fault of mysqldump on view +--echo # +--echo # Bug21014 Segmentation fault of mysqldump on view +--echo # create database mysqldump_tables; use mysqldump_tables; @@ -1237,7 +1246,9 @@ drop database mysqldump_views; drop table mysqldump_tables.basetable; drop database mysqldump_tables; -# Bug20221 Dumping of multiple databases containing view(s) yields maleformed dumps +--echo # +--echo # Bug20221 Dumping of multiple databases containing view(s) yields maleformed dumps +--echo # create database mysqldump_dba; use mysqldump_dba; @@ -1276,9 +1287,9 @@ drop table t1; drop database mysqldump_dbb; use test; -# -# Bug#21215 mysqldump creating incomplete backups without warning -# +--echo # +--echo # Bug#21215 mysqldump creating incomplete backups without warning +--echo # # Create user without sufficient privs to perform the requested operation create user mysqltest_1@localhost; @@ -1318,35 +1329,89 @@ grant REPLICATION CLIENT on *.* to mysqltest_1@localhost; drop table t1; drop user mysqltest_1@localhost; -# -# Bug #21527 mysqldump incorrectly tries to LOCK TABLES on the -# information_schema database. -# +--echo # +--echo # Bug #21527 mysqldump incorrectly tries to LOCK TABLES on the +--echo # information_schema database. +--echo # +--echo # Bug #21424 mysqldump failing to export/import views +--echo # + +# Do as root connect (root,localhost,root,,test,$MASTER_MYPORT,$MASTER_MYSOCK); connection root; create database mysqldump_myDB; use mysqldump_myDB; create user myDB_User; -grant create view, select on mysqldump_myDB.* to myDB_User@localhost; +grant create, create view, select, insert on mysqldump_myDB.* to myDB_User@localhost; create table t1 (c1 int); insert into t1 values (3); +# Do as a user connect (user1,localhost,myDB_User,,mysqldump_myDB,$MASTER_MYPORT,$MASTER_MYSOCK); connection user1; use mysqldump_myDB; +create table u1 (f1 int); +insert into u1 values (4); create view v1 (c1) as select * from t1; -# Backup should not fail. ---exec $MYSQL_DUMP --all-databases --add-drop-table > $MYSQLTEST_VARDIR/tmp/bug21527.sql +# Backup should not fail for Bug #21527. Flush priviliges test begins. +--exec $MYSQL_DUMP --skip-comments --add-drop-table --flush-privileges --ignore-table=mysql.general_log --ignore-table=mysql.slow_log --databases mysqldump_myDB mysql > $MYSQLTEST_VARDIR/tmp/bug21527.sql # Clean up connection root; use mysqldump_myDB; drop view v1; drop table t1; +drop table u1; +revoke all privileges on mysqldump_myDB.* from myDB_User@localhost; +drop user myDB_User; +drop database mysqldump_myDB; +flush privileges; + +--echo # Bug #21424 continues from here. +--echo # Restore. Flush Privileges test ends. +--echo # + +--exec $MYSQL < $MYSQLTEST_VARDIR/tmp/bug21527.sql; + +# Do as a user +connection user1; +use mysqldump_myDB; + +# Ultimate test for correct data. +select * from mysqldump_myDB.v1; +select * from mysqldump_myDB.u1; + +#Final cleanup. +connection root; +use mysqldump_myDB; +drop view v1; +drop table t1; +drop table u1; revoke all privileges on mysqldump_myDB.* from myDB_User@localhost; drop user myDB_User; drop database mysqldump_myDB; use test; ---echo End of 5.0 tests +--echo # +--echo # BUG#13926: --order-by-primary fails if PKEY contains quote character +--echo # + +--disable_warnings +DROP TABLE IF EXISTS `t1`; +CREATE TABLE `t1` ( + `a b` INT, + `c"d` INT, + `e``f` INT, + PRIMARY KEY (`a b`, `c"d`, `e``f`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1; +insert into t1 values (0815, 4711, 2006); + +--exec $MYSQL_DUMP --skip-comments --compatible=ansi --order-by-primary test t1 +--exec $MYSQL_DUMP --skip-comments --order-by-primary test t1 +DROP TABLE `t1`; +--enable_warnings + +--echo # +--echo # End of 5.0 tests +--echo # diff --git a/mysql-test/t/mysqltest.test b/mysql-test/t/mysqltest.test index 6a0b805f43b..c30af8c8f26 100644 --- a/mysql-test/t/mysqltest.test +++ b/mysql-test/t/mysqltest.test @@ -507,9 +507,21 @@ echo $where2; let $where3=a long $where variable content; echo $where3; +let $where3=a long \\\$where variable content; +echo $where3; + let $novar1= $novar2; echo $novar1; +let $cat=na; +let $cat=ba$cat$cat; +echo banana = $cat; + +# ba\$cat\$cat should have been sufficient. +# ba\\\$cat\\\$cat -> ba\$cat\$cat -> ba$cat$cat -> banana +# Magnus' upcoming patch will fix the missing second interpretation. +let $cat=ba\\\$cat\\\$cat; +echo Not a banana: $cat; # Test illegal uses of let diff --git a/mysql-test/t/ps.test b/mysql-test/t/ps.test index 5b2e37ecc94..f1e8e77d94e 100644 --- a/mysql-test/t/ps.test +++ b/mysql-test/t/ps.test @@ -988,6 +988,58 @@ execute stmt; drop temporary table t1; deallocate prepare stmt; +# +# BUG#22085: Crash on the execution of a prepared statement that +# uses an IN subquery with aggregate functions in HAVING +# + +CREATE TABLE t1( + ID int(10) unsigned NOT NULL auto_increment, + Member_ID varchar(15) NOT NULL default '', + Action varchar(12) NOT NULL, + Action_Date datetime NOT NULL, + Track varchar(15) default NULL, + User varchar(12) default NULL, + Date_Updated timestamp NOT NULL default CURRENT_TIMESTAMP on update + CURRENT_TIMESTAMP, + PRIMARY KEY (ID), + KEY Action (Action), + KEY Action_Date (Action_Date) +); + +INSERT INTO t1(Member_ID, Action, Action_Date, Track) VALUES + ('111111', 'Disenrolled', '2006-03-01', 'CAD' ), + ('111111', 'Enrolled', '2006-03-01', 'CAD' ), + ('111111', 'Disenrolled', '2006-07-03', 'CAD' ), + ('222222', 'Enrolled', '2006-03-07', 'CAD' ), + ('222222', 'Enrolled', '2006-03-07', 'CHF' ), + ('222222', 'Disenrolled', '2006-08-02', 'CHF' ), + ('333333', 'Enrolled', '2006-03-01', 'CAD' ), + ('333333', 'Disenrolled', '2006-03-01', 'CAD' ), + ('444444', 'Enrolled', '2006-03-01', 'CAD' ), + ('555555', 'Disenrolled', '2006-03-01', 'CAD' ), + ('555555', 'Enrolled', '2006-07-21', 'CAD' ), + ('555555', 'Disenrolled', '2006-03-01', 'CHF' ), + ('666666', 'Enrolled', '2006-02-09', 'CAD' ), + ('666666', 'Enrolled', '2006-05-12', 'CHF' ), + ('666666', 'Disenrolled', '2006-06-01', 'CAD' ); + +PREPARE STMT FROM +"SELECT GROUP_CONCAT(Track SEPARATOR ', ') FROM t1 + WHERE Member_ID=? AND Action='Enrolled' AND + (Track,Action_Date) IN (SELECT Track, MAX(Action_Date) FROM t1 + WHERE Member_ID=? + GROUP BY Track + HAVING Track>='CAD' AND + MAX(Action_Date)>'2006-03-01')"; +SET @id='111111'; +EXECUTE STMT USING @id,@id; +SET @id='222222'; +EXECUTE STMT USING @id,@id; + +DEALLOCATE PREPARE STMT; +DROP TABLE t1; + --echo End of 4.1 tests ############################# 5.0 tests start ################################ # @@ -1358,4 +1410,31 @@ DEALLOCATE PREPARE stmt; DROP TABLE IF EXISTS t1, t2, t3; +# +# BUG#21081: SELECT inside stored procedure returns wrong results +# +--disable_warnings +DROP TABLE IF EXISTS t1, t2; +--enable_warnings + +CREATE TABLE t1 (i INT KEY); +CREATE TABLE t2 (i INT); + +INSERT INTO t1 VALUES (1), (2); +INSERT INTO t2 VALUES (1); + +PREPARE stmt FROM "SELECT t2.i FROM t1 LEFT JOIN t2 ON t2.i = t1.i + WHERE t1.i = ?"; + +SET @arg= 1; +EXECUTE stmt USING @arg; +SET @arg= 2; +EXECUTE stmt USING @arg; +SET @arg= 1; +EXECUTE stmt USING @arg; + +DEALLOCATE PREPARE stmt; +DROP TABLE t1, t2; + + --echo End of 5.0 tests. diff --git a/mysql-test/t/round.test b/mysql-test/t/round.test new file mode 100644 index 00000000000..d018fa7e34e --- /dev/null +++ b/mysql-test/t/round.test @@ -0,0 +1,145 @@ +--disable_warnings +DROP TABLE IF EXISTS t1; +--enable_warnings + +CREATE TABLE t1 (sint8 tinyint not null); +INSERT INTO t1 VALUES ('0.1'); +INSERT INTO t1 VALUES ('0.5'); +INSERT INTO t1 VALUES ('127.4'); +INSERT INTO t1 VALUES ('127.5'); +INSERT INTO t1 VALUES ('-0.1'); +INSERT INTO t1 VALUES ('-0.5'); +INSERT INTO t1 VALUES ('-127.4'); +INSERT INTO t1 VALUES ('-127.5'); +INSERT INTO t1 VALUES ('-128.4'); +INSERT INTO t1 VALUES ('-128.5'); +SELECT * FROM t1; +DROP TABLE t1; + +CREATE TABLE t1 (uint8 tinyint unsigned not null); +INSERT INTO t1 VALUES ('0.1'); +INSERT INTO t1 VALUES ('0.5'); +INSERT INTO t1 VALUES ('127.4'); +INSERT INTO t1 VALUES ('127.5'); +INSERT INTO t1 VALUES ('-0.1'); +INSERT INTO t1 VALUES ('-0.5'); +INSERT INTO t1 VALUES ('255.4'); +INSERT INTO t1 VALUES ('255.5'); +SELECT * FROM t1; +DROP TABLE t1; + + +CREATE TABLE t1 (sint16 smallint not null); +INSERT INTO t1 VALUES ('0.1'); +INSERT INTO t1 VALUES ('0.5'); +INSERT INTO t1 VALUES ('32767.4'); +INSERT INTO t1 VALUES ('32767.5'); +INSERT INTO t1 VALUES ('-0.1'); +INSERT INTO t1 VALUES ('-0.5'); +INSERT INTO t1 VALUES ('-32767.4'); +INSERT INTO t1 VALUES ('-32767.5'); +INSERT INTO t1 VALUES ('-32768.4'); +INSERT INTO t1 VALUES ('-32768.5'); +SELECT * FROM t1; +DROP TABLE t1; + + +CREATE TABLE t1 (uint16 smallint unsigned not null); +INSERT INTO t1 VALUES ('0.1'); +INSERT INTO t1 VALUES ('0.5'); +INSERT INTO t1 VALUES ('32767.4'); +INSERT INTO t1 VALUES ('32767.5'); +INSERT INTO t1 VALUES ('-0.1'); +INSERT INTO t1 VALUES ('-0.5'); +INSERT INTO t1 VALUES ('65535.4'); +INSERT INTO t1 VALUES ('65535.5'); +SELECT * FROM t1; +DROP TABLE t1; + +CREATE TABLE t1 (sint24 mediumint not null); +INSERT INTO t1 VALUES ('0.1'); +INSERT INTO t1 VALUES ('0.5'); +INSERT INTO t1 VALUES ('8388607.4'); +INSERT INTO t1 VALUES ('8388607.5'); +INSERT INTO t1 VALUES ('-0.1'); +INSERT INTO t1 VALUES ('-0.5'); +INSERT INTO t1 VALUES ('-8388607.4'); +INSERT INTO t1 VALUES ('-8388607.5'); +INSERT INTO t1 VALUES ('-8388608.4'); +INSERT INTO t1 VALUES ('-8388608.5'); +SELECT * FROM t1; +DROP TABLE t1; + +CREATE TABLE t1 (uint24 mediumint unsigned not null); +INSERT INTO t1 VALUES ('0.1'); +INSERT INTO t1 VALUES ('0.5'); +INSERT INTO t1 VALUES ('8388607.4'); +INSERT INTO t1 VALUES ('8388607.5'); +INSERT INTO t1 VALUES ('-0.1'); +INSERT INTO t1 VALUES ('-0.5'); +INSERT INTO t1 VALUES ('16777215.4'); +INSERT INTO t1 VALUES ('16777215.5'); +SELECT * FROM t1; +DROP TABLE t1; + +CREATE TABLE t1 (sint64 bigint not null); +INSERT INTO t1 VALUES ('0.1'); +INSERT INTO t1 VALUES ('0.5'); +INSERT INTO t1 VALUES ('9223372036854775807.4'); +INSERT INTO t1 VALUES ('9223372036854775807.5'); +INSERT INTO t1 VALUES ('-0.1'); +INSERT INTO t1 VALUES ('-0.5'); +INSERT INTO t1 VALUES ('-9223372036854775807.4'); +INSERT INTO t1 VALUES ('-9223372036854775807.5'); +INSERT INTO t1 VALUES ('-9223372036854775808.4'); +INSERT INTO t1 VALUES ('-9223372036854775808.5'); +SELECT * FROM t1; +DROP TABLE t1; + +CREATE TABLE t1 (uint64 bigint unsigned not null); +INSERT INTO t1 VALUES ('0.1'); +INSERT INTO t1 VALUES ('0.5'); +INSERT INTO t1 VALUES ('9223372036854775807.4'); +INSERT INTO t1 VALUES ('9223372036854775807.5'); +INSERT INTO t1 VALUES ('-0.1'); +INSERT INTO t1 VALUES ('-0.5'); +INSERT INTO t1 VALUES ('18446744073709551615.4'); +INSERT INTO t1 VALUES ('18446744073709551615.5'); +INSERT INTO t1 VALUES ('1844674407370955161.0'); +INSERT INTO t1 VALUES ('1844674407370955161.1'); +INSERT INTO t1 VALUES ('1844674407370955161.2'); +INSERT INTO t1 VALUES ('1844674407370955161.3'); +INSERT INTO t1 VALUES ('1844674407370955161.4'); +INSERT INTO t1 VALUES ('1844674407370955161.5'); +INSERT INTO t1 VALUES ('1844674407370955161.0e1'); +INSERT INTO t1 VALUES ('1844674407370955161.1e1'); +INSERT INTO t1 VALUES ('1844674407370955161.2e1'); +INSERT INTO t1 VALUES ('1844674407370955161.3e1'); +INSERT INTO t1 VALUES ('1844674407370955161.4e1'); +INSERT INTO t1 VALUES ('1844674407370955161.5e1'); +INSERT INTO t1 VALUES ('18446744073709551610e-1'); +INSERT INTO t1 VALUES ('18446744073709551611e-1'); +INSERT INTO t1 VALUES ('18446744073709551612e-1'); +INSERT INTO t1 VALUES ('18446744073709551613e-1'); +INSERT INTO t1 VALUES ('18446744073709551614e-1'); +INSERT INTO t1 VALUES ('18446744073709551615e-1'); +SELECT * FROM t1; +DROP TABLE t1; + +CREATE TABLE t1 (str varchar(128), sint64 bigint not null default 0); +INSERT INTO t1 (str) VALUES ('1.5'); +INSERT INTO t1 (str) VALUES ('1.00005e4'); +INSERT INTO t1 (str) VALUES ('1.0005e3'); +INSERT INTO t1 (str) VALUES ('1.005e2'); +INSERT INTO t1 (str) VALUES ('1.05e1'); +INSERT INTO t1 (str) VALUES ('1.5e0'); +INSERT INTO t1 (str) VALUES ('100005e-1'); +INSERT INTO t1 (str) VALUES ('100050e-2'); +INSERT INTO t1 (str) VALUES ('100500e-3'); +INSERT INTO t1 (str) VALUES ('105000e-4'); +INSERT INTO t1 (str) VALUES ('150000e-5'); +UPDATE t1 SET sint64=str; +SELECT * FROM t1; +DROP TABLE t1; + + diff --git a/mysql-test/t/row.test b/mysql-test/t/row.test index 6301cc0f584..63c611e6be6 100644 --- a/mysql-test/t/row.test +++ b/mysql-test/t/row.test @@ -92,3 +92,50 @@ SELECT ROW(NULL,10) <=> ROW(3,NULL); # SELECT ROW(1,1,1) = ROW(1,1,1) as `1`, ROW(1,1,1) = ROW(1,2,1) as `0`, ROW(1,NULL,1) = ROW(2,2,1) as `0`, ROW(1,NULL,1) = ROW(1,2,2) as `0`, ROW(1,NULL,1) = ROW(1,2,1) as `null` ; select row(NULL,1)=(2,0); + +# +# Bug #16081: row equalities are to be used for query optimizations +# + +CREATE TABLE t1 (a int, b int, PRIMARY KEY (a,b)); +INSERT INTO t1 VALUES (1,1), (2,1), (3,1), (1,2), (3,2), (3,3); + +EXPLAIN SELECT * FROM t1 WHERE a=3 AND b=2; +EXPLAIN SELECT * FROM t1 WHERE (a,b)=(3,2); +SELECT * FROM t1 WHERE a=3 and b=2; +SELECT * FROM t1 WHERE (a,b)=(3,2); + +CREATE TABLE t2 (a int, b int, c int, PRIMARY KEY (a,b,c)); +INSERT INTO t2 VALUES + (1,1,2), (3,1,3), (1,2,2), (4,4,2), + (1,1,1), (3,1,1), (1,2,1); + +EXPLAIN SELECT * FROM t1,t2 WHERE t1.a=t2.a AND t1.b=t2.b; +EXPLAIN SELECT * FROM t1,t2 WHERE (t1.a,t1.b)=(t2.a,t2.b); +SELECT * FROM t1,t2 WHERE t1.a=t2.a and t1.b=t2.b; +SELECT * FROM t1,t2 WHERE (t1.a,t1.b)=(t2.a,t2.b); + +EXPLAIN SELECT * FROM t1,t2 WHERE t1.a=t2.a AND t1.b=2; +EXPLAIN SELECT * FROM t1,t2 WHERE (t1.a,t1.b)=(t2.a,2); +SELECT * FROM t1,t2 WHERE t1.a=1 and t1.b=t2.b; +SELECT * FROM t1,t2 WHERE (t1.a,t1.b)=(t2.a,2); + +EXPLAIN EXTENDED SELECT * FROM t1,t2 WHERE (t1.a,t1.b)=(t2.a,t2.b+1); +SELECT * FROM t1,t2 WHERE (t1.a,t1.b)=(t2.a,t2.b+1); + +EXPLAIN EXTENDED SELECT * FROM t1,t2 WHERE (t1.a-1,t1.b)=(t2.a-1,t2.b+1); +SELECT * FROM t1,t2 WHERE (t1.a-1,t1.b)=(t2.a-1,t2.b+1); + +EXPLAIN SELECT * FROM t2 WHERE a=3 AND b=2; +EXPLAIN SELECT * FROM t2 WHERE (a,b)=(3,2); +SELECT * FROM t2 WHERE a=3 and b=2; +SELECT * FROM t2 WHERE (a,b)=(3,2); + +EXPLAIN SELECT * FROM t1,t2 WHERE t2.a=t1.a AND t2.b=2 AND t2.c=1; +EXPLAIN EXTENDED SELECT * FROM t1,t2 WHERE (t2.a,(t2.b,t2.c))=(t1.a,(2,1)); +SELECT * FROM t1,t2 WHERE (t2.a,(t2.b,t2.c))=(t1.a,(2,1)); + +EXPLAIN EXTENDED SELECT * FROM t1,t2 WHERE t2.a=t1.a AND (t2.b,t2.c)=(2,1); +SELECT * FROM t1,t2 WHERE t2.a=t1.a AND (t2.b,t2.c)=(2,1); + +DROP TABLE t1,t2; diff --git a/mysql-test/t/rpl_insert_id.test b/mysql-test/t/rpl_insert_id.test index fa66306aaa6..331a913256c 100644 --- a/mysql-test/t/rpl_insert_id.test +++ b/mysql-test/t/rpl_insert_id.test @@ -1,10 +1,21 @@ -# See if queries that use both auto_increment and LAST_INSERT_ID() -# are replicated well - -# We also check how the foreign_key_check variable is replicated +--echo # +--echo # Setup +--echo # source include/master-slave.inc; source include/have_innodb.inc; +use test; +--disable_warnings +drop table if exists t1, t2, t3; +--enable_warnings + +--echo # +--echo # See if queries that use both auto_increment and LAST_INSERT_ID() +--echo # are replicated well +--echo # +--echo # We also check how the foreign_key_check variable is replicated +--echo # + connection master; create table t1(a int auto_increment, key(a)); create table t2(b int auto_increment, c int, key(b)); @@ -39,7 +50,9 @@ select * from t1; select * from t2; connection master; -# check if INSERT SELECT in auto_increment is well replicated (bug #490) +--echo # +--echo # check if INSERT SELECT in auto_increment is well replicated (bug #490) +--echo # drop table t2; drop table t1; @@ -62,10 +75,11 @@ save_master_pos; connection slave; sync_with_master; -# -# Bug#8412: Error codes reported in binary log for CHARACTER SET, -# FOREIGN_KEY_CHECKS -# +--echo # +--echo # Bug#8412: Error codes reported in binary log for CHARACTER SET, +--echo # FOREIGN_KEY_CHECKS +--echo # + connection master; SET TIMESTAMP=1000000000; CREATE TABLE t1 ( a INT UNIQUE ); @@ -78,9 +92,10 @@ connection master; drop table t1; sync_slave_with_master; -# -# Bug#14553: NULL in WHERE resets LAST_INSERT_ID -# +--echo # +--echo # Bug#14553: NULL in WHERE resets LAST_INSERT_ID +--echo # + connection master; create table t1(a int auto_increment, key(a)); create table t2(a int); @@ -95,8 +110,10 @@ connection master; drop table t1; drop table t2; sync_slave_with_master; -# End of 4.1 tests +--echo # +--echo # End of 4.1 tests +--echo # # # BUG#15728: LAST_INSERT_ID function inside a stored function returns 0 @@ -228,6 +245,138 @@ select * from t1 order by n; connection master; drop table t1; -# End of 5.0 tests +# +# BUG#20339: stored procedure using LAST_INSERT_ID() does not +# replicate statement-based +# +--disable_warnings +DROP PROCEDURE IF EXISTS p1; +DROP TABLE IF EXISTS t1, t2; +--enable_warnings + +# Reset result of LAST_INSERT_ID(). +SELECT LAST_INSERT_ID(0); + +CREATE TABLE t1 ( + id INT NOT NULL DEFAULT 0, + last_id INT, + PRIMARY KEY (id) +); + +CREATE TABLE t2 ( + id INT NOT NULL AUTO_INCREMENT, + last_id INT, + PRIMARY KEY (id) +); + +delimiter |; +CREATE PROCEDURE p1() +BEGIN + INSERT INTO t2 (last_id) VALUES (LAST_INSERT_ID()); + INSERT INTO t1 (last_id) VALUES (LAST_INSERT_ID()); +END| +delimiter ;| + +CALL p1(); +SELECT * FROM t1; +SELECT * FROM t2; sync_slave_with_master; +SELECT * FROM t1; +SELECT * FROM t2; + +connection master; + +DROP PROCEDURE p1; +DROP TABLE t1, t2; + + +# +# BUG#21726: Incorrect result with multiple invocations of +# LAST_INSERT_ID +# +--disable_warnings +DROP PROCEDURE IF EXISTS p1; +DROP FUNCTION IF EXISTS f1; +DROP FUNCTION IF EXISTS f2; +DROP FUNCTION IF EXISTS f3; +DROP TABLE IF EXISTS t1, t2; +--enable_warnings + +CREATE TABLE t1 ( + i INT NOT NULL AUTO_INCREMENT PRIMARY KEY, + j INT DEFAULT 0 +); +CREATE TABLE t2 (i INT); + +delimiter |; +CREATE PROCEDURE p1() +BEGIN + INSERT INTO t1 (i) VALUES (NULL); + INSERT INTO t2 (i) VALUES (LAST_INSERT_ID()); + INSERT INTO t1 (i) VALUES (NULL), (NULL); + INSERT INTO t2 (i) VALUES (LAST_INSERT_ID()); +END | + +CREATE FUNCTION f1() RETURNS INT MODIFIES SQL DATA +BEGIN + INSERT INTO t1 (i) VALUES (NULL); + INSERT INTO t2 (i) VALUES (LAST_INSERT_ID()); + INSERT INTO t1 (i) VALUES (NULL), (NULL); + INSERT INTO t2 (i) VALUES (LAST_INSERT_ID()); + RETURN 0; +END | + +CREATE FUNCTION f2() RETURNS INT NOT DETERMINISTIC + RETURN LAST_INSERT_ID() | + +CREATE FUNCTION f3() RETURNS INT MODIFIES SQL DATA +BEGIN + INSERT INTO t2 (i) VALUES (LAST_INSERT_ID()); + RETURN 0; +END | +delimiter ;| + +INSERT INTO t1 VALUES (NULL, -1); +CALL p1(); +SELECT f1(); +INSERT INTO t1 VALUES (NULL, f2()), (NULL, LAST_INSERT_ID()), + (NULL, LAST_INSERT_ID()), (NULL, f2()), (NULL, f2()); +INSERT INTO t1 VALUES (NULL, f2()); +INSERT INTO t1 VALUES (NULL, LAST_INSERT_ID()), (NULL, LAST_INSERT_ID(5)), + (NULL, @@LAST_INSERT_ID); +# Test replication of substitution "IS NULL" -> "= LAST_INSERT_ID". +INSERT INTO t1 VALUES (NULL, 0), (NULL, LAST_INSERT_ID()); +UPDATE t1 SET j= -1 WHERE i IS NULL; + +# Test statement-based replication of function calls. +INSERT INTO t1 (i) VALUES (NULL); + +connection master1; +INSERT INTO t1 (i) VALUES (NULL); + +connection master; +SELECT f3(); + +SELECT * FROM t1; +SELECT * FROM t2; + +sync_slave_with_master; +SELECT * FROM t1; +SELECT * FROM t2; + +connection master; +DROP PROCEDURE p1; +DROP FUNCTION f1; +DROP FUNCTION f2; +DROP FUNCTION f3; +DROP TABLE t1, t2; + + +sync_slave_with_master; + +--echo +--echo # End of 5.0 tests +--echo + + diff --git a/mysql-test/t/rpl_max_relay_size.test b/mysql-test/t/rpl_max_relay_size.test index 9b6b06e0b14..be1fbf172fc 100644 --- a/mysql-test/t/rpl_max_relay_size.test +++ b/mysql-test/t/rpl_max_relay_size.test @@ -7,7 +7,11 @@ source include/master-slave.inc; connection slave; stop slave; connection master; -# Generate a big enough master's binlog to cause relay log rotations + +--echo # +--echo # Generate a big enough master's binlog to cause relay log rotations +--echo # + create table t1 (a int); let $1=800; disable_query_log; @@ -23,6 +27,11 @@ drop table t1; save_master_pos; connection slave; reset slave; + +--echo # +--echo # Test 1 +--echo # + set global max_binlog_size=8192; set global max_relay_log_size=8192-1; # mapped to 4096 select @@global.max_relay_log_size; @@ -30,7 +39,13 @@ start slave; sync_with_master; --replace_result $MASTER_MYPORT MASTER_PORT --replace_column 1 # 8 # 9 # 23 # 33 # +--vertical_results show slave status; + +--echo # +--echo # Test 2 +--echo # + stop slave; reset slave; set global max_relay_log_size=(5*4096); @@ -39,7 +54,13 @@ start slave; sync_with_master; --replace_result $MASTER_MYPORT MASTER_PORT --replace_column 1 # 8 # 9 # 23 # 33 # +--vertical_results show slave status; + +--echo # +--echo # Test 3: max_relay_log_size = 0 +--echo # + stop slave; reset slave; set global max_relay_log_size=0; @@ -48,9 +69,12 @@ start slave; sync_with_master; --replace_result $MASTER_MYPORT MASTER_PORT --replace_column 1 # 8 # 9 # 23 # 33 # +--vertical_results show slave status; -# Tests below are mainly to ensure that we have not coded with wrong assumptions +--echo # +--echo # Test 4: Tests below are mainly to ensure that we have not coded with wrong assumptions +--echo # stop slave; reset slave; @@ -59,8 +83,13 @@ reset slave; flush logs; --replace_result $MASTER_MYPORT MASTER_PORT --replace_column 1 # 8 # 9 # 23 # 33 # +--vertical_results show slave status; +--echo # +--echo # Test 5 +--echo # + reset slave; start slave; sync_with_master; @@ -75,8 +104,13 @@ connection slave; sync_with_master; --replace_result $MASTER_MYPORT MASTER_PORT --replace_column 1 # 8 # 9 # 23 # 33 # +--vertical_results show slave status; -# one more rotation, to be sure Relay_Log_Space is correctly updated + +--echo # +--echo # Test 6: one more rotation, to be sure Relay_Log_Space is correctly updated +--echo # + flush logs; connection master; drop table t1; @@ -85,6 +119,7 @@ connection slave; sync_with_master; --replace_result $MASTER_MYPORT MASTER_PORT --replace_column 1 # 8 # 9 # 23 # 33 # +--vertical_results show slave status; connection master; @@ -92,5 +127,6 @@ connection master; flush logs; show master status; -# End of 4.1 tests -# +--echo # +--echo # End of 4.1 tests +--echo # diff --git a/mysql-test/t/rpl_ndb_innodb_trans-slave.opt b/mysql-test/t/rpl_ndb_innodb_trans-slave.opt new file mode 100644 index 00000000000..627becdbfb5 --- /dev/null +++ b/mysql-test/t/rpl_ndb_innodb_trans-slave.opt @@ -0,0 +1 @@ +--innodb diff --git a/mysql-test/t/rpl_ndb_innodb_trans.test b/mysql-test/t/rpl_ndb_innodb_trans.test new file mode 100644 index 00000000000..127c2464570 --- /dev/null +++ b/mysql-test/t/rpl_ndb_innodb_trans.test @@ -0,0 +1,66 @@ +# Test of a transaction mixing the two engines + +-- source include/have_ndb.inc +-- source include/have_innodb.inc +-- source include/master-slave.inc + +create table t1 (a int, unique(a)) engine=ndbcluster; +create table t2 (a int, unique(a)) engine=innodb; + + +begin; +insert into t1 values(1); +insert into t2 values(1); +rollback; + +select count(*) from t1; +select count(*) from t2; +sync_slave_with_master; +select count(*) from t1; +select count(*) from t2; +connection master; + +begin; +load data infile '../std_data_ln/rpl_loaddata.dat' into table t2; +load data infile '../std_data_ln/rpl_loaddata.dat' into table t1; +rollback; + +select count(*) from t1; +select count(*) from t2; +sync_slave_with_master; +select count(*) from t1; +select count(*) from t2; +connection master; + +delete from t1; +delete from t2; +begin; +load data infile '../std_data_ln/rpl_loaddata.dat' into table t2; +load data infile '../std_data_ln/rpl_loaddata.dat' into table t1; +rollback; + +select count(*) from t1; +select count(*) from t2; +sync_slave_with_master; +select count(*) from t1; +select count(*) from t2; +connection master; + +delete from t1; +delete from t2; +begin; +insert into t2 values(3),(4); +insert into t1 values(3),(4); +load data infile '../std_data_ln/rpl_loaddata.dat' into table t2; +load data infile '../std_data_ln/rpl_loaddata.dat' into table t1; +rollback; + +select count(*) from t1; +select count(*) from t2; +sync_slave_with_master; +select count(*) from t1; +select count(*) from t2; +connection master; + +drop table t1,t2; +sync_slave_with_master; diff --git a/mysql-test/t/rpl_view.test b/mysql-test/t/rpl_view.test index d0990b4fbee..812e5d44d58 100644 --- a/mysql-test/t/rpl_view.test +++ b/mysql-test/t/rpl_view.test @@ -129,3 +129,24 @@ DROP TABLE t1; --sync_with_master --connection master +# +# BUG#19419: "VIEW: View that the column name is different +# by master and slave is made". +# +connection master; +create table t1(a int, b int); +insert into t1 values (1, 1), (1, 2), (1, 3); +create view v1(a, b) as select a, sum(b) from t1 group by a; + +sync_slave_with_master; +explain v1; +show create table v1; +select * from v1; + +connection master; +drop table t1; +drop view v1; + +sync_slave_with_master; + +--echo End of 5.0 tests diff --git a/mysql-test/t/sp.test b/mysql-test/t/sp.test index 4b0f463a9e3..87d19baf888 100644 --- a/mysql-test/t/sp.test +++ b/mysql-test/t/sp.test @@ -1,13 +1,9 @@ # # Basic stored PROCEDURE tests # -# Please keep this file free of --error cases and other -# things that will not run in a single debugged mysqld -# process (e.g. master-slave things). -# # Test cases for bugs are added at the end. See template there. # -# Tests that require --error go into sp-error.test +# Some tests that require --error go into sp-error.test # Tests that require inndb go into sp_trans.test # Tests that check privilege and security issues go to sp-security.test. # Tests that require multiple connections, except security/privilege tests, @@ -6322,6 +6318,111 @@ create procedure bug21416() show create procedure bug21416| call bug21416()| drop procedure bug21416| + +# +# BUG#21414: SP: Procedure undroppable, to some extent +# +--disable_warnings +DROP PROCEDURE IF EXISTS bug21414| +--enable_warnings + +CREATE PROCEDURE bug21414() SELECT 1| + +FLUSH TABLES WITH READ LOCK| + +--error ER_CANT_UPDATE_WITH_READLOCK +DROP PROCEDURE bug21414| + +UNLOCK TABLES| + +--echo The following should succeed. +DROP PROCEDURE bug21414| + + +# +# BUG#21311: Possible stack overrun if SP has non-latin1 name +# +set names utf8| +--disable_warnings +drop database if exists това_е_дълго_име_за_база_данни_нали| +--enable_warnings +create database това_е_дълго_име_за_база_данни_нали| +INSERT INTO mysql.proc VALUES ('това_е_дълго_име_за_база_данни_нали','това_е_процедура_Ñ_доÑта_дълго_име_нали_и_още_по_дълго','PROCEDURE','това_е_процедура_Ñ_доÑта_дълго_име_нали_и_още_по_дълго','SQL','CONTAINS_SQL','NO','DEFINER','','','bad_body','root@localhost',now(), now(),'','')| +--error ER_SP_PROC_TABLE_CORRUPT +call това_е_дълго_име_за_база_данни_нали.това_е_процедура_Ñ_доÑта_дълго_име_нали_и_още_по_дълго()| +drop database това_е_дълго_име_за_база_данни_нали| + + +# +# BUG#21493: Crash on the second call of a procedure containing +# a select statement that uses an IN aggregating subquery +# + +CREATE TABLE t3 ( + Member_ID varchar(15) NOT NULL, + PRIMARY KEY (Member_ID) +)| + +CREATE TABLE t4 ( + ID int(10) unsigned NOT NULL auto_increment, + Member_ID varchar(15) NOT NULL default '', + Action varchar(12) NOT NULL, + Action_Date datetime NOT NULL, + Track varchar(15) default NULL, + User varchar(12) default NULL, + Date_Updated timestamp NOT NULL default CURRENT_TIMESTAMP on update + CURRENT_TIMESTAMP, + PRIMARY KEY (ID), + KEY Action (Action), + KEY Action_Date (Action_Date) +)| + + +INSERT INTO t3(Member_ID) VALUES + ('111111'), ('222222'), ('333333'), ('444444'), ('555555'), ('666666')| + +INSERT INTO t4(Member_ID, Action, Action_Date, Track) VALUES + ('111111', 'Disenrolled', '2006-03-01', 'CAD' ), + ('111111', 'Enrolled', '2006-03-01', 'CAD' ), + ('111111', 'Disenrolled', '2006-07-03', 'CAD' ), + ('222222', 'Enrolled', '2006-03-07', 'CAD' ), + ('222222', 'Enrolled', '2006-03-07', 'CHF' ), + ('222222', 'Disenrolled', '2006-08-02', 'CHF' ), + ('333333', 'Enrolled', '2006-03-01', 'CAD' ), + ('333333', 'Disenrolled', '2006-03-01', 'CAD' ), + ('444444', 'Enrolled', '2006-03-01', 'CAD' ), + ('555555', 'Disenrolled', '2006-03-01', 'CAD' ), + ('555555', 'Enrolled', '2006-07-21', 'CAD' ), + ('555555', 'Disenrolled', '2006-03-01', 'CHF' ), + ('666666', 'Enrolled', '2006-02-09', 'CAD' ), + ('666666', 'Enrolled', '2006-05-12', 'CHF' ), + ('666666', 'Disenrolled', '2006-06-01', 'CAD' )| + +--disable_warnings +DROP FUNCTION IF EXISTS bug21493| +--enable_warnings + +CREATE FUNCTION bug21493(paramMember VARCHAR(15)) RETURNS varchar(45) +BEGIN +DECLARE tracks VARCHAR(45); +SELECT GROUP_CONCAT(Track SEPARATOR ', ') INTO tracks FROM t4 + WHERE Member_ID=paramMember AND Action='Enrolled' AND + (Track,Action_Date) IN (SELECT Track, MAX(Action_Date) FROM t4 + WHERE Member_ID=paramMember GROUP BY Track); +RETURN tracks; +END| + +SELECT bug21493('111111')| +SELECT bug21493('222222')| + +SELECT bug21493(Member_ID) FROM t3| + +DROP FUNCTION bug21493| +DROP TABLE t3,t4| + +--echo End of 5.0 tests + + # # BUG#NNNN: New bug synopsis # diff --git a/mysql-test/t/strict.test b/mysql-test/t/strict.test index 6f22b81172d..6ebbb53ed8e 100644 --- a/mysql-test/t/strict.test +++ b/mysql-test/t/strict.test @@ -649,9 +649,9 @@ UPDATE t1 SET col2 =col2 + 50 WHERE col2 > 0; UPDATE t1 SET col1 =col1 / 0 WHERE col1 > 0; --error 1365 UPDATE t1 SET col1= MOD(col1,0) WHERE col1 > 0; ---error 1264 +--error 1366 INSERT INTO t1 (col1) VALUES (''); ---error 1264 +--error 1366 INSERT INTO t1 (col1) VALUES ('a59b'); --error 1265 INSERT INTO t1 (col1) VALUES ('1a'); @@ -710,9 +710,9 @@ INSERT INTO t1 (col2) VALUES(18446744073709551616.0); UPDATE t1 SET col1 =col1 / 0 WHERE col1 > 0; --error 1365 UPDATE t1 SET col1= MOD(col1,0) WHERE col1 > 0; ---error 1264 +--error 1366 INSERT INTO t1 (col1) VALUES (''); ---error 1264 +--error 1366 INSERT INTO t1 (col1) VALUES ('a59b'); --error 1265 INSERT INTO t1 (col1) VALUES ('1a'); diff --git a/mysql-test/t/strict_autoinc_1myisam.test b/mysql-test/t/strict_autoinc_1myisam.test new file mode 100644 index 00000000000..d9ecce30974 --- /dev/null +++ b/mysql-test/t/strict_autoinc_1myisam.test @@ -0,0 +1,8 @@ +# +# Bug#20573 Strict mode auto-increment +# + +let $type= 'MYISAM' ; +--source include/strict_autoinc.inc + +# end of test diff --git a/mysql-test/t/strict_autoinc_2innodb.test b/mysql-test/t/strict_autoinc_2innodb.test new file mode 100644 index 00000000000..83dfe950938 --- /dev/null +++ b/mysql-test/t/strict_autoinc_2innodb.test @@ -0,0 +1,10 @@ +-- source include/have_innodb.inc + +# +# Bug#20573 Strict mode auto-increment +# + +let $type= 'InnoDB' ; +--source include/strict_autoinc.inc + +# end of test diff --git a/mysql-test/t/strict_autoinc_3heap.test b/mysql-test/t/strict_autoinc_3heap.test new file mode 100644 index 00000000000..f266ecdfda2 --- /dev/null +++ b/mysql-test/t/strict_autoinc_3heap.test @@ -0,0 +1,8 @@ +# +# Bug#20573 Strict mode auto-increment +# + +let $type= 'MEMORY' ; +--source include/strict_autoinc.inc + +# end of test diff --git a/mysql-test/t/strict_autoinc_4bdb.test b/mysql-test/t/strict_autoinc_4bdb.test new file mode 100644 index 00000000000..10d6bfd41e7 --- /dev/null +++ b/mysql-test/t/strict_autoinc_4bdb.test @@ -0,0 +1,10 @@ +-- source include/have_bdb.inc + +# +# Bug#20573 Strict mode auto-increment +# + +let $type= 'BDB' ; +--source include/strict_autoinc.inc + +# end of test diff --git a/mysql-test/t/strict_autoinc_5ndb.test b/mysql-test/t/strict_autoinc_5ndb.test new file mode 100644 index 00000000000..9e2090fddef --- /dev/null +++ b/mysql-test/t/strict_autoinc_5ndb.test @@ -0,0 +1,10 @@ +-- source include/have_ndb.inc + +# +# Bug#20573 Strict mode auto-increment +# + +let $type= 'NDB' ; +--source include/strict_autoinc.inc + +# end of test diff --git a/mysql-test/t/subselect.test b/mysql-test/t/subselect.test index ed122e9ff5a..7811301a9bc 100644 --- a/mysql-test/t/subselect.test +++ b/mysql-test/t/subselect.test @@ -665,7 +665,7 @@ CREATE TABLE t2 ( ) ENGINE=MyISAM; INSERT INTO t2 VALUES ('AUS','Australia','Oceania','Australia and New Zealand',7741220.00,1901,18886000,79.8,351182.00,392911.00,'Australia','Constitutional Monarchy, Federation','Elisabeth II',135,'AU'); -INSERT INTO t2 VALUES ('AZE','Azerbaijan','Asia','Middle East',86600.00,1991,7734000,62.9,4127.00,4100.00,'Azärbaycan','Federal Republic','Heydär Äliyev',144,'AZ'); +INSERT INTO t2 VALUES ('AZE','Azerbaijan','Asia','Middle East',86600.00,1991,7734000,62.9,4127.00,4100.00,'Azärbaycan','Federal Republic','Heydär Äliyev',144,'AZ'); select t2.Continent, t1.Name, t1.Population from t2 LEFT JOIN t1 ON t2.Code = t1.t2 where t1.Population IN (select max(t1.Population) AS Population from t1, t2 where t1.t2 = t2.Code group by Continent); @@ -1526,7 +1526,7 @@ CREATE TABLE t1 ( ) ENGINE=MyISAM; INSERT INTO t1 VALUES ('XXX','Xxxxx','Oceania','Xxxxxx',26.00,0,0,0,0,0,'Xxxxx','Xxxxx','Xxxxx',NULL,'XX'); INSERT INTO t1 VALUES ('ASM','American Samoa','Oceania','Polynesia',199.00,0,68000,75.1,334.00,NULL,'Amerika Samoa','US Territory','George W. Bush',54,'AS'); -INSERT INTO t1 VALUES ('ATF','French Southern territories','Antarctica','Antarctica',7780.00,0,0,NULL,0.00,NULL,'Terres australes françaises','Nonmetropolitan Territory of France','Jacques Chirac',NULL,'TF'); +INSERT INTO t1 VALUES ('ATF','French Southern territories','Antarctica','Antarctica',7780.00,0,0,NULL,0.00,NULL,'Terres australes françaises','Nonmetropolitan Territory of France','Jacques Chirac',NULL,'TF'); INSERT INTO t1 VALUES ('UMI','United States Minor Outlying Islands','Oceania','Micronesia/Caribbean',16.00,0,0,NULL,0.00,NULL,'United States Minor Outlying Islands','Dependent Territory of the US','George W. Bush',NULL,'UM'); /*!40000 ALTER TABLE t1 ENABLE KEYS */; SELECT DISTINCT Continent AS c FROM t1 WHERE Code <> SOME ( SELECT Code FROM t1 WHERE Continent = c AND Population < 200); @@ -1892,6 +1892,69 @@ select * from t1 r1 group by r2.retailerId); drop table t1; +# +# Bug #21180: Subselect with index for both WHERE and ORDER BY +# produces empty result +# +create table t1(a int, primary key (a)); +insert into t1 values (10); + +create table t2 (a int primary key, b varchar(32), c int, unique key b(c, b)); +insert into t2(a, c, b) values (1,10,'359'), (2,10,'35988'), (3,10,'35989'); + +explain SELECT sql_no_cache t1.a, r.a, r.b FROM t1 LEFT JOIN t2 r + ON r.a = (SELECT t2.a FROM t2 WHERE t2.c = t1.a AND t2.b <= '359899' + ORDER BY t2.c DESC, t2.b DESC LIMIT 1) WHERE t1.a = 10; +SELECT sql_no_cache t1.a, r.a, r.b FROM t1 LEFT JOIN t2 r + ON r.a = (SELECT t2.a FROM t2 WHERE t2.c = t1.a AND t2.b <= '359899' + ORDER BY t2.c DESC, t2.b DESC LIMIT 1) WHERE t1.a = 10; + +explain SELECT sql_no_cache t1.a, r.a, r.b FROM t1 LEFT JOIN t2 r + ON r.a = (SELECT t2.a FROM t2 WHERE t2.c = t1.a AND t2.b <= '359899' + ORDER BY t2.c, t2.b LIMIT 1) WHERE t1.a = 10; +SELECT sql_no_cache t1.a, r.a, r.b FROM t1 LEFT JOIN t2 r + ON r.a = (SELECT t2.a FROM t2 WHERE t2.c = t1.a AND t2.b <= '359899' + ORDER BY t2.c, t2.b LIMIT 1) WHERE t1.a = 10; + +drop table t1,t2; + +# +# Bug #21853: assert failure for a grouping query with +# an ALL/ANY quantified subquery in HAVING +# + +CREATE TABLE t1 ( + field1 int NOT NULL, + field2 int NOT NULL, + field3 int NOT NULL, + PRIMARY KEY (field1,field2,field3) +); +CREATE TABLE t2 ( + fieldA int NOT NULL, + fieldB int NOT NULL, + PRIMARY KEY (fieldA,fieldB) +); + +INSERT INTO t1 VALUES + (1,1,1), (1,1,2), (1,2,1), (1,2,2), (1,2,3), (1,3,1); +INSERT INTO t2 VALUES (1,1), (1,2), (1,3); + +SELECT field1, field2, COUNT(*) + FROM t1 GROUP BY field1, field2; + +SELECT field1, field2 + FROM t1 + GROUP BY field1, field2 + HAVING COUNT(*) >= ALL (SELECT fieldB + FROM t2 WHERE fieldA = field1); +SELECT field1, field2 + FROM t1 + GROUP BY field1, field2 + HAVING COUNT(*) < ANY (SELECT fieldB + FROM t2 WHERE fieldA = field1); + +DROP TABLE t1, t2; + # End of 4.1 tests # @@ -2280,3 +2343,60 @@ SELECT * FROM t1,t2 ORDER BY t1.t DESC LIMIT 1); DROP TABLE t1, t2; + +# +# Bug#14654 : Cannot select from the same table twice within a UNION +# statement +# +CREATE TABLE t1 (i INT); + +(SELECT i FROM t1) UNION (SELECT i FROM t1); +SELECT sql_no_cache * FROM t1 WHERE NOT EXISTS + ( + (SELECT i FROM t1) UNION + (SELECT i FROM t1) + ); + +SELECT * FROM t1 +WHERE NOT EXISTS (((SELECT i FROM t1) UNION (SELECT i FROM t1))); + +#TODO:not supported +--error 1064 +explain select ((select t11.i from t1 t11) union (select t12.i from t1 t12)) + from t1; +#supported +explain select * from t1 where not exists + ((select t11.i from t1 t11) union (select t12.i from t1 t12)); + +DROP TABLE t1; + +# +# Bug #21540: Subqueries with no from and aggregate functions return +# wrong results +CREATE TABLE t1 (a INT, b INT); +CREATE TABLE t2 (a INT); +INSERT INTO t2 values (1); +INSERT INTO t1 VALUES (1,1),(1,2),(2,3),(3,4); +SELECT (SELECT COUNT(DISTINCT t1.b) from t2) FROM t1 GROUP BY t1.a; +SELECT (SELECT COUNT(DISTINCT t1.b) from t2 union select 1 from t2 where 12 < 3) + FROM t1 GROUP BY t1.a; +SELECT COUNT(DISTINCT t1.b), (SELECT COUNT(DISTINCT t1.b)) FROM t1 GROUP BY t1.a; +SELECT COUNT(DISTINCT t1.b), + (SELECT COUNT(DISTINCT t1.b) union select 1 from DUAL where 12 < 3) + FROM t1 GROUP BY t1.a; +SELECT ( + SELECT ( + SELECT COUNT(DISTINCT t1.b) + ) +) +FROM t1 GROUP BY t1.a; +SELECT ( + SELECT ( + SELECT ( + SELECT COUNT(DISTINCT t1.b) + ) + ) + FROM t1 GROUP BY t1.a LIMIT 1) +FROM t1 t2 +GROUP BY t2.a; +DROP TABLE t1,t2; diff --git a/mysql-test/t/temp_table.test b/mysql-test/t/temp_table.test index 3920b305b78..8cb9e34ca08 100644 --- a/mysql-test/t/temp_table.test +++ b/mysql-test/t/temp_table.test @@ -116,4 +116,50 @@ insert into t2 values (NULL, 'foo'), (NULL, 'bar'); select d, c from t1 left join t2 on b = c where a = 3 order by d; drop table t1, t2; -# End of 4.1 tests + +# +# BUG#21096: locking issue ; temporary table conflicts. +# +# The problem was that on DROP TEMPORARY table name lock was acquired, +# which should not be done. +# +--disable_warnings +DROP TABLE IF EXISTS t1; +--enable_warnings + +CREATE TABLE t1 (i INT); + +LOCK TABLE t1 WRITE; + +connect (conn1, localhost, root,,); + +CREATE TEMPORARY TABLE t1 (i INT); + +--echo The following command should not block +DROP TEMPORARY TABLE t1; + +disconnect conn1; +connection default; + +DROP TABLE t1; + +# +# Check that it's not possible to drop a base table with +# DROP TEMPORARY statement. +# +CREATE TABLE t1 (i INT); +CREATE TEMPORARY TABLE t2 (i INT); + +--error 1051 +DROP TEMPORARY TABLE t2, t1; + +# Table t2 should have been dropped. +--error 1146 +SELECT * FROM t2; +# But table t1 should still be there. +SELECT * FROM t1; + +DROP TABLE t1; + + +--echo End of 4.1 tests. diff --git a/mysql-test/t/trigger.test b/mysql-test/t/trigger.test index 2a145e1eeaa..6bd812d473e 100644 --- a/mysql-test/t/trigger.test +++ b/mysql-test/t/trigger.test @@ -1421,4 +1421,23 @@ DROP TABLE t1; DROP TABLE t2; +# +# Bug#20670 "UPDATE using key and invoking trigger that modifies +# this key does not stop" +# + +--disable_warnings +drop table if exists t1; +--enable_warnings +create table t1 (i int, j int key); +insert into t1 values (1,1), (2,2), (3,3); +create trigger t1_bu before update on t1 for each row + set new.j = new.j + 10; +# This should not work indefinitely and should cause +# expected result +update t1 set i= i+ 10 where j > 2; +select * from t1; +drop table t1; + + --echo End of 5.0 tests diff --git a/mysql-test/t/type_bit.test b/mysql-test/t/type_bit.test index e028dbc51d9..d46ba667665 100644 --- a/mysql-test/t/type_bit.test +++ b/mysql-test/t/type_bit.test @@ -238,4 +238,27 @@ select * from t1; --disable_metadata drop table t1; +# +# Bug#15583: BIN()/OCT()/CONV() do not work with BIT values +# +create table bug15583(b BIT(8), n INT); +insert into bug15583 values(128, 128); +insert into bug15583 values(null, null); +insert into bug15583 values(0, 0); +insert into bug15583 values(255, 255); +select hex(b), bin(b), oct(b), hex(n), bin(n), oct(n) from bug15583; +select hex(b)=hex(n) as should_be_onetrue, bin(b)=bin(n) as should_be_onetrue, oct(b)=oct(n) as should_be_onetrue from bug15583; +select hex(b + 0), bin(b + 0), oct(b + 0), hex(n), bin(n), oct(n) from bug15583; +select conv(b, 10, 2), conv(b + 0, 10, 2) from bug15583; +drop table bug15583; + +# +# Bug #22271: data casting may affect data stored in the next column(s?) +# + +create table t1(a bit(1), b smallint unsigned); +insert into t1 (b, a) values ('2', '1'); +select hex(a), b from t1; +drop table t1; + --echo End of 5.0 tests diff --git a/mysql-test/t/type_date.test b/mysql-test/t/type_date.test index 78bdd9b8a80..c6050753943 100644 --- a/mysql-test/t/type_date.test +++ b/mysql-test/t/type_date.test @@ -36,8 +36,8 @@ INSERT INTO t1 VALUES ( "2000-1-2" ); INSERT INTO t1 VALUES ( "2000-1-3" ); INSERT INTO t1 VALUES ( "2000-1-4" ); INSERT INTO t1 VALUES ( "2000-1-5" ); -SELECT * FROM t1 WHERE datum BETWEEN "2000-1-2" AND "2000-1-4"; -SELECT * FROM t1 WHERE datum BETWEEN "2000-1-2" AND datum - INTERVAL 100 DAY; +SELECT * FROM t1 WHERE datum BETWEEN cast("2000-1-2" as date) AND cast("2000-1-4" as date); +SELECT * FROM t1 WHERE datum BETWEEN cast("2000-1-2" as date) AND datum - INTERVAL 100 DAY; DROP TABLE t1; # @@ -115,4 +115,11 @@ INSERT INTO t1 VALUES ('abc'); SELECT * FROM t1; DROP TABLE t1; +# +# Bug#21677: Wrong result when comparing a DATE and a DATETIME in BETWEEN +# +create table t1(start_date date, end_date date); +insert into t1 values ('2000-01-01','2000-01-02'); +select 1 from t1 where cast('2000-01-01 12:01:01' as datetime) between start_date and end_date; +drop table t1; # End of 4.1 tests diff --git a/mysql-test/t/type_float.test b/mysql-test/t/type_float.test index 5bfd744e4a8..965826629bd 100644 --- a/mysql-test/t/type_float.test +++ b/mysql-test/t/type_float.test @@ -178,7 +178,16 @@ show warnings; desc t3; drop table t1,t2,t3; -# End of 4.1 tests +# +# Bug #22129: A small double precision number becomes zero +# +# check if underflows are detected correctly +select 1e-308, 1.00000001e-300, 100000000e-300; + +# check if overflows are detected correctly +select 10e307; + +--echo End of 4.1 tests # # bug #12694 (float(m,d) specifications) diff --git a/mysql-test/t/user_var.test b/mysql-test/t/user_var.test index b2a9728de00..644ca506eba 100644 --- a/mysql-test/t/user_var.test +++ b/mysql-test/t/user_var.test @@ -144,9 +144,6 @@ select @@version; --replace_column 1 # select @@global.version; -# End of 4.1 tests - -# # Bug #6598: problem with cast(NULL as signed integer); # @@ -212,3 +209,5 @@ insert into t1 values (1,2),(2,3),(3,1); select @var:=f2 from t1 group by f1 order by f2 desc limit 1; select @var; drop table t1; + +# End of 4.1 tests diff --git a/mysql-test/t/view.test b/mysql-test/t/view.test index edff38274c4..b631d2032c4 100644 --- a/mysql-test/t/view.test +++ b/mysql-test/t/view.test @@ -347,13 +347,13 @@ create view v3 (x,y,z) as select b, a, b from t1; create view v4 (x,y,z) as select c+1, b, a from t1; create algorithm=temptable view v5 (x,y,z) as select c, b, a from t1; # try insert to VIEW with fields duplicate --- error 1288 +-- error 1471 insert into v3 values (-60,4,30); # try insert to VIEW with expression in SELECT list --- error 1288 +-- error 1471 insert into v4 values (-60,4,30); # try insert to VIEW using temporary table algorithm --- error 1288 +-- error 1471 insert into v5 values (-60,4,30); insert into v1 values (-60,4,30); insert into v1 (z,y,x) values (50,6,-100); @@ -375,13 +375,13 @@ create view v3 (x,y,z) as select b, a, b from t1; create view v4 (x,y,z) as select c+1, b, a from t1; create algorithm=temptable view v5 (x,y,z) as select c, b, a from t1; # try insert to VIEW with fields duplicate --- error 1288 +-- error 1471 insert into v3 select c, b, a from t2; # try insert to VIEW with expression in SELECT list --- error 1288 +-- error 1471 insert into v4 select c, b, a from t2; # try insert to VIEW using temporary table algorithm --- error 1288 +-- error 1471 insert into v5 select c, b, a from t2; insert into v1 select c, b, a from t2; insert into v1 (z,y,x) select a+20,b+2,-100 from t2; @@ -1249,14 +1249,14 @@ drop table t1; # create table t1 (s1 smallint); create view v1 as select * from t1 where 20 < (select (s1) from t1); --- error 1288 +-- error 1471 insert into v1 values (30); create view v2 as select * from t1; create view v3 as select * from t1 where 20 < (select (s1) from v2); --- error 1288 +-- error 1471 insert into v3 values (30); create view v4 as select * from v2 where 20 < (select (s1) from t1); --- error 1288 +-- error 1471 insert into v4 values (30); drop view v4, v3, v2, v1; drop table t1; @@ -2449,8 +2449,8 @@ INSERT INTO t1 VALUES CREATE VIEW v1 AS SELECT * FROM t1; -SELECT * FROM t1 WHERE td BETWEEN '2005.01.02' AND '2005.01.04'; -SELECT * FROM v1 WHERE td BETWEEN '2005.01.02' AND '2005.01.04'; +SELECT * FROM t1 WHERE td BETWEEN CAST('2005.01.02' AS DATE) AND CAST('2005.01.04' AS DATE); +SELECT * FROM v1 WHERE td BETWEEN CAST('2005.01.02' AS DATE) AND CAST('2005.01.04' AS DATE); DROP VIEW v1; DROP TABLE t1; @@ -2825,7 +2825,7 @@ BEGIN END | delimiter ;| ---error ER_NON_UPDATABLE_TABLE +--error ER_NON_INSERTABLE_TABLE SELECT f2(); DROP FUNCTION f1; @@ -2833,5 +2833,50 @@ DROP FUNCTION f2; DROP VIEW v1, v2; DROP TABLE t1; +# +# Bug #5500: wrong select_type in EXPLAIN output for queries over views +# +CREATE TABLE t1 (s1 int); +CREATE VIEW v1 AS SELECT * FROM t1; + +EXPLAIN SELECT * FROM t1; +EXPLAIN SELECT * FROM v1; + +INSERT INTO t1 VALUES (1), (3), (2); + +EXPLAIN SELECT * FROM t1 t WHERE t.s1+1 < (SELECT MAX(t1.s1) FROM t1); +EXPLAIN SELECT * FROM v1 t WHERE t.s1+1 < (SELECT MAX(t1.s1) FROM t1); + +DROP VIEW v1; +DROP TABLE t1; + +# +# Bug #5505: Wrong error message on INSERT into a view +# +create table t1 (s1 int); +create view v1 as select s1 as a, s1 as b from t1; +--error 1471 +insert into v1 values (1,1); +update v1 set a = 5; +drop view v1; +drop table t1; + +# +# Bug #21646: view qith a subquery in ON expression +# + +CREATE TABLE t1(pk int PRIMARY KEY); +CREATE TABLE t2(pk int PRIMARY KEY, fk int, ver int, org int); + +CREATE ALGORITHM=MERGE VIEW v1 AS +SELECT t1.* + FROM t1 JOIN t2 + ON t2.fk = t1.pk AND + t2.ver = (SELECT MAX(t.ver) FROM t2 t WHERE t.org = t2.org); +SHOW WARNINGS; +SHOW CREATE VIEW v1; + +DROP VIEW v1; +DROP TABLE t1, t2; --echo End of 5.0 tests. diff --git a/mysql-test/t/warnings.test b/mysql-test/t/warnings.test index 4768c7574e5..5e9d25aa09b 100644 --- a/mysql-test/t/warnings.test +++ b/mysql-test/t/warnings.test @@ -156,4 +156,60 @@ select * from t1 limit 1, 0; select * from t1 limit 0, 0; drop table t1; -# End of 4.1 tests +--echo End of 4.1 tests + +# +# Bug#20778: strange characters in warning message 1366 when called in SP +# + +let $engine_type= innodb; + +CREATE TABLE t1( f1 CHAR(20) ); +CREATE TABLE t2( f1 CHAR(20), f2 CHAR(25) ); +CREATE TABLE t3( f1 CHAR(20), f2 CHAR(25), f3 DATE ); + +INSERT INTO t1 VALUES ( 'a`' ); +INSERT INTO t2 VALUES ( 'a`', 'a`' ); +INSERT INTO t3 VALUES ( 'a`', 'a`', '1000-01-1' ); + +DROP PROCEDURE IF EXISTS sp1; +DROP PROCEDURE IF EXISTS sp2; +DROP PROCEDURE IF EXISTS sp3; +delimiter //; +CREATE PROCEDURE sp1() +BEGIN + DECLARE x NUMERIC ZEROFILL; + SELECT f1 INTO x FROM t1 LIMIT 1; +END// +CREATE PROCEDURE sp2() +BEGIN + DECLARE x NUMERIC ZEROFILL; + SELECT f1 INTO x FROM t2 LIMIT 1; +END// +CREATE PROCEDURE sp3() +BEGIN + DECLARE x NUMERIC ZEROFILL; + SELECT f1 INTO x FROM t3 LIMIT 1; +END// +delimiter ;// +CALL sp1(); +CALL sp2(); +CALL sp3(); + +DROP PROCEDURE IF EXISTS sp1; +delimiter //; +CREATE PROCEDURE sp1() +BEGIN +declare x numeric unsigned zerofill; +SELECT f1 into x from t2 limit 1; +END// +delimiter ;// +CALL sp1(); +DROP TABLE t1; +DROP TABLE t2; +DROP TABLE t3; +DROP PROCEDURE sp1; +DROP PROCEDURE sp2; +DROP PROCEDURE sp3; + +--echo End of 5.0 tests diff --git a/mysql-test/valgrind.supp b/mysql-test/valgrind.supp index 24426727968..f7eb9baa4c7 100644 --- a/mysql-test/valgrind.supp +++ b/mysql-test/valgrind.supp @@ -14,6 +14,14 @@ fun:pthread_create* } +{ + pthread allocate_tls memory loss + Memcheck:Leak + fun:calloc + fun:_dl_allocate_tls + fun:pthread_create* +} + { pthread allocate_dtv memory loss Memcheck:Leak @@ -114,6 +122,24 @@ fun:compress2 } +{ + libz longest_match 3 + Memcheck:Cond + fun:longest_match + fun:deflate_slow + fun:deflate + fun:gzclose +} + +{ + libz longest_match 4 + Memcheck:Cond + fun:longest_match + fun:deflate_slow + fun:deflate + fun:gzflush +} + { libz deflate Memcheck:Cond @@ -133,6 +159,7 @@ fun:gzflush } + # # Warning from my_thread_init becasue mysqld dies before kill thread exists # diff --git a/mysys/my_chsize.c b/mysys/my_chsize.c index 9760de29a08..fe0d0ffa607 100644 --- a/mysys/my_chsize.c +++ b/mysys/my_chsize.c @@ -46,7 +46,9 @@ int my_chsize(File fd, my_off_t newlength, int filler, myf MyFlags) DBUG_PRINT("my",("fd: %d length: %lu MyFlags: %d",fd,(ulong) newlength, MyFlags)); - oldsize = my_seek(fd, 0L, MY_SEEK_END, MYF(MY_WME+MY_FAE)); + if ((oldsize = my_seek(fd, 0L, MY_SEEK_END, MYF(MY_WME+MY_FAE))) == newlength) + DBUG_RETURN(0); + DBUG_PRINT("info",("old_size: %ld", (ulong) oldsize)); if (oldsize > newlength) diff --git a/mysys/my_libwrap.c b/mysys/my_libwrap.c index be8adbab0a1..80fca127716 100644 --- a/mysys/my_libwrap.c +++ b/mysys/my_libwrap.c @@ -31,12 +31,12 @@ void my_fromhost(struct request_info *req) int my_hosts_access(struct request_info *req) { - hosts_access(req); + return hosts_access(req); } char *my_eval_client(struct request_info *req) { - eval_client(req); + return eval_client(req); } #endif /* HAVE_LIBWRAP */ diff --git a/mysys/queues.c b/mysys/queues.c index ecf1058af41..6a285ce7417 100644 --- a/mysys/queues.c +++ b/mysys/queues.c @@ -164,28 +164,22 @@ void delete_queue(QUEUE *queue) void queue_insert(register QUEUE *queue, byte *element) { - reg2 uint idx,next; + reg2 uint idx, next; int cmp; - -#ifndef DBUG_OFF - if (queue->elements < queue->max_elements) -#endif + DBUG_ASSERT(queue->elements < queue->max_elements); + queue->root[0]= element; + idx= ++queue->elements; + /* max_at_top swaps the comparison if we want to order by desc */ + while ((cmp= queue->compare(queue->first_cmp_arg, + element + queue->offset_to_key, + queue->root[(next= idx >> 1)] + + queue->offset_to_key)) && + (cmp ^ queue->max_at_top) < 0) { - queue->root[0]=element; - idx= ++queue->elements; - - /* max_at_top swaps the comparison if we want to order by desc */ - while ((cmp=queue->compare(queue->first_cmp_arg, - element+queue->offset_to_key, - queue->root[(next=idx >> 1)] + - queue->offset_to_key)) && - (cmp ^ queue->max_at_top) < 0) - { - queue->root[idx]=queue->root[next]; - idx=next; - } - queue->root[idx]=element; + queue->root[idx]= queue->root[next]; + idx= next; } + queue->root[idx]= element; } /* Remove item from queue */ @@ -193,16 +187,12 @@ void queue_insert(register QUEUE *queue, byte *element) byte *queue_remove(register QUEUE *queue, uint idx) { -#ifndef DBUG_OFF - if (idx >= queue->max_elements) - return 0; -#endif - { - byte *element=queue->root[++idx]; /* Intern index starts from 1 */ - queue->root[idx]=queue->root[queue->elements--]; - _downheap(queue,idx); - return element; - } + byte *element; + DBUG_ASSERT(idx < queue->max_elements); + element= queue->root[++idx]; /* Intern index starts from 1 */ + queue->root[idx]= queue->root[queue->elements--]; + _downheap(queue, idx); + return element; } /* Fix when element on top has been replaced */ diff --git a/ndb/include/ndb_global.h.in b/ndb/include/ndb_global.h.in index 43f90e1f8b5..122b0edc400 100644 --- a/ndb/include/ndb_global.h.in +++ b/ndb/include/ndb_global.h.in @@ -128,12 +128,8 @@ extern "C" { #include "ndb_init.h" -#ifdef SCO - #ifndef PATH_MAX #define PATH_MAX 1024 #endif -#endif /* SCO */ - #endif diff --git a/netware/BUILD/mwccnlm b/netware/BUILD/mwccnlm index e6840e781f8..030d87288f2 100755 --- a/netware/BUILD/mwccnlm +++ b/netware/BUILD/mwccnlm @@ -3,9 +3,12 @@ # stop on errors set -e -# mwccnlm is having a hard time understanding "-I./../include" -# convert it to "-I../include" -args=" "`echo $* | sed -e 's/-I.\/../-I../g'` +# mwccnlm is having a hard time understanding: +# * "-I./../include", convert it to "-I../include" +# * "-I.../..", convert it to "-I../../" +args=" "`echo $* | sed \ +-e 's/-I.\/../-I../g' \ +-e 's/\(-I[.\/]*.\) /\1\/ /g'` # NOTE: Option 'pipefail' is not standard sh set -o pipefail diff --git a/netware/BUILD/mwenv b/netware/BUILD/mwenv index fa52568fcd6..d8d53293b2c 100755 --- a/netware/BUILD/mwenv +++ b/netware/BUILD/mwenv @@ -1,19 +1,39 @@ #! /bin/sh -# F:/mydev, /home/kp/mydev, and 4.0.21 must be correct before compiling -# This values are normally changed by the nwbootstrap script +if test ! -r ./sql/mysqld.cc +then + echo "you must start from the top source directory" + exit 1 +fi -# the default is "F:/mydev" -export MYDEV="F:/mydev" +# The base path(in wineformat) where compilers, includes and +# libraries are installed +if test -z $MYDEV +then + # the default is "F:/mydev" + export MYDEV="F:/mydev" +fi +echo "MYDEV: $MYDEV" -export MWCNWx86Includes="$MYDEV/libc/include;$MYDEV/fs64/headers;$MYDEV/zlib-1.1.4;$MYDEV/mysql-VERSION/include;$MYDEV" -export MWNWx86Libraries="$MYDEV/libc/imports;$MYDEV/mw/lib;$MYDEV/fs64/imports;$MYDEV/zlib-1.1.4;$MYDEV/openssl;$MYDEV/mysql-VERSION/netware/BUILD" +# Get current dir +BUILD_DIR=`pwd` +echo "BUILD_DIR: $BUILD_DIR" + +# Get current dir in wine format +base=`echo $MYDEV |sed 's/\/.*//'` +base_unix_part=`winepath -- -u $base/` +WINE_BUILD_DIR=`echo "$BUILD_DIR" | sed 's_'$base_unix_part'/__'` +WINE_BUILD_DIR="$base/$WINE_BUILD_DIR" +echo "WINE_BUILD_DIR: $WINE_BUILD_DIR" + +export MWCNWx86Includes="$MYDEV/libc/include;$MYDEV/fs64/headers;$MYDEV/zlib-1.2.3;$WINE_BUILD_DIR/include;$MYDEV" +export MWNWx86Libraries="$MYDEV/libc/imports;$MYDEV/mw/lib;$MYDEV/fs64/imports;$MYDEV/zlib-1.2.3;$MYDEV/openssl;$WINE_BUILD_DIR/netware/BUILD" export MWNWx86LibraryFiles="libcpre.o;libc.imp;netware.imp;mwcrtl.lib;mwcpp.lib;libz.a;neb.imp;zPublics.imp;knetware.imp" export WINEPATH="$MYDEV/mw/bin" -# the default added path is "$HOME/mydev/mysql-x.x-x/netware/BUILD" -export PATH="$PATH:BUILD_DIR/mysql-VERSION/netware/BUILD" +# the default added path is "$BUILD_DIR/netware/BUILD" +export PATH="$PATH:$BUILD_DIR/netware/BUILD" export AR='mwldnlm' export AR_FLAGS='-type library -o' diff --git a/netware/Makefile.am b/netware/Makefile.am index 2d34283c4b3..648ce79c484 100644 --- a/netware/Makefile.am +++ b/netware/Makefile.am @@ -23,7 +23,8 @@ mysqld_safe_SOURCES= mysqld_safe.c my_manage.c mysql_install_db_SOURCES= mysql_install_db.c my_manage.c mysql_test_run_SOURCES= mysql_test_run.c my_manage.c libmysql_SOURCES= libmysqlmain.c -libmysql_LDADD = ../libmysql/.libs/libmysqlclient.a @openssl_libs@ +libmysql_LDADD = ../libmysql/.libs/libmysqlclient.a \ + @openssl_libs@ @yassl_libs@ netware_build_files = client/mysql.def client/mysqladmin.def \ client/mysqlbinlog.def client/mysqlcheck.def \ @@ -45,8 +46,20 @@ link_sources: @LN_CP_F@ $(srcdir)/$$org ../$$f; \ done else -EXTRA_DIST= comp_err.def init_db.sql install_test_db.ncf \ - libmysql.def libmysql.imp \ + +BUILT_SOURCES = libmysql.imp +DISTCLEANFILES = $(BUILT_SOURCES) + +# Create the libmysql.imp from libmysql/libmysql.def +libmysql.imp: $(top_srcdir)/libmysql/libmysql.def + awk 'BEGIN{x=0;} \ + END{printf("\n");} \ + x==1 {printf(" %s",$$1); x++; next} \ + x>1 {printf(",\n %s", $$1); next} \ + /EXPORTS/{x=1}' $(top_srcdir)/libmysql/libmysql.def > libmysql.imp + +EXTRA_DIST= $(BUILT_SOURCES) comp_err.def init_db.sql install_test_db.ncf \ + libmysql.def \ libmysqlmain.c my_manage.c my_manage.h \ my_print_defaults.def myisam_ftdump.def myisamchk.def \ myisamlog.def myisampack.def mysql.def mysql.xdc \ diff --git a/netware/libmysql.imp b/netware/libmysql.imp deleted file mode 100644 index 977fb1b0b1f..00000000000 --- a/netware/libmysql.imp +++ /dev/null @@ -1,85 +0,0 @@ -myodbc_remove_escape, -mysql_add_slave, -mysql_affected_rows, -mysql_change_user, -mysql_character_set_name, -mysql_close, -mysql_data_seek, -mysql_debug, -mysql_disable_reads_from_master, -mysql_disable_rpl_parse, -mysql_dump_debug_info, -mysql_enable_reads_from_master, -mysql_enable_rpl_parse, -mysql_eof, -mysql_errno, -mysql_error, -mysql_escape_string, -mysql_fetch_field, -mysql_fetch_field_direct, -mysql_fetch_fields, -mysql_fetch_lengths, -mysql_fetch_row, -mysql_field_count, -mysql_field_seek, -mysql_field_tell, -mysql_free_result, -mysql_get_client_info, -mysql_get_host_info, -mysql_get_proto_info, -mysql_get_server_info, -mysql_info, -mysql_init, -mysql_insert_id, -mysql_kill, -mysql_list_dbs, -mysql_list_fields, -mysql_list_processes, -mysql_list_tables, -mysql_manager_close, -mysql_manager_command, -mysql_manager_connect, -mysql_manager_fetch_line, -mysql_manager_init, -mysql_master_query, -mysql_master_send_query, -mysql_num_fields, -mysql_num_rows, -mysql_odbc_escape_string, -mysql_options, -mysql_ping, -mysql_query, -mysql_read_query_result, -mysql_reads_from_master_enabled, -mysql_real_connect, -mysql_real_escape_string, -mysql_real_query, -mysql_refresh, -mysql_row_seek, -mysql_row_tell, -mysql_rpl_parse_enabled, -mysql_rpl_probe, -mysql_rpl_query_type, -mysql_select_db, -mysql_send_query, -mysql_server_end, -mysql_server_init, -mysql_set_master, -mysql_shutdown, -mysql_slave_query, -mysql_slave_send_query, -mysql_ssl_set, -mysql_stat, -mysql_store_result, -mysql_thread_end, -mysql_thread_id, -mysql_thread_init, -mysql_thread_safe, -mysql_use_result, -net_safe_read, -#simple_command, -mysql_connect, -mysql_create_db, -mysql_drop_db, - - diff --git a/scripts/mysql_config.sh b/scripts/mysql_config.sh index 84ff518c381..92201a2c8af 100644 --- a/scripts/mysql_config.sh +++ b/scripts/mysql_config.sh @@ -97,11 +97,11 @@ port='@MYSQL_TCP_PORT@' ldflags='@LDFLAGS@' # Create options -# We intentionally add a space to the beginning of lib strings, simplifies replace later +# We intentionally add a space to the beginning and end of lib strings, simplifies replace later libs=" $ldflags -L$pkglibdir -lmysqlclient @ZLIB_DEPS@ @NON_THREADED_LIBS@" -libs="$libs @openssl_libs@ @STATIC_NSS_FLAGS@" -libs_r=" $ldflags -L$pkglibdir -lmysqlclient_r @ZLIB_DEPS@ @LIBS@ @openssl_libs@" -embedded_libs=" $ldflags -L$pkglibdir -lmysqld @ZLIB_DEPS@ @LIBS@ @WRAPLIBS@ @innodb_system_libs@" +libs="$libs @openssl_libs@ @STATIC_NSS_FLAGS@ " +libs_r=" $ldflags -L$pkglibdir -lmysqlclient_r @ZLIB_DEPS@ @LIBS@ @openssl_libs@ " +embedded_libs=" $ldflags -L$pkglibdir -lmysqld @ZLIB_DEPS@ @LIBS@ @WRAPLIBS@ @innodb_system_libs@ @openssl_libs@ " cflags="-I$pkgincludedir @CFLAGS@ " #note: end space! include="-I$pkgincludedir" @@ -111,8 +111,9 @@ include="-I$pkgincludedir" # and -xstrconst to make --cflags usable for Sun Forte C++ for remove in DDBUG_OFF DSAFEMALLOC USAFEMALLOC DSAFE_MUTEX \ DPEDANTIC_SAFEMALLOC DUNIV_MUST_NOT_INLINE DFORCE_INIT_OF_VARS \ - DEXTRA_DEBUG DHAVE_purify 'O[0-9]' 'W[-A-Za-z]*' \ - Xa xstrconst "xc99=none" + DEXTRA_DEBUG DHAVE_purify O 'O[0-9]' 'xO[0-9]' 'W[-A-Za-z]*' \ + Xa xstrconst "xc99=none" \ + unroll2 ip mp restrict do # The first option we might strip will always have a space before it because # we set -I$pkgincludedir as the first option @@ -121,7 +122,7 @@ done cflags=`echo "$cflags"|sed -e 's/ *\$//'` # Same for --libs(_r) -for remove in lmtmalloc +for remove in lmtmalloc static-libcxa i-static do # We know the strings starts with a space libs=`echo "$libs"|sed -e "s/ -$remove */ /g"` diff --git a/scripts/mysqlhotcopy.sh b/scripts/mysqlhotcopy.sh index bf53aa78e15..61cd59457d1 100644 --- a/scripts/mysqlhotcopy.sh +++ b/scripts/mysqlhotcopy.sh @@ -263,6 +263,7 @@ my $hc_locks = ""; my $hc_tables = ""; my $num_tables = 0; my $num_files = 0; +my $raid_dir_regex = '[A-Za-z0-9]{2}'; foreach my $rdb ( @db_desc ) { my $db = $rdb->{src}; @@ -294,7 +295,7 @@ foreach my $rdb ( @db_desc ) { my @raid_dir = (); while ( defined( my $name = readdir DBDIR ) ) { - if ( $name =~ /^\d\d$/ && -d "$db_dir/$name" ) { + if ( $name =~ /^$raid_dir_regex$/ && -d "$db_dir/$name" ) { push @raid_dir, $name; } else { @@ -602,7 +603,7 @@ sub copy_files { # add recursive option for scp $cp.= " -r" if $^O =~ /m^(solaris|linux|freebsd|darwin)$/ && $method =~ /^scp\b/; - my @non_raid = map { "'$_'" } grep { ! m:/\d{2}/[^/]+$: } @$files; + my @non_raid = map { "'$_'" } grep { ! m:/$raid_dir_regex/[^/]+$: } @$files; # add files to copy and the destination directory safe_system( $cp, @non_raid, "'$target'" ) if (@non_raid); @@ -810,7 +811,7 @@ sub get_raid_dirs { my %dirs = (); foreach my $f ( @$r_files ) { - if ( $f =~ m:^(\d\d)/: ) { + if ( $f =~ m:^($raid_dir_regex)/: ) { $dirs{$1} = 1; } } diff --git a/server-tools/instance-manager/guardian.cc b/server-tools/instance-manager/guardian.cc index 24844e05776..e2142c97f33 100644 --- a/server-tools/instance-manager/guardian.cc +++ b/server-tools/instance-manager/guardian.cc @@ -110,20 +110,35 @@ void Guardian_thread::process_instance(Instance *instance, if (instance->is_running()) { - /* clear status fields */ - current_node->restart_counter= 0; - current_node->crash_moment= 0; - current_node->state= STARTED; + /* The instance can be contacted on it's port */ + + /* If STARTING also check that pidfile has been created */ + if (current_node->state == STARTING && + current_node->instance->options.get_pid() == 0) + { + /* Pid file not created yet, don't go to STARTED state yet */ + } + else + { + /* clear status fields */ + log_info("guardian: instance %s is running, set state to STARTED", + instance->options.instance_name); + current_node->restart_counter= 0; + current_node->crash_moment= 0; + current_node->state= STARTED; + } } else { switch (current_node->state) { case NOT_STARTED: - instance->start(); - current_node->last_checked= current_time; log_info("guardian: starting instance %s", instance->options.instance_name); + + /* NOTE, set state to STARTING _before_ start() is called */ current_node->state= STARTING; + instance->start(); + current_node->last_checked= current_time; break; case STARTED: /* fallthrough */ case STARTING: /* let the instance start or crash */ diff --git a/server-tools/instance-manager/instance.cc b/server-tools/instance-manager/instance.cc index 2ed369ba245..b792d132da0 100644 --- a/server-tools/instance-manager/instance.cc +++ b/server-tools/instance-manager/instance.cc @@ -572,18 +572,19 @@ void Instance::kill_instance(int signum) /* if there are no pid, everything seems to be fine */ if ((pid= options.get_pid()) != 0) /* get pid from pidfile */ { - /* - If we cannot kill mysqld, then it has propably crashed. - Let us try to remove staled pidfile and return successfully - as mysqld is probably stopped. - */ - if (!kill(pid, signum)) - options.unlink_pidfile(); - else if (signum == SIGKILL) /* really killed instance with SIGKILL */ - log_error("The instance %s is being stopped forsibly. Normally \ - it should not happed. Probably the instance has been \ - hanging. You should also check your IM setup", - options.instance_name); + if (kill(pid, signum) == 0) + { + /* Kill suceeded */ + if (signum == SIGKILL) /* really killed instance with SIGKILL */ + { + log_error("The instance %s is being stopped forcibly. Normally" \ + "it should not happen. Probably the instance has been" \ + "hanging. You should also check your IM setup", + options.instance_name); + /* After sucessful hard kill the pidfile need to be removed */ + options.unlink_pidfile(); + } + } } return; } diff --git a/server-tools/instance-manager/instance_options.cc b/server-tools/instance-manager/instance_options.cc index 72621ed1662..f86f359959b 100644 --- a/server-tools/instance-manager/instance_options.cc +++ b/server-tools/instance-manager/instance_options.cc @@ -377,7 +377,8 @@ pid_t Instance_options::get_pid() { pid_t pid; - fscanf(pid_file_stream, "%i", &pid); + if (fscanf(pid_file_stream, "%i", &pid) != 1) + pid= -1; my_fclose(pid_file_stream, MYF(0)); return pid; } diff --git a/server-tools/instance-manager/listener.cc b/server-tools/instance-manager/listener.cc index 500b25bec03..58a4093dd05 100644 --- a/server-tools/instance-manager/listener.cc +++ b/server-tools/instance-manager/listener.cc @@ -36,6 +36,27 @@ #include "portability.h" +static void set_non_blocking(int socket) +{ +#ifndef __WIN__ + int flags= fcntl(socket, F_GETFL, 0); + fcntl(socket, F_SETFL, flags | O_NONBLOCK); +#else + u_long arg= 1; + ioctlsocket(socket, FIONBIO, &arg); +#endif +} + + +static void set_no_inherit(int socket) +{ +#ifndef __WIN__ + int flags= fcntl(socket, F_GETFD, 0); + fcntl(socket, F_SETFD, flags | FD_CLOEXEC); +#endif +} + + /* Listener_thread - incapsulates listening functionality */ @@ -157,6 +178,8 @@ void Listener_thread::run() /* accept may return -1 (failure or spurious wakeup) */ if (client_fd >= 0) // connection established { + set_no_inherit(client_fd); + Vio *vio= vio_new(client_fd, socket_index == 0 ? VIO_TYPE_SOCKET : VIO_TYPE_TCPIP, socket_index == 0 ? 1 : 0); @@ -198,25 +221,6 @@ err: return; } -void set_non_blocking(int socket) -{ -#ifndef __WIN__ - int flags= fcntl(socket, F_GETFL, 0); - fcntl(socket, F_SETFL, flags | O_NONBLOCK); -#else - u_long arg= 1; - ioctlsocket(socket, FIONBIO, &arg); -#endif -} - -void set_no_inherit(int socket) -{ -#ifndef __WIN__ - int flags= fcntl(socket, F_GETFD, 0); - fcntl(socket, F_SETFD, flags | FD_CLOEXEC); -#endif -} - int Listener_thread::create_tcp_socket() { /* value to be set by setsockopt */ diff --git a/sql/CMakeLists.txt b/sql/CMakeLists.txt index b01871872ce..9b2fae847d6 100755 --- a/sql/CMakeLists.txt +++ b/sql/CMakeLists.txt @@ -110,5 +110,8 @@ ADD_CUSTOM_COMMAND( COMMAND ${GEN_LEX_HASH_EXE} ARGS > lex_hash.h DEPENDS ${GEN_LEX_HASH_EXE} ) - ADD_DEPENDENCIES(mysqld gen_lex_hash) + +ADD_LIBRARY(udf_example MODULE udf_example.c udf_example.def) +ADD_DEPENDENCIES(udf_example strings) +TARGET_LINK_LIBRARIES(udf_example wsock32) diff --git a/sql/Makefile.am b/sql/Makefile.am index 98c8fe784eb..d9cea960915 100644 --- a/sql/Makefile.am +++ b/sql/Makefile.am @@ -27,7 +27,7 @@ INCLUDES = @ZLIB_INCLUDES@ \ WRAPLIBS= @WRAPLIBS@ SUBDIRS = share libexec_PROGRAMS = mysqld -noinst_PROGRAMS = gen_lex_hash +EXTRA_PROGRAMS = gen_lex_hash bin_PROGRAMS = mysql_tzinfo_to_sql gen_lex_hash_LDFLAGS = @NOINST_LDFLAGS@ LDADD = $(top_builddir)/myisam/libmyisam.a \ @@ -117,7 +117,8 @@ DEFS = -DMYSQL_SERVER \ BUILT_SOURCES = sql_yacc.cc sql_yacc.h lex_hash.h EXTRA_DIST = $(BUILT_SOURCES) nt_servc.cc nt_servc.h \ - message.mc examples/CMakeLists.txt CMakeLists.txt + message.mc examples/CMakeLists.txt CMakeLists.txt \ + udf_example.c udf_example.def DISTCLEANFILES = lex_hash.h sql_yacc.output AM_YFLAGS = -d --debug --verbose @@ -152,7 +153,11 @@ sql_yacc.o: sql_yacc.cc sql_yacc.h $(HEADERS) @echo "If it fails, re-run configure with --with-low-memory" $(CXXCOMPILE) $(LM_CFLAGS) -c $< -lex_hash.h: gen_lex_hash$(EXEEXT) +# This generates lex_hash.h +# NOTE Built sources should depend on their sources not the tool +# this avoid the rebuild of the built files in a source dist +lex_hash.h: gen_lex_hash.cc lex.h + $(MAKE) $(AM_MAKEFLAGS) gen_lex_hash$(EXEEXT) ./gen_lex_hash$(EXEEXT) > $@ # For testing of udf_example.so diff --git a/sql/field.cc b/sql/field.cc index 4860f6ea3da..9b512fc6d4b 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -2316,11 +2316,16 @@ int Field_new_decimal::store(const char *from, uint length, from, length, charset, &decimal_value)) && table->in_use->abort_on_warning) { + /* Because "from" is not NUL-terminated and we use %s in the ER() */ + String from_as_str; + from_as_str.copy(from, length, &my_charset_bin); + push_warning_printf(table->in_use, MYSQL_ERROR::WARN_LEVEL_ERROR, ER_TRUNCATED_WRONG_VALUE_FOR_FIELD, ER(ER_TRUNCATED_WRONG_VALUE_FOR_FIELD), - "decimal", from, field_name, + "decimal", from_as_str.c_ptr(), field_name, (ulong) table->in_use->row_count); + DBUG_RETURN(err); } @@ -2333,13 +2338,20 @@ int Field_new_decimal::store(const char *from, uint length, set_value_on_overflow(&decimal_value, decimal_value.sign()); break; case E_DEC_BAD_NUM: + { + /* Because "from" is not NUL-terminated and we use %s in the ER() */ + String from_as_str; + from_as_str.copy(from, length, &my_charset_bin); + push_warning_printf(table->in_use, MYSQL_ERROR::WARN_LEVEL_WARN, ER_TRUNCATED_WRONG_VALUE_FOR_FIELD, ER(ER_TRUNCATED_WRONG_VALUE_FOR_FIELD), - "decimal", from, field_name, + "decimal", from_as_str.c_ptr(), field_name, (ulong) table->in_use->row_count); my_decimal_set_zero(&decimal_value); + break; + } } #ifndef DBUG_OFF @@ -2482,30 +2494,27 @@ void Field_new_decimal::sql_type(String &str) const int Field_tiny::store(const char *from,uint len,CHARSET_INFO *cs) { - int not_used; // We can ignore result from str2int char *end; - long tmp= my_strntol(cs, from, len, 10, &end, ¬_used); - int error= 0; + int error; if (unsigned_flag) { - if (tmp < 0) + ulonglong tmp= cs->cset->strntoull10rnd(cs, from, len, 1, &end, &error); + if (error == MY_ERRNO_ERANGE || tmp > 255) { - tmp=0; /* purecov: inspected */ - set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1); - error= 1; - } - else if (tmp > 255) - { - tmp= 255; + set_if_smaller(tmp, 255); set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1); error= 1; } else if (table->in_use->count_cuted_fields && check_int(from,len,end,cs)) error= 1; + else + error= 0; + ptr[0]= (char) tmp; } else { + longlong tmp= cs->cset->strntoull10rnd(cs, from, len, 0, &end, &error); if (tmp < -128) { tmp= -128; @@ -2520,8 +2529,10 @@ int Field_tiny::store(const char *from,uint len,CHARSET_INFO *cs) } else if (table->in_use->count_cuted_fields && check_int(from,len,end,cs)) error= 1; + else + error= 0; + ptr[0]= (char) tmp; } - ptr[0]= (char) tmp; return error; } @@ -2686,30 +2697,34 @@ void Field_tiny::sql_type(String &res) const int Field_short::store(const char *from,uint len,CHARSET_INFO *cs) { - int not_used; // We can ignore result from str2int char *end; - long tmp= my_strntol(cs, from, len, 10, &end, ¬_used); - int error= 0; + int error; if (unsigned_flag) { - if (tmp < 0) + ulonglong tmp= cs->cset->strntoull10rnd(cs, from, len, 1, &end, &error); + if (error == MY_ERRNO_ERANGE || tmp > UINT_MAX16) { - tmp=0; - set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1); - error= 1; - } - else if (tmp > UINT_MAX16) - { - tmp=UINT_MAX16; + set_if_smaller(tmp, UINT_MAX16); set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1); error= 1; } else if (table->in_use->count_cuted_fields && check_int(from,len,end,cs)) error= 1; + else + error= 0; +#ifdef WORDS_BIGENDIAN + if (table->s->db_low_byte_first) + { + int2store(ptr,tmp); + } + else +#endif + shortstore(ptr,(short) tmp); } else { + longlong tmp= cs->cset->strntoull10rnd(cs, from, len, 0, &end, &error); if (tmp < INT_MIN16) { tmp= INT_MIN16; @@ -2724,15 +2739,17 @@ int Field_short::store(const char *from,uint len,CHARSET_INFO *cs) } else if (table->in_use->count_cuted_fields && check_int(from,len,end,cs)) error= 1; - } + else + error= 0; #ifdef WORDS_BIGENDIAN - if (table->s->db_low_byte_first) - { - int2store(ptr,tmp); - } - else + if (table->s->db_low_byte_first) + { + int2store(ptr,tmp); + } + else #endif - shortstore(ptr,(short) tmp); + shortstore(ptr,(short) tmp); + } return error; } @@ -2960,30 +2977,27 @@ void Field_short::sql_type(String &res) const int Field_medium::store(const char *from,uint len,CHARSET_INFO *cs) { - int not_used; // We can ignore result from str2int char *end; - long tmp= my_strntol(cs, from, len, 10, &end, ¬_used); - int error= 0; + int error; if (unsigned_flag) { - if (tmp < 0) + ulonglong tmp= cs->cset->strntoull10rnd(cs, from, len, 1, &end, &error); + if (error == MY_ERRNO_ERANGE || tmp > UINT_MAX24) { - tmp=0; - set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1); - error= 1; - } - else if (tmp >= (long) (1L << 24)) - { - tmp=(long) (1L << 24)-1L; + set_if_smaller(tmp, UINT_MAX24); set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1); error= 1; } else if (table->in_use->count_cuted_fields && check_int(from,len,end,cs)) error= 1; + else + error= 0; + int3store(ptr,tmp); } else { + longlong tmp= cs->cset->strntoull10rnd(cs, from, len, 0, &end, &error); if (tmp < INT_MIN24) { tmp= INT_MIN24; @@ -2998,9 +3012,10 @@ int Field_medium::store(const char *from,uint len,CHARSET_INFO *cs) } else if (table->in_use->count_cuted_fields && check_int(from,len,end,cs)) error= 1; + else + error= 0; + int3store(ptr,tmp); } - - int3store(ptr,tmp); return error; } @@ -3196,64 +3211,47 @@ static bool test_if_minus(CHARSET_INFO *cs, int Field_long::store(const char *from,uint len,CHARSET_INFO *cs) { - ulong tmp_scan; - longlong tmp; long store_tmp; int error; char *end; - tmp_scan= cs->cset->scan(cs, from, from+len, MY_SEQ_SPACES); - len-= tmp_scan; - from+= tmp_scan; - - end= (char*) from+len; - tmp= cs->cset->strtoll10(cs, from, &end, &error); - - if (error != MY_ERRNO_EDOM) + if (unsigned_flag) { - if (unsigned_flag) + ulonglong tmp= cs->cset->strntoull10rnd(cs, from, len, 1, &end, &error); + if (error == MY_ERRNO_ERANGE || tmp > (ulonglong) UINT_MAX32) { - if (error < 0) - { - error= 1; - tmp= 0; - } - else if ((ulonglong) tmp > (ulonglong) UINT_MAX32) - { - tmp= UINT_MAX32; - error= 1; - } - else - error= 0; + set_if_smaller(tmp, (ulonglong) UINT_MAX32); + set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1); + error= 1; } + else if (table->in_use->count_cuted_fields && check_int(from,len,end,cs)) + error= 1; else - { - if (error < 0) - { - error= 0; - if (tmp < INT_MIN32) - { - tmp= INT_MIN32; - error= 1; - } - } - else if (tmp > INT_MAX32) - { - tmp= INT_MAX32; - error= 1; - } - } + error= 0; + store_tmp= (long) tmp; } - if (error) + else { - error= error != MY_ERRNO_EDOM ? 1 : 2; - set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1); + longlong tmp= cs->cset->strntoull10rnd(cs, from, len, 0, &end, &error); + if (tmp < INT_MIN32) + { + tmp= INT_MIN32; + set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1); + error= 1; + } + else if (tmp > INT_MAX32) + { + tmp=INT_MAX32; + set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1); + error= 1; + } + else if (table->in_use->count_cuted_fields && check_int(from,len,end,cs)) + error= 1; + else + error= 0; + store_tmp= (long) tmp; } - else if (from+len != end && table->in_use->count_cuted_fields && - check_int(from,len,end,cs)) - error= 2; - store_tmp= (long) tmp; #ifdef WORDS_BIGENDIAN if (table->s->db_low_byte_first) { @@ -3489,33 +3487,20 @@ void Field_long::sql_type(String &res) const int Field_longlong::store(const char *from,uint len,CHARSET_INFO *cs) { - longlong tmp; - int error= 0; + int error; char *end; + ulonglong tmp; - tmp= cs->cset->scan(cs, from, from+len, MY_SEQ_SPACES); - len-= (uint)tmp; - from+= tmp; - if (unsigned_flag) - { - if (!len || test_if_minus(cs, from, from + len)) - { - tmp=0; // Set negative to 0 - error= 1; - } - else - tmp=(longlong) my_strntoull(cs,from,len,10,&end,&error); - } - else - tmp=my_strntoll(cs,from,len,10,&end,&error); - if (error) + tmp= cs->cset->strntoull10rnd(cs,from,len,unsigned_flag,&end,&error); + if (error == MY_ERRNO_ERANGE) { set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1); error= 1; } - else if (from+len != end && table->in_use->count_cuted_fields && - check_int(from,len,end,cs)) - error= 2; + else if (table->in_use->count_cuted_fields && check_int(from,len,end,cs)) + error= 1; + else + error= 0; #ifdef WORDS_BIGENDIAN if (table->s->db_low_byte_first) { @@ -7921,7 +7906,7 @@ int Field_bit::store(const char *from, uint length, CHARSET_INFO *cs) (delta == -1 && (uchar) *from > ((1 << bit_len) - 1)) || (!bit_len && delta < 0)) { - set_rec_bits(0xff, bit_ptr, bit_ofs, bit_len); + set_rec_bits((1 << bit_len) - 1, bit_ptr, bit_ofs, bit_len); memset(ptr, 0xff, bytes_in_rec); if (table->in_use->really_abort_on_warning()) set_warning(MYSQL_ERROR::WARN_LEVEL_ERROR, ER_DATA_TOO_LONG, 1); @@ -8877,7 +8862,7 @@ create_field::create_field(Field *old_field,Field *orig_field) case 3: sql_type= FIELD_TYPE_MEDIUM_BLOB; break; default: sql_type= FIELD_TYPE_LONG_BLOB; break; } - length=(length+charset->mbmaxlen-1) / charset->mbmaxlen; + length/= charset->mbmaxlen; key_length/= charset->mbmaxlen; break; case MYSQL_TYPE_STRING: diff --git a/sql/field.h b/sql/field.h index 65e747e9d2f..b79c2bf77a8 100644 --- a/sql/field.h +++ b/sql/field.h @@ -1432,6 +1432,8 @@ public: uint decimals, flags, pack_length, key_length; Field::utype unireg_check; TYPELIB *interval; // Which interval to use + TYPELIB *save_interval; // Temporary copy for the above + // Used only for UCS2 intervals List interval_list; CHARSET_INFO *charset; Field::geometry_type geom_type; diff --git a/sql/field_conv.cc b/sql/field_conv.cc index 3200f2ca9b2..95ff985376d 100644 --- a/sql/field_conv.cc +++ b/sql/field_conv.cc @@ -428,6 +428,21 @@ static void do_varstring2(Copy_field *copy) length); } + +static void do_varstring2_mb(Copy_field *copy) +{ + int well_formed_error; + CHARSET_INFO *cs= copy->from_field->charset(); + uint char_length= (copy->to_length - HA_KEY_BLOB_LENGTH) / cs->mbmaxlen; + uint from_length= uint2korr(copy->from_ptr); + const char *from_beg= copy->from_ptr + HA_KEY_BLOB_LENGTH; + uint length= cs->cset->well_formed_len(cs, from_beg, from_beg + from_length, + char_length, &well_formed_error); + int2store(copy->to_ptr, length); + memcpy(copy->to_ptr+HA_KEY_BLOB_LENGTH, from_beg, length); +} + + /*************************************************************************** ** The different functions that fills in a Copy_field class ***************************************************************************/ @@ -587,7 +602,8 @@ void (*Copy_field::get_copy_func(Field *to,Field *from))(Copy_field*) return do_field_string; if (to_length != from_length) return (((Field_varstring*) to)->length_bytes == 1 ? - do_varstring1 : do_varstring2); + do_varstring1 : (from->charset()->mbmaxlen == 1 ? + do_varstring2 : do_varstring2_mb)); } else if (to_length < from_length) return (from->charset()->mbmaxlen == 1 ? diff --git a/sql/filesort.cc b/sql/filesort.cc index 42d25dbbaee..b063b416191 100644 --- a/sql/filesort.cc +++ b/sql/filesort.cc @@ -601,6 +601,7 @@ static inline void store_length(uchar *to, uint length, uint pack_length) break; case 3: mi_int3store(to, length); + break; default: mi_int4store(to, length); break; @@ -1268,6 +1269,7 @@ sortlength(THD *thd, SORT_FIELD *sortorder, uint s_length, switch ((sortorder->result_type=sortorder->item->result_type())) { case STRING_RESULT: sortorder->length=sortorder->item->max_length; + set_if_smaller(sortorder->length, thd->variables.max_sort_length); if (use_strnxfrm((cs=sortorder->item->collation.collation))) { sortorder->length= cs->coll->strnxfrmlen(cs, sortorder->length); diff --git a/sql/ha_archive.cc b/sql/ha_archive.cc index bb94a99e700..bc3c819c4ed 100644 --- a/sql/ha_archive.cc +++ b/sql/ha_archive.cc @@ -120,6 +120,8 @@ static bool archive_inited= FALSE; /* Variables for archive share methods */ pthread_mutex_t archive_mutex; static HASH archive_open_tables; +static z_off_t max_zfile_size; +static int zoffset_size; /* The file extension */ #define ARZ ".ARZ" // The data file @@ -203,6 +205,18 @@ bool archive_db_init() } else { + zoffset_size= 2 << ((zlibCompileFlags() >> 6) & 3); + switch (sizeof(z_off_t)) { + case 2: + max_zfile_size= INT_MAX16; + break; + case 8: + max_zfile_size= LONGLONG_MAX; + break; + case 4: + default: + max_zfile_size= INT_MAX32; + } archive_inited= TRUE; DBUG_RETURN(FALSE); } @@ -240,7 +254,7 @@ ha_archive::ha_archive(TABLE *table_arg) buffer.set((char *)byte_buffer, IO_SIZE, system_charset_info); /* The size of the offset value we will use for position() */ - ref_length = 2 << ((zlibCompileFlags() >> 6) & 3); + ref_length = zoffset_size; DBUG_ASSERT(ref_length <= sizeof(z_off_t)); } @@ -480,7 +494,8 @@ int ha_archive::init_archive_writer() DBUG_RETURN(1); } share->archive_write_open= TRUE; - + info(HA_STATUS_TIME); + share->approx_file_size= data_file_length; DBUG_RETURN(0); } @@ -651,10 +666,21 @@ error: */ int ha_archive::real_write_row(byte *buf, gzFile writer) { - z_off_t written; + z_off_t written, total_row_length; uint *ptr, *end; DBUG_ENTER("ha_archive::real_write_row"); - + total_row_length= table->s->reclength; + for (ptr= table->s->blob_field, end= ptr + table->s->blob_fields; + ptr != end; ptr++) + total_row_length+= ((Field_blob*) table->field[*ptr])->get_length(); + if (share->approx_file_size > max_zfile_size - total_row_length) + { + info(HA_STATUS_TIME); + share->approx_file_size= data_file_length; + if (share->approx_file_size > max_zfile_size - total_row_length) + DBUG_RETURN(HA_ERR_RECORD_FILE_FULL); + } + share->approx_file_size+= total_row_length; written= gzwrite(writer, buf, table->s->reclength); DBUG_PRINT("ha_archive::real_write_row", ("Wrote %d bytes expected %d", written, table->s->reclength)); if (!delayed_insert || !bulk_insert) diff --git a/sql/ha_archive.h b/sql/ha_archive.h index 2bac9fa605e..564b9f03bf5 100644 --- a/sql/ha_archive.h +++ b/sql/ha_archive.h @@ -38,6 +38,7 @@ typedef struct st_archive_share { bool dirty; /* Flag for if a flush should occur */ bool crashed; /* Meta file is crashed */ ha_rows rows_recorded; /* Number of rows in tables */ + z_off_t approx_file_size; /* Approximate archive data file size */ } ARCHIVE_SHARE; /* diff --git a/sql/ha_berkeley.cc b/sql/ha_berkeley.cc index 72af402a0dc..4209bc93d30 100644 --- a/sql/ha_berkeley.cc +++ b/sql/ha_berkeley.cc @@ -953,7 +953,10 @@ int ha_berkeley::write_row(byte * record) if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT) table->timestamp_field->set_time(); if (table->next_number_field && record == table->record[0]) - update_auto_increment(); + { + if ((error= update_auto_increment())) + DBUG_RETURN(error); + } if ((error=pack_row(&row, record,1))) DBUG_RETURN(error); /* purecov: inspected */ diff --git a/sql/ha_heap.cc b/sql/ha_heap.cc index 79d4575ff1b..3aaa0287098 100644 --- a/sql/ha_heap.cc +++ b/sql/ha_heap.cc @@ -176,7 +176,10 @@ int ha_heap::write_row(byte * buf) if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT) table->timestamp_field->set_time(); if (table->next_number_field && buf == table->record[0]) - update_auto_increment(); + { + if ((res= update_auto_increment())) + return res; + } res= heap_write(file,buf); if (!res && (++records_changed*HEAP_STATS_UPDATE_THRESHOLD > file->s->records)) diff --git a/sql/ha_innodb.cc b/sql/ha_innodb.cc index c56be6376d0..e99d93784c9 100644 --- a/sql/ha_innodb.cc +++ b/sql/ha_innodb.cc @@ -3252,7 +3252,8 @@ no_commit: /* We must use the handler code to update the auto-increment value to be sure that we increment it correctly. */ - update_auto_increment(); + if ((error= update_auto_increment())) + goto func_exit; auto_inc_used = 1; } @@ -5969,19 +5970,6 @@ ha_innobase::start_stmt( prebuilt->select_lock_type = prebuilt->stored_select_lock_type; } - - if (prebuilt->stored_select_lock_type != LOCK_S - && prebuilt->stored_select_lock_type != LOCK_X) { - sql_print_error("stored_select_lock_type is %lu inside " - "::start_stmt()!", - prebuilt->stored_select_lock_type); - - /* Set the value to LOCK_X: this is just fault - tolerance, we do not know what the correct value - should be! */ - - prebuilt->select_lock_type = LOCK_X; - } } trx->detailed_error[0] = '\0'; diff --git a/sql/ha_myisam.cc b/sql/ha_myisam.cc index 128cc191434..fc3bd3d3b08 100644 --- a/sql/ha_myisam.cc +++ b/sql/ha_myisam.cc @@ -169,6 +169,14 @@ ha_myisam::ha_myisam(TABLE *table_arg) can_enable_indexes(1) {} +handler *ha_myisam::clone(MEM_ROOT *mem_root) +{ + ha_myisam *new_handler= static_cast (handler::clone(mem_root)); + if (new_handler) + new_handler->file->state= file->state; + return new_handler; +} + static const char *ha_myisam_exts[] = { ".MYI", @@ -316,7 +324,11 @@ int ha_myisam::write_row(byte * buf) or a new row, then update the auto_increment value in the record. */ if (table->next_number_field && buf == table->record[0]) - update_auto_increment(); + { + int error; + if ((error= update_auto_increment())) + return error; + } return mi_write(file,buf); } diff --git a/sql/ha_myisam.h b/sql/ha_myisam.h index ca684463311..950817d42bd 100644 --- a/sql/ha_myisam.h +++ b/sql/ha_myisam.h @@ -45,6 +45,7 @@ class ha_myisam: public handler public: ha_myisam(TABLE *table_arg); ~ha_myisam() {} + handler *clone(MEM_ROOT *mem_root); const char *table_type() const { return "MyISAM"; } const char *index_type(uint key_number); const char **bas_ext() const; diff --git a/sql/ha_myisammrg.cc b/sql/ha_myisammrg.cc index 0b6e05fcbd4..a4f23cd3cf0 100644 --- a/sql/ha_myisammrg.cc +++ b/sql/ha_myisammrg.cc @@ -139,7 +139,11 @@ int ha_myisammrg::write_row(byte * buf) if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT) table->timestamp_field->set_time(); if (table->next_number_field && buf == table->record[0]) - update_auto_increment(); + { + int error; + if ((error= update_auto_increment())) + return error; + } return myrg_write(file,buf); } @@ -322,9 +326,22 @@ void ha_myisammrg::info(uint flag) if (flag & HA_STATUS_CONST) { if (table->s->key_parts && info.rec_per_key) + { +#ifdef HAVE_purify + /* + valgrind may be unhappy about it, because optimizer may access values + between file->keys and table->key_parts, that will be uninitialized. + It's safe though, because even if opimizer will decide to use a key + with such a number, it'll be an error later anyway. + */ + bzero((char*) table->key_info[0].rec_per_key, + sizeof(table->key_info[0].rec_per_key) * table->s->key_parts); +#endif memcpy((char*) table->key_info[0].rec_per_key, (char*) info.rec_per_key, - sizeof(table->key_info[0].rec_per_key)*table->s->key_parts); + sizeof(table->key_info[0].rec_per_key) * + min(file->keys, table->s->key_parts)); + } } } diff --git a/sql/ha_ndbcluster.cc b/sql/ha_ndbcluster.cc index 8e8e4419df8..5f18d5534e4 100644 --- a/sql/ha_ndbcluster.cc +++ b/sql/ha_ndbcluster.cc @@ -2131,9 +2131,11 @@ int ha_ndbcluster::write_row(byte *record) if (has_auto_increment) { THD *thd= table->in_use; + int error; m_skip_auto_increment= FALSE; - update_auto_increment(); + if ((error= update_auto_increment())) + DBUG_RETURN(error); /* Ensure that handler is always called for auto_increment values */ thd->next_insert_id= 0; m_skip_auto_increment= !auto_increment_column_changed; @@ -3526,7 +3528,14 @@ int ha_ndbcluster::external_lock(THD *thd, int lock_type) if (lock_type != F_UNLCK) { DBUG_PRINT("info", ("lock_type != F_UNLCK")); - if (!thd->transaction.on) + if (thd->lex->sql_command == SQLCOM_LOAD) + { + m_transaction_on= FALSE; + /* Would be simpler if has_transactions() didn't always say "yes" */ + thd->options|= OPTION_STATUS_NO_TRANS_UPDATE; + thd->no_trans_update= TRUE; + } + else if (!thd->transaction.on) m_transaction_on= FALSE; else m_transaction_on= thd->variables.ndb_use_transactions; diff --git a/sql/handler.cc b/sql/handler.cc index b0051b02d91..4accc746664 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -429,6 +429,8 @@ static int ha_init_errors(void) SETMSG(HA_ERR_TABLE_DEF_CHANGED, ER(ER_TABLE_DEF_CHANGED)); SETMSG(HA_ERR_TABLE_NEEDS_UPGRADE, ER(ER_TABLE_NEEDS_UPGRADE)); SETMSG(HA_ERR_TABLE_READONLY, ER(ER_OPEN_AS_READONLY)); + SETMSG(HA_ERR_AUTOINC_READ_FAILED, ER(ER_AUTOINC_READ_FAILED)); + SETMSG(HA_ERR_AUTOINC_ERANGE, ER(ER_WARN_DATA_OUT_OF_RANGE)); /* Register the error messages for use with my_error(). */ return my_error_register(errmsgs, HA_ERR_FIRST, HA_ERR_LAST); @@ -1374,6 +1376,15 @@ int ha_delete_table(THD *thd, enum db_type table_type, const char *path, /**************************************************************************** ** General handler functions ****************************************************************************/ +handler *handler::clone(MEM_ROOT *mem_root) +{ + handler *new_handler= get_new_handler(table, mem_root, table->s->db_type); + if (new_handler && !new_handler->ha_open(table->s->path, table->db_stat, + HA_OPEN_IGNORE_IF_LOCKED)) + return new_handler; + return NULL; +} + /* Open database-handler. Try O_RDONLY if can't open as O_RDWR */ /* Don't wait for locks if not HA_OPEN_WAIT_IF_LOCKED is set */ @@ -1542,7 +1553,10 @@ prev_insert_id(ulonglong nr, struct system_variables *variables) RETURN 0 ok - 1 get_auto_increment() was called and returned ~(ulonglong) 0 + HA_ERR_AUTOINC_READ_FAILED + get_auto_increment() was called and returned ~(ulonglong) 0 + HA_ERR_AUTOINC_ERANGE + storing value in field caused strict mode failure. IMPLEMENTATION @@ -1586,13 +1600,12 @@ prev_insert_id(ulonglong nr, struct system_variables *variables) thd->next_insert_id is cleared after it's been used for a statement. */ -bool handler::update_auto_increment() +int handler::update_auto_increment() { ulonglong nr; THD *thd= table->in_use; struct system_variables *variables= &thd->variables; bool auto_increment_field_not_null; - bool result= 0; DBUG_ENTER("handler::update_auto_increment"); /* @@ -1616,7 +1629,7 @@ bool handler::update_auto_increment() if (!(nr= thd->next_insert_id)) { if ((nr= get_auto_increment()) == ~(ulonglong) 0) - result= 1; // Mark failure + DBUG_RETURN(HA_ERR_AUTOINC_READ_FAILED); // Mark failure if (variables->auto_increment_increment != 1) nr= next_insert_id(nr-1, variables); @@ -1636,6 +1649,7 @@ bool handler::update_auto_increment() if (likely(!table->next_number_field->store((longlong) nr, TRUE))) thd->insert_id((ulonglong) nr); else + if (thd->killed != THD::KILL_BAD_DATA) /* did we fail strict mode? */ { /* overflow of the field; we'll use the max value, however we try to @@ -1646,6 +1660,8 @@ bool handler::update_auto_increment() if (unlikely(table->next_number_field->store((longlong) nr, TRUE))) thd->insert_id(nr= table->next_number_field->val_int()); } + else + DBUG_RETURN(HA_ERR_AUTOINC_ERANGE); /* We can't set next_insert_id if the auto-increment key is not the @@ -1666,7 +1682,7 @@ bool handler::update_auto_increment() /* Mark that we generated a new value */ auto_increment_column_changed=1; - DBUG_RETURN(result); + DBUG_RETURN(0); } /* @@ -1864,6 +1880,12 @@ void handler::print_error(int error, myf errflag) case HA_ERR_TABLE_READONLY: textno= ER_OPEN_AS_READONLY; break; + case HA_ERR_AUTOINC_READ_FAILED: + textno= ER_AUTOINC_READ_FAILED; + break; + case HA_ERR_AUTOINC_ERANGE: + textno= ER_WARN_DATA_OUT_OF_RANGE; + break; default: { /* The error was "unknown" to this function. diff --git a/sql/handler.h b/sql/handler.h index 44de0cc715a..481a98be285 100644 --- a/sql/handler.h +++ b/sql/handler.h @@ -563,9 +563,10 @@ public: pushed_cond(NULL) {} virtual ~handler(void) { /* TODO: DBUG_ASSERT(inited == NONE); */ } + virtual handler *clone(MEM_ROOT *mem_root); int ha_open(const char *name, int mode, int test_if_locked); void adjust_next_insert_id_after_explicit_value(ulonglong nr); - bool update_auto_increment(); + int update_auto_increment(); virtual void print_error(int error, myf errflag); virtual bool get_error_message(int error, String *buf); uint get_dup_key(int error); diff --git a/sql/item.cc b/sql/item.cc index 34e5e2da165..d56ca95093b 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -1182,6 +1182,7 @@ void Item::split_sum_func2(THD *thd, Item **ref_pointer_array, split_sum_func(thd, ref_pointer_array, fields); } else if ((type() == SUM_FUNC_ITEM || (used_tables() & ~PARAM_TABLE_BIT)) && + type() != SUBSELECT_ITEM && (type() != REF_ITEM || ((Item_ref*)this)->ref_type() == Item_ref::VIEW_REF)) { @@ -3744,6 +3745,7 @@ void Item_field::cleanup() I.e. we can drop 'field'. */ field= result_field= 0; + null_value= FALSE; DBUG_VOID_RETURN; } @@ -3788,14 +3790,49 @@ Item_equal *Item_field::find_item_equal(COND_EQUAL *cond_equal) } +/* + Check whether a field can be substituted by an equal item + + SYNOPSIS + equal_fields_propagator() + arg - *arg != NULL <-> the field is in the context where + substitution for an equal item is valid + + DESCRIPTION + The function checks whether a substitution of the field + occurrence for an equal item is valid. + + NOTES + The following statement is not always true: + x=y => F(x)=F(x/y). + This means substitution of an item for an equal item not always + yields an equavalent condition. + Here's an example: + 'a'='a ' + (LENGTH('a')=1) != (LENGTH('a ')=2) + Such a substitution is surely valid if either the substituted + field is not of a STRING type or if it is an argument of + a comparison predicate. + + RETURN + TRUE substitution is valid + FALSE otherwise +*/ + +bool Item_field::subst_argument_checker(byte **arg) +{ + return (result_type() != STRING_RESULT) || (*arg); +} + + /* Set a pointer to the multiple equality the field reference belongs to (if any) SYNOPSIS equal_fields_propagator() - arg - reference to list of multiple equalities where - the field (this object) is to be looked for + arg - reference to list of multiple equalities where + the field (this object) is to be looked for DESCRIPTION The function looks for a multiple equality containing the field item @@ -3807,7 +3844,7 @@ Item_equal *Item_field::find_item_equal(COND_EQUAL *cond_equal) NOTES This function is supposed to be called as a callback parameter in calls - of the transform method. + of the compile method. RETURN VALUES pointer to the replacing constant item, if the field item was substituted diff --git a/sql/item.h b/sql/item.h index 58a3bfd0d75..0cfb0b01fd8 100644 --- a/sql/item.h +++ b/sql/item.h @@ -410,7 +410,19 @@ public: }; -typedef bool (Item::*Item_processor)(byte *arg); +typedef bool (Item::*Item_processor) (byte *arg); +/* + Analyzer function + SYNOPSIS + argp in/out IN: Analysis parameter + OUT: Parameter to be passed to the transformer + + RETURN + TRUE Invoke the transformer + FALSE Don't do it + +*/ +typedef bool (Item::*Item_analyzer) (byte **argp); typedef Item* (Item::*Item_transformer) (byte *arg); typedef void (*Cond_traverser) (const Item *item, void *arg); @@ -736,6 +748,30 @@ public: virtual Item* transform(Item_transformer transformer, byte *arg); + /* + This function performs a generic "compilation" of the Item tree. + The process of compilation is assumed to go as follows: + + compile() + { + if (this->*some_analyzer(...)) + { + compile children if any; + this->*some_transformer(...); + } + } + + i.e. analysis is performed top-down while transformation is done + bottom-up. + */ + virtual Item* compile(Item_analyzer analyzer, byte **arg_p, + Item_transformer transformer, byte *arg_t) + { + if ((this->*analyzer) (arg_p)) + return ((this->*transformer) (arg_t)); + return 0; + } + virtual void traverse_cond(Cond_traverser traverser, void *arg, traverse_order order) { @@ -750,6 +786,12 @@ public: virtual bool change_context_processor(byte *context) { return 0; } virtual bool reset_query_id_processor(byte *query_id) { return 0; } virtual bool is_expensive_processor(byte *arg) { return 0; } + virtual bool subst_argument_checker(byte **arg) + { + if (*arg) + *arg= NULL; + return TRUE; + } virtual Item *equal_fields_propagator(byte * arg) { return this; } virtual bool set_no_const_sub(byte *arg) { return FALSE; } @@ -1251,6 +1293,7 @@ public: return field->can_be_compared_as_longlong(); } Item_equal *find_item_equal(COND_EQUAL *cond_equal); + bool subst_argument_checker(byte **arg); Item *equal_fields_propagator(byte *arg); bool set_no_const_sub(byte *arg); Item *replace_equal_field(byte *arg); @@ -2141,7 +2184,11 @@ public: { return Item_field::save_in_field(field_arg, no_conversions); } - table_map used_tables() const { return (table_map)0L; } + /* + We use RAND_TABLE_BIT to prevent Item_insert_value from + being treated as a constant and precalculated before execution + */ + table_map used_tables() const { return RAND_TABLE_BIT; } bool walk(Item_processor processor, byte *args) { diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index 919a23ed65d..780d70d51dc 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -77,131 +77,14 @@ static void agg_result_type(Item_result *type, Item **items, uint nitems) This function aggregates result types from the array of items. Found type supposed to be used later for comparison of values of these items. Aggregation itself is performed by the item_cmp_type() function. - - NOTES - Aggregation rules: - If there are DATE/TIME fields/functions in the list and no string - fields/functions in the list then: - The INT_RESULT type will be used for aggregation instead of original - result type of any DATE/TIME field/function in the list - All constant items in the list will be converted to a DATE/TIME using - found field or result field of found function. - - Implementation notes: - The code is equivalent to: - 1. Check the list for presence of a STRING field/function. - Collect the is_const flag. - 2. Get a Field* object to use for type coercion - 3. Perform type conversion. - 1 and 2 are implemented in 2 loops. The first searches for a DATE/TIME - field/function and checks presence of a STRING field/function. - The second loop works only if a DATE/TIME field/function is found. - It checks presence of a STRING field/function in the rest of the list. - - TODO - 1) The current implementation can produce false comparison results for - expressions like: - date_time_field BETWEEN string_field_with_dates AND string_constant - if the string_constant will omit some of leading zeroes. - In order to fully implement correct comparison of DATE/TIME the new - DATETIME_RESULT result type should be introduced and agg_cmp_type() - should return the DATE/TIME field used for the conversion. Later - this field can be used by comparison functions like Item_func_between to - convert string values to ints on the fly and thus return correct results. - This modification will affect functions BETWEEN, IN and CASE. - - 2) If in the list a DATE field/function and a DATETIME field/function - are present in the list then the first found field/function will be - used for conversion. This may lead to wrong results and probably should - be fixed. */ static void agg_cmp_type(THD *thd, Item_result *type, Item **items, uint nitems) { uint i; - Item::Type res= (Item::Type)0; - /* Used only for date/time fields, max_length = 19 */ - char buff[20]; - uchar null_byte; - Field *field= NULL; - - /* - Do not convert items while creating a or showing a view in order - to store/display the original query in these cases. - */ - if (thd->lex->sql_command != SQLCOM_CREATE_VIEW && - thd->lex->sql_command != SQLCOM_SHOW_CREATE) - { - /* Search for date/time fields/functions */ - for (i= 0; i < nitems; i++) - { - if (!items[i]->result_as_longlong()) - { - /* Do not convert anything if a string field/function is present */ - if (!items[i]->const_item() && items[i]->result_type() == STRING_RESULT) - { - i= nitems; - break; - } - continue; - } - if ((res= items[i]->real_item()->type()) == Item::FIELD_ITEM && - items[i]->result_type() != INT_RESULT) - { - field= ((Item_field *)items[i]->real_item())->field; - break; - } - else if (res == Item::FUNC_ITEM) - { - field= items[i]->tmp_table_field_from_field_type(0); - if (field) - field->move_field(buff, &null_byte, 0); - break; - } - } - } - if (field) - { - /* Check the rest of the list for presence of a string field/function. */ - for (i++ ; i < nitems; i++) - { - if (!items[i]->const_item() && items[i]->result_type() == STRING_RESULT && - !items[i]->result_as_longlong()) - { - if (res == Item::FUNC_ITEM) - delete field; - field= 0; - break; - } - } - } - /* - If the first item is a date/time function then its result should be - compared as int - */ - if (field) - /* Suppose we are comparing dates */ - type[0]= INT_RESULT; - else - type[0]= items[0]->result_type(); - - for (i= 0; i < nitems ; i++) - { - Item_result result= items[i]->result_type(); - /* - Use INT_RESULT as result type for DATE/TIME fields/functions and - for constants successfully converted to DATE/TIME - */ - if (field && - ((!items[i]->const_item() && items[i]->result_as_longlong()) || - (items[i]->const_item() && convert_constant_item(thd, field, - &items[i])))) - result= INT_RESULT; - type[0]= item_cmp_type(type[0], result); - } - - if (res == Item::FUNC_ITEM && field) - delete field; + type[0]= items[0]->result_type(); + for (i= 1 ; i < nitems ; i++) + type[0]= item_cmp_type(type[0], items[i]->result_type()); } @@ -1220,10 +1103,32 @@ void Item_func_between::fix_length_and_dec() if (!args[0] || !args[1] || !args[2]) return; agg_cmp_type(thd, &cmp_type, args, 3); - args[0]->cmp_context= args[1]->cmp_context= args[2]->cmp_context= cmp_type; + if (cmp_type == STRING_RESULT && + agg_arg_charsets(cmp_collation, args, 3, MY_COLL_CMP_CONV, 1)) + return; - if (cmp_type == STRING_RESULT) - agg_arg_charsets(cmp_collation, args, 3, MY_COLL_CMP_CONV, 1); + /* + Make a special case of compare with date/time and longlong fields. + They are compared as integers, so for const item this time-consuming + conversion can be done only once, not for every single comparison + */ + if (args[0]->type() == FIELD_ITEM && + thd->lex->sql_command != SQLCOM_CREATE_VIEW && + thd->lex->sql_command != SQLCOM_SHOW_CREATE) + { + Field *field=((Item_field*) args[0])->field; + if (field->can_be_compared_as_longlong()) + { + /* + The following can't be recoded with || as convert_constant_item + changes the argument + */ + if (convert_constant_item(thd, field,&args[1])) + cmp_type=INT_RESULT; // Works for all types. + if (convert_constant_item(thd, field,&args[2])) + cmp_type=INT_RESULT; // Works for all types. + } + } } @@ -2747,16 +2652,16 @@ bool Item_cond::walk(Item_processor processor, byte *arg) SYNOPSIS transform() - transformer the transformer callback function to be applied to the nodes - of the tree of the object - arg parameter to be passed to the transformer + transformer the transformer callback function to be applied to the nodes + of the tree of the object + arg parameter to be passed to the transformer DESCRIPTION - The function recursively applies the transform method with the - same transformer to each member item of the condition list. + The function recursively applies the transform method to each + member item of the condition list. If the call of the method for a member item returns a new item the old item is substituted for a new one. - After this the transform method is applied to the root node + After this the transformer is applied to the root node of the Item_cond object. RETURN VALUES @@ -2787,6 +2692,55 @@ Item *Item_cond::transform(Item_transformer transformer, byte *arg) return Item_func::transform(transformer, arg); } + +/* + Compile Item_cond object with a processor and a transformer callback functions + + SYNOPSIS + compile() + analyzer the analyzer callback function to be applied to the nodes + of the tree of the object + arg_p in/out parameter to be passed to the analyzer + transformer the transformer callback function to be applied to the nodes + of the tree of the object + arg_t parameter to be passed to the transformer + + DESCRIPTION + First the function applies the analyzer to the root node of + the Item_func object. Then if the analyzer succeeeds (returns TRUE) + the function recursively applies the compile method to member + item of the condition list. + If the call of the method for a member item returns a new item + the old item is substituted for a new one. + After this the transformer is applied to the root node + of the Item_cond object. + + RETURN VALUES + Item returned as the result of transformation of the root node +*/ + +Item *Item_cond::compile(Item_analyzer analyzer, byte **arg_p, + Item_transformer transformer, byte *arg_t) +{ + if (!(this->*analyzer)(arg_p)) + return 0; + + List_iterator li(list); + Item *item; + while ((item= li++)) + { + /* + The same parameter value of arg_p must be passed + to analyze any argument of the condition formula. + */ + byte *arg_v= *arg_p; + Item *new_item= item->compile(analyzer, &arg_v, transformer, arg_t); + if (new_item && new_item != item) + li.replace(new_item); + } + return Item_func::transform(transformer, arg_t); +} + void Item_cond::traverse_cond(Cond_traverser traverser, void *arg, traverse_order order) { diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h index 47f9f2aa98f..f2c43833bd9 100644 --- a/sql/item_cmpfunc.h +++ b/sql/item_cmpfunc.h @@ -240,6 +240,7 @@ public: } Item *neg_transformer(THD *thd); virtual Item *negated_item(); + bool subst_argument_checker(byte **arg) { return TRUE; } }; class Item_func_not :public Item_bool_func @@ -1171,6 +1172,9 @@ public: Item *transform(Item_transformer transformer, byte *arg); void traverse_cond(Cond_traverser, void *arg, traverse_order order); void neg_arguments(THD *thd); + bool subst_argument_checker(byte **arg) { return TRUE; } + Item *compile(Item_analyzer analyzer, byte **arg_p, + Item_transformer transformer, byte *arg_t); }; diff --git a/sql/item_func.cc b/sql/item_func.cc index 579e7f88ee6..a294bbd7a71 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -234,22 +234,21 @@ void Item_func::traverse_cond(Cond_traverser traverser, } - /* Transform an Item_func object with a transformer callback function SYNOPSIS transform() - transformer the transformer callback function to be applied to the nodes - of the tree of the object - argument parameter to be passed to the transformer + transformer the transformer callback function to be applied to the nodes + of the tree of the object + argument parameter to be passed to the transformer DESCRIPTION - The function recursively applies the transform method with the - same transformer to each argument the function. - If the call of the method for a member item returns a new item + The function recursively applies the transform method to each + argument of the Item_func node. + If the call of the method for an argument item returns a new item the old item is substituted for a new one. - After this the transform method is applied to the root node + After this the transformer is applied to the root node of the Item_func object. RETURN VALUES @@ -283,6 +282,55 @@ Item *Item_func::transform(Item_transformer transformer, byte *argument) } +/* + Compile Item_func object with a processor and a transformer callback functions + + SYNOPSIS + compile() + analyzer the analyzer callback function to be applied to the nodes + of the tree of the object + arg_p in/out parameter to be passed to the processor + transformer the transformer callback function to be applied to the nodes + of the tree of the object + arg_t parameter to be passed to the transformer + + DESCRIPTION + First the function applies the analyzer to the root node of + the Item_func object. Then if the analizer succeeeds (returns TRUE) + the function recursively applies the compile method to each argument + of the Item_func node. + If the call of the method for an argument item returns a new item + the old item is substituted for a new one. + After this the transformer is applied to the root node + of the Item_func object. + + RETURN VALUES + Item returned as the result of transformation of the root node +*/ + +Item *Item_func::compile(Item_analyzer analyzer, byte **arg_p, + Item_transformer transformer, byte *arg_t) +{ + if (!(this->*analyzer)(arg_p)) + return 0; + if (arg_count) + { + Item **arg,**arg_end; + for (arg= args, arg_end= args+arg_count; arg != arg_end; arg++) + { + /* + The same parameter value of arg_p must be passed + to analyze any argument of the condition formula. + */ + byte *arg_v= *arg_p; + Item *new_item= (*arg)->compile(analyzer, &arg_v, transformer, arg_t); + if (new_item && *arg != new_item) + current_thd->change_item_tree(arg, new_item); + } + } + return (this->*transformer)(arg_t); +} + /* See comments in Item_cmp_func::split_sum_func() */ void Item_func::split_sum_func(THD *thd, Item **ref_pointer_array, @@ -3297,6 +3345,35 @@ longlong Item_func_release_lock::val_int() } +bool Item_func_last_insert_id::fix_fields(THD *thd, Item **ref) +{ + DBUG_ASSERT(fixed == 0); + + if (Item_int_func::fix_fields(thd, ref)) + return TRUE; + + if (arg_count == 0) + { + if (!thd->last_insert_id_used) + { + /* + As this statement calls LAST_INSERT_ID(), set + THD::last_insert_id_used and remember first generated insert + id of the previous statement in THD::current_insert_id. + */ + thd->last_insert_id_used= TRUE; + thd->last_insert_id_used_bin_log= TRUE; + thd->current_insert_id= thd->last_insert_id; + } + null_value= FALSE; + } + + thd->lex->uncacheable(UNCACHEABLE_SIDEEFFECT); + + return FALSE; +} + + longlong Item_func_last_insert_id::val_int() { THD *thd= current_thd; @@ -3306,12 +3383,13 @@ longlong Item_func_last_insert_id::val_int() longlong value= args[0]->val_int(); thd->insert_id(value); null_value= args[0]->null_value; - return value; // Avoid side effect of insert_id() + return value; } - thd->lex->uncacheable(UNCACHEABLE_SIDEEFFECT); - return thd->last_insert_id_used ? thd->current_insert_id : thd->insert_id(); + + return thd->current_insert_id; } + /* This function is just used to test speed of different functions */ longlong Item_func_benchmark::val_int() @@ -3799,13 +3877,13 @@ Item_func_set_user_var::update() case REAL_RESULT: { res= update_hash((void*) &save_result.vreal,sizeof(save_result.vreal), - REAL_RESULT, &my_charset_bin, DERIVATION_IMPLICIT); + REAL_RESULT, &my_charset_bin, DERIVATION_IMPLICIT, 0); break; } case INT_RESULT: { res= update_hash((void*) &save_result.vint, sizeof(save_result.vint), - INT_RESULT, &my_charset_bin, DERIVATION_IMPLICIT, + INT_RESULT, &my_charset_bin, DERIVATION_IMPLICIT, unsigned_flag); break; } @@ -3813,23 +3891,23 @@ Item_func_set_user_var::update() { if (!save_result.vstr) // Null value res= update_hash((void*) 0, 0, STRING_RESULT, &my_charset_bin, - DERIVATION_IMPLICIT); + DERIVATION_IMPLICIT, 0); else res= update_hash((void*) save_result.vstr->ptr(), save_result.vstr->length(), STRING_RESULT, save_result.vstr->charset(), - DERIVATION_IMPLICIT); + DERIVATION_IMPLICIT, 0); break; } case DECIMAL_RESULT: { if (!save_result.vdec) // Null value res= update_hash((void*) 0, 0, DECIMAL_RESULT, &my_charset_bin, - DERIVATION_IMPLICIT); + DERIVATION_IMPLICIT, 0); else res= update_hash((void*) save_result.vdec, sizeof(my_decimal), DECIMAL_RESULT, - &my_charset_bin, DERIVATION_IMPLICIT); + &my_charset_bin, DERIVATION_IMPLICIT, 0); break; } case ROW_RESULT: diff --git a/sql/item_func.h b/sql/item_func.h index c15b0b854b0..31adc033034 100644 --- a/sql/item_func.h +++ b/sql/item_func.h @@ -187,6 +187,8 @@ public: } bool walk(Item_processor processor, byte *arg); Item *transform(Item_transformer transformer, byte *arg); + Item* compile(Item_analyzer analyzer, byte **arg_p, + Item_transformer transformer, byte *arg_t); void traverse_cond(Cond_traverser traverser, void * arg, traverse_order order); bool is_expensive_processor(byte *arg); @@ -889,6 +891,7 @@ public: if (arg_count) max_length= args[0]->max_length; } + bool fix_fields(THD *thd, Item **ref); }; @@ -1173,7 +1176,7 @@ public: String *val_str(String *str); my_decimal *val_decimal(my_decimal *); bool update_hash(void *ptr, uint length, enum Item_result type, - CHARSET_INFO *cs, Derivation dv, bool unsigned_arg= 0); + CHARSET_INFO *cs, Derivation dv, bool unsigned_arg); bool send(Protocol *protocol, String *str_arg); void make_field(Send_field *tmp_field); bool check(bool use_result_field); diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index 2acd1371ce5..31c2f44fc3e 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -1149,12 +1149,13 @@ void Item_func_substr::fix_length_and_dec() } if (arg_count == 3 && args[2]->const_item()) { - int32 length= (int32) args[2]->val_int() * collation.collation->mbmaxlen; + int32 length= (int32) args[2]->val_int(); if (length <= 0) max_length=0; /* purecov: inspected */ else set_if_smaller(max_length,(uint) length); } + max_length*= collation.collation->mbmaxlen; } @@ -2381,17 +2382,33 @@ String *Item_func_conv::val_str(String *str) abs(to_base) > 36 || abs(to_base) < 2 || abs(from_base) > 36 || abs(from_base) < 2 || !(res->length())) { - null_value=1; - return 0; + null_value= 1; + return NULL; } - null_value=0; + null_value= 0; unsigned_flag= !(from_base < 0); - if (from_base < 0) - dec= my_strntoll(res->charset(),res->ptr(),res->length(),-from_base,&endptr,&err); + + if (args[0]->field_type() == MYSQL_TYPE_BIT) + { + /* + Special case: The string representation of BIT doesn't resemble the + decimal representation, so we shouldn't change it to string and then to + decimal. + */ + dec= args[0]->val_int(); + } else - dec= (longlong) my_strntoull(res->charset(),res->ptr(),res->length(),from_base,&endptr,&err); - ptr= longlong2str(dec,ans,to_base); - if (str->copy(ans,(uint32) (ptr-ans), default_charset())) + { + if (from_base < 0) + dec= my_strntoll(res->charset(), res->ptr(), res->length(), + -from_base, &endptr, &err); + else + dec= (longlong) my_strntoull(res->charset(), res->ptr(), res->length(), + from_base, &endptr, &err); + } + + ptr= longlong2str(dec, ans, to_base); + if (str->copy(ans, (uint32) (ptr-ans), default_charset())) return &my_empty_string; return str; } diff --git a/sql/item_sum.cc b/sql/item_sum.cc index bcd8270e52f..5ca1dbba94b 100644 --- a/sql/item_sum.cc +++ b/sql/item_sum.cc @@ -246,7 +246,27 @@ bool Item_sum::register_sum_func(THD *thd, Item **ref) aggr_sl->inner_sum_func_list->next= this; } aggr_sl->inner_sum_func_list= this; - + aggr_sl->with_sum_func= 1; + + /* + Mark Item_subselect(s) as containing aggregate function all the way up + to aggregate function's calculation context. + Note that we must not mark the Item of calculation context itself + because with_sum_func on the calculation context st_select_lex is + already set above. + + with_sum_func being set for an Item means that this Item refers + (somewhere in it, e.g. one of its arguments if it's a function) directly + or through intermediate items to an aggregate function that is calculated + in a context "outside" of the Item (e.g. in the current or outer select). + + with_sum_func being set for an st_select_lex means that this st_select_lex + has aggregate functions directly referenced (i.e. not through a sub-select). + */ + for (sl= thd->lex->current_select; + sl && sl != aggr_sl && sl->master_unit()->item; + sl= sl->master_unit()->outer_select() ) + sl->master_unit()->item->with_sum_func= 1; } return FALSE; } diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc index 30230005f6e..48d6458bd88 100644 --- a/sql/item_timefunc.cc +++ b/sql/item_timefunc.cc @@ -65,7 +65,7 @@ static bool make_datetime(date_time_format_types format, TIME *ltime, ltime->hour, ltime->minute, ltime->second); break; case TIME_MICROSECOND: - length= cs->cset->snprintf(cs, buff, length, "%s%02d:%02d:%02d.%06d", + length= cs->cset->snprintf(cs, buff, length, "%s%02d:%02d:%02d.%06ld", ltime->neg ? "-" : "", ltime->hour, ltime->minute, ltime->second, ltime->second_part); @@ -82,7 +82,7 @@ static bool make_datetime(date_time_format_types format, TIME *ltime, break; case DATE_TIME_MICROSECOND: length= cs->cset->snprintf(cs, buff, length, - "%04d-%02d-%02d %02d:%02d:%02d.%06d", + "%04d-%02d-%02d %02d:%02d:%02d.%06ld", ltime->year, ltime->month, ltime->day, ltime->hour, ltime->minute, ltime->second, ltime->second_part); diff --git a/sql/key.cc b/sql/key.cc index 75161e4f616..5e658312352 100644 --- a/sql/key.cc +++ b/sql/key.cc @@ -18,6 +18,7 @@ /* Functions to handle keys and fields in forms */ #include "mysql_priv.h" +#include "sql_trigger.h" /* ** Search after with key field is. If no key starts with field test @@ -342,12 +343,24 @@ void key_unpack(String *to,TABLE *table,uint idx) /* - Return 1 if any field in a list is part of key or the key uses a field - that is automaticly updated (like a timestamp) + Check if key uses field that is listed in passed field list or is + automatically updated (like a timestamp) or can be updated by before + update trigger defined on the table. + + SYNOPSIS + is_key_used() + table TABLE object with which keys and fields are associated. + idx Key to be checked. + fields List of fields to be checked. + + RETURN VALUE + TRUE Key uses field which meets one the above conditions + FALSE Otherwise */ -bool check_if_key_used(TABLE *table, uint idx, List &fields) +bool is_key_used(TABLE *table, uint idx, List &fields) { + Table_triggers_list *triggers= table->triggers; List_iterator_fast f(fields); KEY_PART_INFO *key_part,*key_part_end; for (key_part=table->key_info[idx].key_part,key_part_end=key_part+ @@ -366,6 +379,9 @@ bool check_if_key_used(TABLE *table, uint idx, List &fields) if (key_part->field->eq(field->field)) return 1; } + if (triggers && + triggers->is_updated_in_before_update_triggers(key_part->field)) + return 1; } /* @@ -374,7 +390,7 @@ bool check_if_key_used(TABLE *table, uint idx, List &fields) */ if (idx != table->s->primary_key && table->s->primary_key < MAX_KEY && (table->file->table_flags() & HA_PRIMARY_KEY_IN_READ_INDEX)) - return check_if_key_used(table, table->s->primary_key, fields); + return is_key_used(table, table->s->primary_key, fields); return 0; } diff --git a/sql/log.cc b/sql/log.cc index 1cd01865f9f..960fc4f60c2 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -566,15 +566,18 @@ bool MYSQL_LOG::open(const char *log_name, case LOG_NORMAL: { char *end; - int len=my_snprintf(buff, sizeof(buff), "%s, Version: %s. " + int len=my_snprintf(buff, sizeof(buff), "%s, Version: %s (%s). " #ifdef EMBEDDED_LIBRARY - "embedded library\n", my_progname, server_version + "embedded library\n", + my_progname, server_version, MYSQL_COMPILATION_COMMENT #elif __NT__ "started with:\nTCP Port: %d, Named Pipe: %s\n", - my_progname, server_version, mysqld_port, mysqld_unix_port + my_progname, server_version, MYSQL_COMPILATION_COMMENT, + mysqld_port, mysqld_unix_port #else "started with:\nTcp port: %d Unix socket: %s\n", - my_progname,server_version,mysqld_port,mysqld_unix_port + my_progname, server_version, MYSQL_COMPILATION_COMMENT, + mysqld_port, mysqld_unix_port #endif ); end=strnmov(buff+len,"Time Id Command Argument\n", @@ -1702,7 +1705,7 @@ bool MYSQL_LOG::write(Log_event *event_info) if (thd) { - if (thd->last_insert_id_used) + if (thd->last_insert_id_used_bin_log) { Intvar_log_event e(thd,(uchar) LAST_INSERT_ID_EVENT, thd->current_insert_id); @@ -1994,7 +1997,7 @@ bool MYSQL_LOG::write(THD *thd,const char *query, uint query_length, tmp_errno=errno; strmov(db,thd->db); } - if (thd->last_insert_id_used) + if (thd->last_insert_id_used_bin_log) { end=strmov(end,",last_insert_id="); end=longlong10_to_str((longlong) thd->current_insert_id,end,-10); diff --git a/sql/log_event.cc b/sql/log_event.cc index cf5dbb1e77c..271658d8054 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -3365,7 +3365,6 @@ int Intvar_log_event::exec_event(struct st_relay_log_info* rli) { switch (type) { case LAST_INSERT_ID_EVENT: - thd->last_insert_id_used = 1; thd->last_insert_id = val; break; case INSERT_ID_EVENT: @@ -3846,7 +3845,7 @@ int User_var_log_event::exec_event(struct st_relay_log_info* rli) a single record and with a single column. Thus, like a column value, it could always have IMPLICIT derivation. */ - e.update_hash(val, val_len, type, charset, DERIVATION_IMPLICIT); + e.update_hash(val, val_len, type, charset, DERIVATION_IMPLICIT, 0); free_root(thd->mem_root,0); rli->inc_event_relay_log_pos(); diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index 762c854d180..381f2a989b5 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -131,7 +131,18 @@ MY_LOCALE *my_locale_by_name(const char *name); #define MAX_ACCEPT_RETRY 10 // Test accept this many times #define MAX_FIELDS_BEFORE_HASH 32 #define USER_VARS_HASH_SIZE 16 -#define STACK_MIN_SIZE 8192 // Abort if less stack during eval. + +/* + Value of 9236 discovered through binary search 2006-09-26 on Ubuntu Dapper + Drake, libc6 2.3.6-0ubuntu2, Linux kernel 2.6.15-27-686, on x86. (Added + 100 bytes as reasonable buffer against growth and other environments' + requirements.) + + Feel free to raise this by the smallest amount you can to get the + "execution_constants" test to pass. + */ +#define STACK_MIN_SIZE 9336 // Abort if less stack during eval. + #define STACK_MIN_SIZE_FOR_OPEN 1024*80 #define STACK_BUFF_ALLOC 256 // For stack overrun checks #ifndef MYSQLD_NET_RETRY_COUNT @@ -425,6 +436,7 @@ void view_store_options(THD *thd, st_table_list *table, String *buff); #define TL_OPTION_UPDATING 1 #define TL_OPTION_FORCE_INDEX 2 #define TL_OPTION_IGNORE_LEAVES 4 +#define TL_OPTION_ALIAS 8 /* Some portable defines */ @@ -445,7 +457,8 @@ enum enum_parsing_place NO_MATTER, IN_HAVING, SELECT_LIST, - IN_WHERE + IN_WHERE, + IN_ON }; struct st_table; @@ -566,7 +579,8 @@ void get_default_definer(THD *thd, LEX_USER *definer); LEX_USER *create_default_definer(THD *thd); LEX_USER *create_definer(THD *thd, LEX_STRING *user_name, LEX_STRING *host_name); LEX_USER *get_current_user(THD *thd, LEX_USER *user); -bool check_string_length(LEX_STRING *str, const char *err_msg, uint max_length); +bool check_string_length(LEX_STRING *str, + const char *err_msg, uint max_length); enum enum_mysql_completiontype { ROLLBACK_RELEASE=-2, ROLLBACK=1, ROLLBACK_AND_CHAIN=7, @@ -1111,17 +1125,17 @@ void key_restore(byte *to_record, byte *from_key, KEY *key_info, uint key_length); bool key_cmp_if_same(TABLE *form,const byte *key,uint index,uint key_length); void key_unpack(String *to,TABLE *form,uint index); -bool check_if_key_used(TABLE *table, uint idx, List &fields); +bool is_key_used(TABLE *table, uint idx, List &fields); int key_cmp(KEY_PART_INFO *key_part, const byte *key, uint key_length); bool init_errmessage(void); void sql_perror(const char *message); void vprint_msg_to_log(enum loglevel level, const char *format, va_list args); -void sql_print_error(const char *format, ...); -void sql_print_warning(const char *format, ...); -void sql_print_information(const char *format, ...); - +void sql_print_error(const char *format, ...) ATTRIBUTE_FORMAT(printf, 1, 2); +void sql_print_warning(const char *format, ...) ATTRIBUTE_FORMAT(printf, 1, 2); +void sql_print_information(const char *format, ...) + ATTRIBUTE_FORMAT(printf, 1, 2); bool fn_format_relative_to_data_home(my_string to, const char *name, @@ -1226,7 +1240,6 @@ extern my_bool opt_log_queries_not_using_indexes; extern bool opt_disable_networking, opt_skip_show_db; extern my_bool opt_character_set_client_handshake; extern bool volatile abort_loop, shutdown_in_progress, grant_option; -extern bool mysql_proc_table_exists; extern uint volatile thread_count, thread_running, global_read_lock; extern my_bool opt_sql_bin_update, opt_safe_user_create, opt_no_mix_types; extern my_bool opt_safe_show_db, opt_local_infile; diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 8228dcbb9bd..1dd15398cd1 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -713,7 +713,7 @@ static void close_connections(void) { if (ip_sock != INVALID_SOCKET) { - (void) shutdown(ip_sock,2); + (void) shutdown(ip_sock, SHUT_RDWR); (void) closesocket(ip_sock); ip_sock= INVALID_SOCKET; } @@ -745,7 +745,7 @@ static void close_connections(void) #ifdef HAVE_SYS_UN_H if (unix_sock != INVALID_SOCKET) { - (void) shutdown(unix_sock,2); + (void) shutdown(unix_sock, SHUT_RDWR); (void) closesocket(unix_sock); (void) unlink(mysqld_unix_port); unix_sock= INVALID_SOCKET; @@ -848,7 +848,7 @@ static void close_server_sock() { ip_sock=INVALID_SOCKET; DBUG_PRINT("info",("calling shutdown on TCP/IP socket")); - VOID(shutdown(tmp_sock,2)); + VOID(shutdown(tmp_sock, SHUT_RDWR)); #if defined(__NETWARE__) /* The following code is disabled for normal systems as it causes MySQL @@ -863,7 +863,7 @@ static void close_server_sock() { unix_sock=INVALID_SOCKET; DBUG_PRINT("info",("calling shutdown on unix socket")); - VOID(shutdown(tmp_sock,2)); + VOID(shutdown(tmp_sock, SHUT_RDWR)); #if defined(__NETWARE__) /* The following code is disabled for normal systems as it may cause MySQL @@ -1025,8 +1025,8 @@ extern "C" sig_handler print_signal_warning(int sig) if (!DBUG_IN_USE) { if (global_system_variables.log_warnings) - sql_print_warning("Got signal %d from thread %d", - sig,my_thread_id()); + sql_print_warning("Got signal %d from thread %ld", + sig, my_thread_id()); } #ifdef DONT_REMEMBER_SIGNAL my_sigset(sig,print_signal_warning); /* int. thread system calls */ @@ -1531,8 +1531,8 @@ static void network_init(void) if (strlen(mysqld_unix_port) > (sizeof(UNIXaddr.sun_path) - 1)) { - sql_print_error("The socket file path is too long (> %d): %s", - sizeof(UNIXaddr.sun_path) - 1, mysqld_unix_port); + sql_print_error("The socket file path is too long (> %lu): %s", + sizeof(UNIXaddr.sun_path) - 1, mysqld_unix_port); unireg_abort(1); } if ((unix_sock= socket(AF_UNIX, SOCK_STREAM, 0)) < 0) @@ -2912,7 +2912,7 @@ static void openssl_lock(int mode, openssl_lock_t *lock, const char *file, } if (err) { - sql_print_error("Fatal: can't %s OpenSSL %s lock", what); + sql_print_error("Fatal: can't %s OpenSSL lock", what); abort(); } } @@ -4088,7 +4088,7 @@ pthread_handler_t handle_connections_sockets(void *arg __attribute__((unused))) if (req.sink) ((void (*)(int))req.sink)(req.fd); - (void) shutdown(new_sock,2); + (void) shutdown(new_sock, SHUT_RDWR); (void) closesocket(new_sock); continue; } @@ -4103,7 +4103,7 @@ pthread_handler_t handle_connections_sockets(void *arg __attribute__((unused))) if (getsockname(new_sock,&dummy, &dummyLen) < 0) { sql_perror("Error on new connection socket"); - (void) shutdown(new_sock,2); + (void) shutdown(new_sock, SHUT_RDWR); (void) closesocket(new_sock); continue; } @@ -4115,7 +4115,7 @@ pthread_handler_t handle_connections_sockets(void *arg __attribute__((unused))) if (!(thd= new THD)) { - (void) shutdown(new_sock,2); + (void) shutdown(new_sock, SHUT_RDWR); VOID(closesocket(new_sock)); continue; } @@ -4129,7 +4129,7 @@ pthread_handler_t handle_connections_sockets(void *arg __attribute__((unused))) vio_delete(vio_tmp); else { - (void) shutdown(new_sock,2); + (void) shutdown(new_sock, SHUT_RDWR); (void) closesocket(new_sock); } delete thd; @@ -7042,15 +7042,16 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)), exit(1); } switch (method-1) { - case 0: - method_conv= MI_STATS_METHOD_NULLS_EQUAL; - break; - case 1: - method_conv= MI_STATS_METHOD_NULLS_NOT_EQUAL; - break; case 2: method_conv= MI_STATS_METHOD_IGNORE_NULLS; break; + case 1: + method_conv= MI_STATS_METHOD_NULLS_EQUAL; + break; + case 0: + default: + method_conv= MI_STATS_METHOD_NULLS_NOT_EQUAL; + break; } global_system_variables.myisam_stats_method= method_conv; break; diff --git a/sql/opt_range.cc b/sql/opt_range.cc index 6189d0412b3..737a296e1d7 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -1034,10 +1034,7 @@ int QUICK_RANGE_SELECT::init_ror_merged_scan(bool reuse_handler) } THD *thd= current_thd; - if (!(file= get_new_handler(head, thd->mem_root, head->s->db_type))) - goto failure; - DBUG_PRINT("info", ("Allocated new handler %p", file)); - if (file->ha_open(head->s->path, head->db_stat, HA_OPEN_IGNORE_IF_LOCKED)) + if (!(file= head->file->clone(thd->mem_root))) { /* Caller will free the memory */ goto failure; @@ -5562,8 +5559,9 @@ void SEL_ARG::test_use_count(SEL_ARG *root) ulong count=count_key_part_usage(root,pos->next_key_part); if (count > pos->next_key_part->use_count) { - sql_print_information("Use_count: Wrong count for key at 0x%lx, %lu should be %lu", - pos,pos->next_key_part->use_count,count); + sql_print_information("Use_count: Wrong count for key at 0x%lx, %lu " + "should be %lu", (long unsigned int)pos, + pos->next_key_part->use_count, count); return; } pos->next_key_part->test_use_count(root); @@ -5571,7 +5569,7 @@ void SEL_ARG::test_use_count(SEL_ARG *root) } if (e_count != elements) sql_print_warning("Wrong use count: %u (should be %u) for tree at 0x%lx", - e_count, elements, (gptr) this); + e_count, elements, (long unsigned int) this); } #endif @@ -6130,42 +6128,42 @@ static bool null_part_in_key(KEY_PART *key_part, const char *key, uint length) } -bool QUICK_SELECT_I::check_if_keys_used(List *fields) +bool QUICK_SELECT_I::is_keys_used(List *fields) { - return check_if_key_used(head, index, *fields); + return is_key_used(head, index, *fields); } -bool QUICK_INDEX_MERGE_SELECT::check_if_keys_used(List *fields) +bool QUICK_INDEX_MERGE_SELECT::is_keys_used(List *fields) { QUICK_RANGE_SELECT *quick; List_iterator_fast it(quick_selects); while ((quick= it++)) { - if (check_if_key_used(head, quick->index, *fields)) + if (is_key_used(head, quick->index, *fields)) return 1; } return 0; } -bool QUICK_ROR_INTERSECT_SELECT::check_if_keys_used(List *fields) +bool QUICK_ROR_INTERSECT_SELECT::is_keys_used(List *fields) { QUICK_RANGE_SELECT *quick; List_iterator_fast it(quick_selects); while ((quick= it++)) { - if (check_if_key_used(head, quick->index, *fields)) + if (is_key_used(head, quick->index, *fields)) return 1; } return 0; } -bool QUICK_ROR_UNION_SELECT::check_if_keys_used(List *fields) +bool QUICK_ROR_UNION_SELECT::is_keys_used(List *fields) { QUICK_SELECT_I *quick; List_iterator_fast it(quick_selects); while ((quick= it++)) { - if (quick->check_if_keys_used(fields)) + if (quick->is_keys_used(fields)) return 1; } return 0; @@ -6724,7 +6722,6 @@ int QUICK_RANGE_SELECT::get_next() } } - /* Get the next record with a different prefix. @@ -9378,7 +9375,6 @@ static void print_ror_scans_arr(TABLE *table, const char *msg, DBUG_VOID_RETURN; } - /***************************************************************************** ** Print a quick range for debugging ** TODO: diff --git a/sql/opt_range.h b/sql/opt_range.h index 9474f2d469f..40a95beb894 100644 --- a/sql/opt_range.h +++ b/sql/opt_range.h @@ -225,8 +225,9 @@ public: Return 1 if any index used by this quick select a) uses field that is listed in passed field list or b) is automatically updated (like a timestamp) + c) can be updated by one of before update triggers defined on table */ - virtual bool check_if_keys_used(List *fields); + virtual bool is_keys_used(List *fields); /* rowid of last row retrieved by this quick select. This is used only when @@ -423,7 +424,7 @@ public: int get_type() { return QS_TYPE_INDEX_MERGE; } void add_keys_and_lengths(String *key_names, String *used_lengths); void add_info_string(String *str); - bool check_if_keys_used(List *fields); + bool is_keys_used(List *fields); #ifndef DBUG_OFF void dbug_dump(int indent, bool verbose); #endif @@ -482,7 +483,7 @@ public: int get_type() { return QS_TYPE_ROR_INTERSECT; } void add_keys_and_lengths(String *key_names, String *used_lengths); void add_info_string(String *str); - bool check_if_keys_used(List *fields); + bool is_keys_used(List *fields); #ifndef DBUG_OFF void dbug_dump(int indent, bool verbose); #endif @@ -536,7 +537,7 @@ public: int get_type() { return QS_TYPE_ROR_UNION; } void add_keys_and_lengths(String *key_names, String *used_lengths); void add_info_string(String *str); - bool check_if_keys_used(List *fields); + bool is_keys_used(List *fields); #ifndef DBUG_OFF void dbug_dump(int indent, bool verbose); #endif diff --git a/sql/opt_sum.cc b/sql/opt_sum.cc index 1f6190241a3..d17c42bca38 100644 --- a/sql/opt_sum.cc +++ b/sql/opt_sum.cc @@ -191,7 +191,7 @@ int opt_sum_query(TABLE_LIST *tables, List &all_fields,COND *conds) Type of range for the key part for this field will be returned in range_fl. */ - if ((outer_tables & table->map) || + if (table->file->inited || (outer_tables & table->map) || !find_key_for_maxmin(0, &ref, item_field->field, conds, &range_fl, &prefix_len)) { @@ -278,7 +278,7 @@ int opt_sum_query(TABLE_LIST *tables, List &all_fields,COND *conds) Type of range for the key part for this field will be returned in range_fl. */ - if ((outer_tables & table->map) || + if (table->file->inited || (outer_tables & table->map) || !find_key_for_maxmin(1, &ref, item_field->field, conds, &range_fl, &prefix_len)) { diff --git a/sql/set_var.cc b/sql/set_var.cc index c667e2f2bcc..d0268d7017b 100644 --- a/sql/set_var.cc +++ b/sql/set_var.cc @@ -1255,8 +1255,8 @@ static void fix_tx_isolation(THD *thd, enum_var_type type) thd->variables.tx_isolation); } -static void fix_completion_type(THD *thd __attribute__(unused), - enum_var_type type __attribute__(unused)) {} +static void fix_completion_type(THD *thd __attribute__((unused)), + enum_var_type type __attribute__((unused))) {} static int check_completion_type(THD *thd, set_var *var) { @@ -1295,14 +1295,14 @@ static void fix_net_retry_count(THD *thd, enum_var_type type) thd->net.retry_count=thd->variables.net_retry_count; } #else /* HAVE_REPLICATION */ -static void fix_net_read_timeout(THD *thd __attribute__(unused), - enum_var_type type __attribute__(unused)) +static void fix_net_read_timeout(THD *thd __attribute__((unused)), + enum_var_type type __attribute__((unused))) {} -static void fix_net_write_timeout(THD *thd __attribute__(unused), - enum_var_type type __attribute__(unused)) +static void fix_net_write_timeout(THD *thd __attribute__((unused)), + enum_var_type type __attribute__((unused))) {} -static void fix_net_retry_count(THD *thd __attribute__(unused), - enum_var_type type __attribute__(unused)) +static void fix_net_retry_count(THD *thd __attribute__((unused)), + enum_var_type type __attribute__((unused))) {} #endif /* HAVE_REPLICATION */ @@ -2571,8 +2571,18 @@ bool sys_var_last_insert_id::update(THD *thd, set_var *var) byte *sys_var_last_insert_id::value_ptr(THD *thd, enum_var_type type, LEX_STRING *base) { - thd->sys_var_tmp.long_value= (long) thd->insert_id(); - return (byte*) &thd->last_insert_id; + if (!thd->last_insert_id_used) + { + /* + As this statement reads @@LAST_INSERT_ID, set + THD::last_insert_id_used and remember first generated insert id + of the previous statement in THD::current_insert_id. + */ + thd->last_insert_id_used= TRUE; + thd->last_insert_id_used_bin_log= TRUE; + thd->current_insert_id= thd->last_insert_id; + } + return (byte*) &thd->current_insert_id; } diff --git a/sql/share/errmsg.txt b/sql/share/errmsg.txt index d10f66e3878..2b6d2b18f88 100644 --- a/sql/share/errmsg.txt +++ b/sql/share/errmsg.txt @@ -3813,7 +3813,7 @@ ER_WRONG_MRG_TABLE cze "V-B¹echny tabulky v MERGE tabulce nejsou definovány stejnì" dan "Tabellerne i MERGE er ikke defineret ens" nla "Niet alle tabellen in de MERGE tabel hebben identieke gedefinities" - eng "All tables in the MERGE table are not identically defined" + eng "Unable to open underlying table which is differently defined or of non-MyISAM type or doesn't exist" est "Kõik tabelid MERGE tabeli määratluses ei ole identsed" fre "Toutes les tables de la table de type MERGE n'ont pas la même définition" ger "Nicht alle Tabellen in der MERGE-Tabelle sind gleich definiert" @@ -5623,9 +5623,14 @@ ER_NO_TRIGGERS_ON_SYSTEM_SCHEMA eng "Triggers can not be created on system tables" ER_REMOVED_SPACES eng "Leading spaces are removed from name '%s'" +ER_AUTOINC_READ_FAILED + eng "Failed to read auto-increment value from storage engine" ER_USERNAME eng "user name" ER_HOSTNAME eng "host name" ER_WRONG_STRING_LENGTH eng "String '%-.70s' is too long for %s (should be no longer than %d)" +ER_NON_INSERTABLE_TABLE + eng "The target table %-.100s of the %s is not insertable-into" + diff --git a/sql/slave.cc b/sql/slave.cc index 55cff94a179..28bb7f12008 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -4613,7 +4613,7 @@ static int connect_to_master(THD* thd, MYSQL* mysql, MASTER_INFO* mi, suppress_warnings= 0; sql_print_error("Slave I/O thread: error %s to master \ '%s@%s:%d': \ -Error: '%s' errno: %d retry-time: %d retries: %d", +Error: '%s' errno: %d retry-time: %d retries: %lu", (reconnect ? "reconnecting" : "connecting"), mi->user,mi->host,mi->port, mysql_error(mysql), last_errno, diff --git a/sql/slave.h b/sql/slave.h index c355f7172a9..65adb4564cc 100644 --- a/sql/slave.h +++ b/sql/slave.h @@ -553,7 +553,8 @@ void init_table_rule_array(DYNAMIC_ARRAY* a, bool* a_inited); const char *print_slave_db_safe(const char *db); int check_expected_error(THD* thd, RELAY_LOG_INFO* rli, int error_code); void skip_load_data_infile(NET* net); -void slave_print_error(RELAY_LOG_INFO* rli, int err_code, const char* msg, ...); +void slave_print_error(RELAY_LOG_INFO *rli, int err_code, const char *msg, ...) + ATTRIBUTE_FORMAT(printf, 3, 4); void end_slave(); /* clean up */ void init_master_info_with_options(MASTER_INFO* mi); diff --git a/sql/sp.cc b/sql/sp.cc index fc72822c15e..49dbed79fe5 100644 --- a/sql/sp.cc +++ b/sql/sp.cc @@ -66,8 +66,6 @@ enum MYSQL_PROC_FIELD_COUNT }; -bool mysql_proc_table_exists= 1; - /* Tells what SP_DEFAULT_ACCESS should be mapped to */ #define SP_DEFAULT_ACCESS_MAPPING SP_CONTAINS_SQL @@ -119,13 +117,6 @@ TABLE *open_proc_table_for_read(THD *thd, Open_tables_state *backup) bool not_used; DBUG_ENTER("open_proc_table"); - /* - Speed up things if mysql.proc doesn't exists. mysql_proc_table_exists - is set when we create or read stored procedure or on flush privileges. - */ - if (!mysql_proc_table_exists) - DBUG_RETURN(0); - thd->reset_n_backup_open_tables_state(backup); bzero((char*) &tables, sizeof(tables)); @@ -135,7 +126,6 @@ TABLE *open_proc_table_for_read(THD *thd, Open_tables_state *backup) MYSQL_LOCK_IGNORE_FLUSH))) { thd->restore_backup_open_tables_state(backup); - mysql_proc_table_exists= 0; DBUG_RETURN(0); } @@ -184,15 +174,6 @@ static TABLE *open_proc_table_for_update(THD *thd) table= open_ltable(thd, &tables, TL_WRITE); - /* - Under explicit LOCK TABLES or in prelocked mode we should not - say that mysql.proc table does not exist if we are unable to - open and lock it for writing since this condition may be - transient. - */ - if (!(thd->locked_tables || thd->prelocked_mode) || table) - mysql_proc_table_exists= test(table); - DBUG_RETURN(table); } @@ -1610,14 +1591,6 @@ sp_cache_routines_and_add_tables_aux(THD *thd, LEX *lex, case SP_KEY_NOT_FOUND: ret= SP_OK; break; - case SP_OPEN_TABLE_FAILED: - /* - Force it to attempt opening it again on subsequent calls; - otherwise we will get one error message the first time, and - then ER_SP_PROC_TABLE_CORRUPT (below) on subsequent tries. - */ - mysql_proc_table_exists= 1; - /* Fall through */ default: /* Any error when loading an existing routine is either some problem @@ -1633,7 +1606,17 @@ sp_cache_routines_and_add_tables_aux(THD *thd, LEX *lex, */ if (!thd->net.report_error) { - char n[NAME_LEN*2+2]; + /* + SP allows full NAME_LEN chars thus he have to allocate enough + size in bytes. Otherwise there is stack overrun could happen + if multibyte sequence is `name`. `db` is still safe because the + rest of the server checks agains NAME_LEN bytes and not chars. + Hence, the overrun happens only if the name is in length > 32 and + uses multibyte (cyrillic, greek, etc.) + + !! Change 3 with SYSTEM_CHARSET_MBMAXLEN when it's defined. + */ + char n[NAME_LEN*3*2+2]; /* m_qname.str is not always \0 terminated */ memcpy(n, name.m_qname.str, name.m_qname.length); diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index e97985fbd45..50cee6eeca4 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -202,7 +202,6 @@ static my_bool acl_load(THD *thd, TABLE_LIST *tables) DBUG_ENTER("acl_load"); grant_version++; /* Privileges updated */ - mysql_proc_table_exists= 1; // Assume mysql.proc exists acl_cache->clear(1); // Clear locked hostname cache @@ -3231,7 +3230,7 @@ bool mysql_grant(THD *thd, const char *db, List &list, { result= TRUE; continue; - } + } if (replace_user_table(thd, tables[0].table, *Str, (!db ? rights : 0), revoke_grant, create_new_users, test(thd->variables.sql_mode & diff --git a/sql/sql_analyse.cc b/sql/sql_analyse.cc index af9246c673a..62b6d4f7920 100644 --- a/sql/sql_analyse.cc +++ b/sql/sql_analyse.cc @@ -807,9 +807,9 @@ void field_str::get_opt_type(String *answer, ha_rows total_rows) else if (num_info.decimals) // DOUBLE(%d,%d) sometime { if (num_info.dval > -FLT_MAX && num_info.dval < FLT_MAX) - sprintf(buff, "FLOAT(%d,%d)", num_info.integers, num_info.decimals); + sprintf(buff, "FLOAT(%d,%d)", (num_info.integers + num_info.decimals), num_info.decimals); else - sprintf(buff, "DOUBLE(%d,%d)", num_info.integers, num_info.decimals); + sprintf(buff, "DOUBLE(%d,%d)", (num_info.integers + num_info.decimals), num_info.decimals); } else if (ev_num_info.llval >= -128 && ev_num_info.ullval <= @@ -916,10 +916,10 @@ void field_real::get_opt_type(String *answer, else { if (min_arg >= -FLT_MAX && max_arg <= FLT_MAX) - sprintf(buff, "FLOAT(%d,%d)", (int) max_length - (item->decimals + 1), + sprintf(buff, "FLOAT(%d,%d)", (int) max_length - (item->decimals + 1) + max_notzero_dec_len, max_notzero_dec_len); else - sprintf(buff, "DOUBLE(%d,%d)", (int) max_length - (item->decimals + 1), + sprintf(buff, "DOUBLE(%d,%d)", (int) max_length - (item->decimals + 1) + max_notzero_dec_len, max_notzero_dec_len); answer->append(buff, (uint) strlen(buff)); } diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 3a12477bc15..85be84d1270 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -902,8 +902,11 @@ void update_non_unique_table_error(TABLE_LIST *update, */ if (update->view) { + /* Issue the ER_NON_INSERTABLE_TABLE error for an INSERT */ if (update->view == duplicate->view) - my_error(ER_NON_UPDATABLE_TABLE, MYF(0), update->alias, operation); + my_error(!strncmp(operation, "INSERT", 6) ? + ER_NON_INSERTABLE_TABLE : ER_NON_UPDATABLE_TABLE, MYF(0), + update->alias, operation); else my_error(ER_VIEW_PREVENT_UPDATE, MYF(0), (duplicate->view ? duplicate->alias : update->alias), @@ -4453,7 +4456,20 @@ bool setup_tables(THD *thd, Name_resolution_context *context, uint tablenr= 0; DBUG_ENTER("setup_tables"); - context->table_list= context->first_name_resolution_table= tables; + /* + Due to the various call paths that lead to setup_tables() it may happen + that context->table_list and context->first_name_resolution_table can be + NULL (this is typically done when creating TABLE_LISTs internally). + TODO: + Investigate all cases when this my happen, initialize the name resolution + context correctly in all those places, and remove the context reset below. + */ + if (!context->table_list || !context->first_name_resolution_table) + { + /* Test whether the context is in a consistent state. */ + DBUG_ASSERT(!context->first_name_resolution_table && !context->table_list); + context->table_list= context->first_name_resolution_table= tables; + } /* this is used for INSERT ... SELECT. diff --git a/sql/sql_class.cc b/sql/sql_class.cc index 093173ab949..645ac6e28f3 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -179,9 +179,9 @@ THD::THD() lock_id(&main_lock_id), user_time(0), in_sub_stmt(0), global_read_lock(0), is_fatal_error(0), rand_used(0), time_zone_used(0), - last_insert_id_used(0), insert_id_used(0), clear_next_insert_id(0), - in_lock_tables(0), bootstrap(0), derived_tables_processing(FALSE), - spcont(NULL) + last_insert_id_used(0), last_insert_id_used_bin_log(0), insert_id_used(0), + clear_next_insert_id(0), in_lock_tables(0), bootstrap(0), + derived_tables_processing(FALSE), spcont(NULL) { stmt_arena= this; thread_stack= 0; @@ -553,10 +553,25 @@ bool THD::store_globals() } -/* Cleanup after a query */ +/* + Cleanup after query. + + SYNOPSIS + THD::cleanup_after_query() + + DESCRIPTION + This function is used to reset thread data to its default state. + + NOTE + This function is not suitable for setting thread data to some + non-default values, as there is only one replication thread, so + different master threads may overwrite data of each other on + slave. +*/ void THD::cleanup_after_query() { + last_insert_id_used= FALSE; if (clear_next_insert_id) { clear_next_insert_id= 0; @@ -568,6 +583,7 @@ void THD::cleanup_after_query() where= THD::DEFAULT_WHERE; } + /* Convert a string to another character set diff --git a/sql/sql_class.h b/sql/sql_class.h index 039c133e885..62cfb0119aa 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -306,7 +306,7 @@ public: const char *log_name); void new_file(bool need_lock); bool write(THD *thd, enum enum_server_command command, - const char *format,...); + const char *format, ...) ATTRIBUTE_FORMAT(printf, 4, 5); bool write(THD *thd, const char *query, uint query_length, time_t query_start=0); bool write(Log_event* event_info); // binary log write @@ -1252,17 +1252,29 @@ public: ulonglong next_insert_id; /* Remember last next_insert_id to reset it if something went wrong */ ulonglong prev_insert_id; + /* - The insert_id used for the last statement or set by SET LAST_INSERT_ID=# - or SELECT LAST_INSERT_ID(#). Used for binary log and returned by - LAST_INSERT_ID() + At the beginning of the statement last_insert_id holds the first + generated value of the previous statement. During statement + execution it is updated to the value just generated, but then + restored to the value that was generated first, so for the next + statement it will again be "the first generated value of the + previous statement". + + It may also be set with "LAST_INSERT_ID(expr)" or + "@@LAST_INSERT_ID= expr", but the effect of such setting will be + seen only in the next statement. */ ulonglong last_insert_id; + /* - Set to the first value that LAST_INSERT_ID() returned for the last - statement. When this is set, last_insert_id_used is set to true. + current_insert_id remembers the first generated value of the + previous statement, and does not change during statement + execution. Its value returned from LAST_INSERT_ID() and + @@LAST_INSERT_ID. */ ulonglong current_insert_id; + ulonglong limit_found_rows; ulonglong options; /* Bitmap of states */ longlong row_count_func; /* For the ROW_COUNT() function */ @@ -1325,7 +1337,31 @@ public: bool last_cuted_field; bool no_errors, password, is_fatal_error; bool query_start_used, rand_used, time_zone_used; - bool last_insert_id_used,insert_id_used, clear_next_insert_id; + + /* + last_insert_id_used is set when current statement calls + LAST_INSERT_ID() or reads @@LAST_INSERT_ID. + */ + bool last_insert_id_used; + + /* + last_insert_id_used is set when current statement or any stored + function called from this statement calls LAST_INSERT_ID() or + reads @@LAST_INSERT_ID, so that binary log LAST_INSERT_ID_EVENT be + generated. Required for statement-based binary log for issuing + "SET LAST_INSERT_ID= #" before "SELECT func()", if func() reads + LAST_INSERT_ID. + */ + bool last_insert_id_used_bin_log; + + /* + insert_id_used is set when current statement updates + THD::last_insert_id, so that binary log INSERT_ID_EVENT be + generated. + */ + bool insert_id_used; + + bool clear_next_insert_id; /* for IS NULL => = last_insert_id() fix in remove_eq_conds() */ bool substitute_null_with_insert_id; bool in_lock_tables; @@ -1461,15 +1497,6 @@ public: insert_id_used=1; substitute_null_with_insert_id= TRUE; } - inline ulonglong insert_id(void) - { - if (!last_insert_id_used) - { - last_insert_id_used=1; - current_insert_id=last_insert_id; - } - return last_insert_id; - } inline ulonglong found_rows(void) { return limit_found_rows; diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc index e420022b8a1..c95fb5d5973 100644 --- a/sql/sql_delete.cc +++ b/sql/sql_delete.cc @@ -342,6 +342,7 @@ cleanup: */ bool mysql_prepare_delete(THD *thd, TABLE_LIST *table_list, Item **conds) { + Item *fake_conds= 0; SELECT_LEX *select_lex= &thd->lex->select_lex; DBUG_ENTER("mysql_prepare_delete"); @@ -367,7 +368,7 @@ bool mysql_prepare_delete(THD *thd, TABLE_LIST *table_list, Item **conds) DBUG_RETURN(TRUE); } } - select_lex->fix_prepare_information(thd, conds); + select_lex->fix_prepare_information(thd, conds, &fake_conds); DBUG_RETURN(FALSE); } diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index c08deedea72..2ce83caa369 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -111,7 +111,7 @@ static int check_insert_fields(THD *thd, TABLE_LIST *table_list, if (!table_list->updatable) { - my_error(ER_NON_UPDATABLE_TABLE, MYF(0), table_list->alias, "INSERT"); + my_error(ER_NON_INSERTABLE_TABLE, MYF(0), table_list->alias, "INSERT"); return -1; } @@ -214,7 +214,7 @@ static int check_insert_fields(THD *thd, TABLE_LIST *table_list, (table_list->view && check_view_insertability(thd, table_list))) { - my_error(ER_NON_UPDATABLE_TABLE, MYF(0), table_list->alias, "INSERT"); + my_error(ER_NON_INSERTABLE_TABLE, MYF(0), table_list->alias, "INSERT"); return -1; } @@ -411,6 +411,15 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list, table= table_list->table; context= &thd->lex->select_lex.context; + /* + These three asserts test the hypothesis that the resetting of the name + resolution context below is not necessary at all since the list of local + tables for INSERT always consists of one table. + */ + DBUG_ASSERT(!table_list->next_local); + DBUG_ASSERT(!context->table_list->next_local); + DBUG_ASSERT(!context->first_name_resolution_table->next_name_resolution_table); + /* Save the state of the current name resolution context. */ ctx_state.save_state(context, table_list); @@ -581,10 +590,8 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list, #endif error=write_record(thd, table ,&info); /* - If auto_increment values are used, save the first one - for LAST_INSERT_ID() and for the update log. - We can't use insert_id() as we don't want to touch the - last_insert_id_used flag. + If auto_increment values are used, save the first one for + LAST_INSERT_ID() and for the update log. */ if (! id && thd->insert_id_used) { // Get auto increment value @@ -993,7 +1000,7 @@ bool mysql_prepare_insert(THD *thd, TABLE_LIST *table_list, update_non_unique_table_error(table_list, "INSERT", duplicate); DBUG_RETURN(TRUE); } - select_lex->fix_prepare_information(thd, &fake_conds); + select_lex->fix_prepare_information(thd, &fake_conds, &fake_conds); select_lex->first_execution= 0; } if (duplic == DUP_UPDATE || duplic == DUP_REPLACE) @@ -1294,6 +1301,9 @@ public: time_t start_time; bool query_start_used,last_insert_id_used,insert_id_used, ignore, log_query; ulonglong last_insert_id; + ulonglong next_insert_id; + ulong auto_increment_increment; + ulong auto_increment_offset; timestamp_auto_set_type timestamp_field_type; uint query_length; @@ -1675,6 +1685,22 @@ static int write_delayed(THD *thd,TABLE *table,enum_duplicates duplic, bool igno row->last_insert_id= thd->last_insert_id; row->timestamp_field_type= table->timestamp_field_type; + /* The session variable settings can always be copied. */ + row->auto_increment_increment= thd->variables.auto_increment_increment; + row->auto_increment_offset= thd->variables.auto_increment_offset; + /* + Next insert id must be set for the first value in a multi-row insert + only. So clear it after the first use. Assume a multi-row insert. + Since the user thread doesn't really execute the insert, + thd->next_insert_id is left untouched between the rows. If we copy + the same insert id to every row of the multi-row insert, the delayed + insert thread would copy this before inserting every row. Thus it + tries to insert all rows with the same insert id. This fails on the + unique constraint. So just the first row would be really inserted. + */ + row->next_insert_id= thd->next_insert_id; + thd->next_insert_id= 0; + di->rows.push_back(row); di->stacked_inserts++; di->status=1; @@ -2046,6 +2072,14 @@ bool delayed_insert::handle_inserts(void) thd.insert_id_used=row->insert_id_used; table->timestamp_field_type= row->timestamp_field_type; + /* The session variable settings can always be copied. */ + thd.variables.auto_increment_increment= row->auto_increment_increment; + thd.variables.auto_increment_offset= row->auto_increment_offset; + /* Next insert id must be used only if non-zero. */ + if (row->next_insert_id) + thd.next_insert_id= row->next_insert_id; + DBUG_PRINT("loop", ("next_insert_id: %lu", (ulong) thd.next_insert_id)); + info.ignore= row->ignore; info.handle_duplicates= row->dup; if (info.ignore || @@ -2067,6 +2101,20 @@ bool delayed_insert::handle_inserts(void) info.error_count++; // Ignore errors thread_safe_increment(delayed_insert_errors,&LOCK_delayed_status); row->log_query = 0; + /* + We must reset next_insert_id. Otherwise all following rows may + become duplicates. If write_record() failed on a duplicate and + next_insert_id would be left unchanged, the next rows would also + be tried with the same insert id and would fail. Since the end + of a multi-row statement is unknown here, all following rows in + the queue would be dropped, regardless which thread added them. + After the queue is used up, next_insert_id is cleared and the + next run will succeed. This could even happen if these come from + the same multi-row statement as the current queue contents. That + way it would look somewhat random which rows are rejected after + a duplicate. + */ + thd.next_insert_id= 0; } if (using_ignore) { @@ -2112,6 +2160,7 @@ bool delayed_insert::handle_inserts(void) /* This should never happen */ table->file->print_error(error,MYF(0)); sql_print_error("%s",thd.net.last_error); + DBUG_PRINT("error", ("HA_EXTRA_NO_CACHE failed in loop")); goto err; } query_cache_invalidate3(&thd, table, 1); @@ -2137,6 +2186,7 @@ bool delayed_insert::handle_inserts(void) { // This shouldn't happen table->file->print_error(error,MYF(0)); sql_print_error("%s",thd.net.last_error); + DBUG_PRINT("error", ("HA_EXTRA_NO_CACHE failed after loop")); goto err; } query_cache_invalidate3(&thd, table, 1); @@ -2144,13 +2194,16 @@ bool delayed_insert::handle_inserts(void) DBUG_RETURN(0); err: + DBUG_EXECUTE("error", max_rows= 0;); /* Remove all not used rows */ while ((row=rows.get())) { delete row; thread_safe_increment(delayed_insert_errors,&LOCK_delayed_status); stacked_inserts--; + DBUG_EXECUTE("error", max_rows++;); } + DBUG_PRINT("error", ("dropped %lu rows after an error", max_rows)); thread_safe_increment(delayed_insert_errors, &LOCK_delayed_status); pthread_mutex_lock(&mutex); DBUG_RETURN(1); @@ -2438,7 +2491,7 @@ bool select_insert::send_data(List &values) */ table->next_number_field->reset(); if (!last_insert_id && thd->insert_id_used) - last_insert_id= thd->insert_id(); + last_insert_id= thd->last_insert_id; } } DBUG_RETURN(error); diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 43aeea2bf53..788276ac654 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -1710,7 +1710,8 @@ bool st_lex::can_be_merged() unit= unit->next_unit()) { if (unit->first_select()->parent_lex == this && - (unit->item == 0 || unit->item->place() != IN_WHERE)) + (unit->item == 0 || + (unit->item->place() != IN_WHERE && unit->item->place() != IN_ON))) { selects_allow_merge= 0; break; @@ -2158,15 +2159,25 @@ static void fix_prepare_info_in_table_list(THD *thd, TABLE_LIST *tbl) /* - fix some structures at the end of preparation + Save WHERE/HAVING/ON clauses and replace them with disposable copies SYNOPSIS st_select_lex::fix_prepare_information - thd thread handler - conds pointer on conditions which will be used for execution statement + thd thread handler + conds in/out pointer to WHERE condition to be met at execution + having_conds in/out pointer to HAVING condition to be met at execution + + DESCRIPTION + The passed WHERE and HAVING are to be saved for the future executions. + This function saves it, and returns a copy which can be thrashed during + this execution of the statement. By saving/thrashing here we mean only + AND/OR trees. + The function also calls fix_prepare_info_in_table_list that saves all + ON expressions. */ -void st_select_lex::fix_prepare_information(THD *thd, Item **conds) +void st_select_lex::fix_prepare_information(THD *thd, Item **conds, + Item **having_conds) { if (!thd->stmt_arena->is_conventional() && first_execution) { @@ -2176,6 +2187,11 @@ void st_select_lex::fix_prepare_information(THD *thd, Item **conds) prep_where= *conds; *conds= where= prep_where->copy_andor_structure(thd); } + if (*having_conds) + { + prep_having= *having_conds; + *having_conds= having= prep_having->copy_andor_structure(thd); + } fix_prepare_info_in_table_list(thd, (TABLE_LIST *)table_list.first); } } diff --git a/sql/sql_lex.h b/sql/sql_lex.h index 2e19c54cbfe..fdf14c691e9 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -656,7 +656,7 @@ public: void print(THD *thd, String *str); static void print_order(String *str, ORDER *order); void print_limit(THD *thd, String *str); - void fix_prepare_information(THD *thd, Item **conds); + void fix_prepare_information(THD *thd, Item **conds, Item **having_conds); /* Destroy the used execution plan (JOIN) of this subtree (this SELECT_LEX and all nested SELECT_LEXes and SELECT_LEX_UNITs). diff --git a/sql/sql_list.h b/sql/sql_list.h index b2bcc4ea401..afad6d0f6ac 100644 --- a/sql/sql_list.h +++ b/sql/sql_list.h @@ -94,9 +94,9 @@ public: inline base_list() { empty(); } inline base_list(const base_list &tmp) :Sql_alloc() { - elements=tmp.elements; - first=tmp.first; - last=tmp.last; + elements= tmp.elements; + first= tmp.first; + last= elements ? tmp.last : &first; } inline base_list(bool error) { } inline bool push_back(void *info) diff --git a/sql/sql_load.cc b/sql/sql_load.cc index b1ba2e96651..bdc08b7bd2d 100644 --- a/sql/sql_load.cc +++ b/sql/sql_load.cc @@ -147,10 +147,6 @@ bool mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list, MYF(0)); DBUG_RETURN(TRUE); } - /* - This needs to be done before external_lock - */ - ha_enable_transaction(thd, FALSE); if (open_and_lock_tables(thd, table_list)) DBUG_RETURN(TRUE); if (setup_tables_and_check_access(thd, &thd->lex->select_lex.context, @@ -394,7 +390,6 @@ bool mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list, table->file->extra(HA_EXTRA_WRITE_CANNOT_REPLACE); table->next_number_field=0; } - ha_enable_transaction(thd, TRUE); if (file >= 0) my_close(file,MYF(0)); free_blobs(table); /* if pack_blob was used */ @@ -621,10 +616,8 @@ read_fixed_length(THD *thd, COPY_INFO &info, TABLE_LIST *table_list, thd->no_trans_update= no_trans_update; /* - If auto_increment values are used, save the first one - for LAST_INSERT_ID() and for the binary/update log. - We can't use insert_id() as we don't want to touch the - last_insert_id_used flag. + If auto_increment values are used, save the first one for + LAST_INSERT_ID() and for the binary/update log. */ if (!id && thd->insert_id_used) id= thd->last_insert_id; @@ -789,10 +782,8 @@ read_sep_field(THD *thd, COPY_INFO &info, TABLE_LIST *table_list, if (write_record(thd, table, &info)) DBUG_RETURN(1); /* - If auto_increment values are used, save the first one - for LAST_INSERT_ID() and for the binary/update log. - We can't use insert_id() as we don't want to touch the - last_insert_id_used flag. + If auto_increment values are used, save the first one for + LAST_INSERT_ID() and for the binary/update log. */ if (!id && thd->insert_id_used) id= thd->last_insert_id; diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 2acbf18f1e6..c62c286cfdb 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -1001,8 +1001,8 @@ static int check_connection(THD *thd) char *passwd= strend(user)+1; uint user_len= passwd - user - 1; char *db= passwd; - char db_buff[NAME_LEN+1]; // buffer to store db in utf8 - char user_buff[USERNAME_LENGTH+1]; // buffer to store user in utf8 + char db_buff[NAME_LEN + 1]; // buffer to store db in utf8 + char user_buff[USERNAME_LENGTH + 1]; // buffer to store user in utf8 uint dummy_errors; /* @@ -1662,7 +1662,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd, password. New clients send the size (1 byte) + string (not null terminated, so also '\0' for empty string). */ - char db_buff[NAME_LEN+1]; // buffer to store db in utf8 + char db_buff[NAME_LEN+1]; // buffer to store db in utf8 char *db= passwd; uint passwd_len= thd->client_capabilities & CLIENT_SECURE_CONNECTION ? *passwd++ : strlen(passwd); @@ -2421,6 +2421,20 @@ mysql_execute_command(THD *thd) DBUG_ENTER("mysql_execute_command"); thd->net.no_send_error= 0; + /* + Remember first generated insert id value of the previous + statement. We remember it here at the beginning of the statement, + and also in Item_func_last_insert_id::fix_fields() and + sys_var_last_insert_id::value_ptr(). Last two places are required + because LAST_INSERT_ID() and @@LAST_INSERT_ID may also be used in + expression that is not executed with mysql_execute_command(). + + And we remember it here because some statements read + @@LAST_INSERT_ID indirectly, like "SELECT * FROM t1 WHERE id IS + NULL", that may replace "id IS NULL" with "id = ". + */ + thd->current_insert_id= thd->last_insert_id; + /* In many cases first table of main SELECT_LEX have special meaning => check that it is first table in global list and relink it first in @@ -3344,8 +3358,6 @@ end_with_restore_list: DBUG_ASSERT(first_table == all_tables && first_table != 0); if ((res= insert_precheck(thd, all_tables))) break; - /* Skip first table, which is the table we are inserting in */ - select_lex->context.table_list= first_table->next_local; if (!thd->locked_tables && !(need_start_waiting= !wait_if_global_read_lock(thd, 0, 1))) @@ -4767,6 +4779,19 @@ end_with_restore_list: } append_identifier(thd, &buff, first_table->table_name, first_table->table_name_length); + if (lex->view_list.elements) + { + List_iterator_fast names(lex->view_list); + LEX_STRING *name; + int i; + + for (i= 0; name= names++; i++) + { + buff.append(i ? ", " : "("); + append_identifier(thd, &buff, name->str, name->length); + } + buff.append(')'); + } buff.append(STRING_WITH_LEN(" AS ")); buff.append(first_table->source.str, first_table->source.length); @@ -5625,7 +5650,8 @@ void mysql_reset_thd_for_next_command(THD *thd) DBUG_ENTER("mysql_reset_thd_for_next_command"); thd->free_list= 0; thd->select_number= 1; - thd->last_insert_id_used= thd->query_start_used= thd->insert_id_used=0; + thd->query_start_used= thd->insert_id_used=0; + thd->last_insert_id_used_bin_log= FALSE; thd->is_fatal_error= thd->time_zone_used= 0; thd->server_status&= ~ (SERVER_MORE_RESULTS_EXISTS | SERVER_QUERY_NO_INDEX_USED | @@ -6087,6 +6113,7 @@ bool add_to_list(THD *thd, SQL_LIST &list,Item *item,bool asc) table_options A set of the following bits: TL_OPTION_UPDATING Table will be updated TL_OPTION_FORCE_INDEX Force usage of index + TL_OPTION_ALIAS an alias in multi table DELETE lock_type How table should be locked use_index List of indexed used in USE INDEX ignore_index List of indexed used in IGNORE INDEX @@ -6115,7 +6142,8 @@ TABLE_LIST *st_select_lex::add_table_to_list(THD *thd, if (!table) DBUG_RETURN(0); // End of memory alias_str= alias ? alias->str : table->table.str; - if (check_table_name(table->table.str, table->table.length)) + if (!test(table_options & TL_OPTION_ALIAS) && + check_table_name(table->table.str, table->table.length)) { my_error(ER_WRONG_TABLE_NAME, MYF(0), table->table.str); DBUG_RETURN(0); diff --git a/sql/sql_select.cc b/sql/sql_select.cc index e9d0e003f6d..6d17faf8509 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -382,12 +382,14 @@ JOIN::prepare(Item ***rref_pointer_array, if ((res= subselect->select_transformer(this)) != Item_subselect::RES_OK) { - select_lex->fix_prepare_information(thd, &conds); + select_lex->fix_prepare_information(thd, &conds, &having); DBUG_RETURN((res == Item_subselect::RES_ERROR)); } } } + select_lex->fix_prepare_information(thd, &conds, &having); + if (having && having->with_sum_func) having->split_sum_func2(thd, ref_pointer_array, all_fields, &having, TRUE); @@ -499,7 +501,6 @@ JOIN::prepare(Item ***rref_pointer_array, if (alloc_func_list()) goto err; - select_lex->fix_prepare_information(thd, &conds); DBUG_RETURN(0); // All OK err: @@ -618,7 +619,6 @@ JOIN::optimize() build_bitmap_for_nested_joins(join_list, 0); sel->prep_where= conds ? conds->copy_andor_structure(thd) : 0; - sel->prep_having= having ? having->copy_andor_structure(thd) : 0; if (arena) thd->restore_active_arena(arena, &backup); @@ -1134,17 +1134,28 @@ JOIN::optimize() tmp_table_param.hidden_field_count= (all_fields.elements - fields_list.elements); + ORDER *tmp_group= ((!simple_group && !procedure && + !(test_flags & TEST_NO_KEY_GROUP)) ? group_list : + (ORDER*) 0); + /* + Pushing LIMIT to the temporary table creation is not applicable + when there is ORDER BY or GROUP BY or there is no GROUP BY, but + there are aggregate functions, because in all these cases we need + all result rows. + */ + ha_rows tmp_rows_limit= ((order == 0 || skip_sort_order || + test(select_options & OPTION_BUFFER_RESULT)) && + !tmp_group && + !thd->lex->current_select->with_sum_func) ? + select_limit : HA_POS_ERROR; + if (!(exec_tmp_table1 = create_tmp_table(thd, &tmp_table_param, all_fields, - ((!simple_group && !procedure && - !(test_flags & TEST_NO_KEY_GROUP)) ? - group_list : (ORDER*) 0), + tmp_group, group_list ? 0 : select_distinct, group_list && simple_group, select_options, - (order == 0 || skip_sort_order || - test(select_options & OPTION_BUFFER_RESULT)) ? - select_limit : HA_POS_ERROR, + tmp_rows_limit, (char *) ""))) DBUG_RETURN(1); @@ -1324,7 +1335,7 @@ JOIN::exec() } (void) result->prepare2(); // Currently, this cannot fail. - if (!tables_list) + if (!tables_list && (tables || !select_lex->with_sum_func)) { // Only test of functions if (select_options & SELECT_DESCRIBE) select_describe(this, FALSE, FALSE, FALSE, @@ -1364,7 +1375,12 @@ JOIN::exec() thd->examined_row_count= 0; DBUG_VOID_RETURN; } - thd->limit_found_rows= thd->examined_row_count= 0; + /* + don't reset the found rows count if there're no tables + as FOUND_ROWS() may be called. + */ + if (tables) + thd->limit_found_rows= thd->examined_row_count= 0; if (zero_result_cause) { @@ -1403,7 +1419,8 @@ JOIN::exec() having= tmp_having; select_describe(this, need_tmp, order != 0 && !skip_sort_order, - select_distinct); + select_distinct, + !tables ? "No tables used" : NullS); DBUG_VOID_RETURN; } @@ -6351,29 +6368,30 @@ finish: /* - Check whether an item is a simple equality predicate and if so - create/find a multiple equality for this predicate + Check whether an equality can be used to build multiple equalities SYNOPSIS - check_equality() - item item to check - cond_equal multiple equalities that must hold together with the predicate + check_simple_equality() + left_item left term of the quality to be checked + right_item right term of the equality to be checked + item equality item if the equality originates from a condition + predicate, 0 if the equality is the result of row elimination + cond_equal multiple equalities that must hold together with the equality DESCRIPTION - This function first checks whether an item is a simple equality i.e. - the one that equates a field with another field or a constant - (item=constant_item or item=field_item). - If this is the case the function looks a for a multiple equality + This function first checks whether the equality (left_item=right_item) + is a simple equality i.e. the one that equates a field with another field + or a constant (field=field_item or field=const_item). + If this is the case the function looks for a multiple equality in the lists referenced directly or indirectly by cond_equal inferring the given simple equality. If it doesn't find any, it builds a multiple equality that covers the predicate, i.e. the predicate can be inferred - from it. + from this multiple equality. The built multiple equality could be obtained in such a way: create a binary multiple equality equivalent to the predicate, then merge it, if possible, with one of old multiple equalities. This guarantees that the set of multiple equalities covering equality - predicates will - be minimal. + predicates will be minimal. EXAMPLE For the where condition @@ -6391,7 +6409,7 @@ finish: and will transform *cond_equal into (ptr(CE),[Item_equal(f,e)]). NOTES - Now only fields that have the same type defintions (verified by + Now only fields that have the same type definitions (verified by the Field::eq_def method) are placed to the same multiple equalities. Because of this some equality predicates are not eliminated and can be used in the constant propagation procedure. @@ -6424,11 +6442,263 @@ finish: copying would be much more complicated. RETURN - TRUE - if the predicate is a simple equality predicate - FALSE - otherwise + TRUE if the predicate is a simple equality predicate to be used + for building multiple equalities + FALSE otherwise */ -static bool check_equality(Item *item, COND_EQUAL *cond_equal) +static bool check_simple_equality(Item *left_item, Item *right_item, + Item *item, COND_EQUAL *cond_equal) +{ + if (left_item->type() == Item::REF_ITEM && + ((Item_ref*)left_item)->ref_type() == Item_ref::VIEW_REF) + { + if (((Item_ref*)left_item)->depended_from) + return FALSE; + left_item= left_item->real_item(); + } + if (right_item->type() == Item::REF_ITEM && + ((Item_ref*)right_item)->ref_type() == Item_ref::VIEW_REF) + { + if (((Item_ref*)right_item)->depended_from) + return FALSE; + right_item= right_item->real_item(); + } + if (left_item->type() == Item::FIELD_ITEM && + right_item->type() == Item::FIELD_ITEM && + !((Item_field*)left_item)->depended_from && + !((Item_field*)right_item)->depended_from) + { + /* The predicate the form field1=field2 is processed */ + + Field *left_field= ((Item_field*) left_item)->field; + Field *right_field= ((Item_field*) right_item)->field; + + if (!left_field->eq_def(right_field)) + return FALSE; + + /* Search for multiple equalities containing field1 and/or field2 */ + bool left_copyfl, right_copyfl; + Item_equal *left_item_equal= + find_item_equal(cond_equal, left_field, &left_copyfl); + Item_equal *right_item_equal= + find_item_equal(cond_equal, right_field, &right_copyfl); + + /* As (NULL=NULL) != TRUE we can't just remove the predicate f=f */ + if (left_field->eq(right_field)) /* f = f */ + return (!(left_field->maybe_null() && !left_item_equal)); + + if (left_item_equal && left_item_equal == right_item_equal) + { + /* + The equality predicate is inference of one of the existing + multiple equalities, i.e the condition is already covered + by upper level equalities + */ + return TRUE; + } + + /* Copy the found multiple equalities at the current level if needed */ + if (left_copyfl) + { + /* left_item_equal of an upper level contains left_item */ + left_item_equal= new Item_equal(left_item_equal); + cond_equal->current_level.push_back(left_item_equal); + } + if (right_copyfl) + { + /* right_item_equal of an upper level contains right_item */ + right_item_equal= new Item_equal(right_item_equal); + cond_equal->current_level.push_back(right_item_equal); + } + + if (left_item_equal) + { + /* left item was found in the current or one of the upper levels */ + if (! right_item_equal) + left_item_equal->add((Item_field *) right_item); + else + { + /* Merge two multiple equalities forming a new one */ + left_item_equal->merge(right_item_equal); + /* Remove the merged multiple equality from the list */ + List_iterator li(cond_equal->current_level); + while ((li++) != right_item_equal); + li.remove(); + } + } + else + { + /* left item was not found neither the current nor in upper levels */ + if (right_item_equal) + right_item_equal->add((Item_field *) left_item); + else + { + /* None of the fields was found in multiple equalities */ + Item_equal *item= new Item_equal((Item_field *) left_item, + (Item_field *) right_item); + cond_equal->current_level.push_back(item); + } + } + return TRUE; + } + + { + /* The predicate of the form field=const/const=field is processed */ + Item *const_item= 0; + Item_field *field_item= 0; + if (left_item->type() == Item::FIELD_ITEM && + !((Item_field*)left_item)->depended_from && + right_item->const_item()) + { + field_item= (Item_field*) left_item; + const_item= right_item; + } + else if (right_item->type() == Item::FIELD_ITEM && + !((Item_field*)right_item)->depended_from && + left_item->const_item()) + { + field_item= (Item_field*) right_item; + const_item= left_item; + } + + if (const_item && + field_item->result_type() == const_item->result_type()) + { + bool copyfl; + + if (field_item->result_type() == STRING_RESULT) + { + CHARSET_INFO *cs= ((Field_str*) field_item->field)->charset(); + if (!item) + { + Item_func_eq *eq_item; + if ((eq_item= new Item_func_eq(left_item, right_item))) + return FALSE; + eq_item->set_cmp_func(); + eq_item->quick_fix_field(); + item= eq_item; + } + if ((cs != ((Item_func *) item)->compare_collation()) || + !cs->coll->propagate(cs, 0, 0)) + return FALSE; + } + + Item_equal *item_equal = find_item_equal(cond_equal, + field_item->field, ©fl); + if (copyfl) + { + item_equal= new Item_equal(item_equal); + cond_equal->current_level.push_back(item_equal); + } + if (item_equal) + { + /* + The flag cond_false will be set to 1 after this, if item_equal + already contains a constant and its value is not equal to + the value of const_item. + */ + item_equal->add(const_item); + } + else + { + item_equal= new Item_equal(const_item, field_item); + cond_equal->current_level.push_back(item_equal); + } + return TRUE; + } + } + return FALSE; +} + + +/* + Convert row equalities into a conjunction of regular equalities + + SYNOPSIS + check_row_equality() + left_row left term of the row equality to be processed + right_row right term of the row equality to be processed + cond_equal multiple equalities that must hold together with the predicate + eq_list results of conversions of row equalities that are not simple + enough to form multiple equalities + + DESCRIPTION + The function converts a row equality of the form (E1,...,En)=(E'1,...,E'n) + into a list of equalities E1=E'1,...,En=E'n. For each of these equalities + Ei=E'i the function checks whether it is a simple equality or a row equality. + If it is a simple equality it is used to expand multiple equalities of + cond_equal. If it is a row equality it converted to a sequence of equalities + between row elements. If Ei=E'i is neither a simple equality nor a row + equality the item for this predicate is added to eq_list. + + RETURN + TRUE if conversion has succeeded (no fatal error) + FALSE otherwise +*/ + +static bool check_row_equality(Item *left_row, Item_row *right_row, + COND_EQUAL *cond_equal, List* eq_list) +{ + uint n= left_row->cols(); + for (uint i= 0 ; i < n; i++) + { + bool is_converted; + Item *left_item= left_row->el(i); + Item *right_item= right_row->el(i); + if (left_item->type() == Item::ROW_ITEM && + right_item->type() == Item::ROW_ITEM) + is_converted= check_row_equality((Item_row *) left_item, + (Item_row *) right_item, + cond_equal, eq_list); + else + is_converted= check_simple_equality(left_item, right_item, 0, cond_equal); + + if (!is_converted) + { + Item_func_eq *eq_item; + if (!(eq_item= new Item_func_eq(left_item, right_item))) + return FALSE; + eq_item->set_cmp_func(); + eq_item->quick_fix_field(); + eq_list->push_back(eq_item); + } + } + return TRUE; +} + + +/* + Eliminate row equalities and form multiple equalities predicates + + SYNOPSIS + check_equality() + item predicate to process + cond_equal multiple equalities that must hold together with the predicate + eq_list results of conversions of row equalities that are not simple + enough to form multiple equalities + + DESCRIPTION + This function checks whether the item is a simple equality + i.e. the one that equates a field with another field or a constant + (field=field_item or field=constant_item), or, a row equality. + For a simple equality the function looks for a multiple equality + in the lists referenced directly or indirectly by cond_equal inferring + the given simple equality. If it doesn't find any, it builds/expands + multiple equality that covers the predicate. + Row equalities are eliminated substituted for conjunctive regular equalities + which are treated in the same way as original equality predicates. + + RETURN + TRUE if re-writing rules have been applied + FALSE otherwise, i.e. + if the predicate is not an equality, + or, if the equality is neither a simple one nor a row equality, + or, if the procedure fails by a fatal error. +*/ + +static bool check_equality(Item *item, COND_EQUAL *cond_equal, + List *eq_list) { if (item->type() == Item::FUNC_ITEM && ((Item_func*) item)->functype() == Item_func::EQ_FUNC) @@ -6436,165 +6706,25 @@ static bool check_equality(Item *item, COND_EQUAL *cond_equal) Item *left_item= ((Item_func*) item)->arguments()[0]; Item *right_item= ((Item_func*) item)->arguments()[1]; - if (left_item->type() == Item::REF_ITEM && - ((Item_ref*)left_item)->ref_type() == Item_ref::VIEW_REF) - { - if (((Item_ref*)left_item)->depended_from) - return FALSE; - left_item= left_item->real_item(); - } - if (right_item->type() == Item::REF_ITEM && - ((Item_ref*)right_item)->ref_type() == Item_ref::VIEW_REF) - { - if (((Item_ref*)right_item)->depended_from) - return FALSE; - right_item= right_item->real_item(); - } - if (left_item->type() == Item::FIELD_ITEM && - right_item->type() == Item::FIELD_ITEM && - !((Item_field*)left_item)->depended_from && - !((Item_field*)right_item)->depended_from) - { - /* The predicate the form field1=field2 is processed */ - - Field *left_field= ((Item_field*) left_item)->field; - Field *right_field= ((Item_field*) right_item)->field; - - if (!left_field->eq_def(right_field)) - return FALSE; - - if (left_field->eq(right_field)) /* f = f */ - return TRUE; - - /* Search for multiple equalities containing field1 and/or field2 */ - bool left_copyfl, right_copyfl; - Item_equal *left_item_equal= - find_item_equal(cond_equal, left_field, &left_copyfl); - Item_equal *right_item_equal= - find_item_equal(cond_equal, right_field, &right_copyfl); - - if (left_item_equal && left_item_equal == right_item_equal) - { - /* - The equality predicate is inference of one of the existing - multiple equalities, i.e the condition is already covered - by upper level equalities - */ - return TRUE; - } - - /* Copy the found multiple equalities at the current level if needed */ - if (left_copyfl) - { - /* left_item_equal of an upper level contains left_item */ - left_item_equal= new Item_equal(left_item_equal); - cond_equal->current_level.push_back(left_item_equal); - } - if (right_copyfl) - { - /* right_item_equal of an upper level contains right_item */ - right_item_equal= new Item_equal(right_item_equal); - cond_equal->current_level.push_back(right_item_equal); - } - - if (left_item_equal) - { - /* left item was found in the current or one of the upper levels */ - if (! right_item_equal) - left_item_equal->add((Item_field *) right_item); - else - { - /* Merge two multiple equalities forming a new one */ - left_item_equal->merge(right_item_equal); - /* Remove the merged multiple equality from the list */ - List_iterator li(cond_equal->current_level); - while ((li++) != right_item_equal); - li.remove(); - } - } - else - { - /* left item was not found neither the current nor in upper levels */ - if (right_item_equal) - right_item_equal->add((Item_field *) left_item); - else - { - /* None of the fields was found in multiple equalities */ - Item_equal *item= new Item_equal((Item_field *) left_item, - (Item_field *) right_item); - cond_equal->current_level.push_back(item); - } - } - return TRUE; - } - - { - /* The predicate of the form field=const/const=field is processed */ - Item *const_item= 0; - Item_field *field_item= 0; - if (left_item->type() == Item::FIELD_ITEM && - !((Item_field*)left_item)->depended_from && - right_item->const_item()) - { - field_item= (Item_field*) left_item; - const_item= right_item; - } - else if (right_item->type() == Item::FIELD_ITEM && - !((Item_field*)right_item)->depended_from && - left_item->const_item()) - { - field_item= (Item_field*) right_item; - const_item= left_item; - } - - if (const_item && - field_item->result_type() == const_item->result_type()) - { - bool copyfl; - - if (field_item->result_type() == STRING_RESULT) - { - CHARSET_INFO *cs= ((Field_str*) field_item->field)->charset(); - if ((cs != ((Item_cond *) item)->compare_collation()) || - !cs->coll->propagate(cs, 0, 0)) - return FALSE; - } - - Item_equal *item_equal = find_item_equal(cond_equal, - field_item->field, ©fl); - if (copyfl) - { - item_equal= new Item_equal(item_equal); - cond_equal->current_level.push_back(item_equal); - } - if (item_equal) - { - /* - The flag cond_false will be set to 1 after this, if item_equal - already contains a constant and its value is not equal to - the value of const_item. - */ - item_equal->add(const_item); - } - else - { - item_equal= new Item_equal(const_item, field_item); - cond_equal->current_level.push_back(item_equal); - } - return TRUE; - } - } - } + if (left_item->type() == Item::ROW_ITEM && + right_item->type() == Item::ROW_ITEM) + return check_row_equality((Item_row *) left_item, + (Item_row *) right_item, + cond_equal, eq_list); + else + return check_simple_equality(left_item, right_item, item, cond_equal); + } return FALSE; } + /* Replace all equality predicates in a condition by multiple equality items SYNOPSIS build_equal_items_for_cond() - cond condition(expression) where to make replacement - inherited path to all inherited multiple equality items + cond condition(expression) where to make replacement + inherited path to all inherited multiple equality items DESCRIPTION At each 'and' level the function detects items for equality predicates @@ -6608,7 +6738,9 @@ static bool check_equality(Item *item, COND_EQUAL *cond_equal) The function also traverses the cond tree and and for each field reference sets a pointer to the multiple equality item containing the field, if there is any. If this multiple equality equates fields to a constant the - function replace the field reference by the constant. + function replaces the field reference by the constant in the cases + when the field is not of a string type or when the field reference is + just an argument of a comparison predicate. The function also determines the maximum number of members in equality lists of each Item_cond_and object assigning it to cond_equal->max_members of this object and updating accordingly @@ -6659,10 +6791,12 @@ static COND *build_equal_items_for_cond(COND *cond, Item_equal *item_equal; uint members; COND_EQUAL cond_equal; + COND *new_cond; cond_equal.upper_levels= inherited; if (cond->type() == Item::COND_ITEM) { + List eq_list; bool and_level= ((Item_cond*) cond)->functype() == Item_func::COND_AND_FUNC; List *args= ((Item_cond*) cond)->argument_list(); @@ -6685,7 +6819,7 @@ static COND *build_equal_items_for_cond(COND *cond, structure here because it's restored before each re-execution of any prepared statement/stored procedure. */ - if (check_equality(item, &cond_equal)) + if (check_equality(item, &cond_equal, &eq_list)) li.remove(); } @@ -6732,10 +6866,14 @@ static COND *build_equal_items_for_cond(COND *cond, } } if (and_level) + { + args->concat(&eq_list); args->concat((List *)&cond_equal.current_level); + } } else if (cond->type() == Item::FUNC_ITEM) { + List eq_list; /* If an equality predicate forms the whole and level, we call it standalone equality and it's processed here. @@ -6746,19 +6884,57 @@ static COND *build_equal_items_for_cond(COND *cond, for WHERE a=b AND c=d AND (b=c OR d=5) b=c is replaced by =(a,b,c,d). */ - if (check_equality(cond, &cond_equal) && - (item_equal= cond_equal.current_level.pop())) + if (check_equality(cond, &cond_equal, &eq_list)) { - item_equal->fix_length_and_dec(); - item_equal->update_used_tables(); - return item_equal; + int n= cond_equal.current_level.elements + eq_list.elements; + if (n == 0) + return new Item_int((longlong) 1,1); + else if (n == 1) + { + if ((item_equal= cond_equal.current_level.pop())) + { + item_equal->fix_length_and_dec(); + item_equal->update_used_tables(); + return item_equal; + } + else + return eq_list.pop(); + } + else + { + /* + Here a new AND level must be created. It can happen only + when a row equality is processed as a standalone predicate. + */ + Item_cond_and *and_cond= new Item_cond_and(eq_list); + and_cond->quick_fix_field(); + List *args= and_cond->argument_list(); + List_iterator_fast it(cond_equal.current_level); + while ((item_equal= it++)) + { + item_equal->fix_length_and_dec(); + item_equal->update_used_tables(); + members= item_equal->members(); + if (cond_equal.max_members < members) + cond_equal.max_members= members; + } + and_cond->cond_equal= cond_equal; + args->concat((List *)&cond_equal.current_level); + + return and_cond; + } } /* For each field reference in cond, not from equal item predicates, set a pointer to the multiple equality it belongs to (if there is any) + as soon the field is not of a string type or the field reference is + an argument of a comparison predicate. */ - cond= cond->transform(&Item::equal_fields_propagator, - (byte *) inherited); + byte *is_subst_valid= (byte *) 1; + cond= cond->compile(&Item::subst_argument_checker, + &is_subst_valid, + &Item::equal_fields_propagator, + (byte *) inherited); cond->update_used_tables(); } return cond; @@ -7038,7 +7214,7 @@ static Item *eliminate_item_equal(COND *cond, COND_EQUAL *upper_levels, /* Substitute every field reference in a condition by the best equal field - and eliminate all multiplle equality predicates + and eliminate all multiple equality predicates SYNOPSIS substitute_for_best_equal_field() @@ -7977,7 +8153,7 @@ remove_eq_conds(THD *thd, COND *cond, Item::cond_result *cond_value) Field *field=((Item_field*) args[0])->field; if (field->flags & AUTO_INCREMENT_FLAG && !field->table->maybe_null && (thd->options & OPTION_AUTO_IS_NULL) && - thd->insert_id() && thd->substitute_null_with_insert_id) + thd->current_insert_id && thd->substitute_null_with_insert_id) { #ifdef HAVE_QUERY_CACHE query_cache_abort(&thd->net); @@ -7985,9 +8161,16 @@ remove_eq_conds(THD *thd, COND *cond, Item::cond_result *cond_value) COND *new_cond; if ((new_cond= new Item_func_eq(args[0], new Item_int("last_insert_id()", - thd->insert_id(), + thd->current_insert_id, 21)))) { + /* + Set THD::last_insert_id_used_bin_log manually, as this + statement uses LAST_INSERT_ID() in a sense, and should + issue LAST_INSERT_ID_EVENT. + */ + thd->last_insert_id_used_bin_log= TRUE; + cond=new_cond; /* Item_func_eq can't be fixed after creation so we do not check @@ -8932,6 +9115,13 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List &fields, thd->variables.max_heap_table_size) : thd->variables.tmp_table_size)/ table->s->reclength); set_if_bigger(table->s->max_rows,1); // For dummy start options + /* + Push the LIMIT clause to the temporary table creation, so that we + materialize only up to 'rows_limit' records instead of all result records. + */ + set_if_smaller(table->s->max_rows, rows_limit); + param->end_write_records= rows_limit; + keyinfo= param->keyinfo; if (group) @@ -8949,10 +9139,11 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List &fields, keyinfo->rec_per_key=0; keyinfo->algorithm= HA_KEY_ALG_UNDEF; keyinfo->name= (char*) "group_key"; - for (; group ; group=group->next,key_part_info++) + ORDER *cur_group= group; + for (; cur_group ; cur_group= cur_group->next, key_part_info++) { - Field *field=(*group->item)->get_tmp_table_field(); - bool maybe_null=(*group->item)->maybe_null; + Field *field=(*cur_group->item)->get_tmp_table_field(); + bool maybe_null=(*cur_group->item)->maybe_null; key_part_info->null_bit=0; key_part_info->field= field; key_part_info->offset= field->offset(); @@ -8965,8 +9156,8 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List &fields, 0 : FIELDFLAG_BINARY; if (!using_unique_constraint) { - group->buff=(char*) group_buff; - if (!(group->field= field->new_key_field(thd->mem_root,table, + cur_group->buff=(char*) group_buff; + if (!(cur_group->field= field->new_key_field(thd->mem_root,table, (char*) group_buff + test(maybe_null), field->null_ptr, @@ -8984,12 +9175,12 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List &fields, key_part_info->null_bit=field->null_bit; key_part_info->null_offset= (uint) (field->null_ptr - (uchar*) table->record[0]); - group->buff++; // Pointer to field data + cur_group->buff++; // Pointer to field data group_buff++; // Skipp null flag } /* In GROUP BY 'a' and 'a ' are equal for VARCHAR fields */ key_part_info->key_part_flag|= HA_END_SPACE_ARE_EQUAL; - group_buff+= group->field->pack_length(); + group_buff+= cur_group->field->pack_length(); } keyinfo->key_length+= key_part_info->length; } @@ -9060,19 +9251,6 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List &fields, } } - /* - Push the LIMIT clause to the temporary table creation, so that we - materialize only up to 'rows_limit' records instead of all result records. - This optimization is not applicable when there is GROUP BY or there is - no GROUP BY, but there are aggregate functions, because both must be - computed for all result rows. - */ - if (!group && !thd->lex->current_select->with_sum_func) - { - set_if_smaller(table->s->max_rows, rows_limit); - param->end_write_records= rows_limit; - } - if (thd->is_fatal_error) // If end of memory goto err; /* purecov: inspected */ table->s->db_record_offset= 1; @@ -9587,9 +9765,13 @@ do_select(JOIN *join,List *fields,TABLE *table,Procedure *procedure) table->file->ha_index_init(0); } /* Set up select_end */ - join->join_tab[join->tables-1].next_select= setup_end_select_func(join); + Next_select_func end_select= setup_end_select_func(join); + if (join->tables) + { + join->join_tab[join->tables-1].next_select= end_select; - join_tab=join->join_tab+join->const_tables; + join_tab=join->join_tab+join->const_tables; + } join->send_records=0; if (join->tables == join->const_tables) { @@ -9599,7 +9781,6 @@ do_select(JOIN *join,List *fields,TABLE *table,Procedure *procedure) */ if (!join->conds || join->conds->val_int()) { - Next_select_func end_select= join->join_tab[join->tables-1].next_select; error= (*end_select)(join,join_tab,0); if (error == NESTED_LOOP_OK || error == NESTED_LOOP_QUERY_LIMIT) error= (*end_select)(join,join_tab,1); @@ -9613,6 +9794,8 @@ do_select(JOIN *join,List *fields,TABLE *table,Procedure *procedure) } else { + DBUG_ASSERT(join->tables); + DBUG_ASSERT(join_tab); error= sub_select(join,join_tab,0); if (error == NESTED_LOOP_OK || error == NESTED_LOOP_NO_MORE_ROWS) error= sub_select(join,join_tab,1); @@ -11564,8 +11747,6 @@ test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,ha_rows select_limit, We must not try to use disabled keys. */ usable_keys= table->s->keys_in_use; - /* we must not consider keys that are disabled by IGNORE INDEX */ - usable_keys.intersect(table->keys_in_use_for_query); for (ORDER *tmp_order=order; tmp_order ; tmp_order=tmp_order->next) { @@ -13189,6 +13370,8 @@ setup_copy_fields(THD *thd, TMP_TABLE_PARAM *param, param->copy_funcs.empty(); for (i= 0; (pos= li++); i++) { + Field *field; + char *tmp; Item *real_pos= pos->real_item(); if (real_pos->type() == Item::FIELD_ITEM) { @@ -13219,17 +13402,25 @@ setup_copy_fields(THD *thd, TMP_TABLE_PARAM *param, set up save buffer and change result_field to point at saved value */ - Field *field= item->field; + field= item->field; item->result_field=field->new_field(thd->mem_root,field->table, 1); - char *tmp=(char*) sql_alloc(field->pack_length()+1); + /* + We need to allocate one extra byte for null handling and + another extra byte to not get warnings from purify in + Field_string::val_int + */ + tmp= (char*) sql_alloc(field->pack_length()+2); if (!tmp) goto err; - if (copy) - { - copy->set(tmp, item->result_field); - item->result_field->move_field(copy->to_ptr,copy->to_null_ptr,1); - copy++; - } + if (copy) + { + copy->set(tmp, item->result_field); + item->result_field->move_field(copy->to_ptr,copy->to_null_ptr,1); +#ifdef HAVE_purify + copy->to_ptr[copy->from_length]= 0; +#endif + copy++; + } } } else if ((real_pos->type() == Item::FUNC_ITEM || @@ -14232,9 +14423,12 @@ static void select_describe(JOIN *join, bool need_tmp_table, bool need_order, item_list.push_back(new Item_string(table_name_buffer, len, cs)); } else - item_list.push_back(new Item_string(table->alias, - strlen(table->alias), + { + TABLE_LIST *tab=table->pos_in_table_list; + item_list.push_back(new Item_string(tab->alias, + strlen(tab->alias), cs)); + } /* type */ item_list.push_back(new Item_string(join_type_str[tab->type], strlen(join_type_str[tab->type]), @@ -14421,8 +14615,8 @@ bool mysql_explain_union(THD *thd, SELECT_LEX_UNIT *unit, select_result *result) // drop UNCACHEABLE_EXPLAIN, because it is for internal usage only uint8 uncacheable= (sl->uncacheable & ~UNCACHEABLE_EXPLAIN); sl->type= (((&thd->lex->select_lex)==sl)? - ((thd->lex->all_selects_list != sl) ? - primary_key_name : "SIMPLE"): + (sl->first_inner_unit() || sl->next_select() ? + "PRIMARY" : "SIMPLE"): ((sl == first)? ((sl->linkage == DERIVED_TABLE_TYPE) ? "DERIVED": diff --git a/sql/sql_show.cc b/sql/sql_show.cc index eb78f4fbdae..4469bbacf90 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -4277,7 +4277,7 @@ ST_FIELD_INFO triggers_fields_info[]= ST_FIELD_INFO variables_fields_info[]= { {"Variable_name", 80, MYSQL_TYPE_STRING, 0, 0, "Variable_name"}, - {"Value", 255, MYSQL_TYPE_STRING, 0, 0, "Value"}, + {"Value", FN_REFLEN, MYSQL_TYPE_STRING, 0, 0, "Value"}, {0, 0, MYSQL_TYPE_STRING, 0, 0, 0} }; diff --git a/sql/sql_table.cc b/sql/sql_table.cc index a340c5ffc98..1c5be098ae0 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -224,7 +224,7 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists, DBUG_ENTER("mysql_rm_table_part2"); - if (lock_table_names(thd, tables)) + if (!drop_temporary && lock_table_names(thd, tables)) DBUG_RETURN(1); /* Don't give warnings for not found errors, as we already generate notes */ @@ -334,7 +334,8 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists, } } - unlock_table_names(thd, tables, (TABLE_LIST*) 0); + if (!drop_temporary) + unlock_table_names(thd, tables, (TABLE_LIST*) 0); thd->no_warnings_for_error= 0; DBUG_RETURN(error); } diff --git a/sql/sql_trigger.cc b/sql/sql_trigger.cc index 6bb50d602c3..c0c9c34cbeb 100644 --- a/sql/sql_trigger.cc +++ b/sql/sql_trigger.cc @@ -1547,6 +1547,38 @@ void Table_triggers_list::mark_fields_used(THD *thd, trg_event_type event) } +/* + Check if field of subject table can be changed in before update trigger. + + SYNOPSIS + is_updated_in_before_update_triggers() + field Field object for field to be checked + + NOTE + Field passed to this function should be bound to the same + TABLE object as Table_triggers_list. + + RETURN VALUE + TRUE Field is changed + FALSE Otherwise +*/ + +bool Table_triggers_list::is_updated_in_before_update_triggers(Field *fld) +{ + Item_trigger_field *trg_fld; + for (trg_fld= trigger_fields[TRG_EVENT_UPDATE][TRG_ACTION_BEFORE]; + trg_fld != 0; + trg_fld= trg_fld->next_trg_field) + { + if (trg_fld->get_settable_routine_parameter() && + trg_fld->field_idx != (uint)-1 && + table->field[trg_fld->field_idx]->eq(fld)) + return TRUE; + } + return FALSE; +} + + /* Trigger BUG#14090 compatibility hook diff --git a/sql/sql_trigger.h b/sql/sql_trigger.h index 521905a2c56..7e0fadfa677 100644 --- a/sql/sql_trigger.h +++ b/sql/sql_trigger.h @@ -116,15 +116,12 @@ public: bodies[TRG_EVENT_DELETE][TRG_ACTION_AFTER]); } - bool has_before_update_triggers() - { - return test(bodies[TRG_EVENT_UPDATE][TRG_ACTION_BEFORE]); - } - void set_table(TABLE *new_table); void mark_fields_used(THD *thd, trg_event_type event); + bool is_updated_in_before_update_triggers(Field *fld); + friend class Item_trigger_field; friend int sp_cache_routines_and_add_tables_for_triggers(THD *thd, LEX *lex, TABLE_LIST *table); diff --git a/sql/sql_update.cc b/sql/sql_update.cc index 84b22c56cf9..24577f63124 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -274,7 +274,7 @@ int mysql_update(THD *thd, { used_index= select->quick->index; used_key_is_modified= (!select->quick->unique_key_range() && - select->quick->check_if_keys_used(&fields)); + select->quick->is_keys_used(&fields)); } else { @@ -282,7 +282,7 @@ int mysql_update(THD *thd, if (used_index == MAX_KEY) // no index for sort order used_index= table->file->key_used_on_scan; if (used_index != MAX_KEY) - used_key_is_modified= check_if_key_used(table, used_index, fields); + used_key_is_modified= is_key_used(table, used_index, fields); } if (used_key_is_modified || order) @@ -568,7 +568,7 @@ int mysql_update(THD *thd, thd->row_count_func= (thd->client_capabilities & CLIENT_FOUND_ROWS) ? found : updated; send_ok(thd, (ulong) thd->row_count_func, - thd->insert_id_used ? thd->insert_id() : 0L,buff); + thd->insert_id_used ? thd->last_insert_id : 0L,buff); DBUG_PRINT("info",("%d records updated",updated)); } thd->count_cuted_fields= CHECK_FIELD_IGNORE; /* calc cuted fields */ @@ -606,6 +606,7 @@ err: bool mysql_prepare_update(THD *thd, TABLE_LIST *table_list, Item **conds, uint order_num, ORDER *order) { + Item *fake_conds= 0; TABLE *table= table_list->table; TABLE_LIST tables; List all_fields; @@ -645,7 +646,7 @@ bool mysql_prepare_update(THD *thd, TABLE_LIST *table_list, DBUG_RETURN(TRUE); } } - select_lex->fix_prepare_information(thd, conds); + select_lex->fix_prepare_information(thd, conds, &fake_conds); DBUG_RETURN(FALSE); } @@ -1094,6 +1095,8 @@ multi_update::initialize_tables(JOIN *join) List temp_fields= *fields_for_table[cnt]; ORDER group; + if (ignore) + table->file->extra(HA_EXTRA_IGNORE_DUP_KEY); if (table == main_table) // First table in join { if (safe_update_on_fly(join->join_tab, &temp_fields)) @@ -1188,21 +1191,15 @@ static bool safe_update_on_fly(JOIN_TAB *join_tab, List *fields) return TRUE; // At most one matching row case JT_REF: case JT_REF_OR_NULL: - return !check_if_key_used(table, join_tab->ref.key, *fields) && - !(table->triggers && - table->triggers->has_before_update_triggers()); + return !is_key_used(table, join_tab->ref.key, *fields); case JT_ALL: /* If range search on index */ if (join_tab->quick) - return !join_tab->quick->check_if_keys_used(fields) && - !(table->triggers && - table->triggers->has_before_update_triggers()); + return !join_tab->quick->is_keys_used(fields); /* If scanning in clustered key */ if ((table->file->table_flags() & HA_PRIMARY_KEY_IN_READ_INDEX) && table->s->primary_key < MAX_KEY) - return !check_if_key_used(table, table->s->primary_key, *fields) && - !(table->triggers && - table->triggers->has_before_update_triggers()); + return !is_key_used(table, table->s->primary_key, *fields); return TRUE; default: break; // Avoid compler warning @@ -1215,7 +1212,11 @@ multi_update::~multi_update() { TABLE_LIST *table; for (table= update_tables ; table; table= table->next_local) + { table->table->no_keyread= table->table->no_cache= 0; + if (ignore) + table->table->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY); + } if (tmp_tables) { @@ -1566,6 +1567,6 @@ bool multi_update::send_eof() thd->row_count_func= (thd->client_capabilities & CLIENT_FOUND_ROWS) ? found : updated; ::send_ok(thd, (ulong) thd->row_count_func, - thd->insert_id_used ? thd->insert_id() : 0L,buff); + thd->insert_id_used ? thd->last_insert_id : 0L,buff); return FALSE; } diff --git a/sql/sql_view.cc b/sql/sql_view.cc index 4e2b48d9faf..94c5ad331dd 100644 --- a/sql/sql_view.cc +++ b/sql/sql_view.cc @@ -1574,7 +1574,7 @@ bool insert_view_fields(THD *thd, List *list, TABLE_LIST *view) list->push_back(fld); else { - my_error(ER_NON_UPDATABLE_TABLE, MYF(0), view->alias, "INSERT"); + my_error(ER_NON_INSERTABLE_TABLE, MYF(0), view->alias, "INSERT"); DBUG_RETURN(TRUE); } } diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index f98e4a708da..cb105d05332 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -753,8 +753,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); predicate bit_expr bit_term bit_factor value_expr term factor table_wild simple_expr udf_expr expr_or_default set_expr_or_default interval_expr - param_marker singlerow_subselect singlerow_subselect_init - exists_subselect exists_subselect_init geometry_function + param_marker geometry_function signed_literal now_or_signed_literal opt_escape sp_opt_default simple_ident_nospvar simple_ident_q @@ -819,7 +818,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); %type internal_variable_name -%type in_subselect in_subselect_init +%type subselect subselect_init get_select_lex %type comp_op @@ -3942,12 +3941,14 @@ select_paren: yyerror(ER(ER_SYNTAX_ERROR)); YYABORT; } - if (sel->linkage == UNION_TYPE && - !sel->master_unit()->first_select()->braces) - { - yyerror(ER(ER_SYNTAX_ERROR)); - YYABORT; - } + if (sel->linkage == UNION_TYPE && + !sel->master_unit()->first_select()->braces && + sel->master_unit()->first_select()->linkage == + UNION_TYPE) + { + yyerror(ER(ER_SYNTAX_ERROR)); + YYABORT; + } /* select in braces, can't contain global parameters */ if (sel->master_unit()->fake_select_lex) sel->master_unit()->global_parameters= @@ -4205,37 +4206,37 @@ bool_pri: | bool_pri EQUAL_SYM predicate { $$= new Item_func_equal($1,$3); } | bool_pri comp_op predicate %prec EQ { $$= (*$2)(0)->create($1,$3); } - | bool_pri comp_op all_or_any in_subselect %prec EQ - { $$= all_any_subquery_creator($1, $2, $3, $4); } + | bool_pri comp_op all_or_any '(' subselect ')' %prec EQ + { $$= all_any_subquery_creator($1, $2, $3, $5); } | predicate ; predicate: - bit_expr IN_SYM '(' expr_list ')' - { - if ($4->elements == 1) - $$= new Item_func_eq($1, $4->head()); - else - { - $4->push_front($1); - $$= new Item_func_in(*$4); - } - } - | bit_expr not IN_SYM '(' expr_list ')' + bit_expr IN_SYM '(' subselect ')' + { $$= new Item_in_subselect($1, $4); } + | bit_expr not IN_SYM '(' subselect ')' + { $$= negate_expression(YYTHD, new Item_in_subselect($1, $5)); } + | bit_expr IN_SYM '(' expr ')' { - if ($5->elements == 1) - $$= new Item_func_ne($1, $5->head()); - else - { - $5->push_front($1); - Item_func_in *item = new Item_func_in(*$5); + $$= new Item_func_eq($1, $4); + } + | bit_expr IN_SYM '(' expr ',' expr_list ')' + { + $6->push_front($4); + $6->push_front($1); + $$= new Item_func_in(*$6); + } + | bit_expr not IN_SYM '(' expr ')' + { + $$= new Item_func_ne($1, $5); + } + | bit_expr not IN_SYM '(' expr ',' expr_list ')' + { + $7->push_front($5); + $7->push_front($1); + Item_func_in *item = new Item_func_in(*$7); item->negate(); $$= item; - } } - | bit_expr IN_SYM in_subselect - { $$= new Item_in_subselect($1, $3); } - | bit_expr not IN_SYM in_subselect - { $$= negate_expression(YYTHD, new Item_in_subselect($1, $4)); } | bit_expr BETWEEN_SYM bit_expr AND_SYM predicate { $$= new Item_func_between($1,$3,$5); } | bit_expr not BETWEEN_SYM bit_expr AND_SYM predicate @@ -4357,6 +4358,10 @@ simple_expr: | '-' simple_expr %prec NEG { $$= new Item_func_neg($2); } | '~' simple_expr %prec NEG { $$= new Item_func_bit_neg($2); } | not2 simple_expr %prec NEG { $$= negate_expression(YYTHD, $2); } + | '(' subselect ')' + { + $$= new Item_singlerow_subselect($2); + } | '(' expr ')' { $$= $2; } | '(' expr ',' expr_list ')' { @@ -4368,8 +4373,10 @@ simple_expr: $5->push_front($3); $$= new Item_row(*$5); } - | EXISTS exists_subselect { $$= $2; } - | singlerow_subselect { $$= $1; } + | EXISTS '(' subselect ')' + { + $$= new Item_exists_subselect($3); + } | '{' ident expr '}' { $$= $3; } | MATCH ident_list_arg AGAINST '(' bit_expr fulltext_options ')' { $2->push_front($5); @@ -5205,11 +5212,13 @@ join_table: /* Change the current name resolution context to a local context. */ if (push_new_name_resolution_context(YYTHD, $1, $3)) YYABORT; + Select->parsing_place= IN_ON; } expr { add_join_on($3,$6); Lex->pop_context(); + Select->parsing_place= NO_MATTER; } | table_ref STRAIGHT_JOIN table_factor ON @@ -5218,12 +5227,14 @@ join_table: /* Change the current name resolution context to a local context. */ if (push_new_name_resolution_context(YYTHD, $1, $3)) YYABORT; + Select->parsing_place= IN_ON; } expr { $3->straight=1; add_join_on($3,$6); Lex->pop_context(); + Select->parsing_place= NO_MATTER; } | table_ref normal_join table_ref USING @@ -5247,6 +5258,7 @@ join_table: /* Change the current name resolution context to a local context. */ if (push_new_name_resolution_context(YYTHD, $1, $5)) YYABORT; + Select->parsing_place= IN_ON; } expr { @@ -5254,6 +5266,7 @@ join_table: Lex->pop_context(); $5->outer_join|=JOIN_TYPE_LEFT; $$=$5; + Select->parsing_place= NO_MATTER; } | table_ref LEFT opt_outer JOIN_SYM table_factor { @@ -5278,6 +5291,7 @@ join_table: /* Change the current name resolution context to a local context. */ if (push_new_name_resolution_context(YYTHD, $1, $5)) YYABORT; + Select->parsing_place= IN_ON; } expr { @@ -5286,6 +5300,7 @@ join_table: YYABORT; add_join_on($$, $8); Lex->pop_context(); + Select->parsing_place= NO_MATTER; } | table_ref RIGHT opt_outer JOIN_SYM table_factor { @@ -6347,14 +6362,17 @@ table_wild_one: ident opt_wild opt_table_alias { if (!Select->add_table_to_list(YYTHD, new Table_ident($1), $3, - TL_OPTION_UPDATING, Lex->lock_option)) + TL_OPTION_UPDATING | + TL_OPTION_ALIAS, Lex->lock_option)) YYABORT; } | ident '.' ident opt_wild opt_table_alias { if (!Select->add_table_to_list(YYTHD, new Table_ident(YYTHD, $1, $3, 0), - $5, TL_OPTION_UPDATING, + $5, + TL_OPTION_UPDATING | + TL_OPTION_ALIAS, Lex->lock_option)) YYABORT; } @@ -6911,6 +6929,9 @@ load: LOAD DATA_SYM YYABORT; } lex->sql_command = SQLCOM_LOAD_MASTER_TABLE; + WARN_DEPRECATED("LOAD TABLE FROM MASTER", + "mysqldump or future " + "BACKUP/RESTORE DATABASE facility"); if (!Select->add_table_to_list(YYTHD, $3, NULL, TL_OPTION_UPDATING)) YYABORT; }; @@ -6949,6 +6970,9 @@ load_data: FROM MASTER_SYM { Lex->sql_command = SQLCOM_LOAD_MASTER_DATA; + WARN_DEPRECATED("LOAD DATA FROM MASTER", + "mysqldump or future " + "BACKUP/RESTORE DATABASE facility"); }; opt_local: @@ -7507,7 +7531,8 @@ user: $$->host.str= (char *) "%"; $$->host.length= 1; - if (check_string_length(&$$->user, ER(ER_USERNAME), USERNAME_LENGTH)) + if (check_string_length(&$$->user, + ER(ER_USERNAME), USERNAME_LENGTH)) YYABORT; } | ident_or_text '@' ident_or_text @@ -7517,9 +7542,10 @@ user: YYABORT; $$->user = $1; $$->host=$3; - if (check_string_length(&$$->user, ER(ER_USERNAME), USERNAME_LENGTH) || - check_string_length(&$$->host, ER(ER_HOSTNAME), - HOSTNAME_LENGTH)) + if (check_string_length(&$$->user, + ER(ER_USERNAME), USERNAME_LENGTH) || + check_string_length(&$$->host, + ER(ER_HOSTNAME), HOSTNAME_LENGTH)) YYABORT; } | CURRENT_USER optional_braces @@ -7572,6 +7598,7 @@ keyword: | TRUNCATE_SYM {} | UNICODE_SYM {} | XA_SYM {} + | UPGRADE_SYM {} ; /* @@ -8894,49 +8921,38 @@ union_option: | ALL { $$=0; } ; -singlerow_subselect: - subselect_start singlerow_subselect_init - subselect_end - { - $$= $2; - }; +subselect: + SELECT_SYM subselect_start subselect_init subselect_end + { + $$= $3; + } + | '(' subselect_start subselect ')' + { + LEX *lex= Lex; + THD *thd= YYTHD; + /* + note that a local variable can't be used for + $3 as it's used in local variable construction + and some compilers can't guarnatee the order + in which the local variables are initialized. + */ + List_iterator it($3->item_list); + Item *item; + /* + we must fill the items list for the "derived table". + */ + while ((item= it++)) + add_item_to_list(thd, item); + } + union_clause subselect_end { $$= $3; }; -singlerow_subselect_init: - select_init2 - { - $$= new Item_singlerow_subselect(Lex->current_select-> - master_unit()->first_select()); - }; - -exists_subselect: - subselect_start exists_subselect_init - subselect_end - { - $$= $2; - }; - -exists_subselect_init: - select_init2 - { - $$= new Item_exists_subselect(Lex->current_select->master_unit()-> - first_select()); - }; - -in_subselect: - subselect_start in_subselect_init - subselect_end - { - $$= $2; - }; - -in_subselect_init: +subselect_init: select_init2 { $$= Lex->current_select->master_unit()->first_select(); }; subselect_start: - '(' SELECT_SYM { LEX *lex=Lex; if (lex->sql_command == (int)SQLCOM_HA_READ || @@ -8945,12 +8961,18 @@ subselect_start: yyerror(ER(ER_SYNTAX_ERROR)); YYABORT; } + /* + we are making a "derived table" for the parenthesis + as we need to have a lex level to fit the union + after the parenthesis, e.g. + (SELECT .. ) UNION ... becomes + SELECT * FROM ((SELECT ...) UNION ...) + */ if (mysql_new_select(Lex, 1)) YYABORT; }; subselect_end: - ')' { LEX *lex=Lex; lex->pop_context(); diff --git a/sql/stacktrace.c b/sql/stacktrace.c index 43f35c452f7..a2fe2ab88f1 100644 --- a/sql/stacktrace.c +++ b/sql/stacktrace.c @@ -222,7 +222,7 @@ terribly wrong...\n"); fprintf(stderr, "Stack trace seems successful - bottom reached\n"); end: - fprintf(stderr, "Please read http://dev.mysql.com/doc/mysql/en/Using_stack_trace.html and follow instructions on how to resolve the stack trace. Resolved\n\ + fprintf(stderr, "Please read http://dev.mysql.com/doc/mysql/en/using-stack-trace.html and follow instructions on how to resolve the stack trace. Resolved\n\ stack trace is much more helpful in diagnosing the problem, so please do \n\ resolve it\n"); } diff --git a/sql/table.cc b/sql/table.cc index 0a95461cf06..1886fdb0b82 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -1592,7 +1592,7 @@ char *get_field(MEM_ROOT *mem, Field *field) bool check_db_name(char *name) { - char *start=name; + char *start= name; /* Used to catch empty names and names with end space */ bool last_char_is_space= TRUE; diff --git a/sql/udf_example.c b/sql/udf_example.c index a80fce81278..2fa7474eb16 100644 --- a/sql/udf_example.c +++ b/sql/udf_example.c @@ -127,7 +127,14 @@ typedef long long longlong; #else #include #include +#if defined(MYSQL_SERVER) #include /* To get strmov() */ +#else +/* when compiled as standalone */ +#define strmov(a,b) strcpy(a,b) +#define bzero(a,b) memset(a,0,b) +#define memcpy_fixed(a,b,c) memcpy(a,b,c) +#endif #endif #include #include @@ -674,10 +681,14 @@ longlong sequence(UDF_INIT *initid __attribute__((unused)), UDF_ARGS *args, ** ****************************************************************************/ +#ifdef __WIN__ +#include +#else #include #include #include #include +#endif my_bool lookup_init(UDF_INIT *initid, UDF_ARGS *args, char *message); void lookup_deinit(UDF_INIT *initid); diff --git a/sql/udf_example.def b/sql/udf_example.def new file mode 100644 index 00000000000..d3081ca7768 --- /dev/null +++ b/sql/udf_example.def @@ -0,0 +1,24 @@ +LIBRARY udf_example +DESCRIPTION 'MySQL Sample for UDF' +VERSION 1.0 +EXPORTS + lookup + lookup_init + reverse_lookup + reverse_lookup_init + metaphon_init + metaphon_deinit + metaphon + myfunc_double_init + myfunc_double + myfunc_int_init + myfunc_int + sequence_init + sequence_deinit + sequence + avgcost_init + avgcost_deinit + avgcost_reset + avgcost_add + avgcost_clear + avgcost diff --git a/sql/unireg.cc b/sql/unireg.cc index 3a139aea4c7..93afd9c9e4e 100644 --- a/sql/unireg.cc +++ b/sql/unireg.cc @@ -228,13 +228,19 @@ bool mysql_create_frm(THD *thd, my_string file_name, goto err3; { - /* Unescape all UCS2 intervals: were escaped in pack_headers */ + /* + Restore all UCS2 intervals. + HEX representation of them is not needed anymore. + */ List_iterator it(create_fields); create_field *field; while ((field=it++)) { - if (field->interval && field->charset->mbminlen > 1) - unhex_type2(field->interval); + if (field->save_interval) + { + field->interval= field->save_interval; + field->save_interval= 0; + } } } DBUG_RETURN(0); @@ -514,18 +520,36 @@ static bool pack_header(uchar *forminfo, enum db_type table_type, reclength=(uint) (field->offset+ data_offset + length); n_length+= (ulong) strlen(field->field_name)+1; field->interval_id=0; + field->save_interval= 0; if (field->interval) { uint old_int_count=int_count; if (field->charset->mbminlen > 1) { - /* Escape UCS2 intervals using HEX notation */ + /* + Escape UCS2 intervals using HEX notation to avoid + problems with delimiters between enum elements. + As the original representation is still needed in + the function make_empty_rec to create a record of + filled with default values it is saved in save_interval + The HEX representation is created from this copy. + */ + field->save_interval= field->interval; + field->interval= (TYPELIB*) sql_alloc(sizeof(TYPELIB)); + *field->interval= *field->save_interval; + field->interval->type_names= + (const char **) sql_alloc(sizeof(char*) * + (field->interval->count+1)); + field->interval->type_names[field->interval->count]= 0; + field->interval->type_lengths= + (uint *) sql_alloc(sizeof(uint) * field->interval->count); + for (uint pos= 0; pos < field->interval->count; pos++) { char *dst; - uint length= field->interval->type_lengths[pos], hex_length; - const char *src= field->interval->type_names[pos]; + uint length= field->save_interval->type_lengths[pos], hex_length; + const char *src= field->save_interval->type_names[pos]; hex_length= length * 2; field->interval->type_lengths[pos]= hex_length; field->interval->type_names[pos]= dst= sql_alloc(hex_length + 1); @@ -777,7 +801,8 @@ static bool make_empty_rec(THD *thd, File file,enum db_type table_type, field->charset, field->geom_type, field->unireg_check, - field->interval, + field->save_interval ? field->save_interval : + field->interval, field->field_name, &table); if (!regfield) diff --git a/strings/ctype-big5.c b/strings/ctype-big5.c index 0ca1cf21129..479fb789816 100644 --- a/strings/ctype-big5.c +++ b/strings/ctype-big5.c @@ -6370,6 +6370,7 @@ static MY_CHARSET_HANDLER my_charset_big5_handler= my_strntoull_8bit, my_strntod_8bit, my_strtoll10_8bit, + my_strntoull10rnd_8bit, my_scan_8bit }; diff --git a/strings/ctype-bin.c b/strings/ctype-bin.c index 54c35c82652..0bd5a1fda76 100644 --- a/strings/ctype-bin.c +++ b/strings/ctype-bin.c @@ -517,6 +517,7 @@ static MY_CHARSET_HANDLER my_charset_handler= my_strntoull_8bit, my_strntod_8bit, my_strtoll10_8bit, + my_strntoull10rnd_8bit, my_scan_8bit }; diff --git a/strings/ctype-cp932.c b/strings/ctype-cp932.c index 5f8a93b1c2b..b4e9ba16d92 100644 --- a/strings/ctype-cp932.c +++ b/strings/ctype-cp932.c @@ -5492,6 +5492,7 @@ static MY_CHARSET_HANDLER my_charset_handler= my_strntoull_8bit, my_strntod_8bit, my_strtoll10_8bit, + my_strntoull10rnd_8bit, my_scan_8bit }; diff --git a/strings/ctype-euc_kr.c b/strings/ctype-euc_kr.c index d6df46f7e05..40e0f4e3d2d 100644 --- a/strings/ctype-euc_kr.c +++ b/strings/ctype-euc_kr.c @@ -8711,6 +8711,7 @@ static MY_CHARSET_HANDLER my_charset_handler= my_strntoull_8bit, my_strntod_8bit, my_strtoll10_8bit, + my_strntoull10rnd_8bit, my_scan_8bit }; diff --git a/strings/ctype-eucjpms.c b/strings/ctype-eucjpms.c index 348eb2f6e87..65fef2dfc4c 100644 --- a/strings/ctype-eucjpms.c +++ b/strings/ctype-eucjpms.c @@ -8677,6 +8677,7 @@ static MY_CHARSET_HANDLER my_charset_handler= my_strntoull_8bit, my_strntod_8bit, my_strtoll10_8bit, + my_strntoull10rnd_8bit, my_scan_8bit }; diff --git a/strings/ctype-gb2312.c b/strings/ctype-gb2312.c index 29ecafc3527..c2fc1e2c190 100644 --- a/strings/ctype-gb2312.c +++ b/strings/ctype-gb2312.c @@ -5762,6 +5762,7 @@ static MY_CHARSET_HANDLER my_charset_handler= my_strntoull_8bit, my_strntod_8bit, my_strtoll10_8bit, + my_strntoull10rnd_8bit, my_scan_8bit }; diff --git a/strings/ctype-gbk.c b/strings/ctype-gbk.c index ef1b33fd82c..c4d06d67eb9 100644 --- a/strings/ctype-gbk.c +++ b/strings/ctype-gbk.c @@ -10015,6 +10015,7 @@ static MY_CHARSET_HANDLER my_charset_handler= my_strntoull_8bit, my_strntod_8bit, my_strtoll10_8bit, + my_strntoull10rnd_8bit, my_scan_8bit }; diff --git a/strings/ctype-latin1.c b/strings/ctype-latin1.c index a3f5aec9605..1298b66bb7e 100644 --- a/strings/ctype-latin1.c +++ b/strings/ctype-latin1.c @@ -411,6 +411,7 @@ static MY_CHARSET_HANDLER my_charset_handler= my_strntoull_8bit, my_strntod_8bit, my_strtoll10_8bit, + my_strntoull10rnd_8bit, my_scan_8bit }; diff --git a/strings/ctype-simple.c b/strings/ctype-simple.c index 12ef77c59b1..e40a1948dcf 100644 --- a/strings/ctype-simple.c +++ b/strings/ctype-simple.c @@ -17,6 +17,7 @@ #include #include "m_string.h" #include "m_ctype.h" +#include "my_sys.h" /* Needed for MY_ERRNO_ERANGE */ #include #include "stdarg.h" @@ -1354,6 +1355,341 @@ longlong my_strtoll10_8bit(CHARSET_INFO *cs __attribute__((unused)), } +#undef ULONGLONG_MAX +/* + Needed under MetroWerks Compiler, since MetroWerks compiler does not + properly handle a constant expression containing a mod operator +*/ +#if defined(__NETWARE__) && defined(__MWERKS__) +static ulonglong ulonglong_max= ~(ulonglong) 0; +#define ULONGLONG_MAX ulonglong_max +#else +#define ULONGLONG_MAX (~(ulonglong) 0) +#endif /* __NETWARE__ && __MWERKS__ */ + + +#define CUTOFF (ULONGLONG_MAX / 10) +#define CUTLIM (ULONGLONG_MAX % 10) +#define DIGITS_IN_ULONGLONG 20 + +static ulonglong d10[DIGITS_IN_ULONGLONG]= +{ + 1, + 10, + 100, + 1000, + 10000, + 100000, + 1000000, + 10000000, + 100000000, + 1000000000, + 10000000000ULL, + 100000000000ULL, + 1000000000000ULL, + 10000000000000ULL, + 100000000000000ULL, + 1000000000000000ULL, + 10000000000000000ULL, + 100000000000000000ULL, + 1000000000000000000ULL, + 10000000000000000000ULL +}; + + +/* + + Convert a string to unsigned long long integer value + with rounding. + + SYNOPSYS + my_strntoull10_8bit() + cs in pointer to character set + str in pointer to the string to be converted + length in string length + unsigned_flag in whether the number is unsigned + endptr out pointer to the stop character + error out returned error code + + DESCRIPTION + This function takes the decimal representation of integer number + from string str and converts it to an signed or unsigned + long long integer value. + Space characters and tab are ignored. + A sign character might precede the digit characters. + The number may have any number of pre-zero digits. + The number may have decimal point and exponent. + Rounding is always done in "away from zero" style: + 0.5 -> 1 + -0.5 -> -1 + + The function stops reading the string str after "length" bytes + or at the first character that is not a part of correct number syntax: + + ::= + [ ] [ E [ ] ] + + ::= + [ [ ] ] + | + ::= ... + + RETURN VALUES + Value of string as a signed/unsigned longlong integer + + endptr cannot be NULL. The function will store the end pointer + to the stop character here. + + The error parameter contains information how things went: + 0 ok + ERANGE If the the value of the converted number is out of range + In this case the return value is: + - ULONGLONG_MAX if unsigned_flag and the number was too big + - 0 if unsigned_flag and the number was negative + - LONGLONG_MAX if no unsigned_flag and the number is too big + - LONGLONG_MIN if no unsigned_flag and the number it too big negative + + EDOM If the string didn't contain any digits. + In this case the return value is 0. +*/ + +ulonglong +my_strntoull10rnd_8bit(CHARSET_INFO *cs __attribute__((unused)), + const char *str, uint length, int unsigned_flag, + char **endptr, int *error) +{ + const char *dot, *end9, *beg, *end= str + length; + ulonglong ull; + ulong ul; + unsigned char ch; + int shift= 0, digits= 0, negative, addon; + + /* Skip leading spaces and tabs */ + for ( ; str < end && (*str == ' ' || *str == '\t') ; str++); + + if (str >= end) + goto ret_edom; + + if ((negative= (*str == '-')) || *str=='+') /* optional sign */ + { + if (++str == end) + goto ret_edom; + } + + beg= str; + end9= (str + 9) > end ? end : (str + 9); + /* Accumulate small number into ulong, for performance purposes */ + for (ul= 0 ; str < end9 && (ch= (unsigned char) (*str - '0')) < 10; str++) + { + ul= ul * 10 + ch; + } + + if (str >= end) /* Small number without dots and expanents */ + { + *endptr= (char*) str; + if (negative) + { + if (unsigned_flag) + { + *error= ul ? MY_ERRNO_ERANGE : 0; + return 0; + } + else + { + *error= 0; + return (ulonglong) (longlong) (long) -ul; + } + } + else + { + *error=0; + return (ulonglong) ul; + } + } + + digits= str - beg; + + /* Continue to accumulate into ulonglong */ + for (dot= NULL, ull= ul; str < end; str++) + { + if ((ch= (unsigned char) (*str - '0')) < 10) + { + if (ull < CUTOFF || (ull == CUTOFF && ch <= CUTLIM)) + { + ull= ull * 10 + ch; + digits++; + continue; + } + /* + Adding the next digit would overflow. + Remember the next digit in "addon", for rounding. + Scan all digits with an optional single dot. + */ + if (ull == CUTOFF) + { + ull= ULONGLONG_MAX; + addon= 1; + str++; + } + else + addon= (*str >= '5'); + for ( ; str < end && (ch= (unsigned char) (*str - '0')) < 10; str++) + { + if (!dot) + shift++; + } + if (str < end && *str == '.' && !dot) + { + str++; + for ( ; str < end && (ch= (unsigned char) (*str - '0')) < 10; str++); + } + goto exp; + } + + if (*str == '.') + { + if (dot) + { + /* The second dot character */ + addon= 0; + goto exp; + } + else + { + dot= str + 1; + } + continue; + } + + /* Unknown character, exit the loop */ + break; + } + shift= dot ? dot - str : 0; /* Right shift */ + addon= 0; + +exp: /* [ E [ ] ] */ + + if (!digits) + { + str= beg; + goto ret_edom; + } + + if (str < end && (*str == 'e' || *str == 'E')) + { + str++; + if (str < end) + { + int negative_exp, exp; + if ((negative_exp= (*str == '-')) || *str=='+') + { + if (++str == end) + goto ret_sign; + } + for (exp= 0 ; + str < end && (ch= (unsigned char) (*str - '0')) < 10; + str++) + { + exp= exp * 10 + ch; + } + shift+= negative_exp ? -exp : exp; + } + } + + if (shift == 0) /* No shift, check addon digit */ + { + if (addon) + { + if (ull == ULONGLONG_MAX) + goto ret_too_big; + ull++; + } + goto ret_sign; + } + + if (shift < 0) /* Right shift */ + { + ulonglong d, r; + + if (-shift >= DIGITS_IN_ULONGLONG) + goto ret_zero; /* Exponent is a big negative number, return 0 */ + + d= d10[-shift]; + r= (ull % d) * 2; + ull /= d; + if (r >= d) + ull++; + goto ret_sign; + } + + if (shift > DIGITS_IN_ULONGLONG) /* Huge left shift */ + { + if (!ull) + goto ret_sign; + goto ret_too_big; + } + + for ( ; shift > 0; shift--, ull*= 10) /* Left shift */ + { + if (ull > CUTOFF) + goto ret_too_big; /* Overflow, number too big */ + } + +ret_sign: + *endptr= (char*) str; + + if (!unsigned_flag) + { + if (negative) + { + if (ull > (ulonglong) LONGLONG_MIN) + { + *error= MY_ERRNO_ERANGE; + return (ulonglong) LONGLONG_MIN; + } + *error= 0; + return (ulonglong) -ull; + } + else + { + if (ull > (ulonglong) LONGLONG_MAX) + { + *error= MY_ERRNO_ERANGE; + return (ulonglong) LONGLONG_MAX; + } + *error= 0; + return ull; + } + } + + /* Unsigned number */ + if (negative && ull) + { + *error= MY_ERRNO_ERANGE; + return 0; + } + *error= 0; + return ull; + +ret_zero: + *endptr= (char*) str; + *error= 0; + return 0; + +ret_edom: + *endptr= (char*) str; + *error= MY_ERRNO_EDOM; + return 0; + +ret_too_big: + *endptr= (char*) str; + *error= MY_ERRNO_ERANGE; + return unsigned_flag ? + ULONGLONG_MAX : + negative ? (ulonglong) LONGLONG_MIN : (ulonglong) LONGLONG_MAX; +} + + /* Check if a constant can be propagated @@ -1434,6 +1770,7 @@ MY_CHARSET_HANDLER my_charset_8bit_handler= my_strntoull_8bit, my_strntod_8bit, my_strtoll10_8bit, + my_strntoull10rnd_8bit, my_scan_8bit }; diff --git a/strings/ctype-sjis.c b/strings/ctype-sjis.c index 57d6d8bae2b..3854837e09a 100644 --- a/strings/ctype-sjis.c +++ b/strings/ctype-sjis.c @@ -4663,6 +4663,7 @@ static MY_CHARSET_HANDLER my_charset_handler= my_strntoull_8bit, my_strntod_8bit, my_strtoll10_8bit, + my_strntoull10rnd_8bit, my_scan_8bit }; diff --git a/strings/ctype-tis620.c b/strings/ctype-tis620.c index dc4f18b516b..85ebbe82731 100644 --- a/strings/ctype-tis620.c +++ b/strings/ctype-tis620.c @@ -891,6 +891,7 @@ static MY_CHARSET_HANDLER my_charset_handler= my_strntoull_8bit, my_strntod_8bit, my_strtoll10_8bit, + my_strntoull10rnd_8bit, my_scan_8bit }; diff --git a/strings/ctype-ucs2.c b/strings/ctype-ucs2.c index 97dca79e84b..4a60220f73e 100644 --- a/strings/ctype-ucs2.c +++ b/strings/ctype-ucs2.c @@ -974,6 +974,35 @@ double my_strntod_ucs2(CHARSET_INFO *cs __attribute__((unused)), } +ulonglong my_strntoull10rnd_ucs2(CHARSET_INFO *cs __attribute__((unused)), + const char *nptr, uint length, int unsign_fl, + char **endptr, int *err) +{ + char buf[256], *b= buf; + ulonglong res; + const uchar *end, *s= (const uchar*) nptr; + my_wc_t wc; + int cnv; + + /* Cut too long strings */ + if (length >= sizeof(buf)) + length= sizeof(buf)-1; + end= s + length; + + while ((cnv= cs->cset->mb_wc(cs,&wc,s,end)) > 0) + { + s+= cnv; + if (wc > (int) (uchar) 'e' || !wc) + break; /* Can't be a number part */ + *b++= (char) wc; + } + + res= my_strntoull10rnd_8bit(cs, buf, b - buf, unsign_fl, endptr, err); + *endptr= (char*) nptr + 2 * (uint) (*endptr- buf); + return res; +} + + /* This is a fast version optimized for the case of radix 10 / -10 */ @@ -1629,6 +1658,7 @@ MY_CHARSET_HANDLER my_charset_ucs2_handler= my_strntoull_ucs2, my_strntod_ucs2, my_strtoll10_ucs2, + my_strntoull10rnd_ucs2, my_scan_ucs2 }; diff --git a/strings/ctype-ujis.c b/strings/ctype-ujis.c index ca27b4bef6b..675ac918e2c 100644 --- a/strings/ctype-ujis.c +++ b/strings/ctype-ujis.c @@ -8545,6 +8545,7 @@ static MY_CHARSET_HANDLER my_charset_handler= my_strntoull_8bit, my_strntod_8bit, my_strtoll10_8bit, + my_strntoull10rnd_8bit, my_scan_8bit }; diff --git a/strings/ctype-utf8.c b/strings/ctype-utf8.c index 3594ab954c6..3a5c01a2861 100644 --- a/strings/ctype-utf8.c +++ b/strings/ctype-utf8.c @@ -2548,6 +2548,7 @@ MY_CHARSET_HANDLER my_charset_utf8_handler= my_strntoull_8bit, my_strntod_8bit, my_strtoll10_8bit, + my_strntoull10rnd_8bit, my_scan_8bit }; diff --git a/strings/strtod.c b/strings/strtod.c index 7171a6e0801..ddb570718a0 100644 --- a/strings/strtod.c +++ b/strings/strtod.c @@ -30,7 +30,8 @@ #include "m_ctype.h" #define MAX_DBL_EXP 308 -#define MAX_RESULT_FOR_MAX_EXP 1.79769313486232 +#define MAX_RESULT_FOR_MAX_EXP 1.7976931348623157 +#define MIN_RESULT_FOR_MIN_EXP 2.225073858507202 static double scaler10[] = { 1.0, 1e10, 1e20, 1e30, 1e40, 1e50, 1e60, 1e70, 1e80, 1e90 }; @@ -57,10 +58,11 @@ double my_strtod(const char *str, char **end_ptr, int *error) { double result= 0.0; uint negative= 0, ndigits, dec_digits= 0, neg_exp= 0; - int exp= 0, digits_after_dec_point= 0; + int exp= 0, digits_after_dec_point= 0, tmp_exp; const char *old_str, *end= *end_ptr, *start_of_number; char next_char; my_bool overflow=0; + double scaler= 1.0; *error= 0; if (str >= end) @@ -91,6 +93,7 @@ double my_strtod(const char *str, char **end_ptr, int *error) while ((next_char= *str) >= '0' && next_char <= '9') { result= result*10.0 + (next_char - '0'); + scaler= scaler*10.0; if (++str == end) { next_char= 0; /* Found end of string */ @@ -114,6 +117,7 @@ double my_strtod(const char *str, char **end_ptr, int *error) { result= result*10.0 + (next_char - '0'); digits_after_dec_point++; + scaler= scaler*10.0; if (++str == end) { next_char= 0; @@ -144,39 +148,54 @@ double my_strtod(const char *str, char **end_ptr, int *error) } while (str < end && my_isdigit(&my_charset_latin1, *str)); } } - if ((exp= (neg_exp ? exp + digits_after_dec_point : - exp - digits_after_dec_point))) + tmp_exp= neg_exp ? exp + digits_after_dec_point : exp - digits_after_dec_point; + if (tmp_exp) { - double scaler; + int order; + /* + Check for underflow/overflow. + order is such an integer number that f = C * 10 ^ order, + where f is the resulting floating point number and 1 <= C < 10. + Here we compute the modulus + */ + order= exp + (neg_exp ? -1 : 1) * (ndigits - 1); + if (order < 0) + order= -order; + if (order >= MAX_DBL_EXP && result) + { + double c; + /* Compute modulus of C (see comment above) */ + c= result / scaler * 10.0; + if (neg_exp) + { + if (order > MAX_DBL_EXP || c < MIN_RESULT_FOR_MIN_EXP) + { + result= 0.0; + goto done; + } + } + else + { + if (order > MAX_DBL_EXP || c > MAX_RESULT_FOR_MAX_EXP) + { + overflow= 1; + goto done; + } + } + } + + exp= tmp_exp; if (exp < 0) { exp= -exp; neg_exp= 1; /* neg_exp was 0 before */ } - if (exp + ndigits >= MAX_DBL_EXP + 1 && result) - { - /* - This is not 100 % as we actually will give an owerflow for - 17E307 but not for 1.7E308 but lets cut some corners to make life - simpler - */ - if (exp + ndigits > MAX_DBL_EXP + 1 || - result >= MAX_RESULT_FOR_MAX_EXP) - { - if (neg_exp) - result= 0.0; - else - overflow= 1; - goto done; - } - } - scaler= 1.0; while (exp >= 100) { - scaler*= 1.0e100; + result= neg_exp ? result/1.0e100 : result*1.0e100; exp-= 100; } - scaler*= scaler10[exp/10]*scaler1[exp%10]; + scaler= scaler10[exp/10]*scaler1[exp%10]; if (neg_exp) result/= scaler; else diff --git a/tests/Makefile.am b/tests/Makefile.am index 3eb3d39de1e..9f143173827 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -43,14 +43,11 @@ INCLUDES = -I$(top_builddir)/include -I$(top_srcdir)/include \ LIBS = @CLIENT_LIBS@ LDADD = @CLIENT_EXTRA_LDFLAGS@ \ $(top_builddir)/libmysql/libmysqlclient.la -if HAVE_NETWARE + mysql_client_test_LDADD= $(LDADD) $(CXXLDFLAGS) mysql_client_test_SOURCES= mysql_client_test.c $(yassl_dummy_link_fix) \ - ../mysys/my_memmem.c -else -mysql_client_test_LDADD= $(LDADD) $(CXXLDFLAGS) -L../mysys -lmysys -mysql_client_test_SOURCES= mysql_client_test.c $(yassl_dummy_link_fix) -endif + $(top_srcdir)/mysys/my_memmem.c + insert_test_SOURCES= insert_test.c $(yassl_dummy_link_fix) select_test_SOURCES= select_test.c $(yassl_dummy_link_fix) insert_test_DEPENDENCIES= $(LIBRARIES) $(pkglib_LTLIBRARIES) diff --git a/tests/mysql_client_test.c b/tests/mysql_client_test.c index 8a444590301..d3f39296445 100644 --- a/tests/mysql_client_test.c +++ b/tests/mysql_client_test.c @@ -15237,6 +15237,43 @@ static void test_bug21206() DBUG_VOID_RETURN; } +/* + Bug#21726: Incorrect result with multiple invocations of + LAST_INSERT_ID + + Test that client gets updated value of insert_id on UPDATE that uses + LAST_INSERT_ID(expr). +*/ +static void test_bug21726() +{ + const char *create_table[]= + { + "DROP TABLE IF EXISTS t1", + "CREATE TABLE t1 (i INT)", + "INSERT INTO t1 VALUES (1)", + }; + const char *update_query= "UPDATE t1 SET i= LAST_INSERT_ID(i + 1)"; + int rc; + my_ulonglong insert_id; + + DBUG_ENTER("test_bug21726"); + myheader("test_bug21726"); + + fill_tables(create_table, sizeof(create_table) / sizeof(*create_table)); + + rc= mysql_query(mysql, update_query); + myquery(rc); + insert_id= mysql_insert_id(mysql); + DIE_UNLESS(insert_id == 2); + + rc= mysql_query(mysql, update_query); + myquery(rc); + insert_id= mysql_insert_id(mysql); + DIE_UNLESS(insert_id == 3); + + DBUG_VOID_RETURN; +} + /* Read and parse arguments and MySQL options from my.cnf @@ -15511,7 +15548,8 @@ static struct my_tests_st my_tests[]= { { "test_bug17667", test_bug17667 }, { "test_bug19671", test_bug19671 }, { "test_bug15752", test_bug15752 }, - { "test_bug21206", test_bug21206}, + { "test_bug21206", test_bug21206 }, + { "test_bug21726", test_bug21726 }, { 0, 0 } }; diff --git a/vio/viosocket.c b/vio/viosocket.c index 1f348c3313d..3ce1c994d79 100644 --- a/vio/viosocket.c +++ b/vio/viosocket.c @@ -276,7 +276,7 @@ int vio_close(Vio * vio) if (vio->type != VIO_CLOSED) { DBUG_ASSERT(vio->sd >= 0); - if (shutdown(vio->sd,2)) + if (shutdown(vio->sd, SHUT_RDWR)) r= -1; if (closesocket(vio->sd)) r= -1; @@ -559,9 +559,13 @@ int vio_write_shared_memory(Vio * vio, const gptr buf, int size) } +/** + Close shared memory and DBUG_PRINT any errors that happen on closing. + @return Zero if all closing functions succeed, and nonzero otherwise. +*/ int vio_close_shared_memory(Vio * vio) { - int r; + int error_count= 0; DBUG_ENTER("vio_close_shared_memory"); if (vio->type != VIO_CLOSED) { @@ -575,23 +579,44 @@ int vio_close_shared_memory(Vio * vio) result if they are success. */ if (UnmapViewOfFile(vio->handle_map) == 0) + { + error_count++; DBUG_PRINT("vio_error", ("UnmapViewOfFile() failed")); + } if (CloseHandle(vio->event_server_wrote) == 0) + { + error_count++; DBUG_PRINT("vio_error", ("CloseHandle(vio->esw) failed")); + } if (CloseHandle(vio->event_server_read) == 0) + { + error_count++; DBUG_PRINT("vio_error", ("CloseHandle(vio->esr) failed")); + } if (CloseHandle(vio->event_client_wrote) == 0) + { + error_count++; DBUG_PRINT("vio_error", ("CloseHandle(vio->ecw) failed")); + } if (CloseHandle(vio->event_client_read) == 0) + { + error_count++; DBUG_PRINT("vio_error", ("CloseHandle(vio->ecr) failed")); + } if (CloseHandle(vio->handle_file_map) == 0) + { + error_count++; DBUG_PRINT("vio_error", ("CloseHandle(vio->hfm) failed")); + } if (CloseHandle(vio->event_conn_closed) == 0) + { + error_count++; DBUG_PRINT("vio_error", ("CloseHandle(vio->ecc) failed")); + } } vio->type= VIO_CLOSED; vio->sd= -1; - DBUG_RETURN(!r); + DBUG_RETURN(error_count); } #endif /* HAVE_SMEM */ #endif /* __WIN__ */ diff --git a/zlib/Makefile.am b/zlib/Makefile.am index 0081c93a2ae..af7d60d8568 100644 --- a/zlib/Makefile.am +++ b/zlib/Makefile.am @@ -18,6 +18,8 @@ INCLUDES= -I$(top_builddir)/include -I$(top_srcdir)/include +LIBS= $(NON_THREADED_LIBS) + pkglib_LTLIBRARIES=libz.la libz_la_LDFLAGS= -version-info 3:3:2