diff options
author | unknown <tomas@mc05.(none)> | 2004-06-01 18:05:43 +0200 |
---|---|---|
committer | unknown <tomas@mc05.(none)> | 2004-06-01 18:05:43 +0200 |
commit | c91972c29a5c41f6030e4b27ab72213919934de6 (patch) | |
tree | d7d574a2d3e6c689a5107360884bfd5950eaec45 | |
parent | cfb496aed8679f2763b3d64655e7b744b9e48793 (diff) | |
parent | 389e8bec492a5cf1a8cd8bb54f8d14518aaa925a (diff) | |
download | mariadb-git-c91972c29a5c41f6030e4b27ab72213919934de6.tar.gz |
Merge tulin@bk-internal.mysql.com:/home/bk/mysql-4.1
into mc05.(none):/space2/tomas/mysql-4.1-ndb-test
configure.in:
Auto merged
ndb/src/kernel/blocks/backup/restore/Restore.cpp:
Auto merged
sql/ha_ndbcluster.cc:
Auto merged
-rwxr-xr-x | BUILD/compile-pentium-maintainer | 13 | ||||
-rwxr-xr-x | Build-tools/Do-compile | 21 | ||||
-rw-r--r-- | configure.in | 2 | ||||
-rw-r--r-- | include/my_global.h | 6 | ||||
-rw-r--r-- | innobase/dict/dict0load.c | 9 | ||||
-rw-r--r-- | innobase/fil/fil0fil.c | 242 | ||||
-rw-r--r-- | innobase/os/os0file.c | 21 | ||||
-rw-r--r-- | innobase/row/row0mysql.c | 169 | ||||
-rw-r--r-- | mysql-test/r/multi_update.result | 1 | ||||
-rw-r--r-- | mysql-test/r/subselect.result | 2 | ||||
-rw-r--r-- | mysql-test/t/multi_update.test | 1 | ||||
-rw-r--r-- | mysql-test/t/subselect.test | 2 | ||||
-rw-r--r-- | mysql-test/t/system_mysql_db_fix.test | 4 | ||||
-rw-r--r-- | sql/handler.h | 4 | ||||
-rw-r--r-- | sql/item.cc | 13 | ||||
-rw-r--r-- | sql/item.h | 39 | ||||
-rw-r--r-- | tests/client_test.c | 90 |
17 files changed, 409 insertions, 230 deletions
diff --git a/BUILD/compile-pentium-maintainer b/BUILD/compile-pentium-maintainer deleted file mode 100755 index 1265154dc76..00000000000 --- a/BUILD/compile-pentium-maintainer +++ /dev/null @@ -1,13 +0,0 @@ -#! /bin/sh - -path=`dirname $0` -. "$path/SETUP.sh" - -extra_flags="$pentium_cflags $debug_cflags" -c_warnings="$c_warnings $debug_extra_warnings" -cxx_warnings="$cxx_warnings $debug_extra_warnings" -extra_configs="$pentium_configs $debug_configs " - -extra_configs="$extra_configs --enable-maintainer-mode" - -. "$path/FINISH.sh" diff --git a/Build-tools/Do-compile b/Build-tools/Do-compile index 03571593f77..5d4a1bdb987 100755 --- a/Build-tools/Do-compile +++ b/Build-tools/Do-compile @@ -7,7 +7,7 @@ use Sys::Hostname; @config_options= (); @make_options= (); -$opt_distribution=$opt_user=$opt_config_env=""; +$opt_distribution=$opt_user=$opt_config_env=$opt_config_extra_env=""; $opt_dbd_options=$opt_perl_options=$opt_config_options=$opt_make_options=$opt_suffix=""; $opt_tmp=$opt_version_suffix=""; $opt_help=$opt_delete=$opt_debug=$opt_stage=$opt_no_test=$opt_no_perl=$opt_with_low_memory=$opt_fast_benchmark=$opt_static_client=$opt_static_server=$opt_static_perl=$opt_sur=$opt_with_small_disk=$opt_local_perl=$opt_tcpip=$opt_build_thread=$opt_use_old_distribution=$opt_enable_shared=$opt_no_crash_me=$opt_no_strip=$opt_with_cluster=$opt_with_debug=$opt_no_benchmark=$opt_no_mysqltest=$opt_without_embedded=$opt_readline=0; @@ -17,6 +17,7 @@ GetOptions( "bdb", "build-thread=i", "config-env=s" => \@config_env, + "config-extra-env=s" => \@config_extra_env, "config-options=s" => \@config_options, "dbd-options=s", "debug", @@ -81,6 +82,12 @@ if (@config_env > 0) $opt_config_env= join(" ", @config_env); } +if (@config_extra_env > 0) +{ + chomp(@config_extra_env); + $opt_config_extra_env= join(" ", @config_extra_env); +} + $host= hostname(); chomp($uname=`uname`); $full_host_name=$host; @@ -91,6 +98,7 @@ $email="$opt_user\@mysql.com"; chomp($pwd = `pwd`); $VER= basename($opt_distribution); $VER=~ /mysql.*-([1-9]\.[0-9]{1,2}\.[0-9]{1,2}.*)\.tar*/; $version=$1; +$release=""; # Shut up perl ($major, $minor, $release) = split(/\./,$version); $log="$pwd/Logs/$host-$major.$minor$opt_version_suffix.log"; $opt_distribution =~ /(mysql[^\/]*)\.tar/; @@ -113,6 +121,8 @@ if (defined($gcc_version) && ! $opt_config_env) } } +$opt_config_env.=" $opt_config_extra_env"; + $new_opt_tmp=0; if ($opt_tmp) { @@ -156,6 +166,9 @@ select STDOUT; $|=1; info("Compiling MySQL$opt_version_suffix at $host$opt_suffix, stage: $opt_stage\n"); +info("LD_LIBRARY_PATH is $ENV{LD_LIBRARY_PATH}"); +info("PATH is $ENV{PATH}"); + log_timestamp(); if (-x "$host/bin/mysqladmin") @@ -448,7 +461,7 @@ exit 0; sub usage { print <<EOF; -$0 version 1.5 +$0 version 1.6 $0 takes the following options: @@ -458,6 +471,10 @@ Compile with support for Berkeley DB tables --config-env=<environment for configure> To set up the environment, like 'CC=cc CXX=gcc CXXFLAGS=-O3' +--config-extra-env <environment for configure> +Additional flags for environment (not CC or CXX). Should be used when one +wants Do-compile to propose proper CC and CXX flags. + --config-options=<options> To add some extra options to configure (e.g. '--with-perl=yes') diff --git a/configure.in b/configure.in index b1234721354..8c91a367679 100644 --- a/configure.in +++ b/configure.in @@ -95,7 +95,6 @@ AC_SUBST(CXXLDFLAGS) AC_PREREQ(2.12)dnl Minimum Autoconf version required. -AM_MAINTAINER_MODE #AC_ARG_PROGRAM # Automaticly invoked by AM_INIT_AUTOMAKE AM_SANITY_CHECK # This is needed is SUBDIRS is set @@ -2663,6 +2662,7 @@ AM_CONDITIONAL(HAVE_NETWARE, test "$netware_dir" = "netware") # Ensure that table handlers gets all modifications to CFLAGS/CXXFLAGS export CC CXX CFLAGS CXXFLAGS LD LDFLAGS AR +ac_configure_args="$ac_configure_args CFLAGS='$CFLAGS' CXXFLAGS='$CXXFLAGS'" if test "$with_server" = "yes" -o "$THREAD_SAFE_CLIENT" != "no" then diff --git a/include/my_global.h b/include/my_global.h index 40396445bdf..57c736d6f75 100644 --- a/include/my_global.h +++ b/include/my_global.h @@ -178,7 +178,11 @@ C_MODE_END #ifdef HAVE_BROKEN_SNPRINTF /* HPUX 10.20 don't have this defined */ #undef HAVE_SNPRINTF #endif -#ifdef HAVE_BROKEN_PREAD /* These doesn't work on HPUX 11.x */ +#ifdef HAVE_BROKEN_PREAD +/* + pread()/pwrite() are not 64 bit safe on HP-UX 11.0 without + installing the kernel patch PHKL_20349 or greater +*/ #undef HAVE_PREAD #undef HAVE_PWRITE #endif diff --git a/innobase/dict/dict0load.c b/innobase/dict/dict0load.c index b55050ee83f..ee4ae9dd1a1 100644 --- a/innobase/dict/dict0load.c +++ b/innobase/dict/dict0load.c @@ -207,7 +207,6 @@ dict_check_tablespaces_or_store_max_id( ulint space_id; ulint max_space_id = 0; mtr_t mtr; - char name[OS_FILE_MAX_PATH]; mutex_enter(&(dict_sys->mutex)); @@ -247,9 +246,7 @@ loop: /* We found one */ - ut_a(len < OS_FILE_MAX_PATH - 10); - ut_memcpy(name, field, len); - name[len] = '\0'; + char* name = mem_strdupl(field, len); field = rec_get_nth_field(rec, 9, &len); ut_a(len == 4); @@ -267,7 +264,9 @@ loop: fil_space_for_table_exists_in_mem(space_id, name, TRUE, TRUE); } - + + mem_free(name); + if (space_id > max_space_id) { max_space_id = space_id; } diff --git a/innobase/fil/fil0fil.c b/innobase/fil/fil0fil.c index b076e3a3315..3b033655856 100644 --- a/innobase/fil/fil0fil.c +++ b/innobase/fil/fil0fil.c @@ -1749,7 +1749,7 @@ fil_delete_tablespace( fil_space_t* space; fil_node_t* node; ulint count = 0; - char path[OS_FILE_MAX_PATH]; + char* path; ut_a(id != 0); stop_ibuf_merges: @@ -1806,11 +1806,8 @@ try_again: } ut_a(space); - ut_a(strlen(space->name) < OS_FILE_MAX_PATH); ut_a(space->n_pending_ibuf_merges == 0); - strcpy(path, space->name); - space->is_being_deleted = TRUE; ut_a(UT_LIST_GET_LEN(space->chain) == 1); @@ -1834,6 +1831,8 @@ try_again: goto try_again; } + path = mem_strdup(space->name); + mutex_exit(&(system->mutex)); #ifndef UNIV_HOTBACKUP /* Invalidate in the buffer pool all pages belonging to the @@ -1851,27 +1850,26 @@ try_again: if (success) { success = os_file_delete(path); + } - if (success) { - /* Write a log record about the deletion of the .ibd - file, so that ibbackup can replay it in the - --apply-log phase. We use a dummy mtr and the familiar - log write mechanism. */ + mem_free(path); + + if (success) { #ifndef UNIV_HOTBACKUP - { - mtr_t mtr; + /* Write a log record about the deletion of the .ibd + file, so that ibbackup can replay it in the + --apply-log phase. We use a dummy mtr and the familiar + log write mechanism. */ + mtr_t mtr; - /* When replaying the operation in ibbackup, do not try - to write any log record */ - mtr_start(&mtr); + /* When replaying the operation in ibbackup, do not try + to write any log record */ + mtr_start(&mtr); - fil_op_write_log(MLOG_FILE_DELETE, id, path, - NULL, &mtr); - mtr_commit(&mtr); - } + fil_op_write_log(MLOG_FILE_DELETE, id, path, NULL, &mtr); + mtr_commit(&mtr); #endif - return(TRUE); - } + return(TRUE); } return(FALSE); @@ -1957,6 +1955,29 @@ fil_rename_tablespace_in_mem( } /*********************************************************************** +Allocates a file name for a single-table tablespace. +The string must be freed by caller with mem_free(). */ +static +char* +fil_make_ibd_name( +/*==============*/ + /* out, own: file name */ + const char* name) /* in: table name */ +{ + ulint namelen = strlen(name); + ulint dirlen = strlen(fil_path_to_mysql_datadir); + char* filename = mem_alloc(namelen + dirlen + sizeof "/.ibd"); + + memcpy(filename, fil_path_to_mysql_datadir, dirlen); + filename[dirlen] = '/'; + memcpy(filename + dirlen + 1, name, namelen); + memcpy(filename + dirlen + namelen + 1, ".ibd", sizeof ".ibd"); + + srv_normalize_path_for_win(filename); + return(filename); +} + +/*********************************************************************** Renames a single-table tablespace. The tablespace must be cached in the tablespace memory cache. */ @@ -1978,9 +1999,9 @@ fil_rename_tablespace( fil_space_t* space; fil_node_t* node; ulint count = 0; - char* path = NULL; + char* path; ibool old_name_was_specified = TRUE; - char old_path[OS_FILE_MAX_PATH]; + char* old_path; ut_a(id != 0); @@ -2059,48 +2080,33 @@ retry: /* Check that the old name in the space is right */ if (old_name_was_specified) { - ut_a(strlen(old_name) + strlen(fil_path_to_mysql_datadir) - < OS_FILE_MAX_PATH - 10); - sprintf(old_path, "%s/%s.ibd", fil_path_to_mysql_datadir, - old_name); - srv_normalize_path_for_win(old_path); + old_path = fil_make_ibd_name(old_name); ut_a(strcmp(space->name, old_path) == 0); ut_a(strcmp(node->name, old_path) == 0); } else { - sprintf(old_path, "%s", space->name); + old_path = mem_strdup(space->name); } /* Rename the tablespace and the node in the memory cache */ - - ut_a(strlen(new_name) + strlen(fil_path_to_mysql_datadir) - < OS_FILE_MAX_PATH - 10); - path = mem_alloc(OS_FILE_MAX_PATH); - - sprintf(path, "%s/%s.ibd", fil_path_to_mysql_datadir, new_name); - - srv_normalize_path_for_win(path); - + path = fil_make_ibd_name(new_name); success = fil_rename_tablespace_in_mem(space, node, path); - if (!success) { - - goto func_exit; - } - - success = os_file_rename(old_path, path); + if (success) { + success = os_file_rename(old_path, path); - if (!success) { - /* We have to revert the changes we made to the tablespace - memory cache */ + if (!success) { + /* We have to revert the changes we made + to the tablespace memory cache */ - ut_a(fil_rename_tablespace_in_mem(space, node, old_path)); + ut_a(fil_rename_tablespace_in_mem(space, node, + old_path)); + } } -func_exit: - if (path) { - mem_free(path); - } + mem_free(path); + mem_free(old_path); + space->stop_ios = FALSE; mutex_exit(&(system->mutex)); @@ -2144,15 +2150,11 @@ fil_create_new_single_table_tablespace( ulint err; byte* page; ibool success; - char path[OS_FILE_MAX_PATH]; + char* path; ut_a(size >= FIL_IBD_FILE_INITIAL_SIZE); - ut_a(strlen(tablename) + strlen(fil_path_to_mysql_datadir) - < OS_FILE_MAX_PATH - 10); - sprintf(path, "%s/%s.ibd", fil_path_to_mysql_datadir, tablename); - - srv_normalize_path_for_win(path); + path = fil_make_ibd_name(tablename); file = os_file_create(path, OS_FILE_CREATE, OS_FILE_NORMAL, OS_DATA_FILE, &ret); @@ -2175,14 +2177,17 @@ fil_create_new_single_table_tablespace( "InnoDB: resolve the problem by removing the file %s\n" "InnoDB: under the 'datadir' of MySQL.\n", path); + mem_free(path); return(DB_TABLESPACE_ALREADY_EXISTS); } if (err == OS_FILE_DISK_FULL) { + mem_free(path); return(DB_OUT_OF_FILE_SPACE); } + mem_free(path); return(DB_ERROR); } @@ -2195,6 +2200,7 @@ fil_create_new_single_table_tablespace( os_file_close(file); os_file_delete(path); + mem_free(path); return(DB_OUT_OF_FILE_SPACE); } @@ -2206,9 +2212,11 @@ fil_create_new_single_table_tablespace( if (*space_id == ULINT_UNDEFINED) { ut_free(page); + error_exit: os_file_close(file); os_file_delete(path); + mem_free(path); return(DB_ERROR); } @@ -2234,11 +2242,7 @@ fil_create_new_single_table_tablespace( if (!ret) { fprintf(stderr, "InnoDB: Error: could not write the first page to tablespace %s\n", path); - - os_file_close(file); - os_file_delete(path); - - return(DB_ERROR); + goto error_exit; } ret = os_file_flush(file); @@ -2246,27 +2250,22 @@ fil_create_new_single_table_tablespace( if (!ret) { fprintf(stderr, "InnoDB: Error: file flush of tablespace %s failed\n", path); - - os_file_close(file); - os_file_delete(path); - - return(DB_ERROR); + goto error_exit; } os_file_close(file); if (*space_id == ULINT_UNDEFINED) { os_file_delete(path); - + error_exit2: + mem_free(path); return(DB_ERROR); } success = fil_space_create(path, *space_id, FIL_TABLESPACE); if (!success) { - os_file_delete(path); - - return(DB_ERROR); + goto error_exit2; } fil_node_create(path, size, *space_id, FALSE); @@ -2282,6 +2281,7 @@ fil_create_new_single_table_tablespace( mtr_commit(&mtr); } #endif + mem_free(path); return(DB_SUCCESS); } @@ -2315,13 +2315,7 @@ fil_reset_too_high_lsns( ulint page_no; ibool success; - filepath = ut_malloc(OS_FILE_MAX_PATH); - - ut_a(strlen(name) < OS_FILE_MAX_PATH - 10); - - sprintf(filepath, "%s/%s.ibd", fil_path_to_mysql_datadir, name); - - srv_normalize_path_for_win(filepath); + filepath = fil_make_ibd_name(name); file = os_file_create_simple_no_error_handling(filepath, OS_FILE_OPEN, OS_FILE_READ_WRITE, &success); @@ -2450,13 +2444,7 @@ fil_open_single_table_tablespace( ulint space_id; ibool ret = TRUE; - filepath = ut_malloc(OS_FILE_MAX_PATH); - - ut_a(strlen(name) < OS_FILE_MAX_PATH - 10); - - sprintf(filepath, "%s/%s.ibd", fil_path_to_mysql_datadir, name); - - srv_normalize_path_for_win(filepath); + filepath = fil_make_ibd_name(name); file = os_file_create_simple_no_error_handling(filepath, OS_FILE_OPEN, OS_FILE_READ_ONLY, &success); @@ -2525,6 +2513,28 @@ func_exit: return(ret); } +#ifdef UNIV_HOTBACKUP +/*********************************************************************** +Allocates a file name for an old version of a single-table tablespace. +The string must be freed by caller with mem_free(). */ +static +char* +fil_make_ibbackup_old_name( +/*=======================*/ + /* out, own: file name */ + const char* name) /* in: original file name */ +{ + static const char suffix[] = "_ibbackup_old_vers_"; + ulint len = strlen(name); + char* path = ut_malloc(len + (15 + sizeof suffix)); + + memcpy(path, name, len); + memcpy(path + len, suffix, (sizeof suffix) - 1); + ut_sprintf_timestamp_without_extra_chars(path + len + sizeof suffix); + return(path); +} +#endif /* UNIV_HOTBACKUP */ + /************************************************************************ Opens an .ibd file and adds the associated single-table tablespace to the InnoDB fil0fil.c data structures. */ @@ -2547,10 +2557,8 @@ fil_load_single_table_tablespace( #ifdef UNIV_HOTBACKUP fil_space_t* space; #endif - filepath = ut_malloc(OS_FILE_MAX_PATH); - - ut_a(strlen(dbname) + strlen(filename) - + strlen(fil_path_to_mysql_datadir) < OS_FILE_MAX_PATH - 100); + filepath = ut_malloc(strlen(dbname) + strlen(filename) + + strlen(fil_path_to_mysql_datadir) + 3); sprintf(filepath, "%s/%s/%s", fil_path_to_mysql_datadir, dbname, filename); @@ -2564,7 +2572,7 @@ fil_load_single_table_tablespace( fprintf(stderr, "InnoDB: Error: could not open single-table tablespace file\n" -"InnoDB: %s!", filepath); +"InnoDB: %s!\n", filepath); ut_free(filepath); @@ -2579,7 +2587,7 @@ fil_load_single_table_tablespace( fprintf(stderr, "InnoDB: Error: could not measure the size of single-table tablespace file\n" -"InnoDB: %s!", filepath); +"InnoDB: %s!\n", filepath); os_file_close(file); ut_free(filepath); @@ -2639,11 +2647,7 @@ fil_load_single_table_tablespace( filepath, space_id, filepath, size); os_file_close(file); - new_path = ut_malloc(OS_FILE_MAX_PATH); - - sprintf(new_path, "%s_ibbackup_old_vers_", filepath); - ut_sprintf_timestamp_without_extra_chars( - new_path + ut_strlen(new_path)); + new_path = fil_make_ibbackup_old_name(filepath); ut_a(os_file_rename(filepath, new_path)); ut_free(page); @@ -2676,11 +2680,8 @@ fil_load_single_table_tablespace( space->name); os_file_close(file); - new_path = ut_malloc(OS_FILE_MAX_PATH); + new_path = fil_make_ibbackup_old_name(filepath); - sprintf(new_path, "%s_ibbackup_old_vers_", filepath); - ut_sprintf_timestamp_without_extra_chars( - new_path + ut_strlen(new_path)); mutex_exit(&(fil_system->mutex)); ut_a(os_file_rename(filepath, new_path)); @@ -2724,7 +2725,8 @@ fil_load_single_table_tablespaces(void) /* out: DB_SUCCESS or error number */ { int ret; - char* dbpath; + char* dbpath = NULL; + ulint dbpath_len = 0; os_file_dir_t dir; os_file_dir_t dbdir; os_file_stat_t dbinfo; @@ -2739,7 +2741,7 @@ fil_load_single_table_tablespaces(void) return(DB_ERROR); } - dbpath = ut_malloc(OS_FILE_MAX_PATH); + dbpath = ut_malloc(dbpath_len); /* Scan all directories under the datadir. They are the database directories of MySQL. */ @@ -2747,6 +2749,7 @@ fil_load_single_table_tablespaces(void) ret = os_file_readdir_next_file(fil_path_to_mysql_datadir, dir, &dbinfo); while (ret == 0) { + ulint len; /* printf("Looking at %s in datadir\n", dbinfo.name); */ if (dbinfo.type == OS_FILE_TYPE_FILE @@ -2757,9 +2760,19 @@ fil_load_single_table_tablespaces(void) /* We found a symlink or a directory; try opening it to see if a symlink is a directory */ - - ut_a(strlen(dbinfo.name) < OS_FILE_MAX_PATH - 10); + len = strlen(fil_path_to_mysql_datadir) + + strlen (dbinfo.name) + 2; + if (len > dbpath_len) { + dbpath_len = len; + if (!dbpath) { + dbpath = mem_alloc(dbpath_len); + } + else { + dbpath = mem_realloc(dbpath, dbpath_len, + __FILE__, __LINE__); + } + } sprintf(dbpath, "%s/%s", fil_path_to_mysql_datadir, dbinfo.name); srv_normalize_path_for_win(dbpath); @@ -2809,7 +2822,9 @@ next_datadir_item: dir, &dbinfo); } - ut_free(dbpath); + if (dbpath) { + ut_free(dbpath); + } /* At the end of directory we should get 1 as the return value, -1 if there was an error */ @@ -2962,14 +2977,13 @@ fil_space_for_table_exists_in_mem( fil_system_t* system = fil_system; fil_space_t* namespace; fil_space_t* space; - char path[OS_FILE_MAX_PATH]; + char* path; ut_ad(system); mutex_enter(&(system->mutex)); - sprintf(path, "%s/%s.ibd", fil_path_to_mysql_datadir, name); - srv_normalize_path_for_win(path); + path = fil_make_ibd_name(name); /* Look if there is a space with the same id */ @@ -2988,6 +3002,7 @@ fil_space_for_table_exists_in_mem( space->mark = TRUE; } + mem_free(path); mutex_exit(&(system->mutex)); return(TRUE); @@ -2995,6 +3010,7 @@ fil_space_for_table_exists_in_mem( if (!print_error_if_does_not_exist) { + mem_free(path); mutex_exit(&(system->mutex)); return(FALSE); @@ -3024,6 +3040,7 @@ fil_space_for_table_exists_in_mem( "InnoDB: You can look from section 15.1 of http://www.innodb.com/ibman.html\n" "InnoDB: how to resolve the issue.\n"); + mem_free(path); mutex_exit(&(system->mutex)); return(FALSE); @@ -3047,11 +3064,13 @@ fil_space_for_table_exists_in_mem( "InnoDB: You can look from section 15.1 of http://www.innodb.com/ibman.html\n" "InnoDB: how to resolve the issue.\n"); + mem_free(path); mutex_exit(&(system->mutex)); return(FALSE); } + mem_free(path); mutex_exit(&(system->mutex)); return(FALSE); @@ -3072,14 +3091,13 @@ fil_get_space_id_for_table( fil_system_t* system = fil_system; fil_space_t* namespace; ulint id = ULINT_UNDEFINED; - char path[OS_FILE_MAX_PATH]; + char* path; ut_ad(system); mutex_enter(&(system->mutex)); - sprintf(path, "%s/%s.ibd", fil_path_to_mysql_datadir, name); - srv_normalize_path_for_win(path); + path = fil_make_ibd_name(name); /* Look if there is a space with the same name; the name is the directory path to the file */ @@ -3091,6 +3109,8 @@ fil_get_space_id_for_table( id = namespace->id; } + mem_free(path); + mutex_exit(&(system->mutex)); return(id); diff --git a/innobase/os/os0file.c b/innobase/os/os0file.c index a27da6d870e..caf09ed9f5f 100644 --- a/innobase/os/os0file.c +++ b/innobase/os/os0file.c @@ -2331,31 +2331,22 @@ os_file_dirname( pathname */ const char* path) /* in: pathname */ { - char* dir; - int i, length, last_slash; - /* find the offset of the last slash */ - length = ut_strlen(path); - for (i = length - 1; i >= 0 && path[i] != OS_FILE_PATH_SEPARATOR; i++); - last_slash = i; - - if (last_slash < 0) { + const char* last_slash = strrchr(path, OS_FILE_PATH_SEPARATOR); + if (!last_slash) { /* no slash in the path, return "." */ return(mem_strdup(".")); } /* ok, there is a slash */ - if (last_slash == 0) { + if (last_slash == path) { /* last slash is the first char of the path */ return(mem_strdup("/")); } /* non-trivial directory component */ - dir = mem_strdup(path); - dir[last_slash] = 0; - - return(dir); + return(mem_strdupl(path, last_slash - path)); } /******************************************************************** @@ -2369,12 +2360,12 @@ os_file_create_subdirs_if_needed( const char* path) /* in: path name */ { char* subdir; - static char rootdir[2] = { OS_FILE_PATH_SEPARATOR, 0 }; ibool success, subdir_exists; os_file_type_t type; subdir = os_file_dirname(path); - if (0 == strcmp(subdir, rootdir) || 0 == strcmp(subdir, ".")) { + if (strlen(subdir) == 1 + && (*subdir == OS_FILE_PATH_SEPARATOR || *subdir == '.')) { /* subdir is root or cwd, nothing to do */ ut_free(subdir); return(TRUE); diff --git a/innobase/row/row0mysql.c b/innobase/row/row0mysql.c index 174b8cbae34..623069cc90c 100644 --- a/innobase/row/row0mysql.c +++ b/innobase/row/row0mysql.c @@ -1951,7 +1951,37 @@ row_discard_tablespace_for_mysql( que_t* graph = NULL; ibool success; ulint err; - char buf[2 * OS_FILE_MAX_PATH]; + char* buf; + + static const char discard_tablespace_proc1[] = + "PROCEDURE DISCARD_TABLESPACE_PROC () IS\n" + "old_id CHAR;\n" + "new_id CHAR;\n" + "new_id_low INT;\n" + "new_id_high INT;\n" + "table_name CHAR;\n" + "BEGIN\n" + "table_name := "; + static const char discard_tablespace_proc2[] = + ";\n" + "new_id_high := %lu;\n" + "new_id_low := %lu;\n" + "new_id := CONCAT(TO_BINARY(new_id_high, 4), TO_BINARY(new_id_low, 4));\n" + "SELECT ID INTO old_id\n" + "FROM SYS_TABLES\n" + "WHERE NAME = table_name;\n" + "IF (SQL %% NOTFOUND) THEN\n" + " COMMIT WORK;\n" + " RETURN;\n" + "END IF;\n" + "UPDATE SYS_TABLES SET ID = new_id\n" + "WHERE ID = old_id;\n" + "UPDATE SYS_COLUMNS SET TABLE_ID = new_id\n" + "WHERE TABLE_ID = old_id;\n" + "UPDATE SYS_INDEXES SET TABLE_ID = new_id\n" + "WHERE TABLE_ID = old_id;\n" + "COMMIT WORK;\n" + "END;\n"; ut_ad(trx->mysql_thread_id == os_thread_get_curr_id()); @@ -1973,9 +2003,10 @@ row_discard_tablespace_for_mysql( if (table->space == 0) { ut_print_timestamp(stderr); - fprintf(stderr, -" InnoDB: Error: table %s\n" -"InnoDB: is in the system tablespace 0 which cannot be discarded\n", name); + fputs(" InnoDB: Error: table ", stderr); + ut_print_name(stderr, name); + fputs("\n" +"InnoDB: is in the system tablespace 0 which cannot be discarded\n", stderr); err = DB_ERROR; goto funct_exit; @@ -1983,36 +2014,16 @@ row_discard_tablespace_for_mysql( new_id = dict_hdr_get_new_id(DICT_HDR_TABLE_ID); - sprintf(buf, - "PROCEDURE DISCARD_TABLESPACE_PROC () IS\n" - "old_id CHAR;\n" - "new_id CHAR;\n" - "new_id_low INT;\n" - "new_id_high INT;\n" - "table_name CHAR;\n" - "BEGIN\n" - "table_name :='%s';\n" - "new_id_high := %lu;\n" - "new_id_low := %lu;\n" - "new_id := CONCAT(TO_BINARY(new_id_high, 4), TO_BINARY(new_id_low, 4));\n" - "SELECT ID INTO old_id\n" - "FROM SYS_TABLES\n" - "WHERE NAME = table_name;\n" - "IF (SQL %% NOTFOUND) THEN\n" - " COMMIT WORK;\n" - " RETURN;\n" - "END IF;\n" - "UPDATE SYS_TABLES SET ID = new_id\n" - "WHERE ID = old_id;\n" - "UPDATE SYS_COLUMNS SET TABLE_ID = new_id\n" - "WHERE TABLE_ID = old_id;\n" - "UPDATE SYS_INDEXES SET TABLE_ID = new_id\n" - "WHERE TABLE_ID = old_id;\n" - "COMMIT WORK;\n" - "END;\n", name, (ulong) ut_dulint_get_high(new_id), - (ulong) ut_dulint_get_low(new_id)); + buf = mem_alloc((sizeof discard_tablespace_proc1) + + (sizeof discard_tablespace_proc2) + + 20 + ut_strlenq(name, '\'')); - ut_a(strlen(buf) < 2 * OS_FILE_MAX_PATH); + memcpy(buf, discard_tablespace_proc1, sizeof discard_tablespace_proc1); + sprintf(ut_strcpyq(buf + (sizeof discard_tablespace_proc1 - 1), + '\'', name), + discard_tablespace_proc2, + (ulong) ut_dulint_get_high(new_id), + (ulong) ut_dulint_get_low(new_id)); graph = pars_sql(buf); @@ -2126,9 +2137,10 @@ row_import_tablespace_for_mysql( if (table->space == 0) { ut_print_timestamp(stderr); - fprintf(stderr, -" InnoDB: Error: table %s\n" -"InnoDB: is in the system tablespace 0 which cannot be imported\n", name); + fputs(" InnoDB: Error: table ", stderr); + ut_print_name(stderr, name); + fputs("\n" +"InnoDB: is in the system tablespace 0 which cannot be imported\n", stderr); err = DB_ERROR; goto funct_exit; @@ -2136,10 +2148,12 @@ row_import_tablespace_for_mysql( if (!table->tablespace_discarded) { ut_print_timestamp(stderr); - fprintf(stderr, + fputs( " InnoDB: Error: you are trying to IMPORT a tablespace\n" -"InnoDB: %s, though you have not called DISCARD on it yet\n" -"InnoDB: during the lifetime of the mysqld process!\n", name); +"InnoDB: ", stderr); + ut_print_name(stderr, name); + fputs(", though you have not called DISCARD on it yet\n" +"InnoDB: during the lifetime of the mysqld process!\n", stderr); err = DB_ERROR; @@ -2469,7 +2483,7 @@ row_drop_table_for_mysql( if (dict_load_table(name) != NULL) { ut_print_timestamp(stderr); fputs(" InnoDB: Error: not able to remove table ", - stderr); + stderr); ut_print_name(stderr, name); fputs(" from the dictionary cache!\n", stderr); err = DB_ERROR; @@ -2491,8 +2505,10 @@ row_drop_table_for_mysql( if (!success) { ut_print_timestamp(stderr); fprintf(stderr, -" InnoDB: Error: not able to delete tablespace %lu of table %s!\n", - (ulong) space_id, name); +" InnoDB: Error: not able to delete tablespace %lu of table ", + (ulong) space_id); + ut_print_name(stderr, name); + fputs("!\n", stderr); err = DB_ERROR; } } @@ -2757,15 +2773,14 @@ row_rename_table_for_mysql( err = DB_TABLE_NOT_FOUND; ut_print_timestamp(stderr); - fprintf(stderr, - " InnoDB: Error: table %s\n" - "InnoDB: does not exist in the InnoDB internal\n" + fputs(" InnoDB: Error: table ", stderr); + ut_print_name(stderr, old_name); + fputs(" does not exist in the InnoDB internal\n" "InnoDB: data dictionary though MySQL is trying to rename the table.\n" "InnoDB: Have you copied the .frm file of the table to the\n" "InnoDB: MySQL database directory from another database?\n" "InnoDB: You can look for further help from section 15.1 of\n" - "InnoDB: http://www.innodb.com/ibman.html\n", - old_name); + "InnoDB: http://www.innodb.com/ibman.php\n", stderr); goto funct_exit; } @@ -2773,12 +2788,12 @@ row_rename_table_for_mysql( err = DB_TABLE_NOT_FOUND; ut_print_timestamp(stderr); - fprintf(stderr, - " InnoDB: Error: table %s\n" - "InnoDB: does not have an .ibd file in the database directory.\n" + fputs(" InnoDB: Error: table ", stderr); + ut_print_name(stderr, old_name); + fputs( + " does not have an .ibd file in the database directory.\n" "InnoDB: You can look for further help from section 15.1 of\n" - "InnoDB: http://www.innodb.com/ibman.html\n", - old_name); + "InnoDB: http://www.innodb.com/ibman.php\n", stderr); goto funct_exit; } @@ -2905,23 +2920,25 @@ row_rename_table_for_mysql( if (err != DB_SUCCESS) { if (err == DB_DUPLICATE_KEY) { ut_print_timestamp(stderr); - fprintf(stderr, - " InnoDB: Error: table %s exists in the InnoDB internal data\n" - "InnoDB: dictionary though MySQL is trying rename table %s to it.\n" + fputs(" InnoDB: Error: table ", stderr); + ut_print_name(stderr, new_name); + fputs(" exists in the InnoDB internal data\n" + "InnoDB: dictionary though MySQL is trying rename table ", stderr); + ut_print_name(stderr, old_name); + fputs(" to it.\n" "InnoDB: Have you deleted the .frm file and not used DROP TABLE?\n" "InnoDB: You can look for further help from section 15.1 of\n" - "InnoDB: http://www.innodb.com/ibman.html\n", - new_name, old_name); - fprintf(stderr, - "InnoDB: If table %s is a temporary table #sql..., then it can be that\n" + "InnoDB: http://www.innodb.com/ibman.php\n" + "InnoDB: If table ", stderr); + ut_print_name(stderr, new_name); + fputs(" is a temporary table #sql..., then it can be that\n" "InnoDB: there are still queries running on the table, and it will be\n" - "InnoDB: dropped automatically when the queries end.\n", new_name); - fprintf(stderr, + "InnoDB: dropped automatically when the queries end.\n" "InnoDB: You can drop the orphaned table inside InnoDB by\n" "InnoDB: creating an InnoDB table with the same name in another\n" "InnoDB: database and moving the .frm file to the current database.\n" "InnoDB: Then MySQL thinks the table exists, and DROP TABLE will\n" - "InnoDB: succeed.\n"); + "InnoDB: succeed.\n", stderr); } trx->error_state = DB_SUCCESS; trx_general_rollback_for_mysql(trx, FALSE, NULL); @@ -2937,9 +2954,12 @@ row_rename_table_for_mysql( trx_general_rollback_for_mysql(trx, FALSE, NULL); trx->error_state = DB_SUCCESS; ut_print_timestamp(stderr); - fprintf(stderr, -" InnoDB: Error in table rename, cannot rename %s to %s\n", old_name, - new_name); + fputs(" InnoDB: Error in table rename, cannot rename ", + stderr); + ut_print_name(stderr, old_name); + fputs(" to ", stderr); + ut_print_name(stderr, new_name); + putc('\n', stderr); err = DB_ERROR; goto funct_exit; @@ -2958,11 +2978,14 @@ row_rename_table_for_mysql( if (err != DB_SUCCESS) { ut_print_timestamp(stderr); - fprintf(stderr, - " InnoDB: Error: in ALTER TABLE table %s\n" - "InnoDB: has or is referenced in foreign key constraints\n" - "InnoDB: which are not compatible with the new table definition.\n", - new_name); + fputs(" InnoDB: Error: in ALTER TABLE ", + stderr); + ut_print_name(stderr, new_name); + fputs("\n" + "InnoDB: has or is referenced in foreign key constraints\n" + "InnoDB: which are not compatible with the new table definition.\n", + stderr); + ut_a(dict_table_rename_in_cache(table, old_name, FALSE)); trx->error_state = DB_SUCCESS; @@ -3160,9 +3183,11 @@ row_check_table_for_mysql( ret = DB_ERROR; + fputs("Error: ", stderr); + dict_index_name_print(stderr, index); fprintf(stderr, - "Error: index %s contains %lu entries, should be %lu\n", - index->name, (ulong) n_rows, + " contains %lu entries, should be %lu\n", + (ulong) n_rows, (ulong) n_rows_in_table); } } diff --git a/mysql-test/r/multi_update.result b/mysql-test/r/multi_update.result index 2b312a86289..d8c70625e35 100644 --- a/mysql-test/r/multi_update.result +++ b/mysql-test/r/multi_update.result @@ -446,6 +446,7 @@ grant update on mysqltest.t1 to mysqltest_1@localhost; update t1, t2 set t1.b=1 where t1.a=t2.a; update t1, t2 set t1.b=(select t3.b from t3 where t1.a=t3.a) where t1.a=t2.a; revoke all privileges on mysqltest.t1 from mysqltest_1@localhost; +revoke all privileges on mysqltest.* from mysqltest_1@localhost; delete from mysql.user where user='mysqltest_1'; drop database mysqltest; create table t1 (a int, primary key (a)); diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result index 9ad3a5a9cf2..a6ff608ab66 100644 --- a/mysql-test/r/subselect.result +++ b/mysql-test/r/subselect.result @@ -334,7 +334,7 @@ Note 1276 Field or reference 'clinic_uq' of SELECT #2 was resolved in SELECT #1 Note 1003 select test.t6.patient_uq AS `patient_uq`,test.t6.clinic_uq AS `clinic_uq` from test.t6 where exists(select test.t7.uq AS `uq`,test.t7.name AS `name` from test.t7 where (test.t7.uq = test.t6.clinic_uq)) select * from t1 where a= (select a from t2,t4 where t2.b=t4.b); ERROR 23000: Column: 'a' in field list is ambiguous -drop table if exists t1,t2,t3; +drop table t1,t2,t3; CREATE TABLE t3 (a varchar(20),b char(1) NOT NULL default '0'); INSERT INTO t3 VALUES ('W','a'),('A','c'),('J','b'); CREATE TABLE t2 (a varchar(20),b int NOT NULL default '0'); diff --git a/mysql-test/t/multi_update.test b/mysql-test/t/multi_update.test index 36854551a7f..492856f9280 100644 --- a/mysql-test/t/multi_update.test +++ b/mysql-test/t/multi_update.test @@ -404,6 +404,7 @@ update t1, t2 set t1.b=1 where t1.a=t2.a; update t1, t2 set t1.b=(select t3.b from t3 where t1.a=t3.a) where t1.a=t2.a; connection root; revoke all privileges on mysqltest.t1 from mysqltest_1@localhost; +revoke all privileges on mysqltest.* from mysqltest_1@localhost; delete from mysql.user where user='mysqltest_1'; drop database mysqltest; diff --git a/mysql-test/t/subselect.test b/mysql-test/t/subselect.test index 0f461ba5277..bdefc87b3fd 100644 --- a/mysql-test/t/subselect.test +++ b/mysql-test/t/subselect.test @@ -135,7 +135,7 @@ explain extended select * from t6 where exists (select * from t7 where uq = clin select * from t1 where a= (select a from t2,t4 where t2.b=t4.b); # different tipes & group functions -drop table if exists t1,t2,t3; +drop table t1,t2,t3; CREATE TABLE t3 (a varchar(20),b char(1) NOT NULL default '0'); INSERT INTO t3 VALUES ('W','a'),('A','c'),('J','b'); diff --git a/mysql-test/t/system_mysql_db_fix.test b/mysql-test/t/system_mysql_db_fix.test index 6f3979bf66e..41fbdec84e7 100644 --- a/mysql-test/t/system_mysql_db_fix.test +++ b/mysql-test/t/system_mysql_db_fix.test @@ -74,5 +74,9 @@ DROP TABLE user; DROP TABLE func;
DROP TABLE tables_priv;
DROP TABLE columns_priv;
+DROP TABLE help_category; +DROP TABLE help_keyword; +DROP TABLE help_relation; +DROP TABLE help_topic; -- enable_query_log
diff --git a/sql/handler.h b/sql/handler.h index 0f8edc2cf12..04a437725ab 100644 --- a/sql/handler.h +++ b/sql/handler.h @@ -403,12 +403,12 @@ public: { return (HA_DDL_SUPPORT); } - virtual int add_index(TABLE *table, KEY *key_info, uint num_of_keys) + virtual int add_index(TABLE *table_arg, KEY *key_info, uint num_of_keys) { my_error(ER_NOT_SUPPORTED_YET, MYF(0), "online add index"); return (HA_DDL_NOT_IMPLEMENTED); } - virtual int drop_index(TABLE *table, uint *key_num, uint num_of_keys) + virtual int drop_index(TABLE *table_arg, uint *key_num, uint num_of_keys) { my_error(ER_NOT_SUPPORTED_YET, MYF(0), "online drop index"); return (HA_DDL_NOT_IMPLEMENTED); diff --git a/sql/item.cc b/sql/item.cc index f3a13411fe3..7db1a448e55 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -753,9 +753,10 @@ void Item_param::reset() str_value.free(); else str_value.length(0); + str_value_ptr.length(0); /* - We must prevent all charset conversions unless data of str_value - has been written to the binary log. + We must prevent all charset conversions untill data has been written + to the binary log. */ str_value.set_charset(&my_charset_bin); state= NO_VALUE; @@ -866,7 +867,7 @@ String *Item_param::val_str(String* str) switch (state) { case STRING_VALUE: case LONG_DATA_VALUE: - return &str_value; + return &str_value_ptr; case REAL_VALUE: str->set(value.real, NOT_FIXED_DEC, &my_charset_bin); return str; @@ -980,6 +981,12 @@ bool Item_param::convert_str_value(THD *thd) } max_length= str_value.length(); decimals= 0; + /* + str_value_ptr is returned from val_str(). It must be not alloced + to prevent it's modification by val_str() invoker. + */ + str_value_ptr.set(str_value.ptr(), str_value.length(), + str_value.charset()); } return rc; } diff --git a/sql/item.h b/sql/item.h index ccf8e8685d0..885a34dce81 100644 --- a/sql/item.h +++ b/sql/item.h @@ -160,6 +160,31 @@ public: /* valXXX methods must return NULL or 0 or 0.0 if null_value is set. */ virtual double val()=0; virtual longlong val_int()=0; + /* + Return string representation of this item object. + + The argument to val_str() is an allocated buffer this or any + nested Item object can use to store return value of this method. + This buffer should only be used if the item itself doesn't have an + own String buffer. In case when the item maintains it's own string + buffer, it's preferrable to return it instead to minimize number of + mallocs/memcpys. + The caller of this method can modify returned string, but only in + case when it was allocated on heap, (is_alloced() is true). This + allows the caller to efficiently use a buffer allocated by a child + without having to allocate a buffer of it's own. The buffer, given + to val_str() as agrument, belongs to the caller and is later used + by the caller at it's own choosing. + A few implications from the above: + - unless you return a string object which only points to your buffer + but doesn't manages it you should be ready that it will be + modified. + - even for not allocated strings (is_alloced() == false) the caller + can change charset (see Item_func_{typecast/binary}. XXX: is this + a bug? + - still you should try to minimize data copying and return internal + object whenever possible. + */ virtual String *val_str(String*)=0; virtual Field *get_tmp_table_field() { return 0; } virtual Field *tmp_table_field(TABLE *t_arg) { return 0; } @@ -390,6 +415,9 @@ public: void print(String *str) { str->append("NULL", 4); } }; + +/* Item represents one placeholder ('?') of prepared statement */ + class Item_param :public Item { public: @@ -399,6 +427,17 @@ public: STRING_VALUE, TIME_VALUE, LONG_DATA_VALUE } state; + /* + A buffer for string and long data values. Historically all allocated + values returned from val_str() were treated as eligible to + modification. I. e. in some cases Item_func_concat can append it's + second argument to return value of the first one. Because of that we + can't return the original buffer holding string data from val_str(), + and have to have one buffer for data and another just pointing to + the data. This is the latter one and it's returned from val_str(). + Can not be declared inside the union as it's not a POD type. + */ + String str_value_ptr; union { longlong integer; diff --git a/tests/client_test.c b/tests/client_test.c index 725d794c4a5..1f80ecc9481 100644 --- a/tests/client_test.c +++ b/tests/client_test.c @@ -9670,12 +9670,12 @@ static void test_union_param() /* bind parameters */ bind[0].buffer_type= FIELD_TYPE_STRING; - bind[0].buffer= &my_val; + bind[0].buffer= (char*) &my_val; bind[0].buffer_length= 4; bind[0].length= &my_length; bind[0].is_null= (char*)&my_null; bind[1].buffer_type= FIELD_TYPE_STRING; - bind[1].buffer= &my_val; + bind[1].buffer= (char*) &my_val; bind[1].buffer_length= 4; bind[1].length= &my_length; bind[1].is_null= (char*)&my_null; @@ -9872,7 +9872,90 @@ static void test_ps_i18n() mysql_stmt_close(stmt); stmt_text= "DROP TABLE t1"; - mysql_real_query(mysql, stmt_text, strlen(stmt_text)); + rc= mysql_real_query(mysql, stmt_text, strlen(stmt_text)); + myquery(rc); + stmt_text= "SET NAMES DEFAULT"; + rc= mysql_real_query(mysql, stmt_text, strlen(stmt_text)); + myquery(rc); +} + + +static void test_bug3796() +{ + MYSQL_STMT *stmt; + MYSQL_BIND bind[1]; + const char *concat_arg0= "concat_with_"; + const int OUT_BUFF_SIZE= 30; + char out_buff[OUT_BUFF_SIZE]; + char canonical_buff[OUT_BUFF_SIZE]; + ulong out_length; + const char *stmt_text; + int rc; + + myheader("test_bug3796"); + + /* Create and fill test table */ + stmt_text= "DROP TABLE IF EXISTS t1"; + rc= mysql_real_query(mysql, stmt_text, strlen(stmt_text)); + myquery(rc); + + stmt_text= "CREATE TABLE t1 (a INT, b VARCHAR(30))"; + rc= mysql_real_query(mysql, stmt_text, strlen(stmt_text)); + myquery(rc); + + stmt_text= "INSERT INTO t1 VALUES(1,'ONE'), (2,'TWO')"; + rc= mysql_real_query(mysql, stmt_text, strlen(stmt_text)); + myquery(rc); + + /* Create statement handle and prepare it with select */ + stmt = mysql_stmt_init(mysql); + stmt_text= "SELECT concat(?, b) FROM t1"; + + rc= mysql_stmt_prepare(stmt, stmt_text, strlen(stmt_text)); + check_execute(stmt, rc); + + /* Bind input buffers */ + bzero(bind, sizeof(bind)); + + bind[0].buffer_type= MYSQL_TYPE_STRING; + bind[0].buffer= (char*) concat_arg0; + bind[0].buffer_length= strlen(concat_arg0); + + mysql_stmt_bind_param(stmt, bind); + + /* Execute the select statement */ + rc= mysql_stmt_execute(stmt); + check_execute(stmt, rc); + + bind[0].buffer= (char*) out_buff; + bind[0].buffer_length= OUT_BUFF_SIZE; + bind[0].length= &out_length; + + mysql_stmt_bind_result(stmt, bind); + + rc= mysql_stmt_fetch(stmt); + printf("Concat result: '%s'\n", out_buff); + check_execute(stmt, rc); + strcpy(canonical_buff, concat_arg0); + strcat(canonical_buff, "ONE"); + assert(strlen(canonical_buff) == out_length && + strncmp(out_buff, canonical_buff, out_length) == 0); + + rc= mysql_stmt_fetch(stmt); + check_execute(stmt, rc); + strcpy(canonical_buff + strlen(concat_arg0), "TWO"); + assert(strlen(canonical_buff) == out_length && + strncmp(out_buff, canonical_buff, out_length) == 0); + printf("Concat result: '%s'\n", out_buff); + + rc= mysql_stmt_fetch(stmt); + assert(rc == MYSQL_NO_DATA); + + mysql_stmt_close(stmt); + + stmt_text= "DROP TABLE IF EXISTS t1"; + rc= mysql_real_query(mysql, stmt_text, strlen(stmt_text)); + myquery(rc); } /* @@ -10164,6 +10247,7 @@ int main(int argc, char **argv) test_order_param(); /* ORDER BY with parameters in select list (Bug #3686 */ test_ps_i18n(); /* test for i18n support in binary protocol */ + test_bug3796(); /* test for select concat(?, <string>) */ end_time= time((time_t *)0); total_time+= difftime(end_time, start_time); |