MySQL Lists are EOL. Please join:

List:Commits« Previous MessageNext Message »
From:msvensson Date:February 10 2006 1:50pm
Subject:bk commit into 5.0 tree (msvensson:1.2020) BUG#14013
View as plain text  
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
  1.2020 06/02/10 14:50:29 msvensson@neptunus.(none) +3 -0
  Bug#14013 mysql_stmt_store_result() bombs if a cursor is open
   - Add code to 'mysql_stmt_store_result' to allow it to be called on 
     a prepared statement with open server side cursor.
   - Add tests to mysql_client_test that uses 'mysql_stmt_store_result'

  tests/mysql_client_test.c
    1.168 06/02/10 14:50:25 msvensson@neptunus.(none) +17 -3
    Update 'fetch_n' function to take parameter indicating if 'mysql_stmt_store_result' should be used on the statement.
    Call fetch_n with parameter set to use 'mysql_stmt_store_result'

  libmysql/libmysql.c
    1.231 06/02/10 14:50:25 msvensson@neptunus.(none) +33 -2
    Allow 'mysql_stmt_store_result' to be called on a statement with an open server side cursor.
    Detect that a server side cursor is open and send a "fetch" to ask for all rows to be sent to the client.
    Read all binary rows as normal store.
    Check that server said last row was sent after all binary rows has been sent. 

  client/mysqltest.c
    1.198 06/02/10 14:50:25 msvensson@neptunus.(none) +23 -17
    Enable cursor protocol(remove the ifdef BUG14013_FIXED)
    When running in cursor mode, the warnings from execute needs 
    to be extracted after mysql_stmt_execute, put them in a dynamic string 
    for later use.
    Untabify some tabs.

# 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/bug14013/my50-bug14013

--- 1.230/libmysql/libmysql.c	2005-08-04 13:25:02 +02:00
+++ 1.231/libmysql/libmysql.c	2006-02-10 14:50:25 +01:00
@@ -4757,12 +4757,39 @@
 
   if (!stmt->field_count)
     DBUG_RETURN(0);
-  if ((int) stmt->state < (int) MYSQL_STMT_EXECUTE_DONE ||
-      mysql->status != MYSQL_STATUS_GET_RESULT)
+
+  if ((int) stmt->state < (int) MYSQL_STMT_EXECUTE_DONE)
+  {
+    set_stmt_error(stmt, CR_COMMANDS_OUT_OF_SYNC, unknown_sqlstate);
+    DBUG_RETURN(1);
+  }
+
+  if (mysql->status == MYSQL_STATUS_READY &&
+      stmt->server_status & SERVER_STATUS_CURSOR_EXISTS)
+  {
+    /*
+      Server side cursor exist, tell server to start sending the rows
+    */
+    NET *net= &mysql->net;
+    char buff[4 /* statement id */ +
+              4 /* number of rows to fetch */];
+
+    /* Send row request to the server */
+    int4store(buff, stmt->stmt_id);
+    int4store(buff + 4, (int)~0); /* number of rows to fetch */
+    if (cli_advanced_command(mysql, COM_STMT_FETCH, buff, sizeof(buff),
+                             NullS, 0, 1))
+    {
+      set_stmt_errmsg(stmt, net->last_error, net->last_errno, net->sqlstate);
+      DBUG_RETURN(1);
+    }
+  }
+  else if (mysql->status != MYSQL_STATUS_GET_RESULT)
   {
     set_stmt_error(stmt, CR_COMMANDS_OUT_OF_SYNC, unknown_sqlstate);
     DBUG_RETURN(1);
   }
+
   if (result->data)
   {
     free_root(&result->alloc, MYF(MY_KEEP_PREALLOC));
@@ -4802,6 +4829,10 @@
     mysql->status= MYSQL_STATUS_READY;
     DBUG_RETURN(1);
   }
+
+  /* Assert that if there was a cursor, all rows have been fetched */
+  DBUG_ASSERT(mysql->status != MYSQL_STATUS_READY ||
+              (mysql->server_status & SERVER_STATUS_LAST_ROW_SENT));
 
   if (stmt->update_max_length)
   {

--- 1.197/client/mysqltest.c	2006-02-01 11:36:27 +01:00
+++ 1.198/client/mysqltest.c	2006-02-10 14:50:25 +01:00
@@ -3167,7 +3167,7 @@
 
   if (mysql_stmt_fetch(stmt) != MYSQL_NO_DATA)
     die("fetch didn't end with MYSQL_NO_DATA from statement: %d %s",
-	mysql_stmt_error(stmt), mysql_stmt_errno(stmt));
+	mysql_stmt_errno(stmt), mysql_stmt_error(stmt));
 
   free_replace_column();
 
@@ -3632,7 +3632,7 @@
   if (mysql_stmt_prepare(stmt, query, query_len))
   {
     handle_error(query, command,  mysql_stmt_errno(stmt),
-		 mysql_stmt_error(stmt), mysql_stmt_sqlstate(stmt), ds);
+                 mysql_stmt_error(stmt), mysql_stmt_sqlstate(stmt), ds);
     goto end;
   }
 
@@ -3648,30 +3648,35 @@
     parameter markers.
   */
 
