Merge sanja.is.com.ua:/home/bell/mysql/bk/mysql-5.0

into sanja.is.com.ua:/home/bell/mysql/bk/work-repl-5.0


sql/item.cc:
  Auto merged
sql/item_func.cc:
  Auto merged
sql/sql_parse.cc:
  Auto merged
sql/sql_select.cc:
  Auto merged
This commit is contained in:
unknown 2005-02-10 20:08:11 +02:00
commit 592ee68568
35 changed files with 345 additions and 261 deletions

View File

@ -2379,6 +2379,8 @@ void usage()
#include <help_end.h>
#include <help_end.h>
static my_bool
get_one_option(int optid, const struct my_option *opt __attribute__((unused)),

View File

@ -1809,6 +1809,18 @@ static my_bool my_realloc_str(NET *net, ulong length)
}
/* Clear possible error statee of struct NET */
static void net_clear_error(NET *net)
{
if (net->last_errno)
{
net->last_errno= 0;
net->last_error[0]= '\0';
strmov(net->sqlstate, not_error_sqlstate);
}
}
/*
Set statement error code, sqlstate, and error message
from given errcode and sqlstate.
@ -2499,6 +2511,11 @@ int cli_stmt_execute(MYSQL_STMT *stmt)
set_stmt_error(stmt, CR_PARAMS_NOT_BOUND, unknown_sqlstate);
DBUG_RETURN(1);
}
if (stmt->mysql->status != MYSQL_STATUS_READY)
{
set_stmt_error(stmt, CR_COMMANDS_OUT_OF_SYNC, unknown_sqlstate);
DBUG_RETURN(1);
}
net_clear(net); /* Sets net->write_pos */
/* Reserve place for null-marker bytes */
@ -4858,6 +4875,11 @@ my_bool STDCALL mysql_stmt_close(MYSQL_STMT *stmt)
if (mysql)
{
mysql->stmts= list_delete(mysql->stmts, &stmt->list);
/*
Clear NET error state: if the following commands come through
successfully, connection will still be usable for other commands.
*/
net_clear_error(&mysql->net);
if ((int) stmt->state > (int) MYSQL_STMT_INIT_DONE)
{
char buff[MYSQL_STMT_HEADER]; /* 4 bytes - stmt id */

View File

@ -194,8 +194,8 @@ MY_LOG_DIR="$MYSQL_TEST_DIR/var/log"
#
# Set LD_LIBRARY_PATH if we are using shared libraries
#
LD_LIBRARY_PATH="$BASEDIR/lib:$BASEDIR/libmysql/.libs:$LD_LIBRARY_PATH"
DYLD_LIBRARY_PATH="$BASEDIR/lib:$BASEDIR/libmysql/.libs:$DYLD_LIBRARY_PATH"
LD_LIBRARY_PATH="$BASEDIR/lib:$BASEDIR/libmysql/.libs:$BASEDIR/zlib/.libs:$LD_LIBRARY_PATH"
DYLD_LIBRARY_PATH="$BASEDIR/lib:$BASEDIR/libmysql/.libs:$BASEDIR/zlib/.libs:$DYLD_LIBRARY_PATH"
export LD_LIBRARY_PATH DYLD_LIBRARY_PATH
#
@ -692,6 +692,7 @@ then
fi
MYSQL_CLIENT_TEST="$MYSQL_CLIENT_TEST --no-defaults --testcase --user=root --socket=$MASTER_MYSOCK --port=$MYSQL_TCP_PORT --silent"
MYSQL_DUMP="$MYSQL_DUMP --no-defaults -uroot --socket=$MASTER_MYSOCK --password=$DBPASSWD $EXTRA_MYSQLDUMP_OPT"
MYSQL_BINLOG="$MYSQL_BINLOG --no-defaults --local-load=$MYSQL_TMP_DIR --character-sets-dir=$CHARSETSDIR $EXTRA_MYSQLBINLOG_OPT"
MYSQL_FIX_SYSTEM_TABLES="$MYSQL_FIX_SYSTEM_TABLES --no-defaults --host=localhost --port=$MASTER_MYPORT --socket=$MASTER_MYSOCK --user=root --password=$DBPASSWD --basedir=$BASEDIR --bindir=$CLIENT_BINDIR --verbose"
MYSQL="$MYSQL --host=localhost --port=$MASTER_MYPORT --socket=$MASTER_MYSOCK --user=root --password=$DBPASSWD"
@ -1151,8 +1152,7 @@ start_master()
fi
if [ -n "$EXTRA_MASTER_MYSQLD_TRACE" ]
then
EXTRA_MASTER_MYSQLD_OPT="$EXTRA_MASTER_MYSQLD_OPT \
$EXTRA_MASTER_MYSQLD_TRACE$1"
CURR_MASTER_MYSQLD_TRACE="$EXTRA_MASTER_MYSQLD_TRACE$1"
fi
if [ -z "$DO_BENCH" ]
then
@ -1177,7 +1177,7 @@ start_master()
$MASTER_40_ARGS \
$SMALL_SERVER \
$EXTRA_MASTER_OPT $EXTRA_MASTER_MYSQLD_OPT \
$NOT_FIRST_MASTER_EXTRA_OPTS"
$NOT_FIRST_MASTER_EXTRA_OPTS $CURR_MASTER_MYSQLD_TRACE"
else
master_args="--no-defaults --log-bin=$MYSQL_TEST_DIR/var/log/master-bin$1 \
--server-id=$id --rpl-recovery-rank=1 \

View File

@ -655,9 +655,9 @@ insert into t1 (a,b) values (1,2),(1,3),(2,5);
select a, 0.1*0+1 r2, sum(1) r1 from t1 where a = 1 group by a having r1>1 and r2=1;
a r2 r1
1 1.0 2
select a, rand()*0+1 r2, sum(1) r1 from t1 where a = 1 group by a having r1>1 and r2=1;
select a, round(rand(100)*10) r2, sum(1) r1 from t1 where a = 1 group by a having r1>1 and r2<=2;
a r2 r1
1 1 2
1 2 2
select a,sum(b) from t1 where a=1 group by c;
a sum(b)
1 5

View File

@ -355,3 +355,13 @@ id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t3 ref a a 44 const,const 6 Using where
1 SIMPLE t1 ref heap_idx heap_idx 22 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);
select a from t1 where a in (1,3);
a
1
3
explain select a from t1 where a in (1,3);
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 range a a 5 NULL 2 Using where
drop table t1;

View File

@ -2666,7 +2666,6 @@ 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
Note 1265 Data truncated for column 'c12' at row 1
Warning 1264 Out of range value adjusted for column 'c12' at row 1
execute my_select ;
c1 127
@ -2717,7 +2716,6 @@ 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
Note 1265 Data truncated for column 'c12' at row 1
Warning 1264 Out of range value adjusted for column 'c12' at row 1
execute my_select ;
c1 -128

View File

@ -2649,7 +2649,6 @@ 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
Note 1265 Data truncated for column 'c12' at row 1
Warning 1264 Out of range value adjusted for column 'c12' at row 1
execute my_select ;
c1 127
@ -2700,7 +2699,6 @@ 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
Note 1265 Data truncated for column 'c12' at row 1
Warning 1264 Out of range value adjusted for column 'c12' at row 1
execute my_select ;
c1 -128

View File

@ -2650,7 +2650,6 @@ 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
Note 1265 Data truncated for column 'c12' at row 1
Warning 1264 Out of range value adjusted for column 'c12' at row 1
execute my_select ;
c1 127
@ -2701,7 +2700,6 @@ 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
Note 1265 Data truncated for column 'c12' at row 1
Warning 1264 Out of range value adjusted for column 'c12' at row 1
execute my_select ;
c1 -128

View File

@ -2586,7 +2586,6 @@ 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
Note 1265 Data truncated for column 'c12' at row 1
Warning 1264 Out of range value adjusted for column 'c12' at row 1
execute my_select ;
c1 127
@ -2637,7 +2636,6 @@ 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
Note 1265 Data truncated for column 'c12' at row 1
Warning 1264 Out of range value adjusted for column 'c12' at row 1
execute my_select ;
c1 -128
@ -5597,7 +5595,6 @@ 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
Note 1265 Data truncated for column 'c12' at row 1
Warning 1264 Out of range value adjusted for column 'c12' at row 1
execute my_select ;
c1 127
@ -5648,7 +5645,6 @@ 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
Note 1265 Data truncated for column 'c12' at row 1
Warning 1264 Out of range value adjusted for column 'c12' at row 1
execute my_select ;
c1 -128

View File

@ -1433,7 +1433,7 @@ Note 1003 (select `test`.`t1`.`s1` AS `s1` from `test`.`t1`)
s1
tttt
drop table t1;
create table t1 (s1 char(5) not null, index s1(s1));
create table t1 (s1 char(5), index s1(s1));
create table t2 (s1 char(5), index s1(s1));
insert into t1 values ('a1'),('a2'),('a3');
insert into t2 values ('a1'),('a2');
@ -1459,25 +1459,25 @@ a2 1
a3 1
explain extended select s1, s1 NOT IN (SELECT s1 FROM t2) from t1;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 index NULL s1 5 NULL 3 Using index
1 PRIMARY t1 index NULL s1 6 NULL 3 Using index
2 DEPENDENT SUBQUERY t2 index_subquery s1 s1 6 func 2 Using index
Warnings:
Note 1003 select `test`.`t1`.`s1` AS `s1`,not(<in_optimizer>(`test`.`t1`.`s1`,<exists>(<index_lookup>(<cache>(`test`.`t1`.`s1`) in t2 on s1 checking NULL)))) AS `s1 NOT IN (SELECT s1 FROM t2)` from `test`.`t1`
explain extended select s1, s1 = ANY (SELECT s1 FROM t2) from t1;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 index NULL s1 5 NULL 3 Using index
1 PRIMARY t1 index NULL s1 6 NULL 3 Using index
2 DEPENDENT SUBQUERY t2 index_subquery s1 s1 6 func 2 Using index
Warnings:
Note 1003 select `test`.`t1`.`s1` AS `s1`,<in_optimizer>(`test`.`t1`.`s1`,<exists>(<index_lookup>(<cache>(`test`.`t1`.`s1`) in t2 on s1 checking NULL))) AS `s1 = ANY (SELECT s1 FROM t2)` from `test`.`t1`
explain extended select s1, s1 <> ALL (SELECT s1 FROM t2) from t1;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 index NULL s1 5 NULL 3 Using index
1 PRIMARY t1 index NULL s1 6 NULL 3 Using index
2 DEPENDENT SUBQUERY t2 index_subquery s1 s1 6 func 2 Using index
Warnings:
Note 1003 select `test`.`t1`.`s1` AS `s1`,not(<in_optimizer>(`test`.`t1`.`s1`,<exists>(<index_lookup>(<cache>(`test`.`t1`.`s1`) in t2 on s1 checking NULL)))) AS `s1 <> ALL (SELECT s1 FROM t2)` from `test`.`t1`
explain extended select s1, s1 NOT IN (SELECT s1 FROM t2 WHERE s1 < 'a2') from t1;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 index NULL s1 5 NULL 3 Using index
1 PRIMARY t1 index NULL s1 6 NULL 3 Using index
2 DEPENDENT SUBQUERY t2 index_subquery s1 s1 6 func 1 Using index; Using where
Warnings:
Note 1003 select `test`.`t1`.`s1` AS `s1`,not(<in_optimizer>(`test`.`t1`.`s1`,<exists>(<index_lookup>(<cache>(`test`.`t1`.`s1`) in t2 on s1 checking NULL where (`test`.`t2`.`s1` < _latin1'a2'))))) AS `s1 NOT IN (SELECT s1 FROM t2 WHERE s1 < 'a2')` from `test`.`t1`
@ -2133,34 +2133,6 @@ SELECT DISTINCT Continent AS c FROM t1 WHERE Code <> SOME ( SELECT Code FROM t1
c
Oceania
drop table t1;
CREATE TABLE t1 ( f1 BIGINT );
INSERT INTO t1 SET f1= NULL;
INSERT INTO t1 SET f1= 1;
CREATE TABLE t2 ( f1 BIGINT );
SELECT f1 FROM t1
WHERE f1 <> ALL ( SELECT f1 FROM t2 );
f1
NULL
1
INSERT INTO t2 VALUES (1), (2);
SELECT f1 FROM t1
WHERE f1 <> ALL ( SELECT f1 FROM t2 WHERE f1 > 2 );
f1
NULL
1
SELECT f1 FROM t1
WHERE f1 <> ALL ( SELECT f1 FROM t2 WHERE f1 > 2
UNION
SELECT f1 FROM t2 WHERE f1 > 3);
f1
NULL
1
SELECT f1 FROM t1
WHERE f1 <> ALL ( SELECT SUM(f1) AS sf1 FROM t2 HAVING sf1 > 10000);
f1
NULL
1
drop table t1,t2;
create table t1 (a1 int);
create table t2 (b1 int);
select * from t1 where a2 > any(select b1 from t2);

View File

@ -113,8 +113,8 @@ select @a:=0;
select @a, @a:=@a+count(*), count(*), @a from t1 group by i;
@a @a:=@a+count(*) count(*) @a
0 1 1 0
0 3 2 0
0 6 3 0
0 2 2 0
0 3 3 0
select @a:=0;
@a:=0
0

View File

@ -480,7 +480,8 @@ drop table t1;
create table t1 (a integer, b integer, c integer);
insert into t1 (a,b) values (1,2),(1,3),(2,5);
select a, 0.1*0+1 r2, sum(1) r1 from t1 where a = 1 group by a having r1>1 and r2=1;
select a, rand()*0+1 r2, sum(1) r1 from t1 where a = 1 group by a having r1>1 and r2=1;
# rand(100)*10 will be < 2 only for the first row (of 6)
select a, round(rand(100)*10) r2, sum(1) r1 from t1 where a = 1 group by a having r1>1 and r2<=2;
select a,sum(b) from t1 where a=1 group by c;
select a*sum(b) from t1 where a=1 group by c;
select sum(a)*sum(b) from t1 where a=1 group by c;

View File

@ -251,3 +251,9 @@ explain select * from t1 ignore key(btree_idx), t3 where t1.name='matt' and t3.a
drop table t1, t2, t3;
# Fix for BUG#8371: wrong rec_per_key value for hash index on temporary table
create temporary table t1 ( a int, index (a) ) engine=memory;
insert into t1 values (1),(2),(3),(4),(5);
select a from t1 where a in (1,3);
explain select a from t1 where a in (1,3);
drop table t1;

View File

@ -894,7 +894,7 @@ drop table t1;
#
# IN optimisation test results
#
create table t1 (s1 char(5) not null, index s1(s1));
create table t1 (s1 char(5), index s1(s1));
create table t2 (s1 char(5), index s1(s1));
insert into t1 values ('a1'),('a2'),('a3');
insert into t2 values ('a1'),('a2');
@ -1392,34 +1392,6 @@ INSERT INTO t1 VALUES ('UMI','United States Minor Outlying Islands','Oceania','M
SELECT DISTINCT Continent AS c FROM t1 WHERE Code <> SOME ( SELECT Code FROM t1 WHERE Continent = c AND Population < 200);
drop table t1;
#
# Test cases for bug #7351:
# quantified predicate with subquery returning empty result set
#
CREATE TABLE t1 ( f1 BIGINT );
INSERT INTO t1 SET f1= NULL;
INSERT INTO t1 SET f1= 1;
CREATE TABLE t2 ( f1 BIGINT );
SELECT f1 FROM t1
WHERE f1 <> ALL ( SELECT f1 FROM t2 );
INSERT INTO t2 VALUES (1), (2);
SELECT f1 FROM t1
WHERE f1 <> ALL ( SELECT f1 FROM t2 WHERE f1 > 2 );
SELECT f1 FROM t1
WHERE f1 <> ALL ( SELECT f1 FROM t2 WHERE f1 > 2
UNION
SELECT f1 FROM t2 WHERE f1 > 3);
SELECT f1 FROM t1
WHERE f1 <> ALL ( SELECT SUM(f1) AS sf1 FROM t2 HAVING sf1 > 10000);
drop table t1,t2;
#
# Test for BUG#7885: Server crash when 'any' subselect compared to
# non-existant field.

View File

@ -45,7 +45,7 @@ int my_rename(const char *from, const char *to, myf MyFlags)
}
#endif
#if defined(HAVE_RENAME)
#ifdef __WIN__
#if defined(__WIN__) || defined(__NETWARE__)
/*
On windows we can't rename over an existing file:
Remove any conflicting files:

View File

@ -85,7 +85,7 @@ FastScheduler::activateSendPacked()
void
FastScheduler::doJob()
{
Uint32 init_loopCount = 0;
Uint32 loopCount = 0;
Uint32 TminLoops = getBOccupancy() + EXTRA_SIGNALS_PER_DO_JOB;
Uint32 TloopMax = (Uint32)globalData.loopMax;
if (TminLoops < TloopMax) {
@ -94,10 +94,9 @@ FastScheduler::doJob()
if (TloopMax < MIN_NUMBER_OF_SIG_PER_DO_JOB) {
TloopMax = MIN_NUMBER_OF_SIG_PER_DO_JOB;
}//if
register Signal* signal = getVMSignals();
register Uint32 tHighPrio= globalData.highestAvailablePrio;
do{
Uint32 loopCount = init_loopCount;
register Uint32 tHighPrio = globalData.highestAvailablePrio;
register Signal* signal = getVMSignals();
while ((tHighPrio < LEVEL_IDLE) && (loopCount < TloopMax)) {
// signal->garbage_register();
// To ensure we find bugs quickly
@ -155,24 +154,27 @@ FastScheduler::doJob()
}//if
loopCount++;
}//while
if (globalData.sendPackedActivated == 1) {
Uint32 t1 = theDoJobTotalCounter;
Uint32 t2 = theDoJobCallCounter;
t1 += (loopCount - init_loopCount);
t2++;
theDoJobTotalCounter = t1;
theDoJobCallCounter = t2;
if (t2 == 8192) {
reportDoJobStatistics(t1 >> 13);
theDoJobCallCounter = 0;
theDoJobTotalCounter = 0;
}//if
}//if
init_loopCount = loopCount;
sendPacked();
tHighPrio = globalData.highestAvailablePrio;
if(getBOccupancy() > MAX_OCCUPANCY)
{
if(loopCount != TloopMax)
abort();
assert( loopCount == TloopMax );
TloopMax += 512;
}
} while ((getBOccupancy() > MAX_OCCUPANCY) ||
((init_loopCount < TloopMax) &&
(globalData.highestAvailablePrio < LEVEL_IDLE)));
((loopCount < TloopMax) &&
(tHighPrio < LEVEL_IDLE)));
theDoJobCallCounter ++;
theDoJobTotalCounter += loopCount;
if (theDoJobCallCounter == 8192) {
reportDoJobStatistics(theDoJobTotalCounter >> 13);
theDoJobCallCounter = 0;
theDoJobTotalCounter = 0;
}//if
}//FastScheduler::doJob()
void FastScheduler::sendPacked()

View File

@ -192,7 +192,7 @@ void install_db(char *datadir)
char error[PATH_MAX];
// input file
snprintf(input, PATH_MAX, "%s/bin/init_db.sql", base_dir);
snprintf(input, PATH_MAX, "%s/bin/test_db.sql", base_dir);
snprintf(output, PATH_MAX, "%s/install.out", datadir);
snprintf(error, PATH_MAX, "%s/install.err", datadir);
@ -1160,7 +1160,8 @@ void setup(char *file)
setenv("MASTER_MYPORT", "9306", 1);
setenv("SLAVE_MYPORT", "9307", 1);
setenv("MYSQL_TCP_PORT", "3306", 1);
snprintf(file_path, PATH_MAX*2, "%s/mysql_client_test --no-defaults --testcase--user=root --port=%u ", bin_dir, master_port);
setenv("MYSQL_CLIENT_TEST",file_path,1);
}
/******************************************************************************

View File

@ -149,7 +149,7 @@ bool Field::check_int(const char *str, int length, const char *int_end,
truncation.
SYNOPSIS
Field::check_overflow()
Field::warn_if_overflow()
op_result decimal library return code (E_DEC_* see include/decimal.h)
RETURN
@ -157,19 +157,22 @@ bool Field::check_int(const char *str, int length, const char *int_end,
0 no error or some other errors except overflow
*/
int Field::check_overflow(int op_result)
int Field::warn_if_overflow(int op_result)
{
if (op_result == E_DEC_OVERFLOW)
{
set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
return 1;
}
else if (op_result == E_DEC_TRUNCATED)
if (op_result == E_DEC_TRUNCATED)
{
set_warning(MYSQL_ERROR::WARN_LEVEL_NOTE, WARN_DATA_TRUNCATED, 1);
/* we return 1 only in case of EFL */
/* We return 0 here as this is not a critical issue */
}
return 0;
}
#ifdef NOT_USED
static bool test_if_real(const char *str,int length, CHARSET_INFO *cs)
{
@ -507,7 +510,7 @@ longlong Field::convert_decimal2longlong(const my_decimal *val,
i= 0;
*err= 1;
}
else if (check_overflow(my_decimal2int(E_DEC_ERROR &
else if (warn_if_overflow(my_decimal2int(E_DEC_ERROR &
~E_DEC_OVERFLOW & ~E_DEC_TRUNCATED,
val, TRUE, &i)))
{
@ -515,7 +518,7 @@ longlong Field::convert_decimal2longlong(const my_decimal *val,
*err= 1;
}
}
else if (check_overflow(my_decimal2int(E_DEC_ERROR &
else if (warn_if_overflow(my_decimal2int(E_DEC_ERROR &
~E_DEC_OVERFLOW & ~E_DEC_TRUNCATED,
val, FALSE, &i)))
{
@ -616,7 +619,7 @@ int Field_str::store_decimal(const my_decimal *d)
{
double val;
/* TODO: use decimal2string? */
int err= check_overflow(my_decimal2double(E_DEC_FATAL_ERROR &
int err= warn_if_overflow(my_decimal2double(E_DEC_FATAL_ERROR &
~E_DEC_OVERFLOW, d, &val));
return err | store(val);
}
@ -1552,12 +1555,17 @@ void Field_new_decimal::set_value_on_overflow(my_decimal *decimal_value,
checks if decimal_value fits into field size.
if it does, stores the decimal in the buffer using binary format.
Otherwise sets maximal number that can be stored in the field.
RETURN
0 ok
1 error
*/
bool Field_new_decimal::store_value(const my_decimal *decimal_value)
{
DBUG_ENTER("Field_new_decimal::store_value");
my_decimal *dec= (my_decimal*)decimal_value;
int error= 0;
DBUG_ENTER("Field_new_decimal::store_value");
DBUG_EXECUTE("enter", print_decimal(dec););
/* check that we do not try to write negative value in unsigned field */
@ -1565,16 +1573,18 @@ bool Field_new_decimal::store_value(const my_decimal *decimal_value)
{
DBUG_PRINT("info", ("unsigned overflow"));
set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
error= 1;
dec= &decimal_zero;
}
DBUG_PRINT("info", ("saving with precision %d, scale: %d",
(int)field_length, (int)decimals()));
DBUG_EXECUTE("info", print_decimal(dec););
if (check_overflow(my_decimal2binary(E_DEC_FATAL_ERROR & ~E_DEC_OVERFLOW,
dec, ptr,
field_length,
decimals())))
if (warn_if_overflow(my_decimal2binary(E_DEC_FATAL_ERROR &
~E_DEC_OVERFLOW,
dec, ptr,
field_length,
decimals())))
{
my_decimal buff;
DBUG_PRINT("info", ("overflow"));
@ -1584,20 +1594,20 @@ bool Field_new_decimal::store_value(const my_decimal *decimal_value)
DBUG_RETURN(1);
}
DBUG_EXECUTE("info", print_decimal_buff(dec, ptr, bin_size););
DBUG_RETURN(0);
DBUG_RETURN(error);
}
int Field_new_decimal::store(const char *from, uint length,
CHARSET_INFO *charset)
{
DBUG_ENTER("Field_new_decimal::store(char*)");
int err;
my_decimal decimal_value;
DBUG_ENTER("Field_new_decimal::store(char*)");
switch ((err= str2my_decimal(E_DEC_FATAL_ERROR &
~(E_DEC_OVERFLOW | E_DEC_BAD_NUM),
from, length, charset, &decimal_value)))
{
from, length, charset, &decimal_value))) {
case E_DEC_TRUNCATED:
set_warning(MYSQL_ERROR::WARN_LEVEL_NOTE, WARN_DATA_TRUNCATED, 1);
break;
@ -1624,9 +1634,11 @@ int Field_new_decimal::store(const char *from, uint length,
int Field_new_decimal::store(double nr)
{
my_decimal decimal_value;
int err= double2my_decimal(E_DEC_FATAL_ERROR &
~E_DEC_OVERFLOW, nr,
&decimal_value);
int err;
DBUG_ENTER("Field_new_decimal::store(double)");
err= double2my_decimal(E_DEC_FATAL_ERROR & ~E_DEC_OVERFLOW, nr,
&decimal_value);
/*
TODO: fix following when double2my_decimal when double2decimal
will return E_DEC_TRUNCATED always correctly
@ -1638,10 +1650,18 @@ int Field_new_decimal::store(double nr)
if (nr2 != nr)
err= E_DEC_TRUNCATED;
}
if (check_overflow(err))
set_value_on_overflow(&decimal_value, decimal_value.sign());
store_value(&decimal_value);
return err;
if (err)
{
if (check_overflow(err))
set_value_on_overflow(&decimal_value, decimal_value.sign());
/* Only issue a warning if store_value doesn't issue an warning */
table->in_use->got_warning= 0;
}
if (store_value(&decimal_value))
err= 1;
else if (err && !table->in_use->got_warning)
err= warn_if_overflow(err);
DBUG_RETURN(err);
}
@ -1649,10 +1669,19 @@ int Field_new_decimal::store(longlong nr)
{
my_decimal decimal_value;
int err;
if ((err= check_overflow(int2my_decimal(E_DEC_FATAL_ERROR & ~E_DEC_OVERFLOW,
nr, unsigned_flag, &decimal_value))))
set_value_on_overflow(&decimal_value, decimal_value.sign());
store_value(&decimal_value);
if ((err= int2my_decimal(E_DEC_FATAL_ERROR & ~E_DEC_OVERFLOW,
nr, unsigned_flag, &decimal_value)))
{
if (check_overflow(err))
set_value_on_overflow(&decimal_value, decimal_value.sign());
/* Only issue a warning if store_value doesn't issue an warning */
table->in_use->got_warning= 0;
}
if (store_value(&decimal_value))
err= 1;
else if (err && !table->in_use->got_warning)
err= warn_if_overflow(err);
return err;
}
@ -1694,7 +1723,7 @@ my_decimal* Field_new_decimal::val_decimal(my_decimal *decimal_value)
String *Field_new_decimal::val_str(String *val_buffer,
String *val_ptr __attribute__((unused)))
String *val_ptr __attribute__((unused)))
{
my_decimal decimal_value;
int fixed_precision= (zerofill ?
@ -1728,6 +1757,7 @@ void Field_new_decimal::sql_type(String &str) const
add_zerofill_and_unsigned(str);
}
/****************************************************************************
** tiny int
****************************************************************************/

View File

@ -290,7 +290,11 @@ public:
int cuted_increment);
void set_datetime_warning(const uint level, const uint code,
double nr, timestamp_type ts_type);
int check_overflow(int op_result);
inline bool check_overflow(int op_result)
{
return (op_result == E_DEC_OVERFLOW);
}
int warn_if_overflow(int op_result);
virtual field_cast_enum field_cast_type()= 0;
bool field_cast_compatible(field_cast_enum type);
/* maximum possible display length */

View File

@ -60,8 +60,7 @@ int ha_heap::open(const char *name, int mode, uint test_if_locked)
{
/* Initialize variables for the opened table */
set_keys_for_scanning();
if (table->s->tmp_table == NO_TMP_TABLE)
update_key_stats();
update_key_stats();
}
return (file ? 0 : 1);
}
@ -104,6 +103,8 @@ void ha_heap::update_key_stats()
for (uint i= 0; i < table->s->keys; i++)
{
KEY *key=table->key_info+i;
if (!key->rec_per_key)
continue;
if (key->algorithm != HA_KEY_ALG_BTREE)
{
ha_rows hash_buckets= file->s->keydef[i].hash_buckets;
@ -124,8 +125,8 @@ int ha_heap::write_row(byte * buf)
if (table->next_number_field && buf == table->record[0])
update_auto_increment();
res= heap_write(file,buf);
if (!res && table->s->tmp_table == NO_TMP_TABLE &&
++records_changed*HEAP_STATS_UPDATE_THRESHOLD > file->s->records)
if (!res && (++records_changed*HEAP_STATS_UPDATE_THRESHOLD >
file->s->records))
update_key_stats();
return res;
}
@ -137,8 +138,8 @@ int ha_heap::update_row(const byte * old_data, byte * new_data)
if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_UPDATE)
table->timestamp_field->set_time();
res= heap_update(file,old_data,new_data);
if (!res && table->s->tmp_table == NO_TMP_TABLE &&
++records_changed*HEAP_STATS_UPDATE_THRESHOLD > file->s->records)
if (!res && ++records_changed*HEAP_STATS_UPDATE_THRESHOLD >
file->s->records)
update_key_stats();
return res;
}

View File

@ -542,6 +542,58 @@ void Item_splocal::print(String *str)
/*
Move SUM items out from item tree and replace with reference
SYNOPSIS
split_sum_func2()
thd Thread handler
ref_pointer_array Pointer to array of reference fields
fields All fields in select
ref Pointer to item
NOTES
This is from split_sum_func2() for items that should be split
All found SUM items are added FIRST in the fields list and
we replace the item with a reference.
thd->fatal_error() may be called if we are out of memory
*/
void Item::split_sum_func2(THD *thd, Item **ref_pointer_array,
List<Item> &fields, Item **ref)
{
if (type() != SUM_FUNC_ITEM && with_sum_func)
{
/* Will split complicated items and ignore simple ones */
split_sum_func(thd, ref_pointer_array, fields);
}
else if ((type() == SUM_FUNC_ITEM ||
(used_tables() & ~PARAM_TABLE_BIT)) &&
type() != REF_ITEM)
{
/*
Replace item with a reference so that we can easily calculate
it (in case of sum functions) or copy it (in case of fields)
The test above is to ensure we don't do a reference for things
that are constants (PARAM_TABLE_BIT is in effect a constant)
or already referenced (for example an item in HAVING)
*/
uint el= fields.elements;
Item *new_item;
ref_pointer_array[el]= this;
if (!(new_item= new Item_ref(ref_pointer_array + el, 0, name)))
return; // fatal_error is set
fields.push_front(this);
ref_pointer_array[el]= this;
thd->change_item_tree(ref, new_item);
}
}
/*
Aggregate two collations together taking
into account their coercibility (aka derivation):

View File

@ -334,6 +334,9 @@ public:
virtual void update_used_tables() {}
virtual void split_sum_func(THD *thd, Item **ref_pointer_array,
List<Item> &fields) {}
/* Called for items that really have to be split */
void split_sum_func2(THD *thd, Item **ref_pointer_array, List<Item> &fields,
Item **ref);
virtual bool get_date(TIME *ltime,uint fuzzydate);
virtual bool get_time(TIME *ltime);
virtual bool get_date_result(TIME *ltime,uint fuzzydate)

View File

@ -704,13 +704,12 @@ longlong Item_in_optimizer::val_int()
{
DBUG_ASSERT(fixed == 1);
cache->store(args[0]);
longlong tmp= args[1]->val_int_result();
if (cache->null_value)
{
if (tmp)
null_value= 1;
null_value= 1;
return 0;
}
longlong tmp= args[1]->val_int_result();
null_value= args[1]->null_value;
return tmp;
}
@ -2349,10 +2348,10 @@ Item *Item_cond::transform(Item_transformer transformer, byte *arg)
Move SUM items out from item tree and replace with reference
SYNOPSIS
split_sum_func()
thd Thread handler
ref_pointer_array Pointer to array of reference fields
fields All fields in select
split_sum_func()
thd Thread handler
ref_pointer_array Pointer to array of reference fields
fields All fields in select
NOTES
This function is run on all expression (SELECT list, WHERE, HAVING etc)
@ -2362,16 +2361,6 @@ Item *Item_cond::transform(Item_transformer transformer, byte *arg)
so that we can easily find and calculate them.
(Calculation done by update_sum_func() and copy_sum_funcs() in
sql_select.cc)
All found SUM items are added FIRST in the fields list and
we replace the item with a reference.
We also replace all functions without side effects (like RAND() or UDF's)
that uses columns as arguments.
For functions with side effects, we just remember any fields referred
by the function to ensure that we get a copy of the field value for the
first accepted row. This ensures that we can do things like
SELECT a*SUM(b) FROM t1 WHERE a=1
*/
void Item_cond::split_sum_func(THD *thd, Item **ref_pointer_array,
@ -2379,37 +2368,8 @@ void Item_cond::split_sum_func(THD *thd, Item **ref_pointer_array,
{
List_iterator<Item> li(list);
Item *item;
used_tables_cache=0;
const_item_cache=1;
while ((item=li++))
{
/* with_sum_func is set for items that contains a SUM expression */
if (item->type() != SUM_FUNC_ITEM &&
(item->with_sum_func ||
(item->used_tables() & PSEUDO_TABLE_BITS)))
item->split_sum_func(thd, ref_pointer_array, fields);
else if (item->type() == SUM_FUNC_ITEM ||
(item->used_tables() && item->type() != REF_ITEM))
{
/*
Replace item with a reference so that we can easily calculate
it (in case of sum functions) or copy it (in case of fields)
The test above is to ensure we don't do a reference for things
that are constants or are not yet calculated as in:
SELECT RAND() as r1, SUM(a) as r2 FROM t1 HAVING r1 > 1 AND r2 > 0
*/
Item **ref= li.ref();
uint el= fields.elements;
ref_pointer_array[el]= item;
Item *new_item= new Item_ref(ref_pointer_array + el, 0, item->name);
fields.push_front(item);
thd->change_item_tree(ref, new_item);
}
item->update_used_tables();
used_tables_cache|=item->used_tables();
const_item_cache&=item->const_item();
}
while ((item= li++))
item->split_sum_func2(thd, ref_pointer_array, fields, li.ref());
}

View File

@ -401,27 +401,14 @@ Item *Item_func::transform(Item_transformer transformer, byte *argument)
}
/* See comments in Item_cmp_func::split_sum_func() */
void Item_func::split_sum_func(THD *thd, Item **ref_pointer_array,
List<Item> &fields)
{
Item **arg, **arg_end;
for (arg= args, arg_end= args+arg_count; arg != arg_end ; arg++)
{
Item *item=* arg;
if (item->type() != SUM_FUNC_ITEM &&
(item->with_sum_func ||
(item->used_tables() & PSEUDO_TABLE_BITS)))
item->split_sum_func(thd, ref_pointer_array, fields);
else if (item->type() == SUM_FUNC_ITEM ||
(item->used_tables() && item->type() != REF_ITEM))
{
uint el= fields.elements;
ref_pointer_array[el]= item;
Item *new_item= new Item_ref(ref_pointer_array + el, 0, item->name);
fields.push_front(item);
thd->change_item_tree(arg, new_item);
}
}
(*arg)->split_sum_func2(thd, ref_pointer_array, fields, arg);
}

View File

@ -90,24 +90,10 @@ void Item_row::split_sum_func(THD *thd, Item **ref_pointer_array,
{
Item **arg, **arg_end;
for (arg= items, arg_end= items+arg_count; arg != arg_end ; arg++)
{
Item *item= *arg;
if (item->type() != SUM_FUNC_ITEM &&
(item->with_sum_func ||
(item->used_tables() & PSEUDO_TABLE_BITS)))
item->split_sum_func(thd, ref_pointer_array, fields);
else if (item->type() == SUM_FUNC_ITEM ||
(item->used_tables() && item->type() != REF_ITEM))
{
uint el= fields.elements;
ref_pointer_array[el]= *arg;
Item *new_item= new Item_ref(ref_pointer_array + el, 0, (*arg)->name);
fields.push_front(*arg);
thd->change_item_tree(arg, new_item);
}
}
(*arg)->split_sum_func2(thd, ref_pointer_array, fields, arg);
}
void Item_row::update_used_tables()
{
used_tables_cache= 0;

View File

@ -1778,19 +1778,7 @@ String *Item_func_elt::val_str(String *str)
void Item_func_make_set::split_sum_func(THD *thd, Item **ref_pointer_array,
List<Item> &fields)
{
if (item->type() != SUM_FUNC_ITEM &&
(item->with_sum_func ||
(item->used_tables() & PSEUDO_TABLE_BITS)))
item->split_sum_func(thd, ref_pointer_array, fields);
else if (item->type() == SUM_FUNC_ITEM ||
(item->used_tables() && item->type() != REF_ITEM))
{
uint el= fields.elements;
ref_pointer_array[el]= item;
Item *new_item= new Item_ref(ref_pointer_array + el, 0, item->name);
fields.push_front(item);
thd->change_item_tree(&item, new_item);
}
item->split_sum_func2(thd, ref_pointer_array, fields, &item);
Item_str_func::split_sum_func(thd, ref_pointer_array, fields);
}

View File

@ -889,8 +889,10 @@ Item_in_subselect::single_value_transformer(JOIN *join,
ref_pointer_array,
(char *)"<ref>",
this->full_name()));
#ifdef CORRECT_BUT_TOO_SLOW_TO_BE_USABLE
if (!abort_on_null && left_expr->maybe_null)
item= new Item_cond_or(new Item_func_isnull(left_expr), item);
#endif
/*
AND and comparison functions can't be changed during fix_fields()
we can assign select_lex->having here, and pass 0 as last
@ -944,8 +946,10 @@ Item_in_subselect::single_value_transformer(JOIN *join,
goto err;
item= new Item_cond_or(item,
new Item_func_isnull(orig_item));
#ifdef CORRECT_BUT_TOO_SLOW_TO_BE_USABLE
if (left_expr->maybe_null)
item= new Item_cond_or(new Item_func_isnull(left_expr), item);
#endif
}
item->name= (char *)in_additional_cond;
/*
@ -975,8 +979,10 @@ Item_in_subselect::single_value_transformer(JOIN *join,
new Item_null_helper(this, item,
(char *)"<no matter>",
(char *)"<result>"));
#ifdef CORRECT_BUT_TOO_SLOW_TO_BE_USABLE
if (!abort_on_null && left_expr->maybe_null)
item= new Item_cond_or(new Item_func_isnull(left_expr), item);
#endif
select_lex->having= join->having= item;
select_lex->having_fix_field= 1;
/*

View File

@ -3302,12 +3302,14 @@ default_service_handling(char **argv,
if (Service.got_service_option(argv, "install"))
{
Service.Install(1, servicename, displayname, path_and_service, account_name);
Service.Install(1, servicename, displayname, path_and_service,
account_name);
return 0;
}
if (Service.got_service_option(argv, "install-manual"))
{
Service.Install(0, servicename, displayname, path_and_service, account_name);
Service.Install(0, servicename, displayname, path_and_service,
account_name);
return 0;
}
if (Service.got_service_option(argv, "remove"))
@ -3327,7 +3329,7 @@ int main(int argc, char **argv)
application PID e.g.: MySQLShutdown1890; MySQLShutdown2342
*/
int10_to_str((int) GetCurrentProcessId(),strmov(shutdown_event_name,
"MySQLShutdown"), 10);
"MySQLShutdown"), 10);
/* Must be initialized early for comparison of service name */
system_charset_info= &my_charset_utf8_general_ci;
@ -3361,7 +3363,8 @@ int main(int argc, char **argv)
}
else if (argc == 3) /* install or remove any optional service */
{
if (!default_service_handling(argv, argv[2], argv[2], file_path, "", NULL))
if (!default_service_handling(argv, argv[2], argv[2], file_path, "",
NULL))
return 0;
if (Service.IsService(argv[2]))
{
@ -3388,24 +3391,20 @@ int main(int argc, char **argv)
--defaults-file=file, but that was not enforced in 4.1, so we don't
enforce it here.)
*/
char *extra_opt= NULL;
char *account_name = NULL;
const char *extra_opt= NullS;
const char *account_name = NullS;
int index;
for (index = 3; index < argc; index++)
{
if (strncmp(argv[index], "--local-service", 15) == 0)
{
account_name=(char*)malloc(27);
strmov(account_name, "NT AUTHORITY\\LocalService\0");
}
if (!strcmp(argv[index], "--local-service"))
account_name= "NT AUTHORITY\\LocalService";
else
{
extra_opt= argv[index];
}
}
if (argc != 5 || account_name)
if (!default_service_handling(argv, argv[2], argv[2], file_path, extra_opt, account_name))
if (argc == 4 || account_name)
if (!default_service_handling(argv, argv[2], argv[2], file_path,
extra_opt, account_name))
return 0;
}
else if (argc == 1 && Service.IsService(MYSQL_SERVICENAME))

View File

@ -48,8 +48,9 @@ class NTService
//service install / un-install
BOOL Install(int startType,LPCSTR szInternName,LPCSTR szDisplayName,LPCSTR szFullPath,
LPCSTR szAccountName=NULL,LPCSTR szPassword=NULL);
BOOL Install(int startType,LPCSTR szInternName,LPCSTR szDisplayName,
LPCSTR szFullPath, LPCSTR szAccountName=NULL,
LPCSTR szPassword=NULL);
BOOL SeekStatus(LPCSTR szInternName, int OperationType);
BOOL Remove(LPCSTR szInternName);
BOOL IsService(LPCSTR ServiceName);

View File

@ -1027,6 +1027,7 @@ public:
bool charset_is_system_charset, charset_is_collation_connection;
bool slow_command;
bool no_trans_update, abort_on_warning;
bool got_warning; /* Set on call to push_warning() */
longlong row_count_func; /* For the ROW_COUNT() function */
sp_rcontext *spcont; // SP runtime context
sp_cache *sp_proc_cache;

View File

@ -108,6 +108,7 @@ MYSQL_ERROR *push_warning(THD *thd, MYSQL_ERROR::enum_warning_level level,
if (thd->query_id != thd->warn_id)
mysql_reset_errors(thd);
thd->got_warning= 1;
if (thd->spcont &&
thd->spcont->find_handler(code,
((int) level >=

View File

@ -140,15 +140,6 @@ public:
delete *prev;
*prev=node;
}
inline void *pop(void)
{
if (first == &end_of_list) return 0;
list_node *tmp=first;
first=first->next;
if (!--elements)
last= &first;
return tmp->info;
}
inline void concat(base_list *list)
{
if (!list->is_empty())
@ -158,6 +149,15 @@ public:
elements+= list->elements;
}
}
inline void *pop(void)
{
if (first == &end_of_list) return 0;
list_node *tmp=first;
first=first->next;
if (!--elements)
last= &first;
return tmp->info;
}
inline void disjoin(base_list *list)
{
list_node **prev= &first;

View File

@ -1313,7 +1313,7 @@ enum enum_mysql_completiontype {
SAVEPOINT_NAME_ROLLBACK=2,
SAVEPOINT_NAME_RELEASE=4,
COMMIT_AND_CHAIN=6,
ROLLBACK_AND_CHAIN=7,
ROLLBACK_AND_CHAIN=7
};
int mysql_endtrans(THD *thd, enum enum_mysql_completiontype completion,

View File

@ -8247,6 +8247,7 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
keyinfo->key_length=(uint16) reclength;
keyinfo->name= (char*) "distinct_key";
keyinfo->algorithm= HA_KEY_ALG_UNDEF;
keyinfo->rec_per_key=0;
if (null_pack_length)
{
key_part_info->null_bit=0;
@ -11843,6 +11844,7 @@ setup_copy_fields(THD *thd, TMP_TABLE_PARAM *param,
res_selected_fields.empty();
res_all_fields.empty();
List_iterator_fast<Item> itr(res_all_fields);
List<Item> extra_funcs;
uint i, border= all_fields.elements - elements;
DBUG_ENTER("setup_copy_fields");
@ -11904,7 +11906,12 @@ setup_copy_fields(THD *thd, TMP_TABLE_PARAM *param,
*/
if (!(pos=new Item_copy_string(pos)))
goto err;
if (param->copy_funcs.push_back(pos))
if (i < border) // HAVING, ORDER and GROUP BY
{
if (extra_funcs.push_back(pos))
goto err;
}
else if (param->copy_funcs.push_back(pos))
goto err;
}
res_all_fields.push_back(pos);
@ -11916,6 +11923,12 @@ setup_copy_fields(THD *thd, TMP_TABLE_PARAM *param,
for (i= 0; i < border; i++)
itr++;
itr.sublist(res_selected_fields, elements);
/*
Put elements from HAVING, ORDER BY and GROUP BY last to ensure that any
reference used in these will resolve to a item that is already calculated
*/
param->copy_funcs.concat(&extra_funcs);
DBUG_RETURN(0);
err:

View File

@ -30,6 +30,7 @@
#include <my_global.h>
#include <my_sys.h>
#include <mysql.h>
#include <errmsg.h>
#include <my_getopt.h>
#include <m_string.h>
@ -12512,6 +12513,77 @@ static void test_bug6761(void)
}
/* Bug#8330 - mysql_stmt_execute crashes (libmysql) */
static void test_bug8330()
{
const char *stmt_text;
MYSQL_STMT *stmt[2];
int i, rc;
char *query= "select a,b from t1 where a=?";
MYSQL_BIND bind[2];
long lval[2];
myheader("test_bug8330");
stmt_text= "drop table if exists t1";
/* in case some previos test failed */
rc= mysql_real_query(mysql, stmt_text, strlen(stmt_text));
myquery(rc);
stmt_text= "create table t1 (a int, b int)";
rc= mysql_real_query(mysql, stmt_text, strlen(stmt_text));
myquery(rc);
bzero(bind, sizeof(bind));
for (i=0; i < 2; i++)
{
stmt[i]= mysql_stmt_init(mysql);
rc= mysql_stmt_prepare(stmt[i], query, strlen(query));
check_execute(stmt[i], rc);
bind[i].buffer_type= MYSQL_TYPE_LONG;
bind[i].buffer= (void*) &lval[i];
bind[i].is_null= 0;
mysql_stmt_bind_param(stmt[i], &bind[i]);
}
rc= mysql_stmt_execute(stmt[0]);
check_execute(stmt[0], rc);
rc= mysql_stmt_execute(stmt[1]);
DIE_UNLESS(rc && mysql_stmt_errno(stmt[1]) == CR_COMMANDS_OUT_OF_SYNC);
rc= mysql_stmt_execute(stmt[0]);
check_execute(stmt[0], rc);
mysql_stmt_close(stmt[0]);
mysql_stmt_close(stmt[1]);
stmt_text= "drop table t1";
rc= mysql_real_query(mysql, stmt_text, strlen(stmt_text));
myquery(rc);
}
/* Bug#7990 - mysql_stmt_close doesn't reset mysql->net.last_error */
static void test_bug7990()
{
MYSQL_STMT *stmt;
int rc;
myheader("test_bug7990");
stmt= mysql_stmt_init(mysql);
rc= mysql_stmt_prepare(stmt, "foo", 3);
/*
XXX: the fact that we store errno both in STMT and in
MYSQL is not documented and is subject to change in 5.0
*/
DIE_UNLESS(rc && mysql_stmt_errno(stmt) && mysql_errno(mysql));
mysql_stmt_close(stmt);
DIE_UNLESS(!mysql_errno(mysql));
}
/*
Read and parse arguments and MySQL options from my.cnf
*/
@ -12730,6 +12802,8 @@ static struct my_tests_st my_tests[]= {
{ "test_cursors_with_union", test_cursors_with_union },
{ "test_truncation", test_truncation },
{ "test_truncation_option", test_truncation_option },
{ "test_bug8330", test_bug8330 },
{ "test_bug7990", test_bug7990 },
{ 0, 0 }
};