Below is the list of changes that have just been committed into a local
5.0 repository of msvensson. When msvensson does a push these changes will
be propagated to the main repository and, within 24 hours after the
push, to the public repository.
For information on how to access the public repository
see http://dev.mysql.com/doc/mysql/en/installing-source-tree.html
ChangeSet@stripped, 2006-12-01 14:58:25+01:00, msvensson@neptunus.(none) +3 -0
Bug#15518 Reusing a stmt that has failed during prepare does not clear error
- Always reset error when calling mysql_stmt_prepare a second time
- Don't sned COM_STMT_CLOSE to server it conection has been lost.
- Add test to mysql_client_test
- Remove mysql_stmt_close in mysqltest after each query
- Close all open statements in mysqltest if disable_ps_protocol is called.
client/mysqltest.c@stripped, 2006-12-01 14:58:22+01:00, msvensson@neptunus.(none) +21 -4
Don't close the statement after each query - reprepare it in next query.
When "disable_ps_protocol" is issued make sure to close all open
statements. Otherwise the test for @@max_prepared_statements fails. But we
also get a test that the statements that are open can be closed and reopened
in the middle of the tests.
libmysql/libmysql.c@stripped, 2006-12-01 14:58:22+01:00, msvensson@neptunus.(none) +11 -3
Reset the last error every time mysql_stmt_prepare is called.
Don't send COM_STMT_CLOSE to the server if connection has been
lost - that will just trigger a reconnect and since the statement
has been automatically closed in the server an error will
be returned.
tests/mysql_client_test.c@stripped, 2006-12-01 14:58:22+01:00, msvensson@neptunus.(none)
+60 -8
Add testcase for bug15518, re-prepare a previously prepare statement that has failed
to prepare. Test also when connection to server has been lost inbetween.
Change all assert to DIE_UNLESS wo we get printout of line and an error message
if it fails.
# This is a BitKeeper patch. What follows are the unified diffs for the
# set of deltas contained in the patch. The rest of the patch, the part
# that BitKeeper cares about, is below these diffs.
# User: msvensson
# Host: neptunus.(none)
# Root: /home/msvensson/mysql/bug15518/my50-bug15518
--- 1.250/libmysql/libmysql.c 2006-12-01 14:58:32 +01:00
+++ 1.251/libmysql/libmysql.c 2006-12-01 14:58:32 +01:00
@@ -2038,6 +2038,13 @@ mysql_stmt_prepare(MYSQL_STMT *stmt, con
DBUG_RETURN(1);
}
+ /*
+ Reset the last error in any case: that would clear the statement
+ if the previous prepare failed.
+ */
+ stmt->last_errno= 0;
+ stmt->last_error[0]= '\0';
+
if ((int) stmt->state > (int) MYSQL_STMT_INIT_DONE)
{
/* This is second prepare with another statement */
@@ -2051,17 +2058,18 @@ mysql_stmt_prepare(MYSQL_STMT *stmt, con
*/
stmt->bind_param_done= stmt->bind_result_done= FALSE;
stmt->param_count= stmt->field_count= 0;
- stmt->last_errno= 0;
- stmt->last_error[0]= '\0';
free_root(&stmt->mem_root, MYF(MY_KEEP_PREALLOC));
int4store(buff, stmt->stmt_id);
+
/*
+ Close statement in server if still connected
+
If there was a 'use' result from another statement, or from
mysql_use_result it won't be freed in mysql_stmt_free_result and
we should get 'Commands out of sync' here.
*/
- if (stmt_command(mysql, COM_STMT_CLOSE, buff, 4, stmt))
+ if (mysql->net.vio && stmt_command(mysql, COM_STMT_CLOSE, buff, 4, stmt))
{
set_stmt_errmsg(stmt, mysql->net.last_error, mysql->net.last_errno,
mysql->net.sqlstate);
--- 1.261/client/mysqltest.c 2006-12-01 14:58:32 +01:00
+++ 1.262/client/mysqltest.c 2006-12-01 14:58:32 +01:00
@@ -719,6 +719,20 @@ void close_connections()
}
+void close_statements()
+{
+ struct st_connection *con;
+ DBUG_ENTER("close_statements");
+ for (con= connections; con < next_con; con++)
+ {
+ if (con->stmt)
+ mysql_stmt_close(con->stmt);
+ con->stmt= 0;
+ }
+ DBUG_VOID_RETURN;
+}
+
+
void close_files()
{
DBUG_ENTER("close_files");
@@ -2855,6 +2869,10 @@ void do_close_connection(struct st_comma
}
}
#endif
+ if (next_con->stmt)
+ mysql_stmt_close(next_con->stmt);
+ next_con->stmt= 0;
+
mysql_close(&con->mysql);
if (con->util_mysql)
mysql_close(con->util_mysql);
@@ -5050,10 +5068,7 @@ end:
*/
var_set_errno(mysql_stmt_errno(stmt));
-#ifndef BUG15518_FIXED
- mysql_stmt_close(stmt);
- cur_con->stmt= NULL;
-#endif
+
DBUG_VOID_RETURN;
}
@@ -5838,6 +5853,8 @@ int main(int argc, char **argv)
break;
case Q_DISABLE_PS_PROTOCOL:
ps_protocol_enabled= 0;
+ /* Close any open statements */
+ close_statements();
break;
case Q_ENABLE_PS_PROTOCOL:
ps_protocol_enabled= ps_protocol;
--- 1.213/tests/mysql_client_test.c 2006-12-01 14:58:32 +01:00
+++ 1.214/tests/mysql_client_test.c 2006-12-01 14:58:32 +01:00
@@ -11014,7 +11014,7 @@ static void test_view()
rc= mysql_stmt_execute(stmt);
check_execute(stmt, rc);
rc= my_process_stmt_result(stmt);
- assert(1 == rc);
+ DIE_UNLESS(1 == rc);
}
mysql_stmt_close(stmt);
@@ -11057,7 +11057,7 @@ static void test_view_where()
rc= mysql_stmt_execute(stmt);
check_execute(stmt, rc);
rc= my_process_stmt_result(stmt);
- assert(4 == rc);
+ DIE_UNLESS(4 == rc);
}
mysql_stmt_close(stmt);
@@ -11140,7 +11140,7 @@ static void test_view_2where()
rc= mysql_stmt_execute(stmt);
check_execute(stmt, rc);
rc= my_process_stmt_result(stmt);
- assert(0 == rc);
+ DIE_UNLESS(0 == rc);
mysql_stmt_close(stmt);
@@ -11193,7 +11193,7 @@ static void test_view_star()
rc= mysql_stmt_execute(stmt);
check_execute(stmt, rc);
rc= my_process_stmt_result(stmt);
- assert(0 == rc);
+ DIE_UNLESS(0 == rc);
}
mysql_stmt_close(stmt);
@@ -11256,7 +11256,7 @@ static void test_view_insert()
rc= mysql_stmt_execute(select_stmt);
check_execute(select_stmt, rc);
rowcount= (int)my_process_stmt_result(select_stmt);
- assert((i+1) == rowcount);
+ DIE_UNLESS((i+1) == rowcount);
}
mysql_stmt_close(insert_stmt);
mysql_stmt_close(select_stmt);
@@ -11297,7 +11297,7 @@ static void test_left_join_view()
rc= mysql_stmt_execute(stmt);
check_execute(stmt, rc);
rc= my_process_stmt_result(stmt);
- assert(3 == rc);
+ DIE_UNLESS(3 == rc);
}
mysql_stmt_close(stmt);
@@ -11373,7 +11373,7 @@ static void test_view_insert_fields()
rc= mysql_stmt_execute(stmt);
check_execute(stmt, rc);
rc= my_process_stmt_result(stmt);
- assert(1 == rc);
+ DIE_UNLESS(1 == rc);
mysql_stmt_close(stmt);
rc= mysql_query(mysql, "DROP VIEW v1");
@@ -12851,6 +12851,57 @@ static void test_bug7990()
DIE_UNLESS(!mysql_errno(mysql));
}
+/*
+ Bug #15518 - Reusing a stmt that has failed during prepare
+ does not clear error
+*/
+
+static void test_bug15518()
+{
+ MYSQL_STMT *stmt;
+ MYSQL* mysql1;
+ int rc;
+ myheader("test_bug15518");
+
+ mysql1= mysql_init(NULL);
+
+ if (!mysql_real_connect(mysql1, opt_host, opt_user, opt_password,
+ opt_db ? opt_db : "test", opt_port, opt_unix_socket,
+ CLIENT_MULTI_STATEMENTS))
+ {
+ fprintf(stderr, "Failed to connect to the database\n");
+ DIE_UNLESS(0);
+ }
+
+ stmt= mysql_stmt_init(mysql1);
+ rc= mysql_stmt_prepare(stmt, "foo", 3);
+ DIE_UNLESS(rc && mysql_stmt_errno(stmt) && mysql_errno(mysql1));
+
+ /* Use the same stmt and prepare another query */
+ rc= mysql_stmt_prepare(stmt, "foo2", 4);
+ DIE_UNLESS(rc && mysql_stmt_errno(stmt) && mysql_errno(mysql1));
+
+ mysql_stmt_close(stmt);
+ DIE_UNLESS(!mysql_errno(mysql1));
+
+ /*
+ part2, when connection to server is closed
+ */
+ stmt= mysql_stmt_init(mysql1);
+ rc= mysql_stmt_prepare(stmt, "foo", 3);
+ DIE_UNLESS(rc && mysql_stmt_errno(stmt) && mysql_errno(mysql1));
+
+ /* Close connection to server */
+ mysql_close(mysql1);
+
+ /* Use the same stmt and prepare another query */
+ rc= mysql_stmt_prepare(stmt, "foo2", 4);
+ DIE_UNLESS(rc && mysql_stmt_errno(stmt) && mysql_errno(mysql1));
+
+ mysql_stmt_close(stmt);
+ DIE_UNLESS(mysql_errno(mysql1));
+}
+
static void test_view_sp_list_fields()
{
@@ -15009,7 +15060,7 @@ static void test_bug17667()
}
else
{
- assert(0==1);
+ DIE_UNLESS(0==1);
}
}
@@ -15588,6 +15639,7 @@ static struct my_tests_st my_tests[]= {
{ "test_bug15752", test_bug15752 },
{ "test_bug21206", test_bug21206 },
{ "test_bug21726", test_bug21726 },
+ { "test_bug15518", test_bug15518 },
{ 0, 0 }
};
| Thread |
|---|
| • bk commit into 5.0 tree (msvensson:1.2352) BUG#15518 | msvensson | 1 Dec |