-#ifdef BUG14013_FIXED
-  /*
-    Use cursor when retrieving result
-  */
   if (cursor_protocol_enabled)
   {
+    /*
+      Use cursor when retrieving result
+    */
     ulong type= CURSOR_TYPE_READ_ONLY;
     if (mysql_stmt_attr_set(stmt, STMT_ATTR_CURSOR_TYPE, (void*) &type))
       die("mysql_stmt_attr_set(STMT_ATTR_CURSOR_TYPE) failed': %d %s",
-	  mysql_stmt_errno(stmt), mysql_stmt_error(stmt));
+          mysql_stmt_errno(stmt), mysql_stmt_error(stmt));
   }
-#endif
 
   /*
     Execute the query
-   */
+  */
   if (mysql_stmt_execute(stmt))
   {
     handle_error(query, command, mysql_stmt_errno(stmt),
-		 mysql_stmt_error(stmt), mysql_stmt_sqlstate(stmt), ds);
+                 mysql_stmt_error(stmt), mysql_stmt_sqlstate(stmt), ds);
     goto end;
   }
 
   /*
+    When running in cursor_protocol get the warnings from execute here
+    and keep them in a separate string for later.
+  */
+  if (cursor_protocol_enabled && !disable_warnings)
+    append_warnings(&ds_execute_warnings, mysql);
+
+  /*
     We instruct that we want to update the "max_length" field in
      mysql_stmt_store_result(), this is our only way to know how much
      buffer to allocate for result data
@@ -3680,7 +3685,7 @@
     my_bool one= 1;
     if (mysql_stmt_attr_set(stmt, STMT_ATTR_UPDATE_MAX_LENGTH, (void*) &one))
       die("mysql_stmt_attr_set(STMT_ATTR_UPDATE_MAX_LENGTH) failed': %d %s",
-	  mysql_stmt_errno(stmt), mysql_stmt_error(stmt));
+          mysql_stmt_errno(stmt), mysql_stmt_error(stmt));
   }
 
   /*
@@ -3690,7 +3695,7 @@
   if (mysql_stmt_store_result(stmt))
   {
     handle_error(query, command, mysql_stmt_errno(stmt),
-		 mysql_stmt_error(stmt), mysql_stmt_sqlstate(stmt), ds);
+                 mysql_stmt_error(stmt), mysql_stmt_sqlstate(stmt), ds);
     goto end;
   }
 
@@ -3711,10 +3716,10 @@
       uint num_fields= mysql_num_fields(res);
 
       if (display_metadata)
-	append_metadata(ds, fields, num_fields);
+        append_metadata(ds, fields, num_fields);
 
       if (!display_result_vertically)
-	append_table_headings(ds, fields, num_fields);
+        append_table_headings(ds, fields, num_fields);
 
       append_stmt_result(ds, stmt, fields, num_fields);
 
@@ -3736,10 +3741,11 @@
 
       /* Append warnings to ds - if there are any */
       if (append_warnings(&ds_execute_warnings, mysql) ||
-	  ds_prepare_warnings.length ||
-	  ds_warnings->length)
+          ds_execute_warnings.length ||
+          ds_prepare_warnings.length ||
+          ds_warnings->length)
       {
-	dynstr_append_mem(ds, "Warnings:\n", 10);
+        dynstr_append_mem(ds, "Warnings:\n", 10);
 	if (ds_warnings->length)
 	  dynstr_append_mem(ds, ds_warnings->str,
 			    ds_warnings->length);

--- 1.167/tests/mysql_client_test.c	2005-12-08 07:55:54 +01:00
+++ 1.168/tests/mysql_client_test.c	2006-02-10 14:50:25 +01:00
@@ -1049,7 +1049,10 @@
   reading from the rest.
 */
 
-my_bool fetch_n(const char **query_list, unsigned query_count)
+enum fetch_type { USE_ROW_BY_ROW_FETCH= 0, USE_STORE_RESULT= 1 };
+
+my_bool fetch_n(const char **query_list, unsigned query_count,
+                enum fetch_type fetch_type)
 {
   unsigned open_statements= query_count;
   int rc, error_count= 0;
@@ -1065,6 +1068,15 @@
                     query_list[fetch - fetch_array]);
   }
 
+  if (fetch_type == USE_STORE_RESULT)
+  {
+    for (fetch= fetch_array; fetch < fetch_array + query_count; ++fetch)
+    {
+      rc= mysql_stmt_store_result(fetch->handle);
+      check_execute(fetch->handle, rc);
+    }
+  }
+
   while (open_statements)
   {
     for (fetch= fetch_array; fetch < fetch_array + query_count; ++fetch)
@@ -11867,7 +11879,8 @@
 
   fill_tables(basic_tables, sizeof(basic_tables)/sizeof(*basic_tables));
 
-  fetch_n(queries, sizeof(queries)/sizeof(*queries));
+  fetch_n(queries, sizeof(queries)/sizeof(*queries), USE_ROW_BY_ROW_FETCH);
+  fetch_n(queries, sizeof(queries)/sizeof(*queries), USE_STORE_RESULT);
   DBUG_VOID_RETURN;
 }
 
@@ -11880,7 +11893,8 @@
     "SELECT t1.id FROM t1 WHERE t1.id < 5"
   };
   myheader("test_cursors_with_union");
-  fetch_n(queries, sizeof(queries)/sizeof(*queries));
+  fetch_n(queries, sizeof(queries)/sizeof(*queries), USE_ROW_BY_ROW_FETCH);
+  fetch_n(queries, sizeof(queries)/sizeof(*queries), USE_STORE_RESULT);
 }
 
 /*
Thread
bk commit into 5.0 tree (msvensson:1.2020) BUG#14013msvensson10 Feb