diff options
-rw-r--r-- | libmysql/libmysql.c | 11 | ||||
-rw-r--r-- | sql/sql_prepare.cc | 14 | ||||
-rw-r--r-- | sql/sql_select.h | 2 | ||||
-rw-r--r-- | tests/mysql_client_test.c | 68 |
4 files changed, 88 insertions, 7 deletions
diff --git a/libmysql/libmysql.c b/libmysql/libmysql.c index 1176fc5e23a..f09b09314d0 100644 --- a/libmysql/libmysql.c +++ b/libmysql/libmysql.c @@ -2862,6 +2862,17 @@ int STDCALL mysql_stmt_execute(MYSQL_STMT *stmt) mysql->status= MYSQL_STATUS_READY; stmt->read_row_func= stmt_read_row_from_cursor; } + else if (stmt->flags & CURSOR_TYPE_READ_ONLY) + { + /* + This is a single-row result set, a result set with no rows, EXPLAIN, + SHOW VARIABLES, or some other command which either a) bypasses the + cursors framework in the server and writes rows directly to the + network or b) is more efficient if all (few) result set rows are + precached on client and server's resources are freed. + */ + DBUG_RETURN(mysql_stmt_store_result(stmt)); + } else { stmt->mysql->unbuffered_fetch_owner= &stmt->unbuffered_fetch_cancelled; diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc index 1cbc52a2a5a..7e2c37f130e 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -1970,6 +1970,7 @@ void mysql_stmt_execute(THD *thd, char *packet, uint packet_length) { ulong stmt_id= uint4korr(packet); ulong flags= (ulong) ((uchar) packet[4]); + Cursor *cursor= 0; /* Query text for binary log, or empty string if the query is not put into binary log. @@ -2007,15 +2008,17 @@ void mysql_stmt_execute(THD *thd, char *packet, uint packet_length) statement: we can't open a cursor for it. */ flags= 0; + my_error(ER_SP_BAD_CURSOR_QUERY, MYF(0)); + goto err; } else { DBUG_PRINT("info",("Using READ_ONLY cursor")); if (!stmt->cursor && - !(stmt->cursor= new (&stmt->main_mem_root) Cursor())) + !(cursor= stmt->cursor= new (&stmt->main_mem_root) Cursor())) DBUG_VOID_RETURN; /* If lex->result is set, mysql_execute_command will use it */ - stmt->lex->result= &stmt->cursor->result; + stmt->lex->result= &cursor->result; } } #ifndef EMBEDDED_LIBRARY @@ -2061,11 +2064,10 @@ void mysql_stmt_execute(THD *thd, char *packet, uint packet_length) my_pthread_setprio(pthread_self(), WAIT_PRIOR); thd->protocol= &thd->protocol_simple; // Use normal protocol - if (flags & (ulong) CURSOR_TYPE_READ_ONLY) + if (cursor && cursor->is_open()) { - if (stmt->cursor->is_open()) - stmt->cursor->init_from_thd(thd); - stmt->cursor->state= stmt->state; + cursor->init_from_thd(thd); + cursor->state= stmt->state; } else { diff --git a/sql/sql_select.h b/sql/sql_select.h index 353f1fc5157..556d5b3d89b 100644 --- a/sql/sql_select.h +++ b/sql/sql_select.h @@ -370,7 +370,7 @@ public: void close(); void set_unit(SELECT_LEX_UNIT *unit_arg) { unit= unit_arg; } - Cursor() :join(0), unit(0) {} + Cursor() :Item_arena(TRUE), join(0), unit(0) {} ~Cursor(); }; diff --git a/tests/mysql_client_test.c b/tests/mysql_client_test.c index 2e4522f9d02..721ec81e19c 100644 --- a/tests/mysql_client_test.c +++ b/tests/mysql_client_test.c @@ -12782,6 +12782,72 @@ static void test_bug8722() } +MYSQL_STMT *open_cursor(char *query) +{ + int rc; + const ulong type= (ulong)CURSOR_TYPE_READ_ONLY; + + MYSQL_STMT *stmt= mysql_stmt_init(mysql); + rc= mysql_stmt_prepare(stmt, query, strlen(query)); + check_execute(stmt, rc); + + mysql_stmt_attr_set(stmt, STMT_ATTR_CURSOR_TYPE, (void*) &type); + return stmt; +} + + +static void test_bug8880() +{ + MYSQL_STMT *stmt_list[2], **stmt; + MYSQL_STMT **stmt_list_end= (MYSQL_STMT**) stmt_list + 2; + int rc; + + myheader("test_bug8880"); + + mysql_query(mysql, "drop table if exists t1"); + mysql_query(mysql, "create table t1 (a int not null primary key, b int)"); + rc= mysql_query(mysql, "insert into t1 values (1,1)"); + myquery(rc); /* one check is enough */ + /* + when inserting 2 rows everything works well + mysql_query(mysql, "INSERT INTO t1 VALUES (1,1),(2,2)"); + */ + for (stmt= stmt_list; stmt < stmt_list_end; stmt++) + *stmt= open_cursor("select a from t1"); + for (stmt= stmt_list; stmt < stmt_list_end; stmt++) + { + rc= mysql_stmt_execute(*stmt); + check_execute(*stmt, rc); + } + for (stmt= stmt_list; stmt < stmt_list_end; stmt++) + mysql_stmt_close(*stmt); +} + + +static void test_bug9159() +{ + MYSQL_STMT *stmt; + int rc; + const char *stmt_text= "select a, b from t1"; + const unsigned long type= CURSOR_TYPE_READ_ONLY; + + myheader("test_bug9159"); + + mysql_query(mysql, "drop table if exists t1"); + mysql_query(mysql, "create table t1 (a int not null primary key, b int)"); + rc= mysql_query(mysql, "insert into t1 values (1,1)"); + myquery(rc); + + stmt= mysql_stmt_init(mysql); + mysql_stmt_prepare(stmt, stmt_text, strlen(stmt_text)); + mysql_stmt_attr_set(stmt, STMT_ATTR_CURSOR_TYPE, (const void *)&type); + + mysql_stmt_execute(stmt); + mysql_stmt_close(stmt); + rc= mysql_query(mysql, "drop table if exists t1"); + myquery(rc); +} + /* Read and parse arguments and MySQL options from my.cnf */ @@ -13005,6 +13071,8 @@ static struct my_tests_st my_tests[]= { { "test_bug7990", test_bug7990 }, { "test_bug8378", test_bug8378 }, { "test_bug8722", test_bug8722 }, + { "test_bug8880", test_bug8880 }, + { "test_bug9159", test_bug9159 }, { 0, 0 } }; |