summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorunknown <msvensson@neptunus.(none)>2007-01-16 13:39:42 +0100
committerunknown <msvensson@neptunus.(none)>2007-01-16 13:39:42 +0100
commit7b965030418e9460c9f0324cdea0f0decd9686ee (patch)
treec33a821cc43b96773ccb3649535c3122cf5a87b9
parent89d106c1a4efad141e7850373335482ad46aeec5 (diff)
downloadmariadb-git-7b965030418e9460c9f0324cdea0f0decd9686ee.tar.gz
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 - Set stmt->state to MYSQL_STMT_INIT_DONE before closing prepared stmt in server. - 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: 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: Reset the last error every time mysql_stmt_prepare is called. Set state to MYSQL_STMT_INIT_DONE befoe closing it in the server. That way we will always have right status regardless of wheter close fails or not. tests/mysql_client_test.c: 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 so we get printout of line and an error message if it fails.
-rw-r--r--client/mysqltest.c25
-rw-r--r--libmysql/libmysql.c14
-rw-r--r--tests/mysql_client_test.c93
3 files changed, 117 insertions, 15 deletions
diff --git a/client/mysqltest.c b/client/mysqltest.c
index 005f204d571..b163b5887e4 100644
--- a/client/mysqltest.c
+++ b/client/mysqltest.c
@@ -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_command *command)
}
}
#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;
diff --git a/libmysql/libmysql.c b/libmysql/libmysql.c
index 6a592f64e49..a5dcb66f002 100644
--- a/libmysql/libmysql.c
+++ b/libmysql/libmysql.c
@@ -2038,6 +2038,13 @@ mysql_stmt_prepare(MYSQL_STMT *stmt, const char *query, ulong length)
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,23 +2058,24 @@ mysql_stmt_prepare(MYSQL_STMT *stmt, const char *query, ulong length)
*/
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 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.
*/
+ stmt->state= MYSQL_STMT_INIT_DONE;
if (stmt_command(mysql, COM_STMT_CLOSE, buff, 4, stmt))
{
set_stmt_errmsg(stmt, mysql->net.last_error, mysql->net.last_errno,
mysql->net.sqlstate);
DBUG_RETURN(1);
}
- stmt->state= MYSQL_STMT_INIT_DONE;
}
if (stmt_command(mysql, COM_STMT_PREPARE, query, length, stmt))
diff --git a/tests/mysql_client_test.c b/tests/mysql_client_test.c
index aa993230a7f..22aa1e6ef21 100644
--- a/tests/mysql_client_test.c
+++ b/tests/mysql_client_test.c
@@ -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,82 @@ 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);
+
+ /*
+ The prepare of foo should fail with errno 1064 since
+ it's not a valid query
+ */
+ rc= mysql_stmt_prepare(stmt, "foo", 3);
+ if (!opt_silent)
+ fprintf(stdout, "rc: %d, mysql_stmt_errno: %d, mysql_errno: %d\n",
+ rc, mysql_stmt_errno(stmt), mysql_errno(mysql1));
+ DIE_UNLESS(rc && mysql_stmt_errno(stmt) && mysql_errno(mysql1));
+
+ /*
+ Use the same stmt and reprepare with another query that
+ suceeds
+ */
+ rc= mysql_stmt_prepare(stmt, "SHOW STATUS", 12);
+ if (!opt_silent)
+ fprintf(stdout, "rc: %d, mysql_stmt_errno: %d, mysql_errno: %d\n",
+ rc, mysql_stmt_errno(stmt), mysql_errno(mysql1));
+ DIE_UNLESS(!rc || mysql_stmt_errno(stmt) || mysql_errno(mysql1));
+
+ mysql_stmt_close(stmt);
+ DIE_UNLESS(!mysql_errno(mysql1));
+
+ /*
+ part2, when connection to server has been closed
+ after first prepare
+ */
+ stmt= mysql_stmt_init(mysql1);
+ rc= mysql_stmt_prepare(stmt, "foo", 3);
+ if (!opt_silent)
+ fprintf(stdout, "rc: %d, mysql_stmt_errno: %d, mysql_errno: %d\n",
+ rc, mysql_stmt_errno(stmt), mysql_errno(mysql1));
+ DIE_UNLESS(rc && mysql_stmt_errno(stmt) && mysql_errno(mysql1));
+
+ /* Close connection to server */
+ mysql_close(mysql1);
+
+ /*
+ Use the same stmt and reprepare with another query that
+ suceeds. The prepare should fail with error 2013 since
+ connection to server has been closed.
+ */
+ rc= mysql_stmt_prepare(stmt, "SHOW STATUS", 12);
+ if (!opt_silent)
+ fprintf(stdout, "rc: %d, mysql_stmt_errno: %d\n",
+ rc, mysql_stmt_errno(stmt));
+ DIE_UNLESS(rc && mysql_stmt_errno(stmt));
+
+ mysql_stmt_close(stmt);
+ DIE_UNLESS(mysql_errno(mysql1));
+}
+
static void test_view_sp_list_fields()
{
@@ -15009,7 +15085,7 @@ static void test_bug17667()
}
else
{
- assert(0==1);
+ DIE_UNLESS(0==1);
}
}
@@ -15588,6 +15664,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 }
};