Commit 50c37672 authored by anozdrin/alik@quad.opbmk's avatar anozdrin/alik@quad.opbmk

Merge quad.opbmk:/mnt/raid/alik/MySQL/devel/5.0

into  quad.opbmk:/mnt/raid/alik/MySQL/devel/5.0-rt-merged
parents 3bff5b59 44fe22e7
......@@ -2456,7 +2456,7 @@ static my_bool execute(MYSQL_STMT *stmt, char *packet, ulong length)
int4store(buff+5, 1); /* iteration count */
res= test(cli_advanced_command(mysql, COM_STMT_EXECUTE, buff, sizeof(buff),
packet, length, 1, NULL) ||
packet, length, 1, stmt) ||
(*mysql->methods->read_query_result)(mysql));
stmt->affected_rows= mysql->affected_rows;
stmt->server_status= mysql->server_status;
......@@ -2673,7 +2673,7 @@ stmt_read_row_from_cursor(MYSQL_STMT *stmt, unsigned char **row)
int4store(buff + 4, stmt->prefetch_rows); /* number of rows to fetch */
if ((*mysql->methods->advanced_command)(mysql, COM_STMT_FETCH,
buff, sizeof(buff), NullS, 0,
1, NULL))
1, stmt))
{
set_stmt_errmsg(stmt, net->last_error, net->last_errno, net->sqlstate);
return 1;
......@@ -3340,7 +3340,7 @@ mysql_stmt_send_long_data(MYSQL_STMT *stmt, uint param_number,
*/
if ((*mysql->methods->advanced_command)(mysql, COM_STMT_SEND_LONG_DATA,
buff, sizeof(buff), data,
length, 1, NULL))
length, 1, stmt))
{
set_stmt_errmsg(stmt, mysql->net.last_error,
mysql->net.last_errno, mysql->net.sqlstate);
......@@ -4737,6 +4737,13 @@ int STDCALL mysql_stmt_store_result(MYSQL_STMT *stmt)
MYSQL_DATA *result= &stmt->result;
DBUG_ENTER("mysql_stmt_store_result");
if (!mysql)
{
/* mysql can be reset in mysql_close called from mysql_reconnect */
set_stmt_error(stmt, CR_SERVER_LOST, unknown_sqlstate);
DBUG_RETURN(1);
}
mysql= mysql->last_used_con;
if (!stmt->field_count)
......@@ -4762,7 +4769,7 @@ int STDCALL mysql_stmt_store_result(MYSQL_STMT *stmt)
int4store(buff, stmt->stmt_id);
int4store(buff + 4, (int)~0); /* number of rows to fetch */
if (cli_advanced_command(mysql, COM_STMT_FETCH, buff, sizeof(buff),
NullS, 0, 1, NULL))
NullS, 0, 1, stmt))
{
set_stmt_errmsg(stmt, net->last_error, net->last_errno, net->sqlstate);
DBUG_RETURN(1);
......@@ -4949,7 +4956,7 @@ static my_bool reset_stmt_handle(MYSQL_STMT *stmt, uint flags)
char buff[MYSQL_STMT_HEADER]; /* packet header: 4 bytes for stmt id */
int4store(buff, stmt->stmt_id);
if ((*mysql->methods->advanced_command)(mysql, COM_STMT_RESET, buff,
sizeof(buff), 0, 0, 0, NULL))
sizeof(buff), 0, 0, 0, stmt))
{
set_stmt_errmsg(stmt, mysql->net.last_error, mysql->net.last_errno,
mysql->net.sqlstate);
......
......@@ -140,4 +140,23 @@ select * from t3;
c
1
drop table t1, t2, t3;
DROP TABLE IF EXISTS t1;
DROP TABLE IF EXISTS t2;
CREATE TABLE t1(a INT PRIMARY KEY) ENGINE=innodb;
CREATE TABLE t2(b INT, FOREIGN KEY(b) REFERENCES t1(a)) ENGINE=innodb;
INSERT INTO t1 VALUES (1);
CREATE TRIGGER t1_bd BEFORE DELETE ON t1 FOR EACH ROW SET @a = 1;
CREATE TRIGGER t1_ad AFTER DELETE ON t1 FOR EACH ROW SET @b = 1;
SET @a = 0;
SET @b = 0;
TRUNCATE t1;
SELECT @a, @b;
@a @b
0 0
INSERT INTO t1 VALUES (1);
DELETE FROM t1;
SELECT @a, @b;
@a @b
1 1
DROP TABLE t2, t1;
End of 5.0 tests
......@@ -8,8 +8,8 @@
# server or run mysql-test-run --debug mysql_client_test and check
# var/log/mysql_client_test.trace
--exec echo "$MYSQL_CLIENT_TEST" > $MYSQLTEST_VARDIR/log/mysql_client_test.log 2>&1
--exec $MYSQL_CLIENT_TEST --getopt-ll-test=25600M >> $MYSQLTEST_VARDIR/log/mysql_client_test.log 2>&1
--exec echo "$MYSQL_CLIENT_TEST" > $MYSQLTEST_VARDIR/log/mysql_client_test.out.log 2>&1
--exec $MYSQL_CLIENT_TEST --getopt-ll-test=25600M >> $MYSQLTEST_VARDIR/log/mysql_client_test.out.log 2>&1
# End of 4.1 tests
echo ok;
......
......@@ -128,5 +128,37 @@ drop table t1, t2, t3;
disconnect connection_update;
disconnect connection_aux;
#
# Bug#34643: TRUNCATE crash if trigger and foreign key.
#
--disable_warnings
DROP TABLE IF EXISTS t1;
DROP TABLE IF EXISTS t2;
--enable_warnings
CREATE TABLE t1(a INT PRIMARY KEY) ENGINE=innodb;
CREATE TABLE t2(b INT, FOREIGN KEY(b) REFERENCES t1(a)) ENGINE=innodb;
INSERT INTO t1 VALUES (1);
CREATE TRIGGER t1_bd BEFORE DELETE ON t1 FOR EACH ROW SET @a = 1;
CREATE TRIGGER t1_ad AFTER DELETE ON t1 FOR EACH ROW SET @b = 1;
SET @a = 0;
SET @b = 0;
TRUNCATE t1;
SELECT @a, @b;
INSERT INTO t1 VALUES (1);
DELETE FROM t1;
SELECT @a, @b;
DROP TABLE t2, t1;
--echo End of 5.0 tests
......@@ -669,11 +669,12 @@ my_bool
cli_advanced_command(MYSQL *mysql, enum enum_server_command command,
const char *header, ulong header_length,
const char *arg, ulong arg_length, my_bool skip_check,
MYSQL_STMT *stmt __attribute__((unused)))
MYSQL_STMT *stmt)
{
NET *net= &mysql->net;
my_bool result= 1;
init_sigpipe_variables
my_bool stmt_skip= stmt ? stmt->state != MYSQL_STMT_INIT_DONE : FALSE;
DBUG_ENTER("cli_advanced_command");
/* Don't give sigpipe errors if the client doesn't want them */
......@@ -681,7 +682,7 @@ cli_advanced_command(MYSQL *mysql, enum enum_server_command command,
if (mysql->net.vio == 0)
{ /* Do reconnect if possible */
if (mysql_reconnect(mysql))
if (mysql_reconnect(mysql) || stmt_skip)
DBUG_RETURN(1);
}
if (mysql->status != MYSQL_STATUS_READY ||
......@@ -712,7 +713,7 @@ cli_advanced_command(MYSQL *mysql, enum enum_server_command command,
goto end;
}
end_server(mysql);
if (mysql_reconnect(mysql))
if (mysql_reconnect(mysql) || stmt_skip)
goto end;
if (net_write_command(net,(uchar) command, header, header_length,
arg, arg_length))
......@@ -2518,6 +2519,9 @@ my_bool mysql_reconnect(MYSQL *mysql)
if (stmt->state != MYSQL_STMT_INIT_DONE)
{
stmt->mysql= 0;
stmt->last_errno= CR_SERVER_LOST;
strmov(stmt->last_error, ER(CR_SERVER_LOST));
strmov(stmt->sqlstate, unknown_sqlstate);
}
else
{
......
......@@ -35,6 +35,7 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds,
READ_RECORD info;
bool using_limit=limit != HA_POS_ERROR;
bool transactional_table, safe_update, const_cond;
bool triggers_applicable;
ha_rows deleted;
uint usable_index= MAX_KEY;
SELECT_LEX *select_lex= &thd->lex->select_lex;
......@@ -93,6 +94,11 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds,
select_lex->no_error= thd->lex->ignore;
/* NOTE: TRUNCATE must not invoke triggers. */
triggers_applicable= table->triggers &&
thd->lex->sql_command != SQLCOM_TRUNCATE;
/*
Test if the user wants to delete all rows and deletion doesn't have
any side-effects (because of triggers), so we can use optimized
......@@ -102,8 +108,7 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds,
*/
if (!using_limit && const_cond && (!conds || conds->val_int()) &&
!(specialflag & (SPECIAL_NO_NEW_FUNC | SPECIAL_SAFE_MODE)) &&
(thd->lex->sql_command == SQLCOM_TRUNCATE ||
!(table->triggers && table->triggers->has_delete_triggers()))
!(triggers_applicable && table->triggers->has_delete_triggers())
)
{
deleted= table->file->records;
......@@ -217,7 +222,7 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds,
init_ftfuncs(thd, select_lex, 1);
thd->proc_info="updating";
if (table->triggers)
if (triggers_applicable)
{
table->triggers->mark_fields_used(thd, TRG_EVENT_DELETE);
if (table->triggers->has_triggers(TRG_EVENT_DELETE,
......@@ -239,7 +244,7 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds,
if (!(select && select->skip_record())&& !thd->net.report_error )
{
if (table->triggers &&
if (triggers_applicable &&
table->triggers->process_triggers(thd, TRG_EVENT_DELETE,
TRG_ACTION_BEFORE, FALSE))
{
......@@ -250,7 +255,7 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds,
if (!(error=table->file->delete_row(table->record[0])))
{
deleted++;
if (table->triggers &&
if (triggers_applicable &&
table->triggers->process_triggers(thd, TRG_EVENT_DELETE,
TRG_ACTION_AFTER, FALSE))
{
......
......@@ -2516,7 +2516,7 @@ void mysql_stmt_close(THD *thd, char *packet)
DBUG_ENTER("mysql_stmt_close");
if (!(stmt= find_prepared_statement(thd, stmt_id, "mysql_stmt_close")))
DBUG_VOID_RETURN;
goto out;
/*
The only way currently a statement can be deallocated when it's
......@@ -2525,6 +2525,9 @@ void mysql_stmt_close(THD *thd, char *packet)
DBUG_ASSERT(! (stmt->flags & (uint) Prepared_statement::IS_IN_USE));
(void) stmt->deallocate();
out:
/* clear errors, response packet is not expected */
thd->clear_error();
DBUG_VOID_RETURN;
}
......@@ -2591,10 +2594,7 @@ void mysql_stmt_get_longdata(THD *thd, char *packet, ulong packet_length)
#ifndef EMBEDDED_LIBRARY
/* Minimal size of long data packet is 6 bytes */
if (packet_length <= MYSQL_LONG_DATA_HEADER)
{
my_error(ER_WRONG_ARGUMENTS, MYF(0), "mysql_stmt_send_long_data");
DBUG_VOID_RETURN;
}
goto out;
#endif
stmt_id= uint4korr(packet);
......@@ -2602,7 +2602,7 @@ void mysql_stmt_get_longdata(THD *thd, char *packet, ulong packet_length)
if (!(stmt=find_prepared_statement(thd, stmt_id,
"mysql_stmt_send_long_data")))
DBUG_VOID_RETURN;
goto out;
param_number= uint2korr(packet);
packet+= 2;
......@@ -2614,7 +2614,7 @@ void mysql_stmt_get_longdata(THD *thd, char *packet, ulong packet_length)
stmt->last_errno= ER_WRONG_ARGUMENTS;
sprintf(stmt->last_error, ER(ER_WRONG_ARGUMENTS),
"mysql_stmt_send_long_data");
DBUG_VOID_RETURN;
goto out;
}
#endif
......@@ -2630,6 +2630,10 @@ void mysql_stmt_get_longdata(THD *thd, char *packet, ulong packet_length)
stmt->last_errno= ER_OUTOFMEMORY;
sprintf(stmt->last_error, ER(ER_OUTOFMEMORY), 0);
}
out:
/* clear errors, response packet is not expected */
thd->clear_error();
DBUG_VOID_RETURN;
}
......
......@@ -11746,6 +11746,7 @@ static void test_bug5194()
rc= mysql_stmt_execute(stmt);
check_execute(stmt, rc);
mysql_stmt_reset(stmt);
}
mysql_stmt_close(stmt);
......@@ -15952,83 +15953,6 @@ static void test_bug27592()
DBUG_VOID_RETURN;
}
#if 0
static void test_bug29948()
{
MYSQL *dbc=NULL;
MYSQL_STMT *stmt=NULL;
MYSQL_BIND bind;
int res=0;
my_bool auto_reconnect=1, error=0, is_null=0;
char kill_buf[20];
const char *query;
int buf;
unsigned long length, cursor_type;
dbc = mysql_init(NULL);
DIE_UNLESS(dbc);
mysql_options(dbc, MYSQL_OPT_RECONNECT, (char*)&auto_reconnect);
if (!mysql_real_connect(dbc, opt_host, opt_user,
opt_password, current_db, opt_port,
opt_unix_socket,
(CLIENT_FOUND_ROWS | CLIENT_MULTI_STATEMENTS |
CLIENT_MULTI_RESULTS)))
{
printf("connection failed: %s (%d)", mysql_error(dbc),
mysql_errno(dbc));
exit(1);
}
bzero(&bind, sizeof(bind));
bind.buffer_type= MYSQL_TYPE_LONG;
bind.buffer= (char *)&buf;
bind.is_null= &is_null;
bind.error= &error;
bind.length= &length;
res= mysql_query(dbc, "DROP TABLE IF EXISTS t1");
myquery(res);
res= mysql_query(dbc, "CREATE TABLE t1 (a INT)");
myquery(res);
res= mysql_query(dbc, "INSERT INTO t1 VALUES(1)");
myquery(res);
stmt= mysql_stmt_init(dbc);
check_stmt(stmt);
cursor_type= CURSOR_TYPE_READ_ONLY;
res= mysql_stmt_attr_set(stmt, STMT_ATTR_CURSOR_TYPE, (void *)&cursor_type);
myquery(res);
query= "SELECT * from t1 where a=?";
res= mysql_stmt_prepare(stmt, query, strlen(query));
myquery(res);
res= mysql_stmt_bind_param(stmt, &bind);
myquery(res);
res= mysql_stmt_execute(stmt);
check_execute(stmt, res);
res= mysql_stmt_bind_result(stmt,&bind);
check_execute(stmt, res);
sprintf(kill_buf, "kill %ld", dbc->thread_id);
mysql_query(dbc, kill_buf);
res= mysql_stmt_store_result(stmt);
DIE_UNLESS(res);
mysql_stmt_free_result(stmt);
mysql_stmt_close(stmt);
mysql_query(dbc, "DROP TABLE t1");
mysql_close(dbc);
}
#endif
/**
Bug#29306 Truncated data in MS Access with decimal (3,1) columns in a VIEW
......@@ -16556,7 +16480,6 @@ static struct my_tests_st my_tests[]= {
{ "test_bug28505", test_bug28505 },
{ "test_bug28934", test_bug28934 },
{ "test_bug27592", test_bug27592 },
/* { "test_bug29948", test_bug29948 }, Bug#35103 */
{ "test_bug29306", test_bug29306 },
{ "test_bug31669", test_bug31669 },
{ "test_bug32265", test_bug32265 },
......
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