Commit fd9f67f8 authored by unknown's avatar unknown

Implement MarkM optimization request to avoid redundnat packet exchange

in cursors.


libmysql/libmysql.c:
  - reset_stmt_handle(): don't reset the server side just because we have 
    an open cursor: the server will close the cursor automatically if 
    needed
sql/sql_prepare.cc:
  - implement Prepared_statement::close_cursor,
  - implicitly close an open cursor in mysql_stmt_execute instead of 
    issuing an error (to reduce the need to explicitly close cursors
    and save network bandwidth).
  - cleanup
sql/sql_select.cc:
  Remove a destructor: cursor destruction can not be done by simply
  calling a destructor, because of cross-references between cursor
  and statement memory.
sql/sql_select.h:
  - add an empty Cursor destructor
tests/mysql_client_test.c:
  - remove a test for dropped functionality
parent 8ba10fa9
...@@ -4907,13 +4907,12 @@ static my_bool reset_stmt_handle(MYSQL_STMT *stmt, uint flags) ...@@ -4907,13 +4907,12 @@ static my_bool reset_stmt_handle(MYSQL_STMT *stmt, uint flags)
{ {
MYSQL *mysql= stmt->mysql; MYSQL *mysql= stmt->mysql;
MYSQL_DATA *result= &stmt->result; MYSQL_DATA *result= &stmt->result;
my_bool has_cursor= stmt->read_row_func == stmt_read_row_from_cursor;
/* /*
Reset stored result set if so was requested or it's a part Reset stored result set if so was requested or it's a part
of cursor fetch. of cursor fetch.
*/ */
if (result->data && (has_cursor || (flags & RESET_STORE_RESULT))) if (result->data && (flags & RESET_STORE_RESULT))
{ {
/* Result buffered */ /* Result buffered */
free_root(&result->alloc, MYF(MY_KEEP_PREALLOC)); free_root(&result->alloc, MYF(MY_KEEP_PREALLOC));
...@@ -4944,7 +4943,7 @@ static my_bool reset_stmt_handle(MYSQL_STMT *stmt, uint flags) ...@@ -4944,7 +4943,7 @@ static my_bool reset_stmt_handle(MYSQL_STMT *stmt, uint flags)
mysql->status= MYSQL_STATUS_READY; mysql->status= MYSQL_STATUS_READY;
} }
} }
if (has_cursor || (flags & RESET_SERVER_SIDE)) if (flags & RESET_SERVER_SIDE)
{ {
/* /*
Reset the server side statement and close the server side Reset the server side statement and close the server side
......
...@@ -106,6 +106,7 @@ class Prepared_statement: public Statement ...@@ -106,6 +106,7 @@ class Prepared_statement: public Statement
virtual ~Prepared_statement(); virtual ~Prepared_statement();
void setup_set_params(); void setup_set_params();
virtual Query_arena::Type type() const; virtual Query_arena::Type type() const;
virtual void close_cursor();
}; };
static void execute_stmt(THD *thd, Prepared_statement *stmt, static void execute_stmt(THD *thd, Prepared_statement *stmt,
...@@ -1986,10 +1987,7 @@ void mysql_stmt_execute(THD *thd, char *packet, uint packet_length) ...@@ -1986,10 +1987,7 @@ void mysql_stmt_execute(THD *thd, char *packet, uint packet_length)
cursor= stmt->cursor; cursor= stmt->cursor;
if (cursor && cursor->is_open()) if (cursor && cursor->is_open())
{ stmt->close_cursor();
my_error(ER_EXEC_STMT_WITH_OPEN_CURSOR, MYF(0));
DBUG_VOID_RETURN;
}
DBUG_ASSERT(thd->free_list == NULL); DBUG_ASSERT(thd->free_list == NULL);
mysql_reset_thd_for_next_command(thd); mysql_reset_thd_for_next_command(thd);
...@@ -2284,6 +2282,7 @@ void mysql_stmt_reset(THD *thd, char *packet) ...@@ -2284,6 +2282,7 @@ void mysql_stmt_reset(THD *thd, char *packet)
if (!(stmt= find_prepared_statement(thd, stmt_id, "mysql_stmt_reset"))) if (!(stmt= find_prepared_statement(thd, stmt_id, "mysql_stmt_reset")))
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
stmt->close_cursor(); /* will reset statement params */
cursor= stmt->cursor; cursor= stmt->cursor;
if (cursor && cursor->is_open()) if (cursor && cursor->is_open())
{ {
...@@ -2295,12 +2294,6 @@ void mysql_stmt_reset(THD *thd, char *packet) ...@@ -2295,12 +2294,6 @@ void mysql_stmt_reset(THD *thd, char *packet)
stmt->state= Query_arena::PREPARED; stmt->state= Query_arena::PREPARED;
/*
Clear parameters from data which could be set by
mysql_stmt_send_long_data() call.
*/
reset_stmt_params(stmt);
mysql_reset_thd_for_next_command(thd); mysql_reset_thd_for_next_command(thd);
send_ok(thd); send_ok(thd);
...@@ -2448,10 +2441,17 @@ void Prepared_statement::setup_set_params() ...@@ -2448,10 +2441,17 @@ void Prepared_statement::setup_set_params()
Prepared_statement::~Prepared_statement() Prepared_statement::~Prepared_statement()
{ {
if (cursor) if (cursor)
{
if (cursor->is_open())
{
cursor->close(FALSE);
free_items();
free_root(cursor->mem_root, MYF(0));
}
cursor->Cursor::~Cursor(); cursor->Cursor::~Cursor();
free_items(); }
if (cursor) else
free_root(cursor->mem_root, MYF(0)); free_items();
delete lex->result; delete lex->result;
} }
...@@ -2460,3 +2460,20 @@ Query_arena::Type Prepared_statement::type() const ...@@ -2460,3 +2460,20 @@ Query_arena::Type Prepared_statement::type() const
{ {
return PREPARED_STATEMENT; return PREPARED_STATEMENT;
} }
void Prepared_statement::close_cursor()
{
if (cursor && cursor->is_open())
{
thd->change_list= cursor->change_list;
cursor->close(FALSE);
cleanup_stmt_and_thd_after_use(this, thd);
free_root(cursor->mem_root, MYF(0));
}
/*
Clear parameters from data which could be set by
mysql_stmt_send_long_data() call.
*/
reset_stmt_params(this);
}
...@@ -1915,12 +1915,6 @@ Cursor::close(bool is_active) ...@@ -1915,12 +1915,6 @@ Cursor::close(bool is_active)
} }
Cursor::~Cursor()
{
if (is_open())
close(FALSE);
}
/*********************************************************************/ /*********************************************************************/
/* /*
......
...@@ -408,7 +408,7 @@ class Cursor: public Sql_alloc, public Query_arena ...@@ -408,7 +408,7 @@ class Cursor: public Sql_alloc, public Query_arena
void set_unit(SELECT_LEX_UNIT *unit_arg) { unit= unit_arg; } void set_unit(SELECT_LEX_UNIT *unit_arg) { unit= unit_arg; }
Cursor(THD *thd); Cursor(THD *thd);
~Cursor(); ~Cursor() {}
}; };
......
...@@ -13050,27 +13050,6 @@ static void test_bug9478() ...@@ -13050,27 +13050,6 @@ static void test_bug9478()
check_execute(stmt, rc); check_execute(stmt, rc);
if (!opt_silent && i == 0) if (!opt_silent && i == 0)
printf("Fetched row: %s\n", a); printf("Fetched row: %s\n", a);
/*
Although protocol-wise an attempt to execute a statement which
already has an open cursor associated with it will yield an error,
the client library behavior tested here is consistent with
the non-cursor execution scenario: mysql_stmt_execute will
silently close the cursor if necessary.
*/
{
char buff[9];
/* Fill in the execute packet */
int4store(buff, stmt->stmt_id);
buff[4]= 0; /* Flag */
int4store(buff+5, 1); /* Reserved for array bind */
rc= ((*mysql->methods->advanced_command)(mysql, COM_STMT_EXECUTE, buff,
sizeof(buff), 0,0,1) ||
(*mysql->methods->read_query_result)(mysql));
DIE_UNLESS(rc);
if (!opt_silent && i == 0)
printf("Got error (as expected): %s\n", mysql_error(mysql));
}
rc= mysql_stmt_execute(stmt); rc= mysql_stmt_execute(stmt);
check_execute(stmt, rc); check_execute(stmt, rc);
...@@ -13429,7 +13408,7 @@ static void test_bug10794() ...@@ -13429,7 +13408,7 @@ static void test_bug10794()
bind[1].length= &a_len; bind[1].length= &a_len;
rc= mysql_stmt_bind_param(stmt, bind); rc= mysql_stmt_bind_param(stmt, bind);
check_execute(stmt, rc); check_execute(stmt, rc);
for (i= 0; i < 34; i++) for (i= 0; i < 42; i++)
{ {
id_val= (i+1)*10; id_val= (i+1)*10;
sprintf(a, "a%d", i); sprintf(a, "a%d", i);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment