"Fossies" - the Fresh Open Source Software Archive

Member "mariadb-connector-c-3.0.8-src/unittest/libmariadb/cursor.c" (18 Dec 2018, 56335 Bytes) of package /linux/misc/mariadb-connector-c-3.0.8-src.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. See also the last Fossies "Diffs" side-by-side code changes report for "cursor.c": 3.0.2-src_vs_3.0.3-src.

    1 /*
    2 Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
    3 
    4 The MySQL Connector/C is licensed under the terms of the GPLv2
    5 <http://www.gnu.org/licenses/old-licenses/gpl-2.0.html>, like most
    6 MySQL Connectors. There are special exceptions to the terms and
    7 conditions of the GPLv2 as it is applied to this software, see the
    8 FLOSS License Exception
    9 <http://www.mysql.com/about/legal/licensing/foss-exception.html>.
   10 
   11 This program is free software; you can redistribute it and/or modify
   12 it under the terms of the GNU General Public License as published
   13 by the Free Software Foundation; version 2 of the License.
   14 
   15 This program is distributed in the hope that it will be useful, but
   16 WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
   17 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
   18 for more details.
   19 
   20 You should have received a copy of the GNU General Public License along
   21 with this program; if not, write to the Free Software Foundation, Inc.,
   22 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA
   23 */
   24 #include "my_test.h"
   25 
   26 /* helper functions */
   27 enum { MAX_COLUMN_LENGTH= 255 };
   28 
   29 typedef struct st_stmt_fetch
   30 {
   31   const char *query;
   32   unsigned stmt_no;
   33   MYSQL_STMT *handle;
   34   my_bool is_open;
   35   MYSQL_BIND *bind_array;
   36   char **out_data;
   37   unsigned long *out_data_length;
   38   unsigned column_count;
   39   unsigned row_count;
   40 } Stmt_fetch;
   41 
   42 MYSQL_STMT *open_cursor(MYSQL *mysql, const char *query)
   43 {
   44   int rc;
   45   const ulong type= (ulong)CURSOR_TYPE_READ_ONLY;
   46 
   47   MYSQL_STMT *stmt= mysql_stmt_init(mysql);
   48   rc= mysql_stmt_prepare(stmt, SL(query));
   49   if (rc) {
   50     diag("Error: %s", mysql_stmt_error(stmt));
   51     return NULL;
   52   }
   53   mysql_stmt_attr_set(stmt, STMT_ATTR_CURSOR_TYPE, (void*) &type);
   54   return stmt;
   55 }
   56 
   57 /*
   58   Create statement handle, prepare it with statement, execute and allocate
   59   fetch buffers.
   60 */
   61 
   62 int stmt_fetch_init(MYSQL *mysql, Stmt_fetch *fetch, unsigned int stmt_no_arg,
   63                      const char *query_arg)
   64 {
   65   unsigned long type= CURSOR_TYPE_READ_ONLY;
   66   int rc;
   67   unsigned int i;
   68   MYSQL_RES *metadata;
   69 
   70   /* Save query and statement number for error messages */
   71   fetch->stmt_no= stmt_no_arg;
   72   fetch->query= query_arg;
   73 
   74   fetch->handle= mysql_stmt_init(mysql);
   75 
   76   rc= mysql_stmt_prepare(fetch->handle, SL(fetch->query));
   77   FAIL_IF(rc, mysql_stmt_error(fetch->handle));
   78 
   79   /*
   80     The attribute is sent to server on execute and asks to open read-only
   81     for result set
   82   */
   83   mysql_stmt_attr_set(fetch->handle, STMT_ATTR_CURSOR_TYPE,
   84                       (const void*) &type);
   85 
   86   rc= mysql_stmt_execute(fetch->handle);
   87   FAIL_IF(rc, mysql_stmt_error(fetch->handle));
   88 
   89   /* Find out total number of columns in result set */
   90   metadata= mysql_stmt_result_metadata(fetch->handle);
   91   fetch->column_count= mysql_num_fields(metadata);
   92   mysql_free_result(metadata);
   93 
   94   /*
   95     Now allocate bind handles and buffers for output data:
   96     calloc memory to reduce number of MYSQL_BIND members we need to
   97     set up.
   98   */
   99 
  100   fetch->bind_array= (MYSQL_BIND *) calloc(1, sizeof(MYSQL_BIND) *
  101                                               fetch->column_count);
  102   fetch->out_data= (char**) calloc(1, sizeof(char*) * fetch->column_count);
  103   fetch->out_data_length= (ulong*) calloc(1, sizeof(ulong) *
  104                                              fetch->column_count);
  105   for (i= 0; i < fetch->column_count; ++i)
  106   {
  107     fetch->out_data[i]= (char*) calloc(1, MAX_COLUMN_LENGTH);
  108     fetch->bind_array[i].buffer_type= MYSQL_TYPE_STRING;
  109     fetch->bind_array[i].buffer= fetch->out_data[i];
  110     fetch->bind_array[i].buffer_length= MAX_COLUMN_LENGTH;
  111     fetch->bind_array[i].length= fetch->out_data_length + i;
  112   }
  113 
  114   mysql_stmt_bind_result(fetch->handle, fetch->bind_array);
  115 
  116   fetch->row_count= 0;
  117   fetch->is_open= TRUE;
  118 
  119   /* Ready for reading rows */
  120   return OK;
  121 }
  122 
  123 
  124 int fill_tables(MYSQL *mysql, const char **query_list, unsigned query_count)
  125 {
  126   int rc;
  127   const char **query;
  128   for (query= query_list; query < query_list + query_count;
  129        ++query)
  130   {
  131     rc= mysql_query(mysql, *query);
  132     check_mysql_rc(rc, mysql);
  133   }
  134   return OK;
  135 }
  136 
  137 int stmt_fetch_fetch_row(Stmt_fetch *fetch)
  138 {
  139   int rc;
  140   unsigned i;
  141 
  142   if ((rc= mysql_stmt_fetch(fetch->handle)) == 0)
  143   {
  144     ++fetch->row_count;
  145     for (i= 0; i < fetch->column_count; ++i)
  146     {
  147       fetch->out_data[i][fetch->out_data_length[i]]= '\0';
  148     }
  149   }
  150   else
  151     fetch->is_open= FALSE;
  152 
  153   return rc;
  154 }
  155 
  156 void stmt_fetch_close(Stmt_fetch *fetch)
  157 {
  158   unsigned i;
  159 
  160   for (i= 0; i < fetch->column_count; ++i)
  161     free(fetch->out_data[i]);
  162   free(fetch->out_data);
  163   free(fetch->out_data_length);
  164   free(fetch->bind_array);
  165   mysql_stmt_close(fetch->handle);
  166 }
  167 
  168 
  169 
  170 enum fetch_type { USE_ROW_BY_ROW_FETCH= 0, USE_STORE_RESULT= 1 };
  171 
  172 int fetch_n(MYSQL *mysql, const char **query_list, unsigned query_count,
  173                 enum fetch_type fetch_type)
  174 {
  175   unsigned open_statements= query_count;
  176   int rc, error_count= 0;
  177   Stmt_fetch *fetch_array= (Stmt_fetch*) calloc(1, sizeof(Stmt_fetch) *
  178                                                   query_count);
  179   Stmt_fetch *fetch;
  180 
  181   for (fetch= fetch_array; fetch < fetch_array + query_count; ++fetch)
  182   {
  183     if (stmt_fetch_init(mysql, fetch, (unsigned int)(fetch - fetch_array),
  184                     query_list[fetch - fetch_array]))
  185       return FAIL;
  186   }
  187 
  188   if (fetch_type == USE_STORE_RESULT)
  189   {
  190     for (fetch= fetch_array; fetch < fetch_array + query_count; ++fetch)
  191     {
  192       rc= mysql_stmt_store_result(fetch->handle);
  193       FAIL_IF(rc, mysql_stmt_error(fetch->handle));
  194     }
  195   }
  196 
  197   while (open_statements)
  198   {
  199     for (fetch= fetch_array; fetch < fetch_array + query_count; ++fetch)
  200     {
  201       if (fetch->is_open && (rc= stmt_fetch_fetch_row(fetch)))
  202       {
  203         open_statements--;
  204         /*
  205           We try to fetch from the rest of the statements in case of
  206           error
  207         */
  208         if (rc != MYSQL_NO_DATA)
  209           error_count++;
  210       }
  211     }
  212   }
  213   if (!error_count)
  214   {
  215     unsigned total_row_count= 0;
  216     for (fetch= fetch_array; fetch < fetch_array + query_count; ++fetch)
  217       total_row_count+= fetch->row_count;
  218   }
  219   for (fetch= fetch_array; fetch < fetch_array + query_count; ++fetch)
  220     stmt_fetch_close(fetch);
  221   free(fetch_array);
  222 
  223   return (error_count) ? FAIL:OK;
  224 }
  225 
  226 static int test_basic_cursors(MYSQL *mysql)
  227 {
  228   const char *basic_tables[]=
  229   {
  230     "DROP TABLE IF EXISTS t1, t2",
  231 
  232     "CREATE TABLE t1 "
  233     "(id INTEGER NOT NULL PRIMARY KEY, "
  234     " name VARCHAR(20) NOT NULL)",
  235 
  236     "INSERT INTO t1 (id, name) VALUES "
  237     "  (2, 'Ja'), (3, 'Ede'), "
  238     "  (4, 'Haag'), (5, 'Kabul'), "
  239     "  (6, 'Almere'), (7, 'Utrecht'), "
  240     "  (8, 'Qandahar'), (9, 'Amsterdam'), "
  241     "  (10, 'Amersfoort'), (11, 'Constantine')",
  242 
  243     "CREATE TABLE t2 "
  244     "(id INTEGER NOT NULL PRIMARY KEY, "
  245     " name VARCHAR(20) NOT NULL)",
  246 
  247     "INSERT INTO t2 (id, name) VALUES "
  248     "  (4, 'Guam'), (5, 'Aruba'), "
  249     "  (6, 'Angola'), (7, 'Albania'), "
  250     "  (8, 'Anguilla'), (9, 'Argentina'), "
  251     "  (10, 'Azerbaijan'), (11, 'Afghanistan'), "
  252     "  (12, 'Burkina Faso'), (13, 'Faroe Islands')"
  253   };
  254 
  255   const char *queries[]=
  256   {
  257     "SELECT * FROM t1",
  258     "SELECT * FROM t2"
  259   };
  260 
  261   
  262   FAIL_IF(fill_tables(mysql, basic_tables, sizeof(basic_tables)/sizeof(*basic_tables)), "fill_tables failed");
  263 
  264   FAIL_IF(fetch_n(mysql, queries, sizeof(queries)/sizeof(*queries), USE_ROW_BY_ROW_FETCH), "fetch_n failed");
  265   FAIL_IF(fetch_n(mysql, queries, sizeof(queries)/sizeof(*queries), USE_STORE_RESULT), "fetch_n failed");
  266   return OK;
  267 }
  268 
  269 
  270 static int test_cursors_with_union(MYSQL *mysql)
  271 {
  272   const char *queries[]=
  273   {
  274     "SELECT t1.name FROM t1 UNION SELECT t2.name FROM t2",
  275     "SELECT t1.id FROM t1 WHERE t1.id < 5"
  276   };
  277   FAIL_IF(fetch_n(mysql, queries, sizeof(queries)/sizeof(*queries), USE_ROW_BY_ROW_FETCH), "fetch_n failed");
  278   FAIL_IF(fetch_n(mysql, queries, sizeof(queries)/sizeof(*queries), USE_STORE_RESULT), "fetch_n failed");
  279 
  280   return OK;
  281 }
  282 
  283 
  284 static int test_cursors_with_procedure(MYSQL *mysql)
  285 {
  286   const char *queries[]=
  287   {
  288     "SELECT * FROM t1 procedure analyse()"
  289   };
  290   FAIL_IF(fetch_n(mysql, queries, sizeof(queries)/sizeof(*queries), USE_ROW_BY_ROW_FETCH), "fetch_n failed");
  291   FAIL_IF(fetch_n(mysql, queries, sizeof(queries)/sizeof(*queries), USE_STORE_RESULT), "fetch_n failed");
  292 
  293   return OK;
  294 }
  295 
  296 /*
  297   Bug#21206: memory corruption when too many cursors are opened at once
  298 
  299   Memory corruption happens when more than 1024 cursors are open
  300   simultaneously.
  301 */
  302 static int test_bug21206(MYSQL *mysql)
  303 {
  304   int retcode= OK;
  305 
  306   const size_t cursor_count= 1025;
  307 
  308   const char *create_table[]=
  309   {
  310     "DROP TABLE IF EXISTS t1",
  311     "CREATE TABLE t1 (i INT)",
  312     "INSERT INTO t1 VALUES (1), (2), (3)"
  313   };
  314   const char *query= "SELECT * FROM t1";
  315 
  316   Stmt_fetch *fetch_array=
  317     (Stmt_fetch*) calloc(cursor_count, sizeof(Stmt_fetch));
  318 
  319   Stmt_fetch *fetch;
  320 
  321   FAIL_IF(fill_tables(mysql, create_table, sizeof(create_table) / sizeof(*create_table)), "fill_tables failed");
  322 
  323   for (fetch= fetch_array; fetch < fetch_array + cursor_count; ++fetch)
  324   {
  325     if ((retcode= stmt_fetch_init(mysql, fetch, (unsigned int)(fetch - fetch_array), query)))
  326       break;
  327   }
  328 
  329   for (fetch= fetch_array; fetch < fetch_array + cursor_count; ++fetch)
  330     stmt_fetch_close(fetch);
  331 
  332   free(fetch_array);
  333 
  334   return retcode;
  335 }
  336 
  337 static int test_bug10729(MYSQL *mysql)
  338 {
  339   MYSQL_STMT *stmt;
  340   MYSQL_BIND my_bind[1];
  341   char a[21];
  342   int rc;
  343   const char *stmt_text;
  344   int i= 0;
  345   const char *name_array[3]= { "aaa", "bbb", "ccc" };
  346   ulong type;
  347 
  348   mysql_query(mysql, "drop table if exists t1");
  349   mysql_query(mysql, "create table t1 (id integer not null primary key,"
  350                                       "name VARCHAR(20) NOT NULL)");
  351   rc= mysql_query(mysql, "insert into t1 (id, name) values "
  352                          "(1, 'aaa'), (2, 'bbb'), (3, 'ccc')");
  353   check_mysql_rc(rc, mysql);
  354 
  355   stmt= mysql_stmt_init(mysql);
  356   FAIL_IF(!stmt, mysql_error(mysql));
  357 
  358   type= (ulong) CURSOR_TYPE_READ_ONLY;
  359   rc= mysql_stmt_attr_set(stmt, STMT_ATTR_CURSOR_TYPE, (void*) &type);
  360   check_stmt_rc(rc, stmt);
  361   stmt_text= "select name from t1";
  362   rc= mysql_stmt_prepare(stmt, SL(stmt_text));
  363   check_stmt_rc(rc, stmt);
  364 
  365   memset(my_bind, '\0', sizeof(my_bind));
  366   my_bind[0].buffer_type= MYSQL_TYPE_STRING;
  367   my_bind[0].buffer= (void*) a;
  368   my_bind[0].buffer_length= sizeof(a);
  369   mysql_stmt_bind_result(stmt, my_bind);
  370 
  371   for (i= 0; i < 3; i++)
  372   {
  373     int row_no= 0;
  374     rc= mysql_stmt_execute(stmt);
  375     check_stmt_rc(rc, stmt);
  376     while ((rc= mysql_stmt_fetch(stmt)) == 0)
  377     {
  378       FAIL_UNLESS(strcmp(a, name_array[row_no]) == 0, "a != name_array[row_no]");
  379       ++row_no;
  380     }
  381     FAIL_UNLESS(rc == MYSQL_NO_DATA, "rc != MYSQL_NO_DATA");
  382   }
  383   rc= mysql_stmt_close(stmt);
  384 
  385   rc= mysql_query(mysql, "drop table t1");
  386   check_mysql_rc(rc, mysql);
  387 
  388   return OK;
  389 }
  390 
  391 /* Bug#10736: cursors and subqueries, memroot management */
  392 
  393 static int test_bug10736(MYSQL *mysql)
  394 {
  395   MYSQL_STMT *stmt;
  396   MYSQL_BIND my_bind[1];
  397   char a[21];
  398   int rc;
  399   const char *stmt_text;
  400   int i= 0;
  401   ulong type;
  402 
  403   rc= mysql_query(mysql, "drop table if exists t1");
  404   check_mysql_rc(rc, mysql);
  405   rc= mysql_query(mysql, "create table t1 (id integer not null primary key,"
  406                                       "name VARCHAR(20) NOT NULL)");
  407   check_mysql_rc(rc, mysql);
  408   rc= mysql_query(mysql, "insert into t1 (id, name) values "
  409                          "(1, 'aaa'), (2, 'bbb'), (3, 'ccc')");
  410   check_mysql_rc(rc, mysql);
  411 
  412   stmt= mysql_stmt_init(mysql);
  413 
  414   type= (ulong) CURSOR_TYPE_READ_ONLY;
  415   rc= mysql_stmt_attr_set(stmt, STMT_ATTR_CURSOR_TYPE, (void*) &type);
  416   check_stmt_rc(rc, stmt);
  417   stmt_text= "select name from t1 where name=(select name from t1 where id=2)";
  418   rc= mysql_stmt_prepare(stmt, SL(stmt_text));
  419   check_stmt_rc(rc, stmt);
  420 
  421   memset(my_bind, '\0', sizeof(my_bind));
  422   my_bind[0].buffer_type= MYSQL_TYPE_STRING;
  423   my_bind[0].buffer= (void*) a;
  424   my_bind[0].buffer_length= sizeof(a);
  425   mysql_stmt_bind_result(stmt, my_bind);
  426 
  427   for (i= 0; i < 3; i++)
  428   {
  429     int row_no= 0;
  430     rc= mysql_stmt_execute(stmt);
  431     check_stmt_rc(rc, stmt);
  432     while ((rc= mysql_stmt_fetch(stmt)) == 0)
  433       ++row_no;
  434     FAIL_UNLESS(rc == MYSQL_NO_DATA, "rc != MYSQL_NO_DATA");
  435   }
  436   rc= mysql_stmt_close(stmt);
  437 
  438   rc= mysql_query(mysql, "drop table t1");
  439   check_mysql_rc(rc, mysql);
  440 
  441   return OK;
  442 }
  443 
  444 /* Bug#10794: cursors, packets out of order */
  445 
  446 static int test_bug10794(MYSQL *mysql)
  447 {
  448   MYSQL_STMT *stmt, *stmt1;
  449   MYSQL_BIND my_bind[2];
  450   char a[21];
  451   int id_val;
  452   ulong a_len;
  453   int rc;
  454   const char *stmt_text;
  455   int i= 0;
  456   ulong type;
  457 
  458   rc= mysql_query(mysql, "drop table if exists t1");
  459   check_mysql_rc(rc, mysql);
  460   rc= mysql_query(mysql, "create table t1 (id integer not null primary key,"
  461                                       "name varchar(20) not null)");
  462   check_mysql_rc(rc, mysql);
  463 
  464   stmt= mysql_stmt_init(mysql);
  465   stmt_text= "insert into t1 (id, name) values (?, ?)";
  466   rc= mysql_stmt_prepare(stmt, SL(stmt_text));
  467   check_stmt_rc(rc, stmt);
  468 
  469   memset(my_bind, '\0', sizeof(my_bind));
  470   my_bind[0].buffer_type= MYSQL_TYPE_LONG;
  471   my_bind[0].buffer= (void*) &id_val;
  472   my_bind[1].buffer_type= MYSQL_TYPE_STRING;
  473   my_bind[1].buffer= (void*) a;
  474   my_bind[1].length= &a_len;
  475   rc= mysql_stmt_bind_param(stmt, my_bind);
  476   check_stmt_rc(rc, stmt);
  477   for (i= 0; i < 42; i++)
  478   {
  479     id_val= (i+1)*10;
  480     sprintf(a, "a%d", i);
  481     a_len= (unsigned long)strlen(a); /* safety against broken sprintf */
  482     rc= mysql_stmt_execute(stmt);
  483     check_stmt_rc(rc, stmt);
  484   }
  485   stmt_text= "select name from t1";
  486   rc= mysql_stmt_prepare(stmt, SL(stmt_text));
  487   type= (ulong) CURSOR_TYPE_READ_ONLY;
  488   mysql_stmt_attr_set(stmt, STMT_ATTR_CURSOR_TYPE, (const void*) &type);
  489   stmt1= mysql_stmt_init(mysql);
  490   mysql_stmt_attr_set(stmt1, STMT_ATTR_CURSOR_TYPE, (const void*) &type);
  491   memset(my_bind, '\0', sizeof(my_bind));
  492   my_bind[0].buffer_type= MYSQL_TYPE_STRING;
  493   my_bind[0].buffer= (void*) a;
  494   my_bind[0].buffer_length= sizeof(a);
  495   my_bind[0].length= &a_len;
  496   rc= mysql_stmt_bind_result(stmt, my_bind);
  497   check_stmt_rc(rc, stmt);
  498   rc= mysql_stmt_execute(stmt);
  499   check_stmt_rc(rc, stmt);
  500   rc= mysql_stmt_fetch(stmt);
  501   check_stmt_rc(rc, stmt);
  502   /* Don't optimize: an attribute of the original test case */
  503   mysql_stmt_free_result(stmt);
  504   mysql_stmt_reset(stmt);
  505   stmt_text= "select name from t1 where id=10";
  506   rc= mysql_stmt_prepare(stmt1, SL(stmt_text));
  507   check_stmt_rc(rc, stmt1);
  508   rc= mysql_stmt_bind_result(stmt1, my_bind);
  509   check_stmt_rc(rc, stmt1);
  510   rc= mysql_stmt_execute(stmt1);
  511   check_stmt_rc(rc, stmt1);
  512   while (1)
  513   {
  514     rc= mysql_stmt_fetch(stmt1);
  515     if (rc == MYSQL_NO_DATA)
  516     {
  517       break;
  518     }
  519     check_stmt_rc(rc, stmt1);
  520   }
  521   mysql_stmt_close(stmt);
  522   mysql_stmt_close(stmt1);
  523 
  524   rc= mysql_query(mysql, "drop table t1");
  525   check_mysql_rc(rc, mysql);
  526 
  527   return OK;
  528 }
  529 
  530 /* Bug#10760: cursors, crash in a fetch after rollback. */
  531 
  532 static int test_bug10760(MYSQL *mysql)
  533 {
  534   MYSQL_STMT *stmt;
  535   MYSQL_BIND my_bind[1];
  536   int rc;
  537   const char *stmt_text;
  538   char id_buf[20];
  539   ulong id_len;
  540   int i= 0;
  541   ulong type;
  542 
  543   rc= mysql_query(mysql, "drop table if exists t1, t2");
  544   check_mysql_rc(rc, mysql);
  545 
  546   /* create tables */
  547   rc= mysql_query(mysql, "create table t1 (id integer not null primary key)"
  548                          " engine=MyISAM");
  549   check_mysql_rc(rc, mysql);;
  550   for (; i < 42; ++i)
  551   {
  552     char buf[100];
  553     sprintf(buf, "insert into t1 (id) values (%d)", i+1);
  554     rc= mysql_query(mysql, buf);
  555     check_mysql_rc(rc, mysql);;
  556   }
  557   mysql_autocommit(mysql, FALSE);
  558   /* create statement */
  559   stmt= mysql_stmt_init(mysql);
  560   type= (ulong) CURSOR_TYPE_READ_ONLY;
  561   mysql_stmt_attr_set(stmt, STMT_ATTR_CURSOR_TYPE, (const void*) &type);
  562 
  563   /*
  564     1: check that a deadlock within the same connection
  565     is resolved and an error is returned. The deadlock is modelled
  566     as follows:
  567     con1: open cursor for select * from t1;
  568     con1: insert into t1 (id) values (1)
  569   */
  570   stmt_text= "select id from t1 order by 1";
  571   rc= mysql_stmt_prepare(stmt, SL(stmt_text));
  572   check_stmt_rc(rc, stmt);;
  573   rc= mysql_stmt_execute(stmt);
  574   check_stmt_rc(rc, stmt);;
  575   rc= mysql_query(mysql, "update t1 set id=id+100");
  576   /*
  577     If cursors are not materialized, the update will return an error;
  578     we mainly test that it won't deadlock.
  579   */
  580   /*  FAIL_IF(!rc, "Error expected"); */
  581   /*
  582     2: check that MyISAM tables used in cursors survive
  583     COMMIT/ROLLBACK.
  584   */
  585   rc= mysql_rollback(mysql);                  /* should not close the cursor */
  586   check_mysql_rc(rc, mysql);;
  587   rc= mysql_stmt_fetch(stmt);
  588   check_stmt_rc(rc, stmt);;
  589 
  590   /*
  591     3: check that cursors to InnoDB tables are closed (for now) by
  592     COMMIT/ROLLBACK.
  593   */
  594   if (check_variable(mysql, "@@have_innodb", "YES"))
  595   {
  596     stmt_text= "select id from t1 order by 1";
  597     rc= mysql_stmt_prepare(stmt, SL(stmt_text));
  598     check_stmt_rc(rc, stmt);;
  599 
  600     rc= mysql_query(mysql, "alter table t1 engine=InnoDB");
  601     check_mysql_rc(rc, mysql);;
  602 
  603     memset(my_bind, '\0', sizeof(my_bind));
  604     my_bind[0].buffer_type= MYSQL_TYPE_STRING;
  605     my_bind[0].buffer= (void*) id_buf;
  606     my_bind[0].buffer_length= sizeof(id_buf);
  607     my_bind[0].length= &id_len;
  608     check_stmt_rc(rc, stmt);;
  609     mysql_stmt_bind_result(stmt, my_bind);
  610 
  611     rc= mysql_stmt_execute(stmt);
  612     rc= mysql_stmt_fetch(stmt);
  613     FAIL_UNLESS(rc == 0, "rc != 0");
  614     rc= mysql_rollback(mysql);                  /* should close the cursor */
  615   }
  616 
  617   mysql_stmt_close(stmt);
  618   rc= mysql_query(mysql, "drop table t1");
  619   check_mysql_rc(rc, mysql);
  620   rc= mysql_autocommit(mysql, TRUE);                /* restore default */
  621   check_mysql_rc(rc, mysql);
  622 
  623   return OK;
  624 }
  625 
  626 /* Bug#11172: cursors, crash on a fetch from a datetime column */
  627 
  628 static int test_bug11172(MYSQL *mysql)
  629 {
  630   MYSQL_STMT *stmt;
  631   MYSQL_BIND bind_in[1], bind_out[2];
  632   MYSQL_TIME hired;
  633   int rc;
  634   const char *stmt_text;
  635   int i= 0, id;
  636   ulong type;
  637 
  638   rc= mysql_query(mysql, "drop table if exists t1");
  639   check_mysql_rc(rc, mysql);
  640   rc= mysql_query(mysql, "create table t1 (id integer not null primary key,"
  641                                       "hired date not null)");
  642   check_mysql_rc(rc, mysql);
  643   rc= mysql_query(mysql,
  644                   "insert into t1 (id, hired) values (1, '1933-08-24'), "
  645                   "(2, '1965-01-01'), (3, '1949-08-17'), (4, '1945-07-07'), "
  646                   "(5, '1941-05-15'), (6, '1978-09-15'), (7, '1936-03-28')");
  647   check_mysql_rc(rc, mysql);
  648   stmt= mysql_stmt_init(mysql);
  649   FAIL_IF(!stmt, mysql_error(mysql));
  650   stmt_text= "SELECT id, hired FROM t1 WHERE hired=?";
  651   rc= mysql_stmt_prepare(stmt, SL(stmt_text));
  652   check_stmt_rc(rc, stmt);
  653 
  654   type= (ulong) CURSOR_TYPE_READ_ONLY;
  655   mysql_stmt_attr_set(stmt, STMT_ATTR_CURSOR_TYPE, (const void*) &type);
  656 
  657   memset(bind_in, '\0', sizeof(bind_in));
  658   memset(bind_out, '\0', sizeof(bind_out));
  659   memset(&hired, '\0', sizeof(hired));
  660   hired.year= 1965;
  661   hired.month= 1;
  662   hired.day= 1;
  663   bind_in[0].buffer_type= MYSQL_TYPE_DATE;
  664   bind_in[0].buffer= (void*) &hired;
  665   bind_in[0].buffer_length= sizeof(hired);
  666   bind_out[0].buffer_type= MYSQL_TYPE_LONG;
  667   bind_out[0].buffer= (void*) &id;
  668   bind_out[1]= bind_in[0];
  669 
  670   for (i= 0; i < 3; i++)
  671   {
  672     rc= mysql_stmt_bind_param(stmt, bind_in);
  673     check_stmt_rc(rc, stmt);
  674     rc= mysql_stmt_bind_result(stmt, bind_out);
  675     check_stmt_rc(rc, stmt);
  676     rc= mysql_stmt_execute(stmt);
  677     check_stmt_rc(rc, stmt);
  678     while ((rc= mysql_stmt_fetch(stmt)) == 0);
  679     FAIL_UNLESS(rc == MYSQL_NO_DATA, "rc != MYSQL_NO_DATA");
  680     if (!mysql_stmt_free_result(stmt))
  681       mysql_stmt_reset(stmt);
  682   }
  683   mysql_stmt_close(stmt);
  684   mysql_rollback(mysql);
  685   mysql_rollback(mysql);
  686 
  687   rc= mysql_query(mysql, "drop table t1");
  688   check_mysql_rc(rc, mysql);
  689 
  690   return OK;
  691 }
  692 
  693 /* Bug#11656: cursors, crash on a fetch from a query with distinct. */
  694 
  695 static int test_bug11656(MYSQL *mysql)
  696 {
  697   MYSQL_STMT *stmt;
  698   MYSQL_BIND my_bind[2];
  699   int rc;
  700   const char *stmt_text;
  701   char buf[2][20];
  702   int i= 0;
  703   ulong type;
  704 
  705   rc= mysql_query(mysql, "drop table if exists t1");
  706   check_mysql_rc(rc, mysql);
  707 
  708   rc= mysql_query(mysql, "create table t1 ("
  709                   "server varchar(40) not null, "
  710                   "test_kind varchar(1) not null, "
  711                   "test_id varchar(30) not null , "
  712                   "primary key (server,test_kind,test_id))");
  713   check_mysql_rc(rc, mysql);
  714 
  715   stmt_text= "select distinct test_kind, test_id from t1 "
  716              "where server in (?, ?)";
  717   stmt= mysql_stmt_init(mysql);
  718   FAIL_IF(!stmt, mysql_error(mysql));
  719   rc= mysql_stmt_prepare(stmt, SL(stmt_text));
  720   check_stmt_rc(rc, stmt);
  721   type= (ulong) CURSOR_TYPE_READ_ONLY;
  722   mysql_stmt_attr_set(stmt, STMT_ATTR_CURSOR_TYPE, (const void*) &type);
  723 
  724   memset(my_bind, '\0', sizeof(my_bind));
  725   strcpy(buf[0], "pcint502_MY2");
  726   strcpy(buf[1], "*");
  727   for (i=0; i < 2; i++)
  728   {
  729     my_bind[i].buffer_type= MYSQL_TYPE_STRING;
  730     my_bind[i].buffer= (uchar* *)&buf[i];
  731     my_bind[i].buffer_length= (unsigned long)strlen(buf[i]);
  732   }
  733   rc= mysql_stmt_bind_param(stmt, my_bind);
  734   check_stmt_rc(rc, stmt);
  735 
  736   rc= mysql_stmt_execute(stmt);
  737   check_stmt_rc(rc, stmt);
  738 
  739   rc= mysql_stmt_fetch(stmt);
  740   FAIL_UNLESS(rc == MYSQL_NO_DATA, "rc != MYSQL_NO_DATA");
  741 
  742   mysql_stmt_close(stmt);
  743   rc= mysql_query(mysql, "drop table t1");
  744   check_mysql_rc(rc, mysql);
  745 
  746   return OK;
  747 }
  748 
  749 /* Cursors: opening a cursor to a compilicated query with ORDER BY */
  750 
  751 static int test_bug11901(MYSQL *mysql)
  752 {
  753   MYSQL_STMT *stmt;
  754   MYSQL_BIND my_bind[2];
  755   int rc;
  756   char workdept[20];
  757   ulong workdept_len; 
  758   uint32 empno; 
  759   const ulong type= (ulong)CURSOR_TYPE_READ_ONLY;
  760   const char *stmt_text;
  761 
  762 
  763   stmt_text= "drop table if exists t1, t2";
  764   rc= mysql_real_query(mysql, SL(stmt_text));
  765   check_mysql_rc(rc, mysql);
  766 
  767   stmt_text= "create table t1 ("
  768     "  empno int(11) not null, firstname varchar(20) not null,"
  769     "  midinit varchar(20) not null, lastname varchar(20) not null,"
  770     "  workdept varchar(6) not null, salary double not null,"
  771     "  bonus float not null, primary key (empno), "
  772     " unique key (workdept, empno) "
  773     ") default charset=latin1 collate=latin1_bin";
  774   rc= mysql_real_query(mysql, SL(stmt_text));
  775   check_mysql_rc(rc, mysql);
  776 
  777   stmt_text= "insert into t1 values "
  778      "(10,  'CHRISTINE', 'I', 'HAAS',      'A00', 52750, 1000),"
  779      "(20,  'MICHAEL',   'L', 'THOMPSON',  'B01', 41250, 800), "
  780      "(30,  'SALLY',     'A', 'KWAN',      'C01', 38250, 800), "
  781      "(50,  'JOHN',      'B', 'GEYER',     'E01', 40175, 800), "
  782      "(60,  'IRVING',    'F', 'STERN',     'D11', 32250, 500), "
  783      "(70,  'EVA',       'D', 'PULASKI',   'D21', 36170, 700), "
  784      "(90,  'EILEEN',    'W', 'HENDERSON', 'E11', 29750, 600), "
  785      "(100, 'THEODORE',  'Q', 'SPENSER',   'E21', 26150, 500), "
  786      "(110, 'VINCENZO',  'G', 'LUCCHESSI', 'A00', 46500, 900), "
  787      "(120, 'SEAN',      '',  'O\\'CONNELL', 'A00', 29250, 600), "
  788      "(130, 'DOLORES',   'M', 'QUINTANA',  'C01', 23800, 500), "
  789      "(140, 'HEATHER',   'A', 'NICHOLLS',  'C01', 28420, 600), "
  790      "(150, 'BRUCE',     '',  'ADAMSON',   'D11', 25280, 500), "
  791      "(160, 'ELIZABETH', 'R', 'PIANKA',    'D11', 22250, 400), "
  792      "(170, 'MASATOSHI', 'J', 'YOSHIMURA', 'D11', 24680, 500), "
  793      "(180, 'MARILYN',   'S', 'SCOUTTEN',  'D11', 21340, 500), "
  794      "(190, 'JAMES',     'H', 'WALKER',    'D11', 20450, 400), "
  795      "(200, 'DAVID',     '',  'BROWN',     'D11', 27740, 600), "
  796      "(210, 'WILLIAM',   'T', 'JONES',     'D11', 18270, 400), "
  797      "(220, 'JENNIFER',  'K', 'LUTZ',      'D11', 29840, 600), "
  798      "(230, 'JAMES',     'J', 'JEFFERSON', 'D21', 22180, 400), "
  799      "(240, 'SALVATORE', 'M', 'MARINO',    'D21', 28760, 600), "
  800      "(250, 'DANIEL',    'S', 'SMITH',     'D21', 19180, 400), "
  801      "(260, 'SYBIL',     'P', 'JOHNSON',   'D21', 17250, 300), "
  802      "(270, 'MARIA',     'L', 'PEREZ',     'D21', 27380, 500), "
  803      "(280, 'ETHEL',     'R', 'SCHNEIDER', 'E11', 26250, 500), "
  804      "(290, 'JOHN',      'R', 'PARKER',    'E11', 15340, 300), "
  805      "(300, 'PHILIP',    'X', 'SMITH',     'E11', 17750, 400), "
  806      "(310, 'MAUDE',     'F', 'SETRIGHT',  'E11', 15900, 300), "
  807      "(320, 'RAMLAL',    'V', 'MEHTA',     'E21', 19950, 400), "
  808      "(330, 'WING',      '',  'LEE',       'E21', 25370, 500), "
  809      "(340, 'JASON',     'R', 'GOUNOT',    'E21', 23840, 500)";
  810 
  811   rc= mysql_real_query(mysql, SL(stmt_text));
  812   check_mysql_rc(rc, mysql);
  813 
  814   stmt_text= "create table t2 ("
  815     " deptno varchar(6) not null, deptname varchar(20) not null,"
  816     " mgrno int(11) not null, location varchar(20) not null,"
  817     " admrdept varchar(6) not null, refcntd int(11) not null,"
  818     " refcntu int(11) not null, primary key (deptno)"
  819     ") default charset=latin1 collate=latin1_bin";
  820   rc= mysql_real_query(mysql, SL(stmt_text));
  821   check_mysql_rc(rc, mysql);
  822 
  823   stmt_text= "insert into t2 values "
  824     "('A00', 'SPIFFY COMPUTER SERV', 10, '', 'A00', 0, 0), "
  825     "('B01', 'PLANNING',             20, '', 'A00', 0, 0), "
  826     "('C01', 'INFORMATION CENTER',   30, '', 'A00', 0, 0), "
  827     "('D01', 'DEVELOPMENT CENTER',   0,  '', 'A00', 0, 0),"
  828     "('D11', 'MANUFACTURING SYSTEM', 60, '', 'D01', 0, 0), "
  829     "('D21', 'ADMINISTRATION SYSTE', 70, '', 'D01', 0, 0), "
  830     "('E01', 'SUPPORT SERVICES',     50, '', 'A00', 0, 0), "
  831     "('E11', 'OPERATIONS',           90, '', 'E01', 0, 0), "
  832     "('E21', 'SOFTWARE SUPPORT',     100,'', 'E01', 0, 0)";
  833   rc= mysql_real_query(mysql, SL(stmt_text));
  834   check_mysql_rc(rc, mysql);
  835 
  836   stmt_text=        "select t1.empno, t1.workdept "
  837                     "from (t1 left join t2 on t2.deptno = t1.workdept) "
  838                     "where t2.deptno in "
  839                     "   (select t2.deptno "
  840                     "    from (t1 left join t2 on t2.deptno = t1.workdept) "
  841                     "    where t1.empno = ?) "
  842                     "order by 1";
  843   stmt= mysql_stmt_init(mysql);
  844   FAIL_IF(!stmt, mysql_error(mysql));
  845   rc= mysql_stmt_prepare(stmt, SL(stmt_text));
  846   check_stmt_rc(rc, stmt);
  847   mysql_stmt_attr_set(stmt, STMT_ATTR_CURSOR_TYPE, (void*) &type);
  848   check_stmt_rc(rc, stmt);
  849 
  850 
  851   memset(my_bind, '\0', sizeof(my_bind));
  852 
  853   my_bind[0].buffer_type= MYSQL_TYPE_LONG;
  854   my_bind[0].buffer= &empno;
  855   rc= mysql_stmt_bind_param(stmt, my_bind);
  856   check_stmt_rc(rc, stmt);
  857 
  858   my_bind[1].buffer_type= MYSQL_TYPE_VAR_STRING;
  859   my_bind[1].buffer= (void*) workdept;
  860   my_bind[1].buffer_length= sizeof(workdept);
  861   my_bind[1].length= &workdept_len;
  862 
  863   rc= mysql_stmt_bind_result(stmt, my_bind);
  864   check_stmt_rc(rc, stmt);
  865 
  866   empno= 10;
  867 
  868   /* ERROR: next statement causes a server crash */
  869   rc= mysql_stmt_execute(stmt);
  870   check_stmt_rc(rc, stmt);
  871 
  872   mysql_stmt_close(stmt);
  873 
  874   rc= mysql_query(mysql, "drop table t1, t2");
  875   check_mysql_rc(rc, mysql);
  876 
  877   return OK;
  878 }
  879 
  880 /* Bug#11904: mysql_stmt_attr_set CURSOR_TYPE_READ_ONLY grouping wrong result */
  881 
  882 static int test_bug11904(MYSQL *mysql)
  883 {
  884   MYSQL_STMT *stmt1;
  885   int rc;
  886   const char *stmt_text;
  887   const ulong type= (ulong)CURSOR_TYPE_READ_ONLY;
  888   MYSQL_BIND my_bind[2];
  889   int country_id=0;
  890   char row_data[11]= {0};
  891 
  892   /* create tables */
  893   rc= mysql_query(mysql, "DROP TABLE IF EXISTS bug11904b");
  894   check_mysql_rc(rc, mysql);
  895   rc= mysql_query(mysql, "CREATE TABLE bug11904b (id int, name char(10), primary key(id, name))");
  896   check_mysql_rc(rc, mysql);
  897 
  898   rc= mysql_query(mysql, "INSERT INTO bug11904b VALUES (1, 'sofia'), (1,'plovdiv'),"
  899                           " (1,'varna'), (2,'LA'), (2,'new york'), (3,'heidelberg'),"
  900                           " (3,'berlin'), (3, 'frankfurt')");
  901 
  902   check_mysql_rc(rc, mysql);
  903   mysql_commit(mysql);
  904   /* create statement */
  905   stmt1= mysql_stmt_init(mysql);
  906   mysql_stmt_attr_set(stmt1, STMT_ATTR_CURSOR_TYPE, (const void*) &type);
  907 
  908   stmt_text= "SELECT id, MIN(name) FROM bug11904b GROUP BY id ORDER BY id";
  909 
  910   rc= mysql_stmt_prepare(stmt1, SL(stmt_text));
  911   check_stmt_rc(rc, stmt1);
  912 
  913   memset(my_bind, 0, sizeof(my_bind));
  914   my_bind[0].buffer_type= MYSQL_TYPE_LONG;
  915   my_bind[0].buffer=& country_id;
  916   my_bind[0].buffer_length= 0;
  917   my_bind[0].length= 0;
  918 
  919   my_bind[1].buffer_type= MYSQL_TYPE_STRING;
  920   my_bind[1].buffer=& row_data;
  921   my_bind[1].buffer_length= sizeof(row_data) - 1;
  922   my_bind[1].length= 0;
  923 
  924   rc= mysql_stmt_bind_result(stmt1, my_bind);
  925   check_stmt_rc(rc, stmt1);
  926 
  927   rc= mysql_stmt_execute(stmt1);
  928   check_stmt_rc(rc, stmt1);
  929 
  930   rc= mysql_stmt_fetch(stmt1);
  931   check_stmt_rc(rc, stmt1);
  932   FAIL_UNLESS(country_id == 1, "country_id != 1");
  933   FAIL_UNLESS(memcmp(row_data, "plovdiv", 7) == 0, "row_data != 'plovdiv'");
  934 
  935   rc= mysql_stmt_fetch(stmt1);
  936   check_stmt_rc(rc, stmt1);
  937   FAIL_UNLESS(country_id == 2, "country_id != 2");
  938   FAIL_UNLESS(memcmp(row_data, "LA", 2) == 0, "row_data != 'LA'");
  939 
  940   rc= mysql_stmt_fetch(stmt1);
  941   check_stmt_rc(rc, stmt1);
  942   FAIL_UNLESS(country_id == 3, "country_id != 3");
  943   FAIL_UNLESS(memcmp(row_data, "berlin", 6) == 0, "row_data != 'Berlin'");
  944 
  945   rc= mysql_stmt_close(stmt1);
  946   check_stmt_rc(rc, stmt1);
  947 
  948   rc= mysql_query(mysql, "drop table bug11904b");
  949   check_mysql_rc(rc, mysql);
  950 
  951   return OK;
  952 }
  953 
  954 
  955 /* Bug#12243: multiple cursors, crash in a fetch after commit. */
  956 
  957 static int test_bug12243(MYSQL *mysql)
  958 {
  959   MYSQL_STMT *stmt1, *stmt2;
  960   int rc;
  961   const char *stmt_text;
  962   ulong type;
  963 
  964   if (!check_variable(mysql, "@@have_innodb", "YES"))
  965   {
  966     diag("Skip -> Test required InnoDB");
  967     return SKIP;
  968   }
  969 
  970   /* create tables */
  971   rc= mysql_query(mysql, "drop table if exists t1");
  972   check_mysql_rc(rc, mysql);
  973   rc= mysql_query(mysql, "create table t1 (a int) engine=InnoDB");
  974   check_mysql_rc(rc, mysql);
  975   rc= mysql_query(mysql, "insert into t1 (a) values (1), (2)");
  976   check_mysql_rc(rc, mysql);
  977   mysql_autocommit(mysql, FALSE);
  978   /* create statement */
  979   stmt1= mysql_stmt_init(mysql);
  980   stmt2= mysql_stmt_init(mysql);
  981   type= (ulong) CURSOR_TYPE_READ_ONLY;
  982   rc= mysql_stmt_attr_set(stmt1, STMT_ATTR_CURSOR_TYPE, (const void*) &type);
  983   check_stmt_rc(rc, stmt1);
  984   rc= mysql_stmt_attr_set(stmt2, STMT_ATTR_CURSOR_TYPE, (const void*) &type);
  985   check_stmt_rc(rc, stmt1);
  986 
  987   stmt_text= "select a from t1";
  988 
  989   rc= mysql_stmt_prepare(stmt1, SL(stmt_text));
  990   check_stmt_rc(rc, stmt1);
  991   rc= mysql_stmt_execute(stmt1);
  992   check_stmt_rc(rc, stmt1);
  993   rc= mysql_stmt_fetch(stmt1);
  994   check_stmt_rc(rc, stmt1);
  995 
  996   rc= mysql_stmt_prepare(stmt2, SL(stmt_text));
  997   check_stmt_rc(rc, stmt2);
  998   rc= mysql_stmt_execute(stmt2);
  999   check_stmt_rc(rc, stmt2);
 1000   rc= mysql_stmt_fetch(stmt2);
 1001   check_stmt_rc(rc, stmt2);
 1002 
 1003   rc= mysql_stmt_close(stmt1);
 1004   check_stmt_rc(rc, stmt1);
 1005   rc= mysql_commit(mysql);
 1006   check_mysql_rc(rc, mysql);
 1007   rc= mysql_stmt_fetch(stmt2);
 1008   check_stmt_rc(rc, stmt2);
 1009 
 1010   mysql_stmt_close(stmt2);
 1011   rc= mysql_query(mysql, "drop table t1");
 1012   check_mysql_rc(rc, mysql);
 1013   mysql_autocommit(mysql, TRUE);                /* restore default */
 1014 
 1015   return OK;
 1016 }
 1017 
 1018 /* Bug#11909: wrong metadata if fetching from two cursors */
 1019 
 1020 static int test_bug11909(MYSQL *mysql)
 1021 {
 1022   MYSQL_STMT *stmt1, *stmt2;
 1023   MYSQL_BIND my_bind[7];
 1024   int rc;
 1025   char firstname[20], midinit[20], lastname[20], workdept[20];
 1026   ulong firstname_len, midinit_len, lastname_len, workdept_len;
 1027   uint32 empno;
 1028   double salary;
 1029   float bonus;
 1030   const char *stmt_text;
 1031   const ulong type= (ulong)CURSOR_TYPE_READ_ONLY;
 1032 
 1033 
 1034   stmt_text= "drop table if exists t1";
 1035   rc= mysql_real_query(mysql, SL(stmt_text));
 1036   check_mysql_rc(rc, mysql);
 1037 
 1038   stmt_text= "create table t1 ("
 1039     "  empno int(11) not null, firstname varchar(20) not null,"
 1040     "  midinit varchar(20) not null, lastname varchar(20) not null,"
 1041     "  workdept varchar(6) not null, salary double not null,"
 1042     "  bonus float not null, primary key (empno)"
 1043     ") default charset=latin1 collate=latin1_bin";
 1044   rc= mysql_real_query(mysql, SL(stmt_text));
 1045   check_mysql_rc(rc, mysql);
 1046 
 1047   stmt_text= "insert into t1 values "
 1048     "(10, 'CHRISTINE', 'I', 'HAAS',     'A00', 52750, 1000), "
 1049     "(20, 'MICHAEL',   'L', 'THOMPSON', 'B01', 41250, 800),"
 1050     "(30, 'SALLY',     'A', 'KWAN',     'C01', 38250, 800),"
 1051     "(50, 'JOHN',      'B', 'GEYER',    'E01', 40175, 800), "
 1052     "(60, 'IRVING',    'F', 'STERN',    'D11', 32250, 500)";
 1053   rc= mysql_real_query(mysql, SL(stmt_text));
 1054   check_mysql_rc(rc, mysql);
 1055 
 1056   /* ****** Begin of trace ****** */
 1057 
 1058   stmt_text= "SELECT empno, firstname, midinit, lastname,"
 1059              "workdept, salary, bonus FROM t1 ORDER BY empno";
 1060   stmt1= mysql_stmt_init(mysql);
 1061   FAIL_IF(!stmt1, mysql_error(mysql));
 1062   rc= mysql_stmt_prepare(stmt1, SL(stmt_text));
 1063   check_stmt_rc(rc, stmt1);
 1064   mysql_stmt_attr_set(stmt1, STMT_ATTR_CURSOR_TYPE,
 1065                       (const void*) &type);
 1066 
 1067   memset(my_bind, '\0', sizeof(my_bind));
 1068   my_bind[0].buffer_type= MYSQL_TYPE_LONG;
 1069   my_bind[0].buffer= (void*) &empno;
 1070 
 1071   my_bind[1].buffer_type= MYSQL_TYPE_VAR_STRING;
 1072   my_bind[1].buffer= (void*) firstname;
 1073   my_bind[1].buffer_length= sizeof(firstname);
 1074   my_bind[1].length= &firstname_len;
 1075 
 1076   my_bind[2].buffer_type= MYSQL_TYPE_VAR_STRING;
 1077   my_bind[2].buffer= (void*) midinit;
 1078   my_bind[2].buffer_length= sizeof(midinit);
 1079   my_bind[2].length= &midinit_len;
 1080 
 1081   my_bind[3].buffer_type= MYSQL_TYPE_VAR_STRING;
 1082   my_bind[3].buffer= (void*) lastname;
 1083   my_bind[3].buffer_length= sizeof(lastname);
 1084   my_bind[3].length= &lastname_len;
 1085 
 1086   my_bind[4].buffer_type= MYSQL_TYPE_VAR_STRING;
 1087   my_bind[4].buffer= (void*) workdept;
 1088   my_bind[4].buffer_length= sizeof(workdept);
 1089   my_bind[4].length= &workdept_len;
 1090 
 1091   my_bind[5].buffer_type= MYSQL_TYPE_DOUBLE;
 1092   my_bind[5].buffer= (void*) &salary;
 1093 
 1094   my_bind[6].buffer_type= MYSQL_TYPE_FLOAT;
 1095   my_bind[6].buffer= (void*) &bonus;
 1096   rc= mysql_stmt_bind_result(stmt1, my_bind);
 1097   check_stmt_rc(rc, stmt1);
 1098 
 1099   rc= mysql_stmt_execute(stmt1);
 1100   check_stmt_rc(rc, stmt1);
 1101 
 1102   rc= mysql_stmt_fetch(stmt1);
 1103   FAIL_UNLESS(rc == 0, "rc != 0");
 1104   FAIL_UNLESS(empno == 10, "empno != 10");
 1105   FAIL_UNLESS(strcmp(firstname, "CHRISTINE""") == 0, "firstname != 'Christine'");
 1106   FAIL_UNLESS(strcmp(midinit, "I""") == 0, "");
 1107   FAIL_UNLESS(strcmp(lastname, "HAAS""") == 0, "lastname != 'HAAS'");
 1108   FAIL_UNLESS(strcmp(workdept, "A00""") == 0, "workdept != 'A00'");
 1109   FAIL_UNLESS(salary == (double) 52750.0, "salary != 52750");
 1110   FAIL_UNLESS(bonus == (float) 1000.0, "bonus =! 1000");
 1111 
 1112   stmt_text = "SELECT empno, firstname FROM t1";
 1113   stmt2= mysql_stmt_init(mysql);
 1114   FAIL_IF(!stmt2, mysql_error(mysql));
 1115   rc= mysql_stmt_prepare(stmt2, SL(stmt_text));
 1116   check_stmt_rc(rc, stmt2);
 1117   mysql_stmt_attr_set(stmt2, STMT_ATTR_CURSOR_TYPE,
 1118                       (const void*) &type);
 1119   rc= mysql_stmt_bind_result(stmt2, my_bind);
 1120   check_stmt_rc(rc, stmt2);
 1121 
 1122   rc= mysql_stmt_execute(stmt2);
 1123   check_stmt_rc(rc, stmt2);
 1124 
 1125   rc= mysql_stmt_fetch(stmt2);
 1126   FAIL_UNLESS(rc == 0, "rc != 0")
 1127 
 1128   FAIL_UNLESS(empno == 10, "empno != 10");
 1129   FAIL_UNLESS(strcmp(firstname, "CHRISTINE""") == 0, "firstname != 'Christine'");
 1130 
 1131   rc= mysql_stmt_reset(stmt2);
 1132   check_stmt_rc(rc, stmt2);
 1133 
 1134   /* ERROR: next statement should return 0 */
 1135 
 1136   rc= mysql_stmt_fetch(stmt1);
 1137   FAIL_UNLESS(rc == 0, "rc != 0");
 1138 
 1139   mysql_stmt_close(stmt1);
 1140   mysql_stmt_close(stmt2);
 1141   rc= mysql_rollback(mysql);
 1142   check_mysql_rc(rc, mysql);
 1143 
 1144   rc= mysql_query(mysql, "drop table t1");
 1145   check_mysql_rc(rc, mysql);
 1146 
 1147   return OK;
 1148 }
 1149 
 1150 /* Bug#13488: wrong column metadata when fetching from cursor */
 1151 
 1152 static int test_bug13488(MYSQL *mysql)
 1153 {
 1154   MYSQL_BIND my_bind[3];
 1155   MYSQL_STMT *stmt1;
 1156   int rc, f1, f2, f3, i;
 1157   const ulong type= CURSOR_TYPE_READ_ONLY;
 1158   const char *query= "select f1, f2, f3 from t1 left join t2 on f1=f2 where f1=1";
 1159 
 1160 
 1161   rc= mysql_query(mysql, "drop table if exists t1, t2");
 1162   check_mysql_rc(rc, mysql);
 1163   rc= mysql_query(mysql, "create table t1 (f1 int not null primary key)");
 1164   check_mysql_rc(rc, mysql);
 1165   rc= mysql_query(mysql, "create table t2 (f2 int not null primary key, "
 1166                   "f3 int not null)");
 1167   check_mysql_rc(rc, mysql);
 1168   rc= mysql_query(mysql, "insert into t1 values (1), (2)");
 1169   check_mysql_rc(rc, mysql);
 1170   rc= mysql_query(mysql, "insert into t2 values (1,2), (2,4)");
 1171   check_mysql_rc(rc, mysql);
 1172 
 1173   memset(my_bind, 0, sizeof(my_bind));
 1174   for (i= 0; i < 3; i++)
 1175   {
 1176     my_bind[i].buffer_type= MYSQL_TYPE_LONG;
 1177     my_bind[i].buffer_length= 4;
 1178     my_bind[i].length= 0;
 1179   }
 1180   my_bind[0].buffer=&f1;
 1181   my_bind[1].buffer=&f2;
 1182   my_bind[2].buffer=&f3;
 1183 
 1184   stmt1= mysql_stmt_init(mysql);
 1185   rc= mysql_stmt_attr_set(stmt1,STMT_ATTR_CURSOR_TYPE, (const void *)&type);
 1186   check_stmt_rc(rc, stmt1);
 1187 
 1188   rc= mysql_stmt_prepare(stmt1, SL(query));
 1189   check_stmt_rc(rc, stmt1);
 1190 
 1191   rc= mysql_stmt_execute(stmt1);
 1192   check_stmt_rc(rc, stmt1);
 1193 
 1194   rc= mysql_stmt_bind_result(stmt1, my_bind);
 1195   check_stmt_rc(rc, stmt1);
 1196 
 1197   rc= mysql_stmt_fetch(stmt1);
 1198   check_stmt_rc(rc, stmt1);
 1199 
 1200   rc= mysql_stmt_free_result(stmt1);
 1201   check_stmt_rc(rc, stmt1);
 1202 
 1203   rc= mysql_stmt_reset(stmt1);
 1204   check_stmt_rc(rc, stmt1);
 1205 
 1206   rc= mysql_stmt_close(stmt1);
 1207   check_stmt_rc(rc, stmt1);
 1208 
 1209   FAIL_UNLESS(f1 == 1, "f1 != 1");
 1210   FAIL_UNLESS(f2 == 1, "f2 != 1");
 1211   FAIL_UNLESS(f3 == 2, "f3 != 2");
 1212   rc= mysql_query(mysql, "drop table t1, t2");
 1213   check_mysql_rc(rc, mysql);
 1214 
 1215   return OK;
 1216 }
 1217 
 1218 /*
 1219   Bug#13524: warnings of a previous command are not reset when fetching
 1220   from a cursor.
 1221 */
 1222 
 1223 static int test_bug13524(MYSQL *mysql)
 1224 {
 1225   MYSQL_STMT *stmt;
 1226   int rc;
 1227   unsigned int warning_count;
 1228   const ulong type= CURSOR_TYPE_READ_ONLY;
 1229   const char *query= "select * from t1";
 1230 
 1231 
 1232   rc= mysql_query(mysql, "drop table if exists t1, t2");
 1233   check_mysql_rc(rc, mysql);
 1234   rc= mysql_query(mysql, "create table t1 (a int not null primary key)");
 1235   check_mysql_rc(rc, mysql);
 1236   rc= mysql_query(mysql, "insert into t1 values (1), (2), (3), (4)");
 1237   check_mysql_rc(rc, mysql);
 1238 
 1239   stmt= mysql_stmt_init(mysql);
 1240   rc= mysql_stmt_attr_set(stmt, STMT_ATTR_CURSOR_TYPE, (const void*) &type);
 1241   check_stmt_rc(rc, stmt);
 1242 
 1243   rc= mysql_stmt_prepare(stmt, SL(query));
 1244   check_stmt_rc(rc, stmt);
 1245 
 1246   rc= mysql_stmt_execute(stmt);
 1247   check_stmt_rc(rc, stmt);
 1248 
 1249   rc= mysql_stmt_fetch(stmt);
 1250   check_stmt_rc(rc, stmt);
 1251 
 1252   warning_count= mysql_warning_count(mysql);
 1253   FAIL_UNLESS(warning_count == 0, "warning_count != 0");
 1254 
 1255   /* Check that DROP TABLE produced a warning (no such table) */
 1256   rc= mysql_query(mysql, "drop table if exists t2");
 1257   check_mysql_rc(rc, mysql);
 1258   warning_count= mysql_warning_count(mysql);
 1259   FAIL_UNLESS(warning_count == 1, "warning_count != 1");
 1260 
 1261   /*
 1262     Check that fetch from a cursor cleared the warning from the previous
 1263     command.
 1264   */
 1265   rc= mysql_stmt_fetch(stmt);
 1266   check_stmt_rc(rc, stmt);
 1267   warning_count= mysql_warning_count(mysql);
 1268   FAIL_UNLESS(warning_count == 0, "warning_count != 0");
 1269 
 1270   /* Cleanup */
 1271   mysql_stmt_close(stmt);
 1272   rc= mysql_query(mysql, "drop table t1");
 1273   check_mysql_rc(rc, mysql);
 1274 
 1275   return OK;
 1276 }
 1277 
 1278 /*
 1279   Bug#14845 "mysql_stmt_fetch returns MYSQL_NO_DATA when COUNT(*) is 0"
 1280 */
 1281 
 1282 static int test_bug14845(MYSQL *mysql)
 1283 {
 1284   MYSQL_STMT *stmt;
 1285   int rc;
 1286   const ulong type= CURSOR_TYPE_READ_ONLY;
 1287   const char *query= "select count(*) from t1 where 1 = 0";
 1288 
 1289 
 1290   rc= mysql_query(mysql, "drop table if exists t1");
 1291   check_mysql_rc(rc, mysql);
 1292   rc= mysql_query(mysql, "create table t1 (id int(11) default null, "
 1293                          "name varchar(20) default null)"
 1294                          "engine=MyISAM DEFAULT CHARSET=utf8");
 1295   check_mysql_rc(rc, mysql);
 1296   rc= mysql_query(mysql, "insert into t1 values (1,'abc'),(2,'def')");
 1297   check_mysql_rc(rc, mysql);
 1298 
 1299   stmt= mysql_stmt_init(mysql);
 1300   rc= mysql_stmt_attr_set(stmt, STMT_ATTR_CURSOR_TYPE, (const void*) &type);
 1301   check_stmt_rc(rc, stmt);
 1302 
 1303   rc= mysql_stmt_prepare(stmt, SL(query));
 1304   check_stmt_rc(rc, stmt);
 1305 
 1306   rc= mysql_stmt_execute(stmt);
 1307   check_stmt_rc(rc, stmt);
 1308 
 1309   rc= mysql_stmt_fetch(stmt);
 1310   FAIL_UNLESS(rc == 0, "");
 1311 
 1312   rc= mysql_stmt_fetch(stmt);
 1313   FAIL_UNLESS(rc == MYSQL_NO_DATA, "");
 1314 
 1315   /* Cleanup */
 1316   mysql_stmt_close(stmt);
 1317   rc= mysql_query(mysql, "drop table t1");
 1318   check_mysql_rc(rc, mysql);
 1319   return OK;
 1320 }
 1321 
 1322 /*
 1323   Bug#14210 "Simple query with > operator on large table gives server
 1324   crash"
 1325 */
 1326 
 1327 static int test_bug14210(MYSQL *mysql)
 1328 {
 1329   MYSQL_STMT *stmt;
 1330   int rc, i;
 1331   const char *stmt_text;
 1332   ulong type;
 1333 
 1334   rc= mysql_query(mysql, "drop table if exists t1");
 1335   check_mysql_rc(rc, mysql);
 1336   /*
 1337     To trigger the problem the table must be InnoDB, although the problem
 1338     itself is not InnoDB related. In case the table is MyISAM this test
 1339     is harmless.
 1340   */
 1341   rc= mysql_query(mysql, "create table t1 (a varchar(255)) engine=InnoDB");
 1342   check_mysql_rc(rc, mysql);
 1343   rc= mysql_query(mysql, "insert into t1 (a) values (repeat('a', 256))");
 1344   check_mysql_rc(rc, mysql);
 1345   rc= mysql_query(mysql, "set @@session.max_heap_table_size=16384");
 1346 
 1347   /* Create a big enough table (more than max_heap_table_size) */
 1348   for (i= 0; i < 8; i++)
 1349   {
 1350     rc= mysql_query(mysql, "insert into t1 (a) select a from t1");
 1351     check_mysql_rc(rc, mysql);
 1352   }
 1353   /* create statement */
 1354   stmt= mysql_stmt_init(mysql);
 1355   type= (ulong) CURSOR_TYPE_READ_ONLY;
 1356   mysql_stmt_attr_set(stmt, STMT_ATTR_CURSOR_TYPE, (const void*) &type);
 1357 
 1358   stmt_text= "select a from t1";
 1359 
 1360   rc= mysql_stmt_prepare(stmt, SL(stmt_text));
 1361   check_stmt_rc(rc, stmt);
 1362   rc= mysql_stmt_execute(stmt);
 1363   while ((rc= mysql_stmt_fetch(stmt)) == 0);
 1364   FAIL_UNLESS(rc == MYSQL_NO_DATA, "rc != MYSQL_NO_DATA");
 1365 
 1366   rc= mysql_stmt_close(stmt);
 1367 
 1368   rc= mysql_query(mysql, "drop table t1");
 1369   check_mysql_rc(rc, mysql);
 1370   rc= mysql_query(mysql, "set @@session.max_heap_table_size=default");
 1371   check_mysql_rc(rc, mysql);
 1372 
 1373   return OK;
 1374 }
 1375 
 1376 /*
 1377   Bug#24179 "select b into $var" fails with --cursor_protocol"
 1378   The failure is correct, check that the returned message is meaningful.
 1379 */
 1380 
 1381 static int test_bug24179(MYSQL *mysql)
 1382 {
 1383   int rc;
 1384   MYSQL_STMT *stmt;
 1385 
 1386   stmt= open_cursor(mysql, "select 1 into @a");
 1387   rc= mysql_stmt_execute(stmt);
 1388   FAIL_UNLESS(rc, "Error expected");
 1389   FAIL_UNLESS(mysql_stmt_errno(stmt) == 1323, "stmt_errno != 1323");
 1390   mysql_stmt_close(stmt);
 1391 
 1392   return OK;
 1393 }
 1394 
 1395 /**
 1396   Bug#32265 Server returns different metadata if prepared statement is used
 1397 */
 1398 
 1399 static int test_bug32265(MYSQL *mysql)
 1400 {
 1401   int rc;
 1402   MYSQL_STMT *stmt;
 1403   MYSQL_FIELD *field;
 1404   MYSQL_RES *metadata;
 1405 
 1406   if (mysql_get_server_version(mysql) < 50100) {
 1407     diag("Test requires MySQL Server version 5.1 or above");
 1408     return SKIP;
 1409   }
 1410 
 1411   rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1");
 1412   check_mysql_rc(rc, mysql);
 1413   rc= mysql_query(mysql, "DROP VIEW IF EXISTS v1");
 1414   rc= mysql_query(mysql, "CREATE  TABLE t1 (a INTEGER)");
 1415   check_mysql_rc(rc, mysql);
 1416   rc= mysql_query(mysql, "INSERT INTO t1 VALUES (1)");
 1417   check_mysql_rc(rc, mysql);
 1418   rc= mysql_query(mysql, "CREATE VIEW v1 AS SELECT * FROM t1");
 1419   check_mysql_rc(rc, mysql);
 1420 
 1421   stmt= open_cursor(mysql, "SELECT * FROM t1");
 1422   rc= mysql_stmt_execute(stmt);
 1423   check_stmt_rc(rc, stmt);
 1424   metadata= mysql_stmt_result_metadata(stmt);
 1425   field= mysql_fetch_field(metadata);
 1426   FAIL_UNLESS(field, "couldn't fetch field");
 1427   FAIL_UNLESS(strcmp(field->table, "t1") == 0, "table != t1");
 1428   FAIL_UNLESS(strcmp(field->org_table, "t1") == 0, "org_table != t1");
 1429   FAIL_UNLESS(strcmp(field->db, schema) == 0, "db != schema");
 1430   mysql_free_result(metadata);
 1431   mysql_stmt_close(stmt);
 1432 
 1433   stmt= open_cursor(mysql, "SELECT a '' FROM t1 ``");
 1434   rc= mysql_stmt_execute(stmt);
 1435   check_stmt_rc(rc, stmt);
 1436   metadata= mysql_stmt_result_metadata(stmt);
 1437   field= mysql_fetch_field(metadata);
 1438   FAIL_UNLESS(strcmp(field->table, "") == 0, "field != ''");
 1439   FAIL_UNLESS(strcmp(field->org_table, "t1") == 0, "org_table != t1");
 1440   FAIL_UNLESS(strcmp(field->db, schema) == 0, "db != schema");
 1441   mysql_free_result(metadata);
 1442   mysql_stmt_close(stmt);
 1443 
 1444   stmt= open_cursor(mysql, "SELECT a '' FROM t1 ``");
 1445   rc= mysql_stmt_execute(stmt);
 1446   check_stmt_rc(rc, stmt);
 1447   metadata= mysql_stmt_result_metadata(stmt);
 1448   field= mysql_fetch_field(metadata);
 1449   FAIL_UNLESS(strcmp(field->table, "") == 0, "table != ''");
 1450   FAIL_UNLESS(strcmp(field->org_table, "t1") == 0, "org_table != t1");
 1451   FAIL_UNLESS(strcmp(field->db, schema) == 0, "db != schema");
 1452   mysql_free_result(metadata);
 1453   mysql_stmt_close(stmt);
 1454 
 1455   stmt= open_cursor(mysql, "SELECT * FROM v1");
 1456   rc= mysql_stmt_execute(stmt);
 1457   check_stmt_rc(rc, stmt);
 1458   metadata= mysql_stmt_result_metadata(stmt);
 1459   field= mysql_fetch_field(metadata);
 1460   FAIL_UNLESS(strcmp(field->table, "v1") == 0, "table != v1");
 1461   FAIL_UNLESS(strcmp(field->org_table, "v1") == 0, "org_table != v1");
 1462   FAIL_UNLESS(strcmp(field->db, schema) == 0, "db != schema");
 1463   mysql_free_result(metadata);
 1464   mysql_stmt_close(stmt);
 1465 
 1466   stmt= open_cursor(mysql, "SELECT * FROM v1 /* SIC */ GROUP BY 1");
 1467   rc= mysql_stmt_execute(stmt);
 1468   check_stmt_rc(rc, stmt);
 1469   metadata= mysql_stmt_result_metadata(stmt);
 1470   field= mysql_fetch_field(metadata);
 1471   FAIL_UNLESS(strcmp(field->table, "v1") == 0, "table != v1");
 1472   FAIL_UNLESS(strcmp(field->org_table, "v1") == 0, "org_table != v1");
 1473   FAIL_UNLESS(strcmp(field->db, schema) == 0, "schema != db");
 1474   mysql_free_result(metadata);
 1475   mysql_stmt_close(stmt);
 1476 
 1477   rc= mysql_query(mysql, "DROP VIEW v1");
 1478   check_mysql_rc(rc, mysql);
 1479   rc= mysql_query(mysql, "DROP TABLE t1");
 1480   check_mysql_rc(rc, mysql);
 1481 
 1482   return OK;
 1483 }
 1484 
 1485 /**
 1486   Bug#38486 Crash when using cursor protocol
 1487 */
 1488 
 1489 static int test_bug38486(MYSQL *mysql)
 1490 {
 1491   MYSQL_STMT *stmt;
 1492   const char *stmt_text;
 1493   int rc;
 1494   unsigned long type= CURSOR_TYPE_READ_ONLY;
 1495 
 1496   stmt= mysql_stmt_init(mysql);
 1497   rc= mysql_stmt_attr_set(stmt, STMT_ATTR_CURSOR_TYPE, (void*)&type);
 1498   check_stmt_rc(rc, stmt);
 1499   stmt_text= "CREATE TABLE t1 (a INT)";
 1500   rc= mysql_stmt_prepare(stmt, SL(stmt_text));
 1501   check_stmt_rc(rc, stmt);
 1502   rc= mysql_stmt_execute(stmt);
 1503   mysql_stmt_close(stmt);
 1504 
 1505   stmt= mysql_stmt_init(mysql);
 1506   rc= mysql_stmt_attr_set(stmt, STMT_ATTR_CURSOR_TYPE, (void*)&type);
 1507   check_stmt_rc(rc, stmt);
 1508   stmt_text= "INSERT INTO t1 VALUES (1)";
 1509   rc= mysql_stmt_prepare(stmt, SL(stmt_text));
 1510   check_stmt_rc(rc, stmt);
 1511   rc= mysql_stmt_execute(stmt);
 1512   check_stmt_rc(rc, stmt);
 1513   mysql_stmt_close(stmt);
 1514 
 1515   return OK;
 1516 }
 1517 
 1518 static int test_bug8880(MYSQL *mysql)
 1519 {
 1520   MYSQL_STMT *stmt_list[2], **stmt;
 1521   MYSQL_STMT **stmt_list_end= (MYSQL_STMT**) stmt_list + 2;
 1522   int rc;
 1523 
 1524 
 1525   rc= mysql_query(mysql, "drop table if exists t1");
 1526   check_mysql_rc(rc, mysql);
 1527   rc= mysql_query(mysql, "create table t1 (a int not null primary key, b int)");
 1528   check_mysql_rc(rc, mysql);
 1529   rc= mysql_query(mysql, "insert into t1 values (1,1)");
 1530   check_mysql_rc(rc, mysql);
 1531   /*
 1532     when inserting 2 rows everything works well
 1533     mysql_query(mysql, "INSERT INTO t1 VALUES (1,1),(2,2)");
 1534   */
 1535   for (stmt= stmt_list; stmt < stmt_list_end; stmt++)
 1536     *stmt= open_cursor(mysql, "select a from t1");
 1537   for (stmt= stmt_list; stmt < stmt_list_end; stmt++)
 1538   {
 1539     rc= mysql_stmt_execute(*stmt);
 1540     check_stmt_rc(rc, *stmt);
 1541   }
 1542   for (stmt= stmt_list; stmt < stmt_list_end; stmt++)
 1543     mysql_stmt_close(*stmt);
 1544   return OK;
 1545 }
 1546 
 1547 static int test_bug9159(MYSQL *mysql)
 1548 {
 1549   MYSQL_STMT *stmt;
 1550   int rc;
 1551   const char *stmt_text= "select a, b from t1";
 1552   const unsigned long type= CURSOR_TYPE_READ_ONLY;
 1553 
 1554 
 1555   mysql_query(mysql, "drop table if exists t1");
 1556   mysql_query(mysql, "create table t1 (a int not null primary key, b int)");
 1557   rc= mysql_query(mysql, "insert into t1 values (1,1)");
 1558   check_mysql_rc(rc, mysql);
 1559 
 1560   stmt= mysql_stmt_init(mysql);
 1561   mysql_stmt_prepare(stmt, SL(stmt_text));
 1562   mysql_stmt_attr_set(stmt, STMT_ATTR_CURSOR_TYPE, (const void *)&type);
 1563 
 1564   mysql_stmt_execute(stmt);
 1565   mysql_stmt_close(stmt);
 1566   rc= mysql_query(mysql, "drop table if exists t1");
 1567   check_mysql_rc(rc, mysql);
 1568   return OK;
 1569 }
 1570 
 1571 /*
 1572   We can't have more than one cursor open for a prepared statement.
 1573   Test re-executions of a PS with cursor; mysql_stmt_reset must close
 1574   the cursor attached to the statement, if there is one.
 1575 */
 1576 
 1577 static int test_bug9478(MYSQL *mysql)
 1578 {
 1579   MYSQL_STMT *stmt;
 1580   MYSQL_BIND my_bind[1];
 1581   char a[6];
 1582   ulong a_len;
 1583   int rc, i;
 1584 
 1585   mysql_query(mysql, "drop table if exists t1");
 1586   mysql_query(mysql, "create table t1 (id integer not null primary key, "
 1587                      " name varchar(20) not null)");
 1588   rc= mysql_query(mysql, "insert into t1 (id, name) values "
 1589                          " (1, 'aaa'), (2, 'bbb'), (3, 'ccc')");
 1590   check_mysql_rc(rc, mysql);
 1591 
 1592   stmt= open_cursor(mysql, "select name from t1 where id=2");
 1593 
 1594   memset(my_bind, '\0', sizeof(my_bind));
 1595   my_bind[0].buffer_type= MYSQL_TYPE_STRING;
 1596   my_bind[0].buffer= (char*) a;
 1597   my_bind[0].buffer_length= sizeof(a);
 1598   my_bind[0].length= &a_len;
 1599   mysql_stmt_bind_result(stmt, my_bind);
 1600 
 1601   for (i= 0; i < 5; i++)
 1602   {
 1603     rc= mysql_stmt_execute(stmt);
 1604     check_stmt_rc(rc, stmt);
 1605     rc= mysql_stmt_fetch(stmt);
 1606     check_stmt_rc(rc, stmt);
 1607 
 1608     /*
 1609       The query above is a one-row result set. Therefore, there is no
 1610       cursor associated with it, as the server won't bother with opening
 1611       a cursor for a one-row result set. The first row was read from the
 1612       server in the fetch above. But there is eof packet pending in the
 1613       network. mysql_stmt_execute will flush the packet and successfully
 1614       execute the statement.
 1615     */
 1616 
 1617     rc= mysql_stmt_execute(stmt);
 1618     check_stmt_rc(rc, stmt);
 1619 
 1620     rc= mysql_stmt_fetch(stmt);
 1621     check_stmt_rc(rc, stmt);
 1622     rc= mysql_stmt_fetch(stmt);
 1623     FAIL_UNLESS(rc == MYSQL_NO_DATA, "rc != MYSQL_NO_DATA");
 1624 
 1625     {
 1626       char buff[8];
 1627       /* Fill in the fetch packet */
 1628       int4store(buff, stmt->stmt_id);
 1629       buff[4]= 1;                               /* prefetch rows */
 1630 /*      rc= ((*mysql->methods->advanced_command)(mysql, COM_STMT_FETCH,
 1631                                                (uchar*) buff,
 1632                                                sizeof(buff), 0,0,1,NULL) ||
 1633            (*mysql->methods->read_query_result)(mysql)); */
 1634       FAIL_UNLESS(rc, "error expected");
 1635     }
 1636 
 1637     rc= mysql_stmt_execute(stmt);
 1638     check_stmt_rc(rc, stmt);
 1639 
 1640     rc= mysql_stmt_fetch(stmt);
 1641     check_stmt_rc(rc, stmt);
 1642 
 1643     rc= mysql_stmt_reset(stmt);
 1644     check_stmt_rc(rc, stmt);
 1645     rc= mysql_stmt_fetch(stmt);
 1646 
 1647     /* mariadb client supports GEOMETRY, so no error will
 1648        be returned 
 1649     FAIL_UNLESS(rc && mysql_stmt_errno(stmt), "Error expected");
 1650     */
 1651   }
 1652   rc= mysql_stmt_close(stmt);
 1653   check_stmt_rc(rc, stmt);
 1654 
 1655   /* Test the case with a server side cursor */
 1656   stmt= open_cursor(mysql, "select name from t1");
 1657 
 1658   mysql_stmt_bind_result(stmt, my_bind);
 1659 
 1660   for (i= 0; i < 5; i++)
 1661   {
 1662     rc= mysql_stmt_execute(stmt);
 1663     check_stmt_rc(rc, stmt);
 1664     rc= mysql_stmt_fetch(stmt);
 1665     check_stmt_rc(rc, stmt);
 1666     rc= mysql_stmt_execute(stmt);
 1667     check_stmt_rc(rc, stmt);
 1668 
 1669     while (! (rc= mysql_stmt_fetch(stmt)));
 1670     FAIL_UNLESS(rc == MYSQL_NO_DATA, "rc != MYSQL_NO_DATA");
 1671 
 1672     rc= mysql_stmt_execute(stmt);
 1673     check_stmt_rc(rc, stmt);
 1674 
 1675     rc= mysql_stmt_fetch(stmt);
 1676     check_stmt_rc(rc, stmt);
 1677 
 1678     rc= mysql_stmt_reset(stmt);
 1679     check_stmt_rc(rc, stmt);
 1680     rc= mysql_stmt_fetch(stmt);
 1681     FAIL_UNLESS(rc && mysql_stmt_errno(stmt), "Error expected");
 1682   }
 1683 
 1684   rc= mysql_stmt_close(stmt);
 1685   check_stmt_rc(rc, stmt);
 1686 
 1687   rc= mysql_query(mysql, "drop table t1");
 1688   check_mysql_rc(rc, mysql);
 1689   return OK;
 1690 }
 1691 
 1692 /* Crash when opening a cursor to a query with DISTICNT and no key */
 1693 
 1694 static int test_bug9520(MYSQL *mysql)
 1695 {
 1696   MYSQL_STMT *stmt;
 1697   MYSQL_BIND my_bind[1];
 1698   char a[6];
 1699   ulong a_len;
 1700   int rc, row_count= 0;
 1701 
 1702 
 1703   mysql_query(mysql, "drop table if exists t1");
 1704   mysql_query(mysql, "create table t1 (a char(5), b char(5), c char(5),"
 1705                      " primary key (a, b, c))");
 1706   rc= mysql_query(mysql, "insert into t1 values ('x', 'y', 'z'), "
 1707                   " ('a', 'b', 'c'), ('k', 'l', 'm')");
 1708   check_mysql_rc(rc, mysql);
 1709 
 1710   stmt= open_cursor(mysql, "select distinct b from t1");
 1711 
 1712   /*
 1713     Not crashes with:
 1714     stmt= open_cursor(mysql, "select distinct a from t1");
 1715   */
 1716 
 1717   rc= mysql_stmt_execute(stmt);
 1718   check_stmt_rc(rc, stmt);
 1719 
 1720   memset(my_bind, '\0', sizeof(my_bind));
 1721   my_bind[0].buffer_type= MYSQL_TYPE_STRING;
 1722   my_bind[0].buffer= (char*) a;
 1723   my_bind[0].buffer_length= sizeof(a);
 1724   my_bind[0].length= &a_len;
 1725 
 1726   mysql_stmt_bind_result(stmt, my_bind);
 1727 
 1728   while (!(rc= mysql_stmt_fetch(stmt)))
 1729     row_count++;
 1730 
 1731   FAIL_UNLESS(rc == MYSQL_NO_DATA, "rc != MYSQL_NO_DATA");
 1732 
 1733   FAIL_UNLESS(row_count == 3, "row_count != 3");
 1734 
 1735   mysql_stmt_close(stmt);
 1736 
 1737   rc= mysql_query(mysql, "drop table t1");
 1738   check_mysql_rc(rc, mysql);
 1739   return OK;
 1740 }
 1741 
 1742 /*
 1743   Error message is returned for unsupported features.
 1744   Test also cursors with non-default PREFETCH_ROWS
 1745 */
 1746 
 1747 static int test_bug9643(MYSQL *mysql)
 1748 {
 1749   MYSQL_STMT *stmt;
 1750   MYSQL_BIND my_bind[1];
 1751   int32 a;
 1752   int rc;
 1753   const char *stmt_text;
 1754   int num_rows= 0;
 1755   ulong type;
 1756   ulong prefetch_rows= 5;
 1757 
 1758 
 1759   mysql_query(mysql, "drop table if exists t1");
 1760   mysql_query(mysql, "create table t1 (id integer not null primary key)");
 1761   rc= mysql_query(mysql, "insert into t1 (id) values "
 1762                          " (1), (2), (3), (4), (5), (6), (7), (8), (9)");
 1763   check_mysql_rc(rc, mysql);
 1764 
 1765   stmt= mysql_stmt_init(mysql);
 1766   /* Not implemented in 5.0 */
 1767   type= (ulong) CURSOR_TYPE_SCROLLABLE;
 1768   rc= mysql_stmt_attr_set(stmt, STMT_ATTR_CURSOR_TYPE, (void*) &type);
 1769   FAIL_UNLESS(rc, "Error expected");
 1770 
 1771   type= (ulong) CURSOR_TYPE_READ_ONLY;
 1772   rc= mysql_stmt_attr_set(stmt, STMT_ATTR_CURSOR_TYPE, (void*) &type);
 1773   check_stmt_rc(rc, stmt);
 1774   rc= mysql_stmt_attr_set(stmt, STMT_ATTR_PREFETCH_ROWS,
 1775                           (void*) &prefetch_rows);
 1776   check_stmt_rc(rc, stmt);
 1777   stmt_text= "select * from t1";
 1778   rc= mysql_stmt_prepare(stmt, SL(stmt_text));
 1779   check_stmt_rc(rc, stmt);
 1780 
 1781   memset(my_bind, '\0', sizeof(my_bind));
 1782   my_bind[0].buffer_type= MYSQL_TYPE_LONG;
 1783   my_bind[0].buffer= (void*) &a;
 1784   my_bind[0].buffer_length= sizeof(a);
 1785   mysql_stmt_bind_result(stmt, my_bind);
 1786 
 1787   rc= mysql_stmt_execute(stmt);
 1788   check_stmt_rc(rc, stmt);
 1789 
 1790   while ((rc= mysql_stmt_fetch(stmt)) == 0)
 1791     ++num_rows;
 1792   FAIL_UNLESS(num_rows == 9, "num_rows != 9");
 1793 
 1794   rc= mysql_stmt_close(stmt);
 1795   FAIL_UNLESS(rc == 0, "");
 1796 
 1797   rc= mysql_query(mysql, "drop table t1");
 1798   check_mysql_rc(rc, mysql);
 1799   return OK;
 1800 }
 1801 
 1802 
 1803 struct my_tests_st my_tests[] = {
 1804   {"test_basic_cursors", test_basic_cursors, TEST_CONNECTION_DEFAULT, 0, NULL , NULL},
 1805   {"test_cursors_with_union", test_cursors_with_union, TEST_CONNECTION_DEFAULT, 0, NULL , NULL},
 1806   {"test_cursors_with_procedure", test_cursors_with_procedure, TEST_CONNECTION_DEFAULT, 0, NULL , NULL},
 1807   {"test_bug21206", test_bug21206, TEST_CONNECTION_DEFAULT, 0, NULL , NULL},
 1808   {"test_bug10729", test_bug10729, TEST_CONNECTION_DEFAULT, 0, NULL , NULL}, 
 1809   {"test_bug10736", test_bug10736, TEST_CONNECTION_DEFAULT, 0, NULL , NULL},
 1810   {"test_bug10794", test_bug10794, TEST_CONNECTION_DEFAULT, 0, NULL , NULL},
 1811   {"test_bug10760", test_bug10760, TEST_CONNECTION_DEFAULT, 0, NULL , NULL},
 1812   {"test_bug11172", test_bug11172, TEST_CONNECTION_DEFAULT, 0, NULL , NULL},
 1813   {"test_bug11656", test_bug11656, TEST_CONNECTION_DEFAULT, 0, NULL , NULL},
 1814   {"test_bug11901", test_bug11901, TEST_CONNECTION_DEFAULT, 0, NULL , NULL},
 1815   {"test_bug11904", test_bug11904, TEST_CONNECTION_DEFAULT, 0, NULL , NULL},
 1816   {"test_bug12243", test_bug12243, TEST_CONNECTION_DEFAULT, 0, NULL , NULL},
 1817   {"test_bug11909", test_bug11909, TEST_CONNECTION_DEFAULT, 0, NULL , NULL},
 1818   {"test_bug13488", test_bug13488, TEST_CONNECTION_DEFAULT, 0, NULL , NULL},
 1819   {"test_bug13524", test_bug13524, TEST_CONNECTION_DEFAULT, 0, NULL , NULL},
 1820   {"test_bug14845", test_bug14845, TEST_CONNECTION_DEFAULT, 0, NULL , NULL},
 1821   {"test_bug14210", test_bug14210, TEST_CONNECTION_DEFAULT, 0, NULL , NULL},
 1822   {"test_bug24179", test_bug24179, TEST_CONNECTION_DEFAULT, 0, NULL , NULL},
 1823   {"test_bug32265", test_bug32265, TEST_CONNECTION_DEFAULT, 0, NULL , NULL},
 1824   {"test_bug38486", test_bug38486, TEST_CONNECTION_DEFAULT, 0, NULL , NULL},
 1825   {"test_bug8880", test_bug8880, TEST_CONNECTION_DEFAULT, 0, NULL , NULL},
 1826   {"test_bug9159", test_bug9159, TEST_CONNECTION_DEFAULT, 0, NULL , NULL},
 1827   {"test_bug9478", test_bug9478, TEST_CONNECTION_DEFAULT, 0, NULL , NULL},
 1828   {"test_bug9520", test_bug9520, TEST_CONNECTION_DEFAULT, 0, NULL , NULL},
 1829   {"test_bug9643", test_bug9643, TEST_CONNECTION_DEFAULT, 0, NULL , NULL},
 1830   {NULL, NULL, 0, 0, NULL, NULL}
 1831 };
 1832 
 1833 int main(int argc, char **argv)
 1834 {
 1835   if (argc > 1)
 1836     get_options(argc, argv);
 1837 
 1838   get_envvars();
 1839 
 1840   run_tests(my_tests);
 1841 
 1842   return(exit_status());
 1843 }