summaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
authorunknown <kostja@bodhi.(none)>2008-05-20 20:36:26 +0400
committerunknown <kostja@bodhi.(none)>2008-05-20 20:36:26 +0400
commit02c901ee5eea72ad0b366066027ba5c6a2438258 (patch)
treed253d230a92a5e5b0cd4824c58c4baef794fb3b0 /tests
parent4175806efca7644c41ab77e5a8f07d1cc5a1ac00 (diff)
downloadmariadb-git-02c901ee5eea72ad0b366066027ba5c6a2438258.tar.gz
Bug#27430 "Crash in subquery code when in PS and table DDL changed after
PREPARE", review fixes: - make the patch follow the specification of WL#4166 and remove the new error that was originally introduced. Now the client never gets an error from reprepare, unless it failed. I.e. even if the statement at hand returns a completely different result set, this is not considered a server error. The C API library, that can not handle this situation, was modified to return a client error. Added additional test coverage. include/errmsg.h: Add a new client side error: now when we automatically reprepare a statement, the new result set may contain a different number of columns. include/mysql_com.h: Add a new server status to be sent to the client if the number of columns in the result set is different. libmysql/errmsg.c: Add a new error message. libmysql/libmysql.c: Make the client library robust against a result set that contains a different number of columns from prepare time. Previously that could never happen, and we simply had an assert. That means in particular that all clients are advised to upgrade with transition to 5.1, if they are using prepared statements C API. Make mysql_stmt_store_result() and mysql_stmt_execute() robust against "broken" statement handles (those that have an error). sql/sql_parse.cc: Clear transient server status flags at start of statement more systematically. sql/share/errmsg.txt: Remove an error that is unused and is not part of any public release. sql/sql_prepare.cc: Instead of returning an error in case the number of result set columns has changed, simply update the client in server status. That will allow modern clients automatically recover from an error. tests/mysql_client_test.c: Add additional coverage to the cases when the number of result set columns changed as a result of reprepare. Cover conversion and truncation of result set columns.
Diffstat (limited to 'tests')
-rw-r--r--tests/mysql_client_test.c107
1 files changed, 101 insertions, 6 deletions
diff --git a/tests/mysql_client_test.c b/tests/mysql_client_test.c
index 350c14926cd..cda7c75ba14 100644
--- a/tests/mysql_client_test.c
+++ b/tests/mysql_client_test.c
@@ -6668,10 +6668,10 @@ static void test_pure_coverage()
check_execute_r(stmt, rc); /* unsupported buffer type */
rc= mysql_stmt_store_result(stmt);
- check_execute(stmt, rc);
+ DIE_UNLESS(rc);
rc= mysql_stmt_store_result(stmt);
- check_execute_r(stmt, rc); /* commands out of sync */
+ DIE_UNLESS(rc); /* Old error must be reset first */
mysql_stmt_close(stmt);
@@ -8423,6 +8423,9 @@ static void test_fetch_offset()
rc= mysql_stmt_fetch_column(stmt, my_bind, 0, 0);
check_execute_r(stmt, rc);
+ rc= mysql_stmt_execute(stmt);
+ check_execute(stmt, rc);
+
rc= mysql_stmt_bind_result(stmt, my_bind);
check_execute(stmt, rc);
@@ -9901,7 +9904,7 @@ static void test_rename()
MYSQL_STMT *stmt;
const char *query= "rename table t1 to t2, t3 to t4";
int rc;
- myheader("test_table_manipulation");
+ myheader("test_table_rename");
rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1, t2, t3, t4");
myquery(rc);
@@ -17383,7 +17386,7 @@ static void test_bug28386()
DBUG_VOID_RETURN;
}
-static void test_wl4166()
+static void test_wl4166_1()
{
MYSQL_STMT *stmt;
int int_data;
@@ -17399,7 +17402,7 @@ static void test_wl4166()
int rc;
int i;
- myheader("test_wl4166");
+ myheader("test_wl4166_1");
rc= mysql_query(mysql, "DROP TABLE IF EXISTS table_4166");
myquery(rc);
@@ -17498,6 +17501,97 @@ static void test_wl4166()
rc= mysql_query(mysql, "DROP TABLE table_4166");
myquery(rc);
+}
+
+
+static void test_wl4166_2()
+{
+ MYSQL_STMT *stmt;
+ int c_int;
+ MYSQL_TIME d_date;
+ MYSQL_BIND bind_out[2];
+ int rc;
+ int i;
+
+ myheader("test_wl4166_2");
+
+ rc= mysql_query(mysql, "drop table if exists t1");
+ myquery(rc);
+ rc= mysql_query(mysql, "create table t1 (c_int int, d_date date)");
+ myquery(rc);
+ rc= mysql_query(mysql,
+ "insert into t1 (c_int, d_date) values (42, '1948-05-15')");
+ myquery(rc);
+
+ stmt= mysql_simple_prepare(mysql, "select * from t1");
+ check_stmt(stmt);
+
+ bzero(bind_out, sizeof(bind_out));
+ bind_out[0].buffer_type= MYSQL_TYPE_LONG;
+ bind_out[0].buffer= (void*) &c_int;
+
+ bind_out[1].buffer_type= MYSQL_TYPE_DATE;
+ bind_out[1].buffer= (void*) &d_date;
+
+ rc= mysql_stmt_bind_result(stmt, bind_out);
+ check_execute(stmt, rc);
+
+ /* int -> varchar transition */
+
+ rc= mysql_query(mysql,
+ "alter table t1 change column c_int c_int varchar(11)");
+ myquery(rc);
+
+ rc= mysql_stmt_execute(stmt);
+ check_execute(stmt, rc);
+
+ rc= mysql_stmt_fetch(stmt);
+ check_execute(stmt, rc);
+
+ DIE_UNLESS(c_int == 42);
+ DIE_UNLESS(d_date.year == 1948);
+ DIE_UNLESS(d_date.month == 5);
+ DIE_UNLESS(d_date.day == 15);
+
+ rc= mysql_stmt_fetch(stmt);
+ DIE_UNLESS(rc == MYSQL_NO_DATA);
+
+ /* varchar to int retrieval with truncation */
+
+ rc= mysql_query(mysql, "update t1 set c_int='abcde'");
+ myquery(rc);
+
+ rc= mysql_stmt_execute(stmt);
+ check_execute(stmt, rc);
+
+ rc= mysql_stmt_fetch(stmt);
+ check_execute_r(stmt, rc);
+
+ DIE_UNLESS(c_int == 0);
+
+ rc= mysql_stmt_fetch(stmt);
+ DIE_UNLESS(rc == MYSQL_NO_DATA);
+
+ /* alter table and increase the number of columns */
+ rc= mysql_query(mysql, "alter table t1 add column d_int int");
+ myquery(rc);
+
+ rc= mysql_stmt_execute(stmt);
+ check_execute_r(stmt, rc);
+
+ rc= mysql_stmt_reset(stmt);
+ check_execute(stmt, rc);
+
+ /* decrease the number of columns */
+ rc= mysql_query(mysql, "alter table t1 drop d_date, drop d_int");
+ myquery(rc);
+
+ rc= mysql_stmt_execute(stmt);
+ check_execute_r(stmt, rc);
+
+ mysql_stmt_close(stmt);
+ rc= mysql_query(mysql, "drop table t1");
+ myquery(rc);
}
@@ -17807,7 +17901,8 @@ static struct my_tests_st my_tests[]= {
{ "test_bug31418", test_bug31418 },
{ "test_bug31669", test_bug31669 },
{ "test_bug28386", test_bug28386 },
- { "test_wl4166", test_wl4166 },
+ { "test_wl4166_1", test_wl4166_1 },
+ { "test_wl4166_2", test_wl4166_2 },
{ 0, 0 }
};