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