Commit c91972c2 authored by unknown's avatar unknown

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
parents cfb496ae 389e8bec
#! /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"
......@@ -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')
......
......@@ -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
......
......@@ -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
......
......@@ -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 @@ dict_check_tablespaces_or_store_max_id(
/* 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 @@ dict_check_tablespaces_or_store_max_id(
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;
}
......
This diff is collapsed.
......@@ -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);
......
......@@ -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);
}
}
......
......@@ -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));
......
......@@ -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');
......
......@@ -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;
......
......@@ -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');
......
......@@ -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
......@@ -403,12 +403,12 @@ class handler :public Sql_alloc
{
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);
......
......@@ -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;
}
......
......@@ -160,6 +160,31 @@ class Item {
/* 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 @@ class Item_null :public Item
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 @@ class Item_param :public Item
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;
......
......@@ -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);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment