summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libmysql/libmysql.c11
-rw-r--r--sql/sql_prepare.cc14
-rw-r--r--sql/sql_select.h2
-rw-r--r--tests/mysql_client_test.c68
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 }
};