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