1 | /* |
2 | Copyright 2011 Kristian Nielsen and Monty Program Ab. |
3 | |
4 | This file is free software; you can redistribute it and/or |
5 | modify it under the terms of the GNU Lesser General Public |
6 | License as published by the Free Software Foundation; either |
7 | version 2.1 of the License, or (at your option) any later version. |
8 | |
9 | This library is distributed in the hope that it will be useful, |
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
12 | Lesser General Public License for more details. |
13 | |
14 | You should have received a copy of the GNU General Public License |
15 | along with this. If not, see <http://www.gnu.org/licenses/>. |
16 | */ |
17 | #include "my_test.h" |
18 | #include "ma_common.h" |
19 | |
20 | #define TEST_ARRAY_SIZE 1024 |
21 | |
22 | static my_bool bulk_enabled= 0; |
23 | |
24 | char *rand_str(size_t length) { |
25 | const char charset[] = "0123456789" |
26 | "abcdefghijklmnopqrstuvwxyz" |
27 | "ABCDEFGHIJKLMNOPQRSTUVWXYZ" ; |
28 | char *dest= (char *)malloc(length+1); |
29 | char *p= dest; |
30 | while (length-- > 0) { |
31 | *dest++ = charset[rand() % sizeof(charset)]; |
32 | } |
33 | *dest = '\0'; |
34 | return p; |
35 | } |
36 | |
37 | static int check_bulk(MYSQL *mysql) |
38 | { |
39 | bulk_enabled= (!(mysql->server_capabilities & CLIENT_MYSQL) && |
40 | (mysql->extension->mariadb_server_capabilities & |
41 | (MARIADB_CLIENT_STMT_BULK_OPERATIONS >> 32))); |
42 | diag("bulk %ssupported" , bulk_enabled ? "" : "not " ); |
43 | return OK; |
44 | } |
45 | |
46 | static int bulk1(MYSQL *mysql) |
47 | { |
48 | MYSQL_STMT *stmt= mysql_stmt_init(mysql); |
49 | const char *stmt_str= "INSERT INTO bulk1 VALUES (?,?)" ; |
50 | unsigned int array_size= TEST_ARRAY_SIZE; |
51 | int rc; |
52 | unsigned int i; |
53 | char **buffer; |
54 | unsigned long *lengths; |
55 | unsigned int *vals; |
56 | MYSQL_BIND bind[2]; |
57 | MYSQL_RES *res; |
58 | MYSQL_ROW row; |
59 | unsigned int intval; |
60 | |
61 | if (!bulk_enabled) |
62 | return SKIP; |
63 | |
64 | rc= mysql_select_db(mysql, "testc" ); |
65 | |
66 | rc= mysql_query(mysql, "DROP TABLE IF EXISTS bulk1" ); |
67 | check_mysql_rc(rc, mysql); |
68 | |
69 | rc= mysql_query(mysql, "CREATE TABLE bulk1 (a int , b VARCHAR(255))" ); |
70 | check_mysql_rc(rc, mysql); |
71 | |
72 | rc= mysql_stmt_prepare(stmt, SL(stmt_str)); |
73 | check_stmt_rc(rc, stmt); |
74 | |
75 | /* allocate memory */ |
76 | buffer= calloc(TEST_ARRAY_SIZE, sizeof(char *)); |
77 | lengths= (unsigned long *)calloc(sizeof(long), TEST_ARRAY_SIZE); |
78 | vals= (unsigned int *)calloc(sizeof(int), TEST_ARRAY_SIZE); |
79 | |
80 | for (i=0; i < TEST_ARRAY_SIZE; i++) |
81 | { |
82 | buffer[i]= rand_str(254); |
83 | lengths[i]= -1; |
84 | vals[i]= i; |
85 | } |
86 | |
87 | memset(bind, 0, sizeof(MYSQL_BIND) * 2); |
88 | bind[0].buffer_type= MYSQL_TYPE_LONG; |
89 | bind[0].buffer= vals; |
90 | bind[1].buffer_type= MYSQL_TYPE_STRING; |
91 | bind[1].buffer= (void *)buffer; |
92 | bind[1].length= (unsigned long *)lengths; |
93 | |
94 | rc= mysql_stmt_attr_set(stmt, STMT_ATTR_ARRAY_SIZE, &array_size); |
95 | check_stmt_rc(rc, stmt); |
96 | |
97 | rc= mysql_stmt_bind_param(stmt, bind); |
98 | check_stmt_rc(rc, stmt); |
99 | |
100 | for (i=0; i < 100; i++) |
101 | { |
102 | rc= mysql_stmt_execute(stmt); |
103 | check_stmt_rc(rc, stmt); |
104 | FAIL_IF(mysql_stmt_affected_rows(stmt) != TEST_ARRAY_SIZE, "affected_rows != TEST_ARRAY_SIZE" ); |
105 | } |
106 | |
107 | for (i=0; i < array_size; i++) |
108 | free(buffer[i]); |
109 | |
110 | free(buffer); |
111 | free(lengths); |
112 | free(vals); |
113 | |
114 | rc= mysql_stmt_close(stmt); |
115 | check_mysql_rc(rc, mysql); |
116 | |
117 | rc= mysql_query(mysql, "SELECT COUNT(*) FROM bulk1" ); |
118 | check_mysql_rc(rc, mysql); |
119 | |
120 | res= mysql_store_result(mysql); |
121 | row= mysql_fetch_row(res); |
122 | intval= atoi(row[0]); |
123 | mysql_free_result(res); |
124 | FAIL_IF(intval != array_size * 100, "Expected 102400 rows" ); |
125 | |
126 | rc= mysql_query(mysql, "SELECT MAX(a) FROM bulk1" ); |
127 | check_mysql_rc(rc, mysql); |
128 | |
129 | res= mysql_store_result(mysql); |
130 | row= mysql_fetch_row(res); |
131 | intval= atoi(row[0]); |
132 | mysql_free_result(res); |
133 | FAIL_IF(intval != array_size - 1, "Expected max value 1024" ); |
134 | |
135 | rc= mysql_query(mysql, "DROP TABLE IF EXISTS bulk1" ); |
136 | check_mysql_rc(rc, mysql); |
137 | return OK; |
138 | } |
139 | |
140 | static int bulk2(MYSQL *mysql) |
141 | { |
142 | MYSQL_STMT *stmt= mysql_stmt_init(mysql); |
143 | int rc; |
144 | MYSQL_BIND bind[2]; |
145 | unsigned int i; |
146 | unsigned int array_size=1024; |
147 | char indicator[1024]; |
148 | long lval[1024]; |
149 | |
150 | if (!bulk_enabled) |
151 | return SKIP; |
152 | rc= mysql_query(mysql, "DROP TABLE IF EXISTS bulk2" ); |
153 | check_mysql_rc(rc, mysql); |
154 | |
155 | rc= mysql_query(mysql, "CREATE TABLE bulk2 (a int default 4, b int default 2)" ); |
156 | check_mysql_rc(rc, mysql); |
157 | |
158 | rc= mysql_stmt_prepare(stmt, SL("INSERT INTO bulk2 VALUES (?,1)" )); |
159 | check_stmt_rc(rc, stmt); |
160 | |
161 | memset(bind, 0, 2 * sizeof(MYSQL_BIND)); |
162 | |
163 | for (i=0; i < array_size; i++) |
164 | { |
165 | indicator[i]= STMT_INDICATOR_DEFAULT; |
166 | lval[i]= i; |
167 | } |
168 | |
169 | bind[0].buffer_type= MYSQL_TYPE_LONG; |
170 | bind[0].u.indicator= indicator; |
171 | bind[1].buffer_type= MYSQL_TYPE_LONG; |
172 | bind[1].buffer= &lval; |
173 | |
174 | rc= mysql_stmt_attr_set(stmt, STMT_ATTR_ARRAY_SIZE, &array_size); |
175 | check_stmt_rc(rc, stmt); |
176 | |
177 | rc= mysql_stmt_bind_param(stmt, bind); |
178 | check_stmt_rc(rc, stmt); |
179 | |
180 | rc= mysql_stmt_execute(stmt); |
181 | check_stmt_rc(rc, stmt); |
182 | |
183 | mysql_stmt_close(stmt); |
184 | rc= mysql_query(mysql, "DROP TABLE IF EXISTS bulk2" ); |
185 | check_mysql_rc(rc, mysql); |
186 | |
187 | return OK; |
188 | } |
189 | |
190 | static int bulk3(MYSQL *mysql) |
191 | { |
192 | struct st_bulk3 { |
193 | char char_value[20]; |
194 | unsigned long length; |
195 | int int_value; |
196 | }; |
197 | |
198 | struct st_bulk3 val[3]= {{"Row 1" , 5, 1}, |
199 | {"Row 02" , 6, 2}, |
200 | {"Row 003" , 7, 3}}; |
201 | int rc; |
202 | MYSQL_BIND bind[2]; |
203 | MYSQL_STMT *stmt= mysql_stmt_init(mysql); |
204 | size_t row_size= sizeof(struct st_bulk3); |
205 | int array_size= 3; |
206 | |
207 | if (!bulk_enabled) |
208 | return SKIP; |
209 | rc= mysql_query(mysql, "DROP TABLE IF EXISTS bulk3" ); |
210 | check_mysql_rc(rc,mysql); |
211 | rc= mysql_query(mysql, "CREATE TABLE bulk3 (name varchar(20), row int)" ); |
212 | check_mysql_rc(rc,mysql); |
213 | |
214 | rc= mysql_stmt_prepare(stmt, SL("INSERT INTO bulk3 VALUES (?,?)" )); |
215 | check_stmt_rc(rc, stmt); |
216 | |
217 | memset(bind, 0, sizeof(MYSQL_BIND)*2); |
218 | |
219 | rc= mysql_stmt_attr_set(stmt, STMT_ATTR_ARRAY_SIZE, &array_size); |
220 | check_stmt_rc(rc, stmt); |
221 | rc= mysql_stmt_attr_set(stmt, STMT_ATTR_ROW_SIZE, &row_size); |
222 | check_stmt_rc(rc, stmt); |
223 | |
224 | bind[0].buffer_type= MYSQL_TYPE_STRING; |
225 | bind[0].buffer= &val[0].char_value; |
226 | bind[0].length= &val[0].length; |
227 | bind[1].buffer_type= MYSQL_TYPE_LONG; |
228 | bind[1].buffer= &val[0].int_value; |
229 | |
230 | rc= mysql_stmt_bind_param(stmt, bind); |
231 | check_stmt_rc(rc, stmt); |
232 | rc= mysql_stmt_execute(stmt); |
233 | check_stmt_rc(rc, stmt); |
234 | |
235 | mysql_stmt_close(stmt); |
236 | rc= mysql_query(mysql, "DROP TABLE IF EXISTS bulk3" ); |
237 | check_mysql_rc(rc, mysql); |
238 | return OK; |
239 | } |
240 | |
241 | static int bulk4(MYSQL *mysql) |
242 | { |
243 | struct st_bulk4 { |
244 | char char_value[20]; |
245 | char indicator1; |
246 | int int_value; |
247 | char indicator2; |
248 | }; |
249 | |
250 | struct st_bulk4 val[]= {{"Row 1" , STMT_INDICATOR_NTS, 0, STMT_INDICATOR_DEFAULT}, |
251 | {"Row 2" , STMT_INDICATOR_NTS, 0, STMT_INDICATOR_DEFAULT}, |
252 | {"Row 3" , STMT_INDICATOR_NTS, 0, STMT_INDICATOR_DEFAULT}}; |
253 | int rc; |
254 | MYSQL_BIND bind[2]; |
255 | MYSQL_RES *res; |
256 | MYSQL_STMT *stmt= mysql_stmt_init(mysql); |
257 | size_t row_size= sizeof(struct st_bulk4); |
258 | int array_size= 3; |
259 | unsigned long lengths[3]= {-1, -1, -1}; |
260 | |
261 | if (!bulk_enabled) |
262 | return SKIP; |
263 | rc= mysql_query(mysql, "DROP TABLE IF EXISTS bulk4" ); |
264 | check_mysql_rc(rc,mysql); |
265 | rc= mysql_query(mysql, "CREATE TABLE bulk4 (name varchar(20), row int not null default 3)" ); |
266 | check_mysql_rc(rc,mysql); |
267 | |
268 | rc= mysql_stmt_prepare(stmt, SL("INSERT INTO bulk4 VALUES (?,?)" )); |
269 | check_stmt_rc(rc, stmt); |
270 | |
271 | memset(bind, 0, sizeof(MYSQL_BIND)*2); |
272 | |
273 | rc= mysql_stmt_attr_set(stmt, STMT_ATTR_ARRAY_SIZE, &array_size); |
274 | check_stmt_rc(rc, stmt); |
275 | rc= mysql_stmt_attr_set(stmt, STMT_ATTR_ROW_SIZE, &row_size); |
276 | check_stmt_rc(rc, stmt); |
277 | |
278 | bind[0].buffer_type= MYSQL_TYPE_STRING; |
279 | bind[0].u.indicator= &val[0].indicator1; |
280 | bind[0].buffer= &val[0].char_value; |
281 | bind[0].length= lengths; |
282 | bind[1].buffer_type= MYSQL_TYPE_LONG; |
283 | bind[1].u.indicator= &val[0].indicator2; |
284 | |
285 | rc= mysql_stmt_bind_param(stmt, bind); |
286 | check_stmt_rc(rc, stmt); |
287 | rc= mysql_stmt_execute(stmt); |
288 | check_stmt_rc(rc, stmt); |
289 | |
290 | mysql_stmt_close(stmt); |
291 | |
292 | rc= mysql_query(mysql, "SELECT * FROM bulk4 WHERE row=3" ); |
293 | check_mysql_rc(rc, mysql); |
294 | res= mysql_store_result(mysql); |
295 | rc= (int)mysql_num_rows(res); |
296 | mysql_free_result(res); |
297 | FAIL_IF(rc != 3, "expected 3 rows" ); |
298 | rc= mysql_query(mysql, "DROP TABLE IF EXISTS bulk4" ); |
299 | check_mysql_rc(rc, mysql); |
300 | return OK; |
301 | } |
302 | |
303 | static int bulk_null(MYSQL *mysql) |
304 | { |
305 | MYSQL_STMT *stmt= mysql_stmt_init(mysql); |
306 | int rc; |
307 | MYSQL_BIND bind[2]; |
308 | unsigned int param_count= 2; |
309 | unsigned int array_size= 2; |
310 | unsigned long lengths[2]= {-1, -1}; |
311 | char **buf= calloc(1, 2 * sizeof(char *)); |
312 | |
313 | if (!bulk_enabled) |
314 | { |
315 | free(buf); |
316 | return SKIP; |
317 | } |
318 | |
319 | buf[0]= strdup("foo" ); |
320 | buf[1]= strdup("foobar" ); |
321 | |
322 | rc= mariadb_stmt_execute_direct(stmt, "DROP TABLE IF EXISTS bulk_null" , -1); |
323 | check_stmt_rc(rc, stmt); |
324 | |
325 | rc= mariadb_stmt_execute_direct(stmt, "CREATE TABLE bulk_null (a int not null auto_increment primary key, b varchar(20))" , -1); |
326 | check_stmt_rc(rc, stmt); |
327 | |
328 | memset(bind, 0, 2 * sizeof(MYSQL_BIND)); |
329 | bind[0].buffer_type= MYSQL_TYPE_NULL; |
330 | bind[1].buffer_type= MYSQL_TYPE_STRING; |
331 | bind[1].buffer= buf; |
332 | bind[1].length= lengths; |
333 | |
334 | mysql_stmt_close(stmt); |
335 | stmt= mysql_stmt_init(mysql); |
336 | |
337 | rc= mysql_stmt_attr_set(stmt, STMT_ATTR_PREBIND_PARAMS, ¶m_count); |
338 | check_stmt_rc(rc, stmt); |
339 | |
340 | rc= mysql_stmt_attr_set(stmt, STMT_ATTR_ARRAY_SIZE, &array_size); |
341 | check_stmt_rc(rc, stmt); |
342 | |
343 | rc= mysql_stmt_bind_param(stmt, bind); |
344 | check_stmt_rc(rc, stmt); |
345 | |
346 | rc= mariadb_stmt_execute_direct(stmt, "INSERT INTO bulk_null VALUES (?, ?)" , -1); |
347 | check_stmt_rc(rc, stmt); |
348 | |
349 | mysql_stmt_close(stmt); |
350 | free(buf); |
351 | rc= mysql_query(mysql, "DROP TABLE IF EXISTS bulk_null" ); |
352 | check_mysql_rc(rc, mysql); |
353 | return OK; |
354 | } |
355 | |
356 | static int bulk5(MYSQL *mysql) |
357 | { |
358 | MYSQL_STMT *stmt= mysql_stmt_init(mysql); |
359 | MYSQL_BIND bind[3]; |
360 | MYSQL_RES *res; |
361 | unsigned long rows; |
362 | unsigned int array_size= 5; |
363 | int rc; |
364 | int intval[]= {12,13,14,15,16}; |
365 | int id[]= {1,2,3,4,5}; |
366 | |
367 | if (!bulk_enabled) |
368 | return SKIP; |
369 | |
370 | rc= mysql_query(mysql, "DROP TABLE IF EXISTS bulk5" ); |
371 | check_mysql_rc(rc, mysql); |
372 | |
373 | rc= mysql_query(mysql, "CREATE TABLE bulk5 (a int, b int)" ); |
374 | check_mysql_rc(rc, mysql); |
375 | |
376 | rc= mysql_query(mysql, "INSERT INTO bulk5 VALUES (1,1), (2,2), (3,3), (4,4), (5,5)" ); |
377 | check_mysql_rc(rc, mysql); |
378 | |
379 | |
380 | memset(bind, 0, sizeof(MYSQL_BIND) * 3); |
381 | |
382 | rc= mysql_stmt_prepare(stmt, SL("UPDATE bulk5 SET a=? WHERE a=?" )); |
383 | check_stmt_rc(rc, stmt); |
384 | |
385 | bind[0].buffer_type= MYSQL_TYPE_LONG; |
386 | bind[0].buffer= &intval; |
387 | bind[1].buffer_type= MYSQL_TYPE_LONG; |
388 | bind[1].buffer= &id; |
389 | |
390 | rc= mysql_stmt_attr_set(stmt, STMT_ATTR_ARRAY_SIZE, &array_size); |
391 | check_stmt_rc(rc, stmt); |
392 | |
393 | rc= mysql_stmt_bind_param(stmt, bind); |
394 | check_stmt_rc(rc, stmt); |
395 | |
396 | rc= mysql_stmt_execute(stmt); |
397 | check_stmt_rc(rc, stmt); |
398 | |
399 | mysql_stmt_close(stmt); |
400 | |
401 | rc= mysql_query(mysql, "SELECT * FROM bulk5 WHERE a=b+11" ); |
402 | check_mysql_rc(rc, mysql); |
403 | |
404 | res= mysql_store_result(mysql); |
405 | rows= (unsigned long)mysql_num_rows(res); |
406 | diag("rows: %lu" , rows); |
407 | mysql_free_result(res); |
408 | |
409 | FAIL_IF(rows != 5, "expected 5 rows" ); |
410 | |
411 | rc= mysql_query(mysql, "DROP TABLE IF EXISTS bulk5" ); |
412 | check_mysql_rc(rc, mysql); |
413 | |
414 | return OK; |
415 | } |
416 | |
417 | static int bulk6(MYSQL *mysql) |
418 | { |
419 | MYSQL_STMT *stmt= mysql_stmt_init(mysql); |
420 | MYSQL_BIND bind[3]; |
421 | MYSQL_RES *res; |
422 | unsigned long rows; |
423 | unsigned int array_size= 5; |
424 | int rc; |
425 | int intval[]= {12,13,14,15,16}; |
426 | int id[]= {1,2,3,4,5}; |
427 | char indicator[5]; |
428 | |
429 | if (!bulk_enabled) |
430 | return SKIP; |
431 | memset(indicator, STMT_INDICATOR_IGNORE, 5); |
432 | |
433 | rc= mysql_query(mysql, "DROP TABLE IF EXISTS bulk6" ); |
434 | check_mysql_rc(rc, mysql); |
435 | |
436 | rc= mysql_query(mysql, "CREATE TABLE bulk6 (a int, b int default 4)" ); |
437 | check_mysql_rc(rc, mysql); |
438 | |
439 | rc= mysql_query(mysql, "INSERT INTO bulk6 VALUES (1,1), (2,2), (3,3), (4,4), (5,5)" ); |
440 | check_mysql_rc(rc, mysql); |
441 | |
442 | |
443 | memset(bind, 0, sizeof(MYSQL_BIND) * 3); |
444 | |
445 | /* 1st case: UPDATE */ |
446 | rc= mysql_stmt_prepare(stmt, SL("UPDATE bulk6 SET a=?, b=? WHERE a=?" )); |
447 | check_stmt_rc(rc, stmt); |
448 | |
449 | bind[0].buffer_type= MYSQL_TYPE_LONG; |
450 | bind[0].buffer= &intval; |
451 | bind[1].buffer_type= MYSQL_TYPE_LONG; |
452 | bind[1].buffer= &intval; |
453 | bind[1].u.indicator= indicator; |
454 | bind[2].buffer_type= MYSQL_TYPE_LONG; |
455 | bind[2].buffer= &id; |
456 | |
457 | rc= mysql_stmt_attr_set(stmt, STMT_ATTR_ARRAY_SIZE, &array_size); |
458 | check_stmt_rc(rc, stmt); |
459 | |
460 | rc= mysql_stmt_bind_param(stmt, bind); |
461 | check_stmt_rc(rc, stmt); |
462 | |
463 | rc= mysql_stmt_execute(stmt); |
464 | check_stmt_rc(rc, stmt); |
465 | |
466 | mysql_stmt_close(stmt); |
467 | |
468 | rc= mysql_query(mysql, "SELECT * FROM bulk6 WHERE a=b+11" ); |
469 | check_mysql_rc(rc, mysql); |
470 | |
471 | res= mysql_store_result(mysql); |
472 | rows= (unsigned long)mysql_num_rows(res); |
473 | mysql_free_result(res); |
474 | |
475 | FAIL_IF(rows != 5, "expected 5 rows" ); |
476 | |
477 | /* 2nd case: INSERT - ignore indicator should be same as default */ |
478 | rc= mysql_query(mysql, "DELETE FROM bulk6" ); |
479 | check_mysql_rc(rc, mysql); |
480 | |
481 | stmt= mysql_stmt_init(mysql); |
482 | rc= mysql_stmt_prepare(stmt, SL("INSERT INTO bulk6 VALUES (?,?)" )); |
483 | check_stmt_rc(rc, stmt); |
484 | |
485 | rc= mysql_stmt_attr_set(stmt, STMT_ATTR_ARRAY_SIZE, &array_size); |
486 | check_stmt_rc(rc, stmt); |
487 | |
488 | /* this should insert 5 default values (=4) */ |
489 | memset(indicator, STMT_INDICATOR_DEFAULT, 5); |
490 | rc= mysql_stmt_bind_param(stmt, bind); |
491 | check_stmt_rc(rc, stmt); |
492 | rc= mysql_stmt_execute(stmt); |
493 | check_stmt_rc(rc, stmt); |
494 | |
495 | /* this should insert 5 default values (=4) */ |
496 | memset(indicator, STMT_INDICATOR_IGNORE, 5); |
497 | rc= mysql_stmt_execute(stmt); |
498 | check_stmt_rc(rc, stmt); |
499 | |
500 | mysql_stmt_close(stmt); |
501 | |
502 | rc= mysql_query(mysql, "SELECT * FROM bulk6 WHERE b=4" ); |
503 | check_mysql_rc(rc, mysql); |
504 | |
505 | res= mysql_store_result(mysql); |
506 | rows= (unsigned long)mysql_num_rows(res); |
507 | mysql_free_result(res); |
508 | |
509 | FAIL_IF(rows != 10, "expected 10 rows" ); |
510 | rc= mysql_query(mysql, "DROP TABLE IF EXISTS bulk6" ); |
511 | check_mysql_rc(rc, mysql); |
512 | |
513 | return OK; |
514 | } |
515 | |
516 | static int test_conc243(MYSQL *mysql) |
517 | { |
518 | MYSQL_STMT *stmt; |
519 | MYSQL_BIND bind[3]; |
520 | MYSQL_RES *result; |
521 | MYSQL_ROW row; |
522 | |
523 | struct st_data { |
524 | unsigned long id; |
525 | char id_ind; |
526 | char forename[30]; |
527 | char forename_ind; |
528 | char surname[30]; |
529 | char surname_ind; |
530 | }; |
531 | |
532 | struct st_data data[]= { |
533 | {0, STMT_INDICATOR_NULL, "Monty" , STMT_INDICATOR_NTS, "Widenius" , STMT_INDICATOR_NTS}, |
534 | {0, STMT_INDICATOR_NULL, "David" , STMT_INDICATOR_NTS, "Axmark" , STMT_INDICATOR_NTS}, |
535 | {0, STMT_INDICATOR_NULL, "default" , STMT_INDICATOR_DEFAULT, "N.N." , STMT_INDICATOR_NTS}, |
536 | }; |
537 | |
538 | unsigned int array_size= 1; |
539 | size_t row_size= sizeof(struct st_data); |
540 | int rc; |
541 | |
542 | if (!bulk_enabled) |
543 | return SKIP; |
544 | rc= mysql_query(mysql, "DROP TABLE IF EXISTS bulk_example2" ); |
545 | check_mysql_rc(rc, mysql); |
546 | |
547 | rc= mysql_query(mysql, "CREATE TABLE bulk_example2 (id INT NOT NULL AUTO_INCREMENT PRIMARY KEY," \ |
548 | "forename CHAR(30) NOT NULL DEFAULT 'unknown', surname CHAR(30))" ); |
549 | check_mysql_rc(rc, mysql); |
550 | |
551 | stmt= mysql_stmt_init(mysql); |
552 | rc= mysql_stmt_prepare(stmt, SL("INSERT INTO bulk_example2 VALUES (?,?,?)" )); |
553 | check_stmt_rc(rc, stmt); |
554 | |
555 | memset(bind, 0, sizeof(MYSQL_BIND) * 3); |
556 | |
557 | /* We autogenerate id's, so all indicators are STMT_INDICATOR_NULL */ |
558 | bind[0].u.indicator= &data[0].id_ind; |
559 | bind[0].buffer_type= MYSQL_TYPE_LONG; |
560 | |
561 | bind[1].buffer= &data[0].forename; |
562 | bind[1].buffer_type= MYSQL_TYPE_STRING; |
563 | bind[1].u.indicator= &data[0].forename_ind; |
564 | |
565 | bind[2].buffer_type= MYSQL_TYPE_STRING; |
566 | bind[2].buffer= &data[0].surname; |
567 | bind[2].u.indicator= &data[0].surname_ind; |
568 | |
569 | /* set array size */ |
570 | mysql_stmt_attr_set(stmt, STMT_ATTR_ARRAY_SIZE, &array_size); |
571 | |
572 | /* set row size */ |
573 | mysql_stmt_attr_set(stmt, STMT_ATTR_ROW_SIZE, &row_size); |
574 | |
575 | /* bind parameter */ |
576 | mysql_stmt_bind_param(stmt, bind); |
577 | |
578 | /* execute */ |
579 | rc= mysql_stmt_execute(stmt); |
580 | check_stmt_rc(rc, stmt); |
581 | |
582 | mysql_stmt_close(stmt); |
583 | |
584 | rc= mysql_query(mysql, "SELECT forename, surname FROM bulk_example2" ); |
585 | check_mysql_rc(rc, mysql); |
586 | |
587 | result= mysql_store_result(mysql); |
588 | FAIL_IF(!result || !mysql_num_rows(result), "Invalid resultset" ); |
589 | row = mysql_fetch_row(result); |
590 | if (strcmp(row[0], "Monty" ) || strcmp(row[1], "Widenius" )) |
591 | { |
592 | mysql_free_result(result); |
593 | diag("Wrong values" ); |
594 | return FAIL; |
595 | } |
596 | mysql_free_result(result); |
597 | rc= mysql_query(mysql, "DROP TABLE bulk_example2" ); |
598 | check_mysql_rc(rc, mysql); |
599 | return OK; |
600 | } |
601 | static int bulk7(MYSQL *mysql) |
602 | { |
603 | MYSQL_STMT *stmt= mysql_stmt_init(mysql); |
604 | int rc; |
605 | int array_size= 5; |
606 | |
607 | rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1" ); |
608 | check_mysql_rc(rc, mysql); |
609 | rc= mysql_query(mysql, "CREATE TABLE t1 (a int)" ); |
610 | check_mysql_rc(rc, mysql); |
611 | rc= mysql_query(mysql, "INSERT INTO t1 VALUES (1)" ); |
612 | check_mysql_rc(rc, mysql); |
613 | |
614 | rc= mysql_stmt_prepare(stmt, SL("UPDATE t1 SET a=a+1" )); |
615 | check_stmt_rc(rc, stmt); |
616 | |
617 | rc= mysql_stmt_attr_set(stmt, STMT_ATTR_ARRAY_SIZE, &array_size); |
618 | check_stmt_rc(rc, stmt); |
619 | rc= mysql_stmt_execute(stmt); |
620 | |
621 | FAIL_IF(!rc, "Error expected: Bulk operation without parameters is not supported" ); |
622 | diag("%s" , mysql_stmt_error(stmt)); |
623 | |
624 | mysql_stmt_close(stmt); |
625 | rc= mysql_query(mysql, "DROP TABLE t1" ); |
626 | check_mysql_rc(rc, mysql); |
627 | |
628 | return OK; |
629 | } |
630 | |
631 | static int test_char_conv1(MYSQL *mysql) |
632 | { |
633 | MYSQL_STMT *stmt; |
634 | int rc; |
635 | MYSQL_BIND bind_in, bind_out; |
636 | char buffer[100]; |
637 | char outbuffer[100]; |
638 | |
639 | if (!bulk_enabled) |
640 | return SKIP; |
641 | stmt= mysql_stmt_init(mysql); |
642 | strcpy (buffer, "\xC3\x82\xC3\x83\xC3\x84\x00" ); |
643 | |
644 | rc= mysql_query(mysql, "SET NAMES UTF8" ); |
645 | check_mysql_rc(rc, mysql); |
646 | rc= mysql_query(mysql, "DROP TABLE IF EXISTS char_conv" ); |
647 | check_mysql_rc(rc, mysql); |
648 | rc= mysql_query(mysql, "CREATE TABLE char_conv (a varchar(20)) CHARSET=latin1" ); |
649 | check_mysql_rc(rc, mysql); |
650 | |
651 | rc= mysql_stmt_prepare(stmt, SL("INSERT INTO char_conv VALUES (?)" )); |
652 | check_stmt_rc(rc, stmt); |
653 | |
654 | memset(&bind_in, 0, sizeof(MYSQL_BIND)); |
655 | bind_in.buffer_type= MYSQL_TYPE_STRING; |
656 | bind_in.buffer_length= -1; |
657 | bind_in.buffer= &buffer; |
658 | |
659 | rc= mysql_stmt_bind_param(stmt, &bind_in); |
660 | check_stmt_rc(rc, stmt); |
661 | |
662 | rc= mysql_stmt_execute(stmt); |
663 | check_stmt_rc(rc, stmt); |
664 | |
665 | mysql_stmt_close(stmt); |
666 | |
667 | stmt= mysql_stmt_init(mysql); |
668 | |
669 | rc= mysql_stmt_prepare(stmt, SL("SELECT a from char_conv" )); |
670 | check_stmt_rc(rc, stmt); |
671 | |
672 | memset(&bind_out, 0, sizeof(MYSQL_BIND)); |
673 | bind_out.buffer_type= MYSQL_TYPE_STRING; |
674 | bind_out.buffer_length= 100; |
675 | bind_out.buffer= outbuffer; |
676 | |
677 | rc= mysql_stmt_bind_result(stmt, &bind_out); |
678 | check_stmt_rc(rc, stmt); |
679 | |
680 | rc= mysql_stmt_execute(stmt); |
681 | check_stmt_rc(rc, stmt); |
682 | |
683 | rc= mysql_stmt_fetch(stmt); |
684 | FAIL_IF(rc == MYSQL_NO_DATA, "Error" ); |
685 | |
686 | mysql_stmt_close(stmt); |
687 | |
688 | |
689 | if (strcmp(buffer, outbuffer)) |
690 | { |
691 | diag("Error: Expected '%s' instead of '%s'" , buffer, outbuffer); |
692 | return FAIL; |
693 | } |
694 | |
695 | rc= mysql_query(mysql, "DROP TABLE char_conv" ); |
696 | check_mysql_rc(rc, mysql); |
697 | |
698 | return OK; |
699 | } |
700 | |
701 | |
702 | static int test_char_conv2(MYSQL *mysql) |
703 | { |
704 | MYSQL_STMT *stmt; |
705 | int rc; |
706 | int array_size= 1; |
707 | MYSQL_BIND bind_in, bind_out; |
708 | char *buffer[1]; |
709 | char outbuffer[100]; |
710 | |
711 | if (!bulk_enabled) |
712 | return SKIP; |
713 | |
714 | stmt= mysql_stmt_init(mysql); |
715 | buffer[0]= calloc(1, 7); |
716 | strcpy (buffer[0], "\xC3\x82\xC3\x83\xC3\x84\x00" ); |
717 | |
718 | rc= mysql_query(mysql, "SET NAMES UTF8" ); |
719 | check_mysql_rc(rc, mysql); |
720 | rc= mysql_query(mysql, "DROP TABLE IF EXISTS char_conv" ); |
721 | check_mysql_rc(rc, mysql); |
722 | rc= mysql_query(mysql, "CREATE TABLE char_conv (a varchar(20)) CHARSET=latin1" ); |
723 | check_mysql_rc(rc, mysql); |
724 | |
725 | rc= mysql_stmt_prepare(stmt, SL("INSERT INTO char_conv VALUES (?)" )); |
726 | check_stmt_rc(rc, stmt); |
727 | |
728 | rc= mysql_stmt_attr_set(stmt, STMT_ATTR_ARRAY_SIZE, &array_size); |
729 | check_stmt_rc(rc, stmt); |
730 | |
731 | memset(&bind_in, 0, sizeof(MYSQL_BIND)); |
732 | bind_in.buffer_type= MYSQL_TYPE_STRING; |
733 | bind_in.buffer_length= -1; |
734 | bind_in.buffer= &buffer; |
735 | |
736 | rc= mysql_stmt_bind_param(stmt, &bind_in); |
737 | check_stmt_rc(rc, stmt); |
738 | |
739 | rc= mysql_stmt_execute(stmt); |
740 | check_stmt_rc(rc, stmt); |
741 | |
742 | mysql_stmt_close(stmt); |
743 | |
744 | stmt= mysql_stmt_init(mysql); |
745 | |
746 | rc= mysql_stmt_prepare(stmt, SL("SELECT a from char_conv" )); |
747 | check_stmt_rc(rc, stmt); |
748 | |
749 | memset(&bind_out, 0, sizeof(MYSQL_BIND)); |
750 | bind_out.buffer_type= MYSQL_TYPE_STRING; |
751 | bind_out.buffer_length= 100; |
752 | bind_out.buffer= outbuffer; |
753 | |
754 | rc= mysql_stmt_bind_result(stmt, &bind_out); |
755 | check_stmt_rc(rc, stmt); |
756 | |
757 | rc= mysql_stmt_execute(stmt); |
758 | check_stmt_rc(rc, stmt); |
759 | |
760 | rc= mysql_stmt_fetch(stmt); |
761 | FAIL_IF(rc == MYSQL_NO_DATA, "Error" ); |
762 | |
763 | mysql_stmt_close(stmt); |
764 | |
765 | |
766 | if (strcmp(buffer[0], outbuffer)) |
767 | { |
768 | diag("Error: Expected '%s' instead of '%s'" , buffer[0], outbuffer); |
769 | return FAIL; |
770 | } |
771 | free(buffer[0]); |
772 | |
773 | rc= mysql_query(mysql, "DROP TABLE char_conv" ); |
774 | check_mysql_rc(rc, mysql); |
775 | |
776 | return OK; |
777 | } |
778 | |
779 | |
780 | static int bulk_skip_row(MYSQL *mysql) |
781 | { |
782 | MYSQL_STMT *stmt; |
783 | MYSQL_BIND bind[3]; |
784 | MYSQL_RES *result; |
785 | MYSQL_ROW row; |
786 | |
787 | struct st_data { |
788 | unsigned long id; |
789 | char id_ind; |
790 | char forename[30]; |
791 | char forename_ind; |
792 | char surname[30]; |
793 | char surname_ind; |
794 | }; |
795 | |
796 | struct st_data data[]={ |
797 | { 0, STMT_INDICATOR_NULL, "Monty" , STMT_INDICATOR_NTS, "Widenius" , STMT_INDICATOR_IGNORE_ROW }, |
798 | { 0, STMT_INDICATOR_IGNORE_ROW, "David" , STMT_INDICATOR_NTS, "Axmark" , STMT_INDICATOR_NTS }, |
799 | { 0, STMT_INDICATOR_NULL, "default" , STMT_INDICATOR_DEFAULT, "N.N." , STMT_INDICATOR_NTS }, |
800 | }; |
801 | |
802 | unsigned int array_size= 3; |
803 | size_t row_size= sizeof(struct st_data); |
804 | int rc; |
805 | |
806 | if (!bulk_enabled) |
807 | return SKIP; |
808 | rc= mysql_query(mysql, "DROP TABLE IF EXISTS bulk_example2" ); |
809 | check_mysql_rc(rc, mysql); |
810 | |
811 | rc= mysql_query(mysql, "CREATE TABLE bulk_example2 (id INT NOT NULL AUTO_INCREMENT PRIMARY KEY," \ |
812 | "forename CHAR(30) NOT NULL DEFAULT 'unknown', surname CHAR(30))" ); |
813 | check_mysql_rc(rc, mysql); |
814 | |
815 | stmt= mysql_stmt_init(mysql); |
816 | rc= mysql_stmt_prepare(stmt, SL("INSERT INTO bulk_example2 VALUES (?,?,?)" )); |
817 | check_stmt_rc(rc, stmt); |
818 | |
819 | memset(bind, 0, sizeof(MYSQL_BIND) * 3); |
820 | |
821 | /* We autogenerate id's, so all indicators are STMT_INDICATOR_NULL */ |
822 | bind[0].u.indicator= &data[0].id_ind; |
823 | bind[0].buffer_type= MYSQL_TYPE_LONG; |
824 | |
825 | bind[1].buffer= &data[0].forename; |
826 | bind[1].buffer_type= MYSQL_TYPE_STRING; |
827 | bind[1].u.indicator= &data[0].forename_ind; |
828 | |
829 | bind[2].buffer_type= MYSQL_TYPE_STRING; |
830 | bind[2].buffer= &data[0].surname; |
831 | bind[2].u.indicator= &data[0].surname_ind; |
832 | |
833 | /* set array size */ |
834 | mysql_stmt_attr_set(stmt, STMT_ATTR_ARRAY_SIZE, &array_size); |
835 | |
836 | /* set row size */ |
837 | mysql_stmt_attr_set(stmt, STMT_ATTR_ROW_SIZE, &row_size); |
838 | |
839 | /* bind parameter */ |
840 | mysql_stmt_bind_param(stmt, bind); |
841 | |
842 | /* execute */ |
843 | rc= mysql_stmt_execute(stmt); |
844 | check_stmt_rc(rc, stmt); |
845 | |
846 | mysql_stmt_close(stmt); |
847 | |
848 | rc= mysql_query(mysql, "SELECT forename, surname FROM bulk_example2" ); |
849 | check_mysql_rc(rc, mysql); |
850 | |
851 | result= mysql_store_result(mysql); |
852 | FAIL_IF(!result || mysql_num_rows(result) != 1, "Invalid resultset" ); |
853 | |
854 | row = mysql_fetch_row(result); |
855 | if (strcmp(row[0], "unknown" ) || strcmp(row[1], "N.N." )) |
856 | { |
857 | mysql_free_result(result); |
858 | diag("Wrong values" ); |
859 | return FAIL; |
860 | } |
861 | mysql_free_result(result); |
862 | rc= mysql_query(mysql, "DROP TABLE bulk_example2" ); |
863 | check_mysql_rc(rc, mysql); |
864 | return OK; |
865 | } |
866 | |
867 | static int bulk_null_null(MYSQL *mysql) |
868 | { |
869 | struct st_bulk4 { |
870 | char char_value[20]; |
871 | char indicator1; |
872 | int int_value; |
873 | char indicator2; |
874 | double double_value; |
875 | char indicator3; |
876 | char time_value[20]; |
877 | char indicator4; |
878 | char decimal_value[4]; |
879 | char indicator5; |
880 | }; |
881 | |
882 | struct st_bulk4 val[]= {{"3" , STMT_INDICATOR_NTS, |
883 | 3, STMT_INDICATOR_NONE, |
884 | 3.0, STMT_INDICATOR_NONE, |
885 | "00:00:00" , STMT_INDICATOR_NTS, |
886 | "3.0" , STMT_INDICATOR_NTS}, |
887 | {"3" , STMT_INDICATOR_NULL, |
888 | 3, STMT_INDICATOR_NULL, |
889 | 3.0, STMT_INDICATOR_NULL, |
890 | "00:00:00" , STMT_INDICATOR_NULL, |
891 | "3.0" , STMT_INDICATOR_NULL}, |
892 | {"3" , STMT_INDICATOR_NTS, |
893 | 3, STMT_INDICATOR_NONE, |
894 | 3.0, STMT_INDICATOR_NONE, |
895 | "00:00:00" , STMT_INDICATOR_NTS, |
896 | "3.0" , STMT_INDICATOR_NTS}}; |
897 | int rc; |
898 | MYSQL_BIND bind[5]; |
899 | MYSQL_RES *res; |
900 | MYSQL_STMT *stmt= mysql_stmt_init(mysql); |
901 | size_t row_size= sizeof(struct st_bulk4); |
902 | int array_size= 3; |
903 | unsigned long server_version= mysql_get_server_version(mysql); |
904 | unsigned long lengths[3]= {-1, -1, -1}; |
905 | |
906 | if (!bulk_enabled) |
907 | return SKIP; |
908 | |
909 | if (server_version > 100300 && |
910 | server_version < 100305) |
911 | return SKIP; |
912 | |
913 | rc= mysql_query(mysql, "DROP TABLE IF EXISTS bulk_null" ); |
914 | check_mysql_rc(rc,mysql); |
915 | rc= mysql_query(mysql, "CREATE TABLE bulk_null " |
916 | "(s varchar(20), " |
917 | " i int, " |
918 | " d double, " |
919 | " t time, " |
920 | " c decimal(3,1))" ); |
921 | check_mysql_rc(rc,mysql); |
922 | |
923 | rc= mysql_stmt_prepare(stmt, "INSERT INTO bulk_null VALUES (?,?,?,?,?)" , -1); |
924 | check_stmt_rc(rc, stmt); |
925 | |
926 | memset(bind, 0, sizeof(MYSQL_BIND)*2); |
927 | |
928 | rc= mysql_stmt_attr_set(stmt, STMT_ATTR_ARRAY_SIZE, &array_size); |
929 | check_stmt_rc(rc, stmt); |
930 | rc= mysql_stmt_attr_set(stmt, STMT_ATTR_ROW_SIZE, &row_size); |
931 | check_stmt_rc(rc, stmt); |
932 | |
933 | bind[0].buffer_type= MYSQL_TYPE_STRING; |
934 | bind[0].u.indicator= &val[0].indicator1; |
935 | bind[0].buffer= &val[0].char_value; |
936 | bind[0].length= lengths; |
937 | bind[1].buffer_type= MYSQL_TYPE_LONG; |
938 | bind[1].buffer= &val[0].int_value; |
939 | bind[1].u.indicator= &val[0].indicator2; |
940 | bind[2].buffer_type= MYSQL_TYPE_DOUBLE; |
941 | bind[2].buffer= &val[0].double_value; |
942 | bind[2].u.indicator= &val[0].indicator3; |
943 | bind[3].buffer_type= MYSQL_TYPE_STRING; |
944 | bind[3].u.indicator= &val[0].indicator4; |
945 | bind[3].buffer= &val[0].time_value; |
946 | bind[3].length= lengths; |
947 | bind[4].buffer_type= MYSQL_TYPE_NEWDECIMAL; |
948 | bind[4].u.indicator= &val[0].indicator5; |
949 | bind[4].buffer= &val[0].decimal_value; |
950 | bind[4].length= lengths; |
951 | |
952 | rc= mysql_stmt_bind_param(stmt, bind); |
953 | check_stmt_rc(rc, stmt); |
954 | rc= mysql_stmt_execute(stmt); |
955 | check_stmt_rc(rc, stmt); |
956 | |
957 | mysql_stmt_close(stmt); |
958 | |
959 | rc= mysql_query(mysql, "SELECT * FROM bulk_null WHERE s='3'" ); |
960 | check_mysql_rc(rc, mysql); |
961 | res= mysql_store_result(mysql); |
962 | rc= (int)mysql_num_rows(res); |
963 | mysql_free_result(res); |
964 | FAIL_IF(rc != 2, "expected 2 rows" ); |
965 | |
966 | rc= mysql_query(mysql, "SELECT * FROM bulk_null WHERE i=3" ); |
967 | check_mysql_rc(rc, mysql); |
968 | res= mysql_store_result(mysql); |
969 | rc= (int)mysql_num_rows(res); |
970 | mysql_free_result(res); |
971 | FAIL_IF(rc != 2, "expected 2 rows" ); |
972 | |
973 | rc= mysql_query(mysql, "SELECT * FROM bulk_null WHERE d=3.0" ); |
974 | check_mysql_rc(rc, mysql); |
975 | res= mysql_store_result(mysql); |
976 | rc= (int)mysql_num_rows(res); |
977 | mysql_free_result(res); |
978 | FAIL_IF(rc != 2, "expected 2 rows" ); |
979 | |
980 | rc= mysql_query(mysql, "SELECT * FROM bulk_null WHERE t='00:00:00'" ); |
981 | check_mysql_rc(rc, mysql); |
982 | res= mysql_store_result(mysql); |
983 | rc= (int)mysql_num_rows(res); |
984 | mysql_free_result(res); |
985 | FAIL_IF(rc != 2, "expected 2 rows" ); |
986 | |
987 | rc= mysql_query(mysql, "SELECT * FROM bulk_null WHERE c=3.0" ); |
988 | check_mysql_rc(rc, mysql); |
989 | res= mysql_store_result(mysql); |
990 | rc= (int)mysql_num_rows(res); |
991 | mysql_free_result(res); |
992 | FAIL_IF(rc != 2, "expected 2 rows" ); |
993 | |
994 | rc= mysql_query(mysql, "DROP TABLE bulk_null" ); |
995 | check_mysql_rc(rc, mysql); |
996 | return OK; |
997 | } |
998 | |
999 | struct my_tests_st my_tests[] = { |
1000 | {"check_bulk" , check_bulk, TEST_CONNECTION_DEFAULT, 0, NULL, NULL}, |
1001 | {"bulk_null_null" , bulk_null_null, TEST_CONNECTION_NEW, 0, NULL, NULL}, |
1002 | {"test_char_conv1" , test_char_conv1, TEST_CONNECTION_NEW, 0, NULL, NULL}, |
1003 | {"test_char_conv2" , test_char_conv2, TEST_CONNECTION_NEW, 0, NULL, NULL}, |
1004 | {"test_conc243" , test_conc243, TEST_CONNECTION_DEFAULT, 0, NULL, NULL}, |
1005 | {"update_no_param" , bulk7, TEST_CONNECTION_DEFAULT, 0, NULL, NULL}, |
1006 | {"bulk5" , bulk5, TEST_CONNECTION_DEFAULT, 0, NULL, NULL}, |
1007 | {"bulk6" , bulk6, TEST_CONNECTION_DEFAULT, 0, NULL, NULL}, |
1008 | {"bulk1" , bulk1, TEST_CONNECTION_DEFAULT, 0, NULL, NULL}, |
1009 | {"bulk2" , bulk2, TEST_CONNECTION_DEFAULT, 0, NULL, NULL}, |
1010 | {"bulk3" , bulk3, TEST_CONNECTION_DEFAULT, 0, NULL, NULL}, |
1011 | {"bulk4" , bulk4, TEST_CONNECTION_DEFAULT, 0, NULL, NULL}, |
1012 | {"bulk_null" , bulk_null, TEST_CONNECTION_DEFAULT, 0, NULL, NULL}, |
1013 | {"bulk_skip_row" , bulk_skip_row, TEST_CONNECTION_DEFAULT, 0, NULL, NULL}, |
1014 | {NULL, NULL, 0, 0, NULL, NULL} |
1015 | }; |
1016 | |
1017 | int main(int argc, char **argv) |
1018 | { |
1019 | if (argc > 1) |
1020 | get_options(argc, argv); |
1021 | |
1022 | get_envvars(); |
1023 | |
1024 | run_tests(my_tests); |
1025 | |
1026 | return(exit_status()); |
1027 | } |
1028 | |