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, 2007-01-16 13:39:42+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
- 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@stripped, 2007-01-16 13:39:38+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, 2007-01-16 13:39:39+01:00, msvensson@neptunus.(none) +11 -3
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@stripped, 2007-01-16 13:39:39+01:00, msvensson@neptunus.(none)
+85 -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 so 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 2007-01-16 13:39:47 +01:00
+++ 1.251/libmysql/libmysql.c 2007-01-16 13:39:47 +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,23 +2058,24 @@ 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 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))
--- 1.261/client/mysqltest.c 2007-01-16 13:39:47 +01:00
+++ 1.262/client/mysqltest.c 2007-01-16 13:39:47 +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 2007-01-16 13:39:47 +01:00
+++ 1.214/tests/mysql_client_test.c 2007-01-16 13:39:47 +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,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 }
};
| Thread |
|---|
| • bk commit into 5.0 tree (msvensson:1.2352) BUG#15518 | msvensson | 16 Jan |