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 | |
25 | |
26 | /** |
27 | Some basic tests of the client API. |
28 | */ |
29 | |
30 | #include "my_test.h" |
31 | #include "ma_common.h" |
32 | |
33 | static int test_conc75(MYSQL *my) |
34 | { |
35 | int rc; |
36 | MYSQL *mysql; |
37 | int i; |
38 | my_bool reconnect= 1; |
39 | |
40 | mysql= mysql_init(NULL); |
41 | |
42 | mysql_options(mysql, MYSQL_OPT_RECONNECT, &reconnect); |
43 | my_test_connect(mysql, hostname, username, password, schema, port, socketname, 0| CLIENT_MULTI_RESULTS | CLIENT_REMEMBER_OPTIONS); |
44 | |
45 | rc= mysql_query(mysql, "DROP TABLE IF EXISTS a" ); |
46 | check_mysql_rc(rc, mysql); |
47 | |
48 | rc= mysql_query(mysql, "CREATE TABLE a (a varchar(200))" ); |
49 | check_mysql_rc(rc, mysql); |
50 | |
51 | rc= mysql_set_character_set(mysql, "utf8" ); |
52 | check_mysql_rc(rc, mysql); |
53 | |
54 | for (i=0; i < 10; i++) |
55 | { |
56 | ulong thread_id= mysql_thread_id(mysql); |
57 | /* force reconnect */ |
58 | mysql_options(mysql, MYSQL_OPT_RECONNECT, &reconnect); |
59 | diag("killing connection" ); |
60 | mysql_kill(my, thread_id); |
61 | mysql_ping(mysql); |
62 | rc= mysql_query(mysql, "load data local infile './nonexistingfile.csv' into table a (`a`)" ); |
63 | FAIL_IF(!test(mysql->options.client_flag | CLIENT_LOCAL_FILES), "client_flags not correct" ); |
64 | diag("thread1: %ld %ld" , thread_id, mysql_thread_id(mysql)); |
65 | FAIL_IF(thread_id == mysql_thread_id(mysql), "new thread id expected" ); |
66 | //diag("cs: %s", mysql->charset->csname); |
67 | //FAIL_IF(strcmp(mysql->charset->csname, "utf8"), "wrong character set"); |
68 | } |
69 | rc= mysql_query(mysql, "DROP TABLE IF EXISTS a" ); |
70 | check_mysql_rc(rc, mysql); |
71 | mysql_close(mysql); |
72 | return OK; |
73 | } |
74 | |
75 | |
76 | static int test_conc74(MYSQL *unused __attribute__((unused))) |
77 | { |
78 | int rc; |
79 | MYSQL *mysql; |
80 | |
81 | mysql= mysql_init(NULL); |
82 | |
83 | |
84 | if (!my_test_connect(mysql, hostname, username, password, schema, port, socketname, 0| CLIENT_MULTI_RESULTS | CLIENT_REMEMBER_OPTIONS)) |
85 | { |
86 | diag("Error: %s" , mysql_error(mysql)); |
87 | mysql_close(mysql); |
88 | return FAIL; |
89 | } |
90 | |
91 | rc= mysql_query(mysql, "DROP TABLE IF EXISTS a" ); |
92 | check_mysql_rc(rc, mysql); |
93 | |
94 | rc= mysql_query(mysql, "CREATE TABLE a (a varchar(200))" ); |
95 | check_mysql_rc(rc, mysql); |
96 | |
97 | mysql->options.client_flag&= ~CLIENT_LOCAL_FILES; |
98 | |
99 | rc= mysql_query(mysql, "load data local infile './nonexistingfile.csv' into table a (`a`)" ); |
100 | FAIL_IF(!rc, "Error expected" ); |
101 | |
102 | rc= mysql_query(mysql, "DROP TABLE IF EXISTS a" ); |
103 | check_mysql_rc(rc, mysql); |
104 | |
105 | mysql_close(mysql); |
106 | return OK; |
107 | } |
108 | |
109 | |
110 | static int test_conc71(MYSQL *my) |
111 | { |
112 | int rc; |
113 | MYSQL *mysql; |
114 | |
115 | /* uncomment if you want to test manually */ |
116 | return SKIP; |
117 | |
118 | mysql= mysql_init(NULL); |
119 | |
120 | |
121 | mysql_options(mysql, MYSQL_SET_CHARSET_NAME, "utf8" ); |
122 | mysql_options(mysql, MYSQL_OPT_COMPRESS, 0); |
123 | mysql_options(mysql, MYSQL_INIT_COMMAND, "/*!40101 SET SQL_MODE='' */" ); |
124 | mysql_options(mysql, MYSQL_INIT_COMMAND, "/*!40101 set @@session.wait_timeout=28800 */" ); |
125 | |
126 | FAIL_IF(!my_test_connect(mysql, hostname, username, password, schema, |
127 | port, socketname, 0), mysql_error(my)); |
128 | |
129 | diag("kill server" ); |
130 | |
131 | rc= mysql_query(mysql, "SELECT 'foo' FROM DUAL" ); |
132 | check_mysql_rc(rc, mysql); |
133 | |
134 | mysql_close(mysql); |
135 | return OK; |
136 | } |
137 | |
138 | static int test_conc70(MYSQL *my) |
139 | { |
140 | int rc; |
141 | MYSQL_RES *res; |
142 | MYSQL_ROW row; |
143 | MYSQL *mysql; |
144 | |
145 | SKIP_CONNECTION_HANDLER; |
146 | |
147 | mysql= mysql_init(NULL); |
148 | |
149 | rc= mysql_query(my, "SET @a:=@@max_allowed_packet" ); |
150 | check_mysql_rc(rc, my); |
151 | |
152 | mysql_query(my, "SET global max_allowed_packet=1024*1024*22" ); |
153 | check_mysql_rc(rc, my); |
154 | |
155 | mysql_options(mysql, MYSQL_OPT_COMPRESS, (void *)1); |
156 | FAIL_IF(!my_test_connect(mysql, hostname, username, password, schema, |
157 | port, socketname, 0), mysql_error(my)); |
158 | |
159 | rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1" ); |
160 | check_mysql_rc(rc, mysql); |
161 | |
162 | rc= mysql_query(mysql, "CREATE TABLE t1 (a LONGBLOB) engine=MyISAM" ); |
163 | check_mysql_rc(rc, mysql); |
164 | |
165 | rc= mysql_query(mysql, "INSERT INTO t1 VALUES (REPEAT('A', 1024 * 1024 * 20))" ); |
166 | check_mysql_rc(rc, mysql); |
167 | |
168 | if (mysql_warning_count(mysql)) |
169 | { |
170 | diag("server doesn't accept package size" ); |
171 | return SKIP; |
172 | } |
173 | |
174 | |
175 | rc= mysql_query(mysql, "SELECT a FROM t1" ); |
176 | check_mysql_rc(rc, mysql); |
177 | |
178 | if (!(res= mysql_store_result(mysql))) |
179 | { |
180 | diag("Error: %s" , mysql_error(mysql)); |
181 | return FAIL; |
182 | } |
183 | |
184 | row= mysql_fetch_row(res); |
185 | diag("Length: %ld" , (long)strlen(row[0])); |
186 | FAIL_IF(strlen(row[0]) != 1024 * 1024 * 20, "Wrong length" ); |
187 | |
188 | mysql_free_result(res); |
189 | rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1" ); |
190 | check_mysql_rc(rc, mysql); |
191 | |
192 | mysql_close(mysql); |
193 | |
194 | rc= mysql_query(my, "SET global max_allowed_packet=@a" ); |
195 | check_mysql_rc(rc, my); |
196 | |
197 | return OK; |
198 | } |
199 | |
200 | static int test_conc68(MYSQL *my) |
201 | { |
202 | int rc; |
203 | MYSQL_RES *res; |
204 | MYSQL_ROW row; |
205 | MYSQL *mysql; |
206 | |
207 | SKIP_CONNECTION_HANDLER; |
208 | |
209 | mysql= mysql_init(NULL); |
210 | |
211 | rc= mysql_query(my, "SET @a:=@@max_allowed_packet" ); |
212 | check_mysql_rc(rc, my); |
213 | |
214 | mysql_query(my, "SET global max_allowed_packet=1024*1024*22" ); |
215 | |
216 | FAIL_IF(!my_test_connect(mysql, hostname, username, password, schema, |
217 | port, socketname, 0), mysql_error(my)); |
218 | |
219 | rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1" ); |
220 | check_mysql_rc(rc, mysql); |
221 | |
222 | rc= mysql_query(mysql, "CREATE TABLE t1 (a LONGBLOB) ENGINE=MyISAM" ); |
223 | check_mysql_rc(rc, mysql); |
224 | |
225 | rc= mysql_query(mysql, "INSERT INTO t1 VALUES (REPEAT('A', 1024 * 1024 * 20))" ); |
226 | check_mysql_rc(rc, mysql); |
227 | if (mysql_warning_count(mysql)) |
228 | { |
229 | diag("server doesn't accept package size" ); |
230 | return SKIP; |
231 | } |
232 | |
233 | rc= mysql_query(mysql, "SELECT a FROM t1" ); |
234 | check_mysql_rc(rc, mysql); |
235 | |
236 | if (!(res= mysql_store_result(mysql))) |
237 | { |
238 | diag("Error: %s" , mysql_error(mysql)); |
239 | return FAIL; |
240 | } |
241 | |
242 | row= mysql_fetch_row(res); |
243 | diag("Length: %ld" , (long)strlen(row[0])); |
244 | FAIL_IF(strlen(row[0]) != 1024 * 1024 * 20, "Wrong length" ); |
245 | |
246 | mysql_free_result(res); |
247 | mysql_close(mysql); |
248 | |
249 | rc= mysql_query(my, "SET global max_allowed_packet=@a" ); |
250 | check_mysql_rc(rc, my); |
251 | |
252 | return OK; |
253 | } |
254 | |
255 | |
256 | static int basic_connect(MYSQL *unused __attribute__((unused))) |
257 | { |
258 | MYSQL_ROW row; |
259 | MYSQL_RES *res; |
260 | MYSQL_FIELD *field; |
261 | int rc; |
262 | |
263 | MYSQL *my= mysql_init(NULL); |
264 | FAIL_IF(!my, "mysql_init() failed" ); |
265 | |
266 | FAIL_IF(!my_test_connect(my, hostname, username, password, schema, |
267 | port, socketname, 0), mysql_error(my)); |
268 | |
269 | rc= mysql_query(my, "SELECT @@version" ); |
270 | check_mysql_rc(rc, my); |
271 | |
272 | res= mysql_store_result(my); |
273 | FAIL_IF(!res, mysql_error(my)); |
274 | field= mysql_fetch_fields(res); |
275 | FAIL_IF(!field, "couldn't fetch field" ); |
276 | while ((row= mysql_fetch_row(res)) != NULL) |
277 | { |
278 | FAIL_IF(mysql_num_fields(res) != 1, "Got the wrong number of fields" ); |
279 | } |
280 | FAIL_IF(mysql_errno(my), mysql_error(my)); |
281 | |
282 | mysql_free_result(res); |
283 | mysql_close(my); |
284 | |
285 | return OK; |
286 | } |
287 | |
288 | |
289 | static int use_utf8(MYSQL *my) |
290 | { |
291 | MYSQL_ROW row; |
292 | MYSQL_RES *res; |
293 | int rc; |
294 | |
295 | /* Make sure that we actually ended up with utf8. */ |
296 | rc= mysql_query(my, "SELECT @@character_set_connection" ); |
297 | check_mysql_rc(rc, my); |
298 | |
299 | res= mysql_store_result(my); |
300 | FAIL_IF(!res, mysql_error(my)); |
301 | |
302 | while ((row= mysql_fetch_row(res)) != NULL) |
303 | { |
304 | FAIL_IF(strcmp(row[0], "utf8" ), "wrong character set" ); |
305 | } |
306 | FAIL_IF(mysql_errno(my), mysql_error(my)); |
307 | mysql_free_result(res); |
308 | |
309 | return OK; |
310 | } |
311 | |
312 | int client_query(MYSQL *mysql) { |
313 | int rc; |
314 | |
315 | rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1" ); |
316 | check_mysql_rc(rc, mysql); |
317 | rc= mysql_query(mysql, "CREATE TABLE t1(" |
318 | "id int primary key auto_increment, " |
319 | "name varchar(20))" ); |
320 | check_mysql_rc(rc, mysql); |
321 | rc= mysql_query(mysql, "CREATE TABLE t1(id int, name varchar(20))" ); |
322 | FAIL_IF(!rc, "Error expected" ); |
323 | rc= mysql_query(mysql, "INSERT INTO t1(name) VALUES('mysql')" ); |
324 | check_mysql_rc(rc, mysql); |
325 | rc= mysql_query(mysql, "INSERT INTO t1(name) VALUES('monty')" ); |
326 | check_mysql_rc(rc, mysql); |
327 | rc= mysql_query(mysql, "INSERT INTO t1(name) VALUES('venu')" ); |
328 | check_mysql_rc(rc, mysql); |
329 | rc= mysql_query(mysql, "INSERT INTO t1(name) VALUES('deleted')" ); |
330 | check_mysql_rc(rc, mysql); |
331 | rc= mysql_query(mysql, "INSERT INTO t1(name) VALUES('deleted')" ); |
332 | check_mysql_rc(rc, mysql); |
333 | rc= mysql_query(mysql, "UPDATE t1 SET name= 'updated' " |
334 | "WHERE name= 'deleted'" ); |
335 | check_mysql_rc(rc, mysql); |
336 | rc= mysql_query(mysql, "UPDATE t1 SET id= 3 WHERE name= 'updated'" ); |
337 | FAIL_IF(!rc, "Error expected" ); |
338 | rc= mysql_query(mysql, "drop table t1" ); |
339 | check_mysql_rc(rc, mysql); |
340 | |
341 | return OK; |
342 | } |
343 | |
344 | static int test_bug12001(MYSQL *mysql) |
345 | { |
346 | MYSQL_RES *result; |
347 | const char *query= "DROP TABLE IF EXISTS test_table;" |
348 | "CREATE TABLE test_table(id INT);" |
349 | "INSERT INTO test_table VALUES(10);" |
350 | "UPDATE test_table SET id=20 WHERE id=10;" |
351 | "SELECT * FROM test_table;" |
352 | "INSERT INTO non_existent_table VALUES(11);" ; |
353 | int rc, res; |
354 | |
355 | |
356 | rc= mysql_query(mysql, query); |
357 | check_mysql_rc(rc, mysql); |
358 | |
359 | do |
360 | { |
361 | if (mysql_field_count(mysql) && |
362 | (result= mysql_use_result(mysql))) |
363 | { |
364 | mysql_free_result(result); |
365 | } |
366 | } |
367 | while (!(res= mysql_next_result(mysql))); |
368 | |
369 | rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_table" ); |
370 | check_mysql_rc(rc, mysql); |
371 | |
372 | FAIL_UNLESS(res==1, "res != 1" ); |
373 | |
374 | return OK; |
375 | } |
376 | |
377 | |
378 | /* connection options */ |
379 | struct my_option_st opt_utf8[] = { |
380 | {MYSQL_SET_CHARSET_NAME, (char *)"utf8" }, |
381 | {0, NULL} |
382 | }; |
383 | |
384 | static int test_bad_union(MYSQL *mysql) |
385 | { |
386 | MYSQL_STMT *stmt; |
387 | int rc; |
388 | const char *query= "SELECT 1, 2 union SELECT 1" ; |
389 | |
390 | stmt= mysql_stmt_init(mysql); |
391 | FAIL_IF(!stmt, mysql_error(mysql)); |
392 | rc= mysql_stmt_prepare(stmt, SL(query)); |
393 | FAIL_UNLESS(rc && mysql_errno(mysql) == 1222, "Error expected" ); |
394 | |
395 | mysql_stmt_close(stmt); |
396 | return OK; |
397 | } |
398 | |
399 | /* |
400 | Test that mysql_insert_id() behaves as documented in our manual |
401 | */ |
402 | static int test_mysql_insert_id(MYSQL *mysql) |
403 | { |
404 | unsigned long long res; |
405 | int rc; |
406 | |
407 | if (mysql_get_server_version(mysql) < 50100) { |
408 | diag("Test requires MySQL Server version 5.1 or above" ); |
409 | return SKIP; |
410 | } |
411 | |
412 | rc= mysql_query(mysql, "drop table if exists t1" ); |
413 | check_mysql_rc(rc, mysql); |
414 | rc= mysql_query(mysql, "drop table if exists t2" ); |
415 | check_mysql_rc(rc, mysql); |
416 | /* table without auto_increment column */ |
417 | rc= mysql_query(mysql, "create table t1 (f1 int, f2 varchar(255), key(f1))" ); |
418 | check_mysql_rc(rc, mysql); |
419 | rc= mysql_query(mysql, "insert into t1 values (1,'a')" ); |
420 | check_mysql_rc(rc, mysql); |
421 | res= mysql_insert_id(mysql); |
422 | FAIL_UNLESS(res == 0, "" ); |
423 | rc= mysql_query(mysql, "insert into t1 values (null,'b')" ); |
424 | check_mysql_rc(rc, mysql); |
425 | res= mysql_insert_id(mysql); |
426 | FAIL_UNLESS(res == 0, "" ); |
427 | rc= mysql_query(mysql, "insert into t1 select 5,'c'" ); |
428 | check_mysql_rc(rc, mysql); |
429 | res= mysql_insert_id(mysql); |
430 | FAIL_UNLESS(res == 0, "" ); |
431 | |
432 | /* |
433 | Test for bug #34889: mysql_client_test::test_mysql_insert_id test fails |
434 | sporadically |
435 | */ |
436 | rc= mysql_query(mysql, "create table t2 (f1 int not null primary key auto_increment, f2 varchar(255))" ); |
437 | check_mysql_rc(rc, mysql); |
438 | rc= mysql_query(mysql, "insert into t2 values (null,'b')" ); |
439 | check_mysql_rc(rc, mysql); |
440 | rc= mysql_query(mysql, "insert into t1 select 5,'c'" ); |
441 | check_mysql_rc(rc, mysql); |
442 | res= mysql_insert_id(mysql); |
443 | FAIL_UNLESS(res == 0, "" ); |
444 | rc= mysql_query(mysql, "drop table t2" ); |
445 | check_mysql_rc(rc, mysql); |
446 | |
447 | rc= mysql_query(mysql, "insert into t1 select null,'d'" ); |
448 | check_mysql_rc(rc, mysql); |
449 | res= mysql_insert_id(mysql); |
450 | FAIL_UNLESS(res == 0, "" ); |
451 | rc= mysql_query(mysql, "insert into t1 values (null,last_insert_id(300))" ); |
452 | check_mysql_rc(rc, mysql); |
453 | res= mysql_insert_id(mysql); |
454 | FAIL_UNLESS(res == 300, "" ); |
455 | rc= mysql_query(mysql, "insert into t1 select null,last_insert_id(400)" ); |
456 | check_mysql_rc(rc, mysql); |
457 | res= mysql_insert_id(mysql); |
458 | /* |
459 | Behaviour change: old code used to return 0; but 400 is consistent |
460 | with INSERT VALUES, and the manual's section of mysql_insert_id() does not |
461 | say INSERT SELECT should be different. |
462 | */ |
463 | FAIL_UNLESS(res == 400, "" ); |
464 | |
465 | /* table with auto_increment column */ |
466 | rc= mysql_query(mysql, "create table t2 (f1 int not null primary key auto_increment, f2 varchar(255)) engine=MyISAM" ); |
467 | check_mysql_rc(rc, mysql); |
468 | rc= mysql_query(mysql, "insert into t2 values (1,'a')" ); |
469 | check_mysql_rc(rc, mysql); |
470 | res= mysql_insert_id(mysql); |
471 | FAIL_UNLESS(res == 1, "" ); |
472 | /* this should not influence next INSERT if it doesn't have auto_inc */ |
473 | rc= mysql_query(mysql, "insert into t1 values (10,'e')" ); |
474 | check_mysql_rc(rc, mysql); |
475 | res= mysql_insert_id(mysql); |
476 | FAIL_UNLESS(res == 0, "" ); |
477 | |
478 | rc= mysql_query(mysql, "insert into t2 values (null,'b')" ); |
479 | check_mysql_rc(rc, mysql); |
480 | res= mysql_insert_id(mysql); |
481 | FAIL_UNLESS(res == 2, "" ); |
482 | rc= mysql_query(mysql, "insert into t2 select 5,'c'" ); |
483 | check_mysql_rc(rc, mysql); |
484 | res= mysql_insert_id(mysql); |
485 | /* |
486 | Manual says that for multirow insert this should have been 5, but does not |
487 | say for INSERT SELECT. This is a behaviour change: old code used to return |
488 | 0. We try to be consistent with INSERT VALUES. |
489 | */ |
490 | FAIL_UNLESS(res == 5, "" ); |
491 | rc= mysql_query(mysql, "insert into t2 select null,'d'" ); |
492 | check_mysql_rc(rc, mysql); |
493 | res= mysql_insert_id(mysql); |
494 | FAIL_UNLESS(res == 6, "" ); |
495 | /* with more than one row */ |
496 | rc= mysql_query(mysql, "insert into t2 values (10,'a'),(11,'b')" ); |
497 | check_mysql_rc(rc, mysql); |
498 | res= mysql_insert_id(mysql); |
499 | FAIL_UNLESS(res == 11, "" ); |
500 | rc= mysql_query(mysql, "insert into t2 select 12,'a' union select 13,'b'" ); |
501 | check_mysql_rc(rc, mysql); |
502 | res= mysql_insert_id(mysql); |
503 | /* |
504 | Manual says that for multirow insert this should have been 13, but does |
505 | not say for INSERT SELECT. This is a behaviour change: old code used to |
506 | return 0. We try to be consistent with INSERT VALUES. |
507 | */ |
508 | FAIL_UNLESS(res == 13, "" ); |
509 | rc= mysql_query(mysql, "insert into t2 values (null,'a'),(null,'b')" ); |
510 | check_mysql_rc(rc, mysql); |
511 | res= mysql_insert_id(mysql); |
512 | FAIL_UNLESS(res == 14, "" ); |
513 | rc= mysql_query(mysql, "insert into t2 select null,'a' union select null,'b'" ); |
514 | check_mysql_rc(rc, mysql); |
515 | res= mysql_insert_id(mysql); |
516 | FAIL_UNLESS(res == 16, "" ); |
517 | rc= mysql_query(mysql, "insert into t2 select 12,'a' union select 13,'b'" ); |
518 | FAIL_IF(!rc, "Error expected" ); |
519 | rc= mysql_query(mysql, "insert ignore into t2 select 12,'a' union select 13,'b'" ); |
520 | check_mysql_rc(rc, mysql); |
521 | res= mysql_insert_id(mysql); |
522 | FAIL_UNLESS(res == 0, "" ); |
523 | rc= mysql_query(mysql, "insert into t2 values (12,'a'),(13,'b')" ); |
524 | FAIL_IF(!rc, "Error expected" ); |
525 | res= mysql_insert_id(mysql); |
526 | FAIL_UNLESS(res == 0, "" ); |
527 | rc= mysql_query(mysql, "insert ignore into t2 values (12,'a'),(13,'b')" ); |
528 | check_mysql_rc(rc, mysql); |
529 | res= mysql_insert_id(mysql); |
530 | FAIL_UNLESS(res == 0, "" ); |
531 | /* mixing autogenerated and explicit values */ |
532 | rc= mysql_query(mysql, "insert into t2 values (null,'e'),(12,'a'),(13,'b')" ); |
533 | FAIL_IF(!rc, "Error expected" ); |
534 | rc= mysql_query(mysql, "insert into t2 values (null,'e'),(12,'a'),(13,'b'),(25,'g')" ); |
535 | FAIL_IF(!rc, "Error expected" ); |
536 | rc= mysql_query(mysql, "insert into t2 values (null,last_insert_id(300))" ); |
537 | check_mysql_rc(rc, mysql); |
538 | res= mysql_insert_id(mysql); |
539 | /* |
540 | according to the manual, this might be 20 or 300, but it looks like |
541 | auto_increment column takes priority over last_insert_id(). |
542 | */ |
543 | diag("res: %lld" , res); |
544 | FAIL_UNLESS(res == 20, "" ); |
545 | /* If first autogenerated number fails and 2nd works: */ |
546 | rc= mysql_query(mysql, "drop table t2" ); |
547 | check_mysql_rc(rc, mysql); |
548 | rc= mysql_query(mysql, "create table t2 (f1 int not null primary key " |
549 | "auto_increment, f2 varchar(200), unique (f2)) engine=MyISAM" ); |
550 | check_mysql_rc(rc, mysql); |
551 | rc= mysql_query(mysql, "insert into t2 values (null,'e')" ); |
552 | res= mysql_insert_id(mysql); |
553 | FAIL_UNLESS(res == 1, "" ); |
554 | rc= mysql_query(mysql, "insert ignore into t2 values (null,'e'),(null,'a'),(null,'e')" ); |
555 | check_mysql_rc(rc, mysql); |
556 | res= mysql_insert_id(mysql); |
557 | FAIL_UNLESS(res == 2, "" ); |
558 | /* If autogenerated fails and explicit works: */ |
559 | rc= mysql_query(mysql, "insert ignore into t2 values (null,'e'),(12,'c'),(null,'d')" ); |
560 | check_mysql_rc(rc, mysql); |
561 | res= mysql_insert_id(mysql); |
562 | /* |
563 | Behaviour change: old code returned 3 (first autogenerated, even if it |
564 | fails); we now return first successful autogenerated. |
565 | */ |
566 | FAIL_UNLESS(res == 13, "" ); |
567 | /* UPDATE may update mysql_insert_id() if it uses LAST_INSERT_ID(#) */ |
568 | rc= mysql_query(mysql, "update t2 set f1=14 where f1=12" ); |
569 | check_mysql_rc(rc, mysql); |
570 | res= mysql_insert_id(mysql); |
571 | FAIL_UNLESS(res == 0, "" ); |
572 | rc= mysql_query(mysql, "update t2 set f1=0 where f1=14" ); |
573 | check_mysql_rc(rc, mysql); |
574 | res= mysql_insert_id(mysql); |
575 | FAIL_UNLESS(res == 0, "" ); |
576 | rc= mysql_query(mysql, "update t2 set f2=last_insert_id(372) where f1=0" ); |
577 | check_mysql_rc(rc, mysql); |
578 | res= mysql_insert_id(mysql); |
579 | FAIL_UNLESS(res == 372, "" ); |
580 | /* check that LAST_INSERT_ID() does not update mysql_insert_id(): */ |
581 | rc= mysql_query(mysql, "insert into t2 values (null,'g')" ); |
582 | check_mysql_rc(rc, mysql); |
583 | res= mysql_insert_id(mysql); |
584 | FAIL_UNLESS(res == 15, "" ); |
585 | rc= mysql_query(mysql, "update t2 set f2=(@li:=last_insert_id()) where f1=15" ); |
586 | check_mysql_rc(rc, mysql); |
587 | res= mysql_insert_id(mysql); |
588 | FAIL_UNLESS(res == 0, "" ); |
589 | /* |
590 | Behaviour change: now if ON DUPLICATE KEY UPDATE updates a row, |
591 | mysql_insert_id() returns the id of the row, instead of not being |
592 | affected. |
593 | */ |
594 | rc= mysql_query(mysql, "insert into t2 values (null,@li) on duplicate key " |
595 | "update f2=concat('we updated ',f2)" ); |
596 | check_mysql_rc(rc, mysql); |
597 | res= mysql_insert_id(mysql); |
598 | FAIL_UNLESS(res == 15, "" ); |
599 | |
600 | rc= mysql_query(mysql, "drop table t1,t2" ); |
601 | check_mysql_rc(rc, mysql); |
602 | return OK; |
603 | } |
604 | |
605 | /* Test simple select to debug */ |
606 | |
607 | static int test_select_direct(MYSQL *mysql) |
608 | { |
609 | int rc; |
610 | MYSQL_RES *result; |
611 | |
612 | |
613 | rc= mysql_autocommit(mysql, TRUE); |
614 | check_mysql_rc(rc, mysql); |
615 | |
616 | rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_select" ); |
617 | check_mysql_rc(rc, mysql); |
618 | |
619 | rc= mysql_query(mysql, "CREATE TABLE test_select(id int, id1 tinyint, " |
620 | " id2 float, " |
621 | " id3 double, " |
622 | " name varchar(50))" ); |
623 | check_mysql_rc(rc, mysql); |
624 | |
625 | /* insert a row and commit the transaction */ |
626 | rc= mysql_query(mysql, "INSERT INTO test_select VALUES(10, 5, 2.3, 4.5, 'venu')" ); |
627 | check_mysql_rc(rc, mysql); |
628 | |
629 | rc= mysql_commit(mysql); |
630 | check_mysql_rc(rc, mysql); |
631 | |
632 | rc= mysql_query(mysql, "SELECT * FROM test_select" ); |
633 | check_mysql_rc(rc, mysql); |
634 | |
635 | /* get the result */ |
636 | result= mysql_store_result(mysql); |
637 | FAIL_IF(!result, "Invalid result set" ); |
638 | |
639 | mysql_free_result(result); |
640 | rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_select" ); |
641 | check_mysql_rc(rc, mysql); |
642 | return OK; |
643 | } |
644 | |
645 | /* |
646 | Ensure we execute the status code while testing |
647 | */ |
648 | |
649 | static int test_status(MYSQL *mysql) |
650 | { |
651 | mysql_stat(mysql); |
652 | check_mysql_rc(mysql_errno(mysql), mysql); |
653 | return OK; |
654 | } |
655 | |
656 | static int bug_conc1(MYSQL *mysql) |
657 | { |
658 | my_test_connect(mysql, hostname, username, password, schema, |
659 | port, socketname, 0); |
660 | diag("errno: %d" , mysql_errno(mysql)); |
661 | FAIL_IF(mysql_errno(mysql) != CR_ALREADY_CONNECTED, |
662 | "Expected errno=CR_ALREADY_CONNECTED" ); |
663 | return OK; |
664 | } |
665 | |
666 | static int test_options_initcmd(MYSQL *unused __attribute__((unused))) |
667 | { |
668 | MYSQL *mysql= mysql_init(NULL); |
669 | MYSQL_RES *res; |
670 | int rc; |
671 | |
672 | mysql_options(mysql, MYSQL_INIT_COMMAND, "DROP TABLE IF EXISTS t1; CREATE TABLE t1 (a int)" ); |
673 | mysql_options(mysql, MYSQL_INIT_COMMAND, "INSERT INTO t1 VALUES (1),(2),(3)" ); |
674 | FAIL_IF(!my_test_connect(mysql, hostname, username, password, schema, |
675 | port, socketname, |
676 | CLIENT_MULTI_STATEMENTS | CLIENT_MULTI_RESULTS), mysql_error(mysql)); |
677 | |
678 | rc= mysql_query(mysql, "SELECT a FROM t1" ); |
679 | check_mysql_rc(rc, mysql); |
680 | |
681 | res= mysql_store_result(mysql); |
682 | FAIL_IF(mysql_num_rows(res) != 3, "Expected 3 rows" ); |
683 | |
684 | mysql_free_result(res); |
685 | |
686 | rc= mysql_query(mysql, "DROP TABLE t1" ); |
687 | check_mysql_rc(rc, mysql); |
688 | mysql_close(mysql); |
689 | return OK; |
690 | } |
691 | |
692 | static int test_extended_init_values(MYSQL *unused __attribute__((unused))) |
693 | { |
694 | MYSQL *mysql= mysql_init(NULL); |
695 | |
696 | mysql_options(mysql, MYSQL_DEFAULT_AUTH, "unknown" ); |
697 | FAIL_IF(strcmp(mysql->options.extension->default_auth, "unknown" ), "option not set" ); |
698 | |
699 | mysql_options(mysql, MYSQL_PLUGIN_DIR, "/tmp/foo" ); |
700 | FAIL_IF(strcmp(mysql->options.extension->plugin_dir, "/tmp/foo" ), "option not set" ); |
701 | |
702 | mysql_close(mysql); |
703 | return OK; |
704 | } |
705 | |
706 | static int test_reconnect_maxpackage(MYSQL *unused __attribute__((unused))) |
707 | { |
708 | int rc; |
709 | ulong max_packet= 0; |
710 | MYSQL *mysql; |
711 | MYSQL_RES *res; |
712 | MYSQL_ROW row; |
713 | char *query; |
714 | my_bool reconnect= 1; |
715 | |
716 | SKIP_CONNECTION_HANDLER; |
717 | |
718 | mysql= mysql_init(NULL); |
719 | |
720 | FAIL_IF(!my_test_connect(mysql, hostname, username, password, schema, |
721 | port, socketname, |
722 | CLIENT_MULTI_STATEMENTS | CLIENT_MULTI_RESULTS), mysql_error(mysql)); |
723 | mysql_options(mysql, MYSQL_OPT_RECONNECT, &reconnect); |
724 | |
725 | rc= mysql_query(mysql, "SELECT @@max_allowed_packet" ); |
726 | check_mysql_rc(rc, mysql); |
727 | res= mysql_store_result(mysql); |
728 | row= mysql_fetch_row(res); |
729 | max_packet= atol(row[0]); |
730 | diag("max_allowed_packet=%lu" , max_packet); |
731 | mysql_free_result(res); |
732 | |
733 | query= (char *)malloc(max_packet + 30); |
734 | memset(query, 0, max_packet + 30); |
735 | |
736 | strcpy(query, "SELECT '" ); |
737 | memset(query + 8, 'A', max_packet); |
738 | strcat(query, "' FROM DUAL" ); |
739 | |
740 | rc= mysql_query(mysql, query); |
741 | free(query); |
742 | if (!rc) |
743 | { |
744 | diag("expected error" ); |
745 | mysql_close(mysql); |
746 | return FAIL; |
747 | } |
748 | else |
749 | diag("Error (expected): %s" , mysql_error(mysql)); |
750 | |
751 | rc= mysql_ping(mysql); |
752 | /* if the server is under load, poll might not report closed |
753 | socket since FIN packet came too late */ |
754 | if (rc) |
755 | rc= mysql_ping(mysql); |
756 | check_mysql_rc(rc, mysql); |
757 | rc= mysql_query(mysql, "SELECT @@max_allowed_packet" ); |
758 | check_mysql_rc(rc, mysql); |
759 | res= mysql_store_result(mysql); |
760 | row= mysql_fetch_row(res); |
761 | max_packet= atol(row[0]); |
762 | diag("max_allowed_packet=%lu" , max_packet); |
763 | mysql_free_result(res); |
764 | |
765 | |
766 | mysql_close(mysql); |
767 | return OK; |
768 | } |
769 | |
770 | static int test_compressed(MYSQL *unused __attribute__((unused))) |
771 | { |
772 | int rc; |
773 | MYSQL *mysql= mysql_init(NULL); |
774 | MYSQL_RES *res; |
775 | my_bool reconnect= 1; |
776 | |
777 | mysql_options(mysql, MYSQL_OPT_COMPRESS, (void *)1); |
778 | FAIL_IF(!my_test_connect(mysql, hostname, username, password, schema, |
779 | port, socketname, |
780 | CLIENT_MULTI_STATEMENTS | CLIENT_MULTI_RESULTS), mysql_error(mysql)); |
781 | mysql_options(mysql, MYSQL_OPT_RECONNECT, &reconnect); |
782 | |
783 | rc= mysql_query(mysql, "SHOW VARIABLES" ); |
784 | check_mysql_rc(rc, mysql); |
785 | |
786 | if ((res= mysql_store_result(mysql))) |
787 | mysql_free_result(res); |
788 | |
789 | mysql_close(mysql); |
790 | |
791 | return OK; |
792 | } |
793 | |
794 | struct my_tests_st my_tests[] = { |
795 | {"test_conc75" , test_conc75, TEST_CONNECTION_DEFAULT, 0, NULL, NULL}, |
796 | {"test_conc74" , test_conc74, TEST_CONNECTION_DEFAULT, 0, NULL, NULL}, |
797 | {"test_conc71" , test_conc71, TEST_CONNECTION_DEFAULT, 0, NULL, NULL}, |
798 | {"test_conc70" , test_conc70, TEST_CONNECTION_DEFAULT, 0, NULL, NULL}, |
799 | {"test_conc68" , test_conc68, TEST_CONNECTION_DEFAULT, 0, NULL, NULL}, |
800 | {"test_compressed" , test_compressed, TEST_CONNECTION_NONE, 0, NULL, NULL}, |
801 | {"test_reconnect_maxpackage" , test_reconnect_maxpackage, TEST_CONNECTION_NONE, 0, NULL, NULL}, |
802 | {"basic_connect" , basic_connect, TEST_CONNECTION_NONE, 0, NULL, NULL}, |
803 | {"use_utf8" , use_utf8, TEST_CONNECTION_NEW, 0, opt_utf8, NULL}, |
804 | {"client_query" , client_query, TEST_CONNECTION_DEFAULT, 0, NULL, NULL}, |
805 | {"test_bad_union" , test_bad_union, TEST_CONNECTION_DEFAULT, 0, NULL, NULL}, |
806 | {"test_select_direct" , test_select_direct, TEST_CONNECTION_DEFAULT, 0, NULL, NULL}, |
807 | {"test_mysql_insert_id" , test_mysql_insert_id, TEST_CONNECTION_DEFAULT, 0, NULL, NULL}, |
808 | {"test_bug12001" , test_bug12001, TEST_CONNECTION_NEW, CLIENT_MULTI_STATEMENTS, NULL, NULL}, |
809 | {"test_status" , test_status, TEST_CONNECTION_NEW, CLIENT_MULTI_STATEMENTS, NULL, NULL}, |
810 | {"bug_conc1" , bug_conc1, TEST_CONNECTION_NEW, 0, NULL, NULL}, |
811 | {"test_options_initcmd" , test_options_initcmd, TEST_CONNECTION_NONE, 0, NULL, NULL}, |
812 | {"test_extended_init_values" , test_extended_init_values, TEST_CONNECTION_NONE, 0, NULL, NULL}, |
813 | {NULL, NULL, 0, 0, NULL, NULL} |
814 | }; |
815 | |
816 | |
817 | int main(int argc, char **argv) |
818 | { |
819 | if (argc > 1) |
820 | get_options(argc, argv); |
821 | |
822 | get_envvars(); |
823 | |
824 | diag("user: %s" , username); |
825 | |
826 | run_tests(my_tests); |
827 | |
828 | return(exit_status()); |
829 | } |
830 | |