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) ...@@ -2456,7 +2456,7 @@ static my_bool execute(MYSQL_STMT *stmt, char *packet, ulong length)
int4store(buff+5, 1); /* iteration count */ int4store(buff+5, 1); /* iteration count */
res= test(cli_advanced_command(mysql, COM_STMT_EXECUTE, buff, sizeof(buff), 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)); (*mysql->methods->read_query_result)(mysql));
stmt->affected_rows= mysql->affected_rows; stmt->affected_rows= mysql->affected_rows;
stmt->server_status= mysql->server_status; stmt->server_status= mysql->server_status;
...@@ -2673,7 +2673,7 @@ stmt_read_row_from_cursor(MYSQL_STMT *stmt, unsigned char **row) ...@@ -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 */ int4store(buff + 4, stmt->prefetch_rows); /* number of rows to fetch */
if ((*mysql->methods->advanced_command)(mysql, COM_STMT_FETCH, if ((*mysql->methods->advanced_command)(mysql, COM_STMT_FETCH,
buff, sizeof(buff), NullS, 0, buff, sizeof(buff), NullS, 0,
1, NULL)) 1, stmt))
{ {
set_stmt_errmsg(stmt, net->last_error, net->last_errno, net->sqlstate); set_stmt_errmsg(stmt, net->last_error, net->last_errno, net->sqlstate);
return 1; return 1;
...@@ -3340,7 +3340,7 @@ mysql_stmt_send_long_data(MYSQL_STMT *stmt, uint param_number, ...@@ -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, if ((*mysql->methods->advanced_command)(mysql, COM_STMT_SEND_LONG_DATA,
buff, sizeof(buff), data, buff, sizeof(buff), data,
length, 1, NULL)) length, 1, stmt))
{ {
set_stmt_errmsg(stmt, mysql->net.last_error, set_stmt_errmsg(stmt, mysql->net.last_error,
mysql->net.last_errno, mysql->net.sqlstate); mysql->net.last_errno, mysql->net.sqlstate);
...@@ -4737,6 +4737,13 @@ int STDCALL mysql_stmt_store_result(MYSQL_STMT *stmt) ...@@ -4737,6 +4737,13 @@ int STDCALL mysql_stmt_store_result(MYSQL_STMT *stmt)
MYSQL_DATA *result= &stmt->result; MYSQL_DATA *result= &stmt->result;
DBUG_ENTER("mysql_stmt_store_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; mysql= mysql->last_used_con;
if (!stmt->field_count) if (!stmt->field_count)
...@@ -4762,7 +4769,7 @@ int STDCALL mysql_stmt_store_result(MYSQL_STMT *stmt) ...@@ -4762,7 +4769,7 @@ int STDCALL mysql_stmt_store_result(MYSQL_STMT *stmt)
int4store(buff, stmt->stmt_id); int4store(buff, stmt->stmt_id);
int4store(buff + 4, (int)~0); /* number of rows to fetch */ int4store(buff + 4, (int)~0); /* number of rows to fetch */
if (cli_advanced_command(mysql, COM_STMT_FETCH, buff, sizeof(buff), 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); set_stmt_errmsg(stmt, net->last_error, net->last_errno, net->sqlstate);
DBUG_RETURN(1); DBUG_RETURN(1);
...@@ -4949,7 +4956,7 @@ static my_bool reset_stmt_handle(MYSQL_STMT *stmt, uint flags) ...@@ -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 */ char buff[MYSQL_STMT_HEADER]; /* packet header: 4 bytes for stmt id */
int4store(buff, stmt->stmt_id); int4store(buff, stmt->stmt_id);
if ((*mysql->methods->advanced_command)(mysql, COM_STMT_RESET, buff, 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, set_stmt_errmsg(stmt, mysql->net.last_error, mysql->net.last_errno,
mysql->net.sqlstate); mysql->net.sqlstate);
......
...@@ -140,4 +140,23 @@ select * from t3; ...@@ -140,4 +140,23 @@ select * from t3;
c c
1 1
drop table t1, t2, t3; 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 End of 5.0 tests
...@@ -8,8 +8,8 @@ ...@@ -8,8 +8,8 @@
# server or run mysql-test-run --debug mysql_client_test and check # server or run mysql-test-run --debug mysql_client_test and check
# var/log/mysql_client_test.trace # var/log/mysql_client_test.trace
--exec echo "$MYSQL_CLIENT_TEST" > $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.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 # End of 4.1 tests
echo ok; echo ok;
......
...@@ -128,5 +128,37 @@ drop table t1, t2, t3; ...@@ -128,5 +128,37 @@ drop table t1, t2, t3;
disconnect connection_update; disconnect connection_update;
disconnect connection_aux; 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 --echo End of 5.0 tests
...@@ -669,11 +669,12 @@ my_bool ...@@ -669,11 +669,12 @@ my_bool
cli_advanced_command(MYSQL *mysql, enum enum_server_command command, cli_advanced_command(MYSQL *mysql, enum enum_server_command command,
const char *header, ulong header_length, const char *header, ulong header_length,
const char *arg, ulong arg_length, my_bool skip_check, const char *arg, ulong arg_length, my_bool skip_check,
MYSQL_STMT *stmt __attribute__((unused))) MYSQL_STMT *stmt)
{ {
NET *net= &mysql->net; NET *net= &mysql->net;
my_bool result= 1; my_bool result= 1;
init_sigpipe_variables init_sigpipe_variables
my_bool stmt_skip= stmt ? stmt->state != MYSQL_STMT_INIT_DONE : FALSE;
DBUG_ENTER("cli_advanced_command"); DBUG_ENTER("cli_advanced_command");
/* Don't give sigpipe errors if the client doesn't want them */ /* 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, ...@@ -681,7 +682,7 @@ cli_advanced_command(MYSQL *mysql, enum enum_server_command command,
if (mysql->net.vio == 0) if (mysql->net.vio == 0)
{ /* Do reconnect if possible */ { /* Do reconnect if possible */
if (mysql_reconnect(mysql)) if (mysql_reconnect(mysql) || stmt_skip)
DBUG_RETURN(1); DBUG_RETURN(1);
} }
if (mysql->status != MYSQL_STATUS_READY || if (mysql->status != MYSQL_STATUS_READY ||
...@@ -712,7 +713,7 @@ cli_advanced_command(MYSQL *mysql, enum enum_server_command command, ...@@ -712,7 +713,7 @@ cli_advanced_command(MYSQL *mysql, enum enum_server_command command,
goto end; goto end;
} }
end_server(mysql); end_server(mysql);
if (mysql_reconnect(mysql)) if (mysql_reconnect(mysql) || stmt_skip)
goto end; goto end;
if (net_write_command(net,(uchar) command, header, header_length, if (net_write_command(net,(uchar) command, header, header_length,
arg, arg_length)) arg, arg_length))
...@@ -2518,6 +2519,9 @@ my_bool mysql_reconnect(MYSQL *mysql) ...@@ -2518,6 +2519,9 @@ my_bool mysql_reconnect(MYSQL *mysql)
if (stmt->state != MYSQL_STMT_INIT_DONE) if (stmt->state != MYSQL_STMT_INIT_DONE)
{ {
stmt->mysql= 0; stmt->mysql= 0;
stmt->last_errno= CR_SERVER_LOST;
strmov(stmt->last_error, ER(CR_SERVER_LOST));
strmov(stmt->sqlstate, unknown_sqlstate);
} }
else else
{ {
......
...@@ -35,6 +35,7 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, ...@@ -35,6 +35,7 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds,
READ_RECORD info; READ_RECORD info;
bool using_limit=limit != HA_POS_ERROR; bool using_limit=limit != HA_POS_ERROR;
bool transactional_table, safe_update, const_cond; bool transactional_table, safe_update, const_cond;
bool triggers_applicable;
ha_rows deleted; ha_rows deleted;
uint usable_index= MAX_KEY; uint usable_index= MAX_KEY;
SELECT_LEX *select_lex= &thd->lex->select_lex; SELECT_LEX *select_lex= &thd->lex->select_lex;
...@@ -93,6 +94,11 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, ...@@ -93,6 +94,11 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds,
select_lex->no_error= thd->lex->ignore; 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 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 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, ...@@ -102,8 +108,7 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds,
*/ */
if (!using_limit && const_cond && (!conds || conds->val_int()) && if (!using_limit && const_cond && (!conds || conds->val_int()) &&
!(specialflag & (SPECIAL_NO_NEW_FUNC | SPECIAL_SAFE_MODE)) && !(specialflag & (SPECIAL_NO_NEW_FUNC | SPECIAL_SAFE_MODE)) &&
(thd->lex->sql_command == SQLCOM_TRUNCATE || !(triggers_applicable && table->triggers->has_delete_triggers())
!(table->triggers && table->triggers->has_delete_triggers()))
) )
{ {
deleted= table->file->records; deleted= table->file->records;
...@@ -217,7 +222,7 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, ...@@ -217,7 +222,7 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds,
init_ftfuncs(thd, select_lex, 1); init_ftfuncs(thd, select_lex, 1);
thd->proc_info="updating"; thd->proc_info="updating";
if (table->triggers) if (triggers_applicable)
{ {
table->triggers->mark_fields_used(thd, TRG_EVENT_DELETE); table->triggers->mark_fields_used(thd, TRG_EVENT_DELETE);
if (table->triggers->has_triggers(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, ...@@ -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 (!(select && select->skip_record())&& !thd->net.report_error )
{ {
if (table->triggers && if (triggers_applicable &&
table->triggers->process_triggers(thd, TRG_EVENT_DELETE, table->triggers->process_triggers(thd, TRG_EVENT_DELETE,
TRG_ACTION_BEFORE, FALSE)) TRG_ACTION_BEFORE, FALSE))
{ {
...@@ -250,7 +255,7 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, ...@@ -250,7 +255,7 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds,
if (!(error=table->file->delete_row(table->record[0]))) if (!(error=table->file->delete_row(table->record[0])))
{ {
deleted++; deleted++;
if (table->triggers && if (triggers_applicable &&
table->triggers->process_triggers(thd, TRG_EVENT_DELETE, table->triggers->process_triggers(thd, TRG_EVENT_DELETE,
TRG_ACTION_AFTER, FALSE)) TRG_ACTION_AFTER, FALSE))
{ {
......
...@@ -2516,7 +2516,7 @@ void mysql_stmt_close(THD *thd, char *packet) ...@@ -2516,7 +2516,7 @@ void mysql_stmt_close(THD *thd, char *packet)
DBUG_ENTER("mysql_stmt_close"); DBUG_ENTER("mysql_stmt_close");
if (!(stmt= find_prepared_statement(thd, stmt_id, "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 The only way currently a statement can be deallocated when it's
...@@ -2525,6 +2525,9 @@ void mysql_stmt_close(THD *thd, char *packet) ...@@ -2525,6 +2525,9 @@ void mysql_stmt_close(THD *thd, char *packet)
DBUG_ASSERT(! (stmt->flags & (uint) Prepared_statement::IS_IN_USE)); DBUG_ASSERT(! (stmt->flags & (uint) Prepared_statement::IS_IN_USE));
(void) stmt->deallocate(); (void) stmt->deallocate();
out:
/* clear errors, response packet is not expected */
thd->clear_error();
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
} }
...@@ -2591,10 +2594,7 @@ void mysql_stmt_get_longdata(THD *thd, char *packet, ulong packet_length) ...@@ -2591,10 +2594,7 @@ void mysql_stmt_get_longdata(THD *thd, char *packet, ulong packet_length)
#ifndef EMBEDDED_LIBRARY #ifndef EMBEDDED_LIBRARY
/* Minimal size of long data packet is 6 bytes */ /* Minimal size of long data packet is 6 bytes */
if (packet_length <= MYSQL_LONG_DATA_HEADER) if (packet_length <= MYSQL_LONG_DATA_HEADER)
{ goto out;
my_error(ER_WRONG_ARGUMENTS, MYF(0), "mysql_stmt_send_long_data");
DBUG_VOID_RETURN;
}
#endif #endif
stmt_id= uint4korr(packet); stmt_id= uint4korr(packet);
...@@ -2602,7 +2602,7 @@ void mysql_stmt_get_longdata(THD *thd, char *packet, ulong packet_length) ...@@ -2602,7 +2602,7 @@ void mysql_stmt_get_longdata(THD *thd, char *packet, ulong packet_length)
if (!(stmt=find_prepared_statement(thd, stmt_id, if (!(stmt=find_prepared_statement(thd, stmt_id,
"mysql_stmt_send_long_data"))) "mysql_stmt_send_long_data")))
DBUG_VOID_RETURN; goto out;
param_number= uint2korr(packet); param_number= uint2korr(packet);
packet+= 2; packet+= 2;
...@@ -2614,7 +2614,7 @@ void mysql_stmt_get_longdata(THD *thd, char *packet, ulong packet_length) ...@@ -2614,7 +2614,7 @@ void mysql_stmt_get_longdata(THD *thd, char *packet, ulong packet_length)
stmt->last_errno= ER_WRONG_ARGUMENTS; stmt->last_errno= ER_WRONG_ARGUMENTS;
sprintf(stmt->last_error, ER(ER_WRONG_ARGUMENTS), sprintf(stmt->last_error, ER(ER_WRONG_ARGUMENTS),
"mysql_stmt_send_long_data"); "mysql_stmt_send_long_data");
DBUG_VOID_RETURN; goto out;
} }
#endif #endif
...@@ -2630,6 +2630,10 @@ void mysql_stmt_get_longdata(THD *thd, char *packet, ulong packet_length) ...@@ -2630,6 +2630,10 @@ void mysql_stmt_get_longdata(THD *thd, char *packet, ulong packet_length)
stmt->last_errno= ER_OUTOFMEMORY; stmt->last_errno= ER_OUTOFMEMORY;
sprintf(stmt->last_error, ER(ER_OUTOFMEMORY), 0); sprintf(stmt->last_error, ER(ER_OUTOFMEMORY), 0);
} }
out:
/* clear errors, response packet is not expected */
thd->clear_error();
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
} }
......
...@@ -11746,6 +11746,7 @@ static void test_bug5194() ...@@ -11746,6 +11746,7 @@ static void test_bug5194()
rc= mysql_stmt_execute(stmt); rc= mysql_stmt_execute(stmt);
check_execute(stmt, rc); check_execute(stmt, rc);
mysql_stmt_reset(stmt);
} }
mysql_stmt_close(stmt); mysql_stmt_close(stmt);
...@@ -15952,83 +15953,6 @@ static void test_bug27592() ...@@ -15952,83 +15953,6 @@ static void test_bug27592()
DBUG_VOID_RETURN; 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 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[]= { ...@@ -16556,7 +16480,6 @@ static struct my_tests_st my_tests[]= {
{ "test_bug28505", test_bug28505 }, { "test_bug28505", test_bug28505 },
{ "test_bug28934", test_bug28934 }, { "test_bug28934", test_bug28934 },
{ "test_bug27592", test_bug27592 }, { "test_bug27592", test_bug27592 },
/* { "test_bug29948", test_bug29948 }, Bug#35103 */
{ "test_bug29306", test_bug29306 }, { "test_bug29306", test_bug29306 },
{ "test_bug31669", test_bug31669 }, { "test_bug31669", test_bug31669 },
{ "test_bug32265", test_bug32265 }, { "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