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 #include "my_test.h"
26
27 /*
28 test gbk charset escaping
29
30 The important part is that 0x27 (') is the second-byte in a invalid
31 two-byte GBK character here. But 0xbf5c is a valid GBK character, so
32 it needs to be escaped as 0x5cbf27
33
34 */
35 #define TEST_BUG8378_IN "\xef\xbb\xbf\x27\xbf\x10"
36 #define TEST_BUG8378_OUT "\xef\xbb\x5c\xbf\x5c\x27\x5c\xbf\x10"
37
38 /* set connection options */
39 struct my_option_st opt_bug8378[] = {
40 {MYSQL_SET_CHARSET_NAME, (char *) "gbk"},
41 {0, NULL}
42 };
43
bug_8378(MYSQL * mysql)44 int bug_8378(MYSQL *mysql) {
45 int rc, len;
46 char out[9], buf[256];
47 MYSQL_RES *res;
48 MYSQL_ROW row;
49
50 len= mysql_real_escape_string(mysql, out, TEST_BUG8378_IN, 4);
51 FAIL_IF(memcmp(out, TEST_BUG8378_OUT, len), "wrong result");
52
53 sprintf(buf, "SELECT '%s' FROM DUAL", TEST_BUG8378_OUT);
54
55 rc= mysql_query(mysql, buf);
56 check_mysql_rc(rc, mysql);
57
58 if ((res= mysql_store_result(mysql))) {
59 row= mysql_fetch_row(res);
60 if (memcmp(row[0], TEST_BUG8378_IN, 4)) {
61 mysql_free_result(res);
62 return FAIL;
63 }
64 mysql_free_result(res);
65 } else
66 return FAIL;
67
68 return OK;
69 }
70
test_client_character_set(MYSQL * mysql)71 int test_client_character_set(MYSQL *mysql)
72 {
73 MY_CHARSET_INFO cs;
74 char *csname= (char*) "utf8";
75 char *csdefault= (char*)mysql_character_set_name(mysql);
76
77 FAIL_IF(mysql_set_character_set(mysql, csname), mysql_error(mysql));
78
79 mysql_get_character_set_info(mysql, &cs);
80
81 FAIL_IF(strcmp(cs.csname, "utf8") || strcmp(cs.name, "utf8_general_ci"), "Character set != UTF8");
82 FAIL_IF(mysql_set_character_set(mysql, csdefault), mysql_error(mysql));
83
84 return OK;
85 }
86
87 /*
88 * Regression test for bug #10214
89 *
90 * Test escaping with NO_BACKSLASH_ESCAPES
91 *
92 */
bug_10214(MYSQL * mysql)93 int bug_10214(MYSQL *mysql)
94 {
95 int len, rc;
96 char out[8];
97
98 /* reset sql_mode */
99 rc= mysql_query(mysql, "SET sql_mode=''");
100 check_mysql_rc(rc, mysql);
101
102 len= mysql_real_escape_string(mysql, out, "a'b\\c", 5);
103 FAIL_IF(memcmp(out, "a\\'b\\\\c", len), "wrong result");
104
105 rc= mysql_query(mysql, "set sql_mode='NO_BACKSLASH_ESCAPES'");
106 check_mysql_rc(rc, mysql);
107 FAIL_IF(!(mysql->server_status & SERVER_STATUS_NO_BACKSLASH_ESCAPES),
108 "wrong server status: NO_BACKSLASH_ESCAPES not set");
109
110 len= mysql_real_escape_string(mysql, out, "a'b\\c", 5);
111 FAIL_IF(memcmp(out, "a''b\\c", len), "wrong result");
112
113 return OK;
114 }
115
116 /*
117 * simple escaping of special chars
118 */
test_escaping(MYSQL * mysql)119 int test_escaping(MYSQL *mysql)
120 {
121 int i= 0, rc, len;
122 char out[20];
123 const char *escape_chars[] = {"'", "\x0", "\n", "\r", "\\", "\0", NULL};
124
125 /* reset sql_mode, mysql_change_user call doesn't reset it */
126 rc= mysql_query(mysql, "SET sql_mode=''");
127 check_mysql_rc(rc, mysql);
128
129 while (escape_chars[i]) {
130 len= mysql_real_escape_string(mysql, out, escape_chars[i], 1);
131 FAIL_IF(len < 2, "Len < 2");
132 i++;
133 }
134
135 return OK;
136 }
137
138 /*
139 * server doesn't reset sql_mode after COM_CHANGE_USER
140 */
bug_41785(MYSQL * mysql)141 int bug_41785(MYSQL *mysql)
142 {
143 char out[10];
144 int rc, len;
145
146 len= mysql_real_escape_string(mysql, out, "\\", 1);
147 FAIL_IF(len != 2, "len != 2");
148
149 rc= mysql_query(mysql, "SET SQL_MODE=NO_BACKSLASH_ESCAPES");
150 check_mysql_rc(rc, mysql);
151 rc= mysql_query(mysql, "SET sql_mode=''");
152 check_mysql_rc(rc, mysql);
153
154 mysql_change_user(mysql, "root", "", "test");
155
156 len= mysql_real_escape_string(mysql, out, "\\", 1);
157 FAIL_IF(len != 2, "len != 2");
158
159 return OK;
160 }
161
test_conversion(MYSQL * mysql)162 static int test_conversion(MYSQL *mysql)
163 {
164 MYSQL_STMT *stmt;
165 const char *stmt_text;
166 int rc;
167 MYSQL_BIND my_bind[1];
168 uchar buff[4];
169 ulong length;
170
171 stmt_text= "DROP TABLE IF EXISTS t1";
172 rc= mysql_real_query(mysql, SL(stmt_text));
173 check_mysql_rc(rc, mysql);
174 stmt_text= "CREATE TABLE t1 (a TEXT) DEFAULT CHARSET latin1";
175 rc= mysql_real_query(mysql, SL(stmt_text));
176 check_mysql_rc(rc, mysql);
177 stmt_text= "SET character_set_connection=utf8, character_set_client=utf8, "
178 " character_set_results=latin1";
179 rc= mysql_real_query(mysql, SL(stmt_text));
180 check_mysql_rc(rc, mysql);
181
182 stmt= mysql_stmt_init(mysql);
183 FAIL_IF(!stmt, mysql_error(mysql));
184 stmt_text= "INSERT INTO t1 (a) VALUES (?)";
185 rc= mysql_stmt_prepare(stmt, SL(stmt_text));
186 check_stmt_rc(rc, stmt);
187
188 memset(my_bind, '\0', sizeof(my_bind));
189 my_bind[0].buffer= (char*) buff;
190 my_bind[0].length= &length;
191 my_bind[0].buffer_type= MYSQL_TYPE_STRING;
192
193 mysql_stmt_bind_param(stmt, my_bind);
194
195 buff[0]= (uchar) 0xC3;
196 buff[1]= (uchar) 0xA0;
197 length= 2;
198
199 rc= mysql_stmt_execute(stmt);
200 check_stmt_rc(rc, stmt);
201
202 stmt_text= "SELECT a FROM t1";
203 rc= mysql_stmt_prepare(stmt, SL(stmt_text));
204 check_stmt_rc(rc, stmt);
205 rc= mysql_stmt_execute(stmt);
206 check_stmt_rc(rc, stmt);
207
208 my_bind[0].buffer_length= sizeof(buff);
209 mysql_stmt_bind_result(stmt, my_bind);
210
211 rc= mysql_stmt_fetch(stmt);
212 check_stmt_rc(rc, stmt);
213 FAIL_UNLESS(length == 1, "length != 1");
214 FAIL_UNLESS(buff[0] == 0xE0, "buff[0] != 0xE0");
215 rc= mysql_stmt_fetch(stmt);
216 FAIL_UNLESS(rc == MYSQL_NO_DATA, "rc != MYSQL_NO_DATA");
217
218 mysql_stmt_close(stmt);
219 stmt_text= "DROP TABLE t1";
220 rc= mysql_real_query(mysql, SL(stmt_text));
221 check_mysql_rc(rc, mysql);
222 stmt_text= "SET NAMES DEFAULT";
223 rc= mysql_real_query(mysql, SL(stmt_text));
224 check_mysql_rc(rc, mysql);
225
226 return OK;
227 }
228
test_bug27876(MYSQL * mysql)229 static int test_bug27876(MYSQL *mysql)
230 {
231 int rc;
232 MYSQL_RES *result;
233
234 uchar utf8_func[] =
235 {
236 0xd1, 0x84, 0xd1, 0x83, 0xd0, 0xbd, 0xd0, 0xba,
237 0xd1, 0x86, 0xd0, 0xb8, 0xd0, 0xb9, 0xd0, 0xba,
238 0xd0, 0xb0,
239 0x00
240 };
241
242 uchar utf8_param[] =
243 {
244 0xd0, 0xbf, 0xd0, 0xb0, 0xd1, 0x80, 0xd0, 0xb0,
245 0xd0, 0xbc, 0xd0, 0xb5, 0xd1, 0x82, 0xd1, 0x8a,
246 0xd1, 0x80, 0x5f, 0xd0, 0xb2, 0xd0, 0xb5, 0xd1,
247 0x80, 0xd1, 0x81, 0xd0, 0xb8, 0xd1, 0x8f,
248 0x00
249 };
250
251 char query[500];
252
253 rc= mysql_query(mysql, "set names utf8");
254 check_mysql_rc(rc, mysql);
255
256 rc= mysql_query(mysql, "select version()");
257 check_mysql_rc(rc, mysql);
258 result= mysql_store_result(mysql);
259 FAIL_IF(!result, "Invalid result set");
260 mysql_free_result(result);
261
262 sprintf(query, "DROP FUNCTION IF EXISTS %s", (char*) utf8_func);
263 rc= mysql_query(mysql, query);
264 check_mysql_rc(rc, mysql);
265
266 sprintf(query,
267 "CREATE FUNCTION %s( %s VARCHAR(25))"
268 " RETURNS VARCHAR(25) DETERMINISTIC RETURN %s",
269 (char*) utf8_func, (char*) utf8_param, (char*) utf8_param);
270 rc= mysql_query(mysql, query);
271 check_mysql_rc(rc, mysql);
272 sprintf(query, "SELECT %s(VERSION())", (char*) utf8_func);
273 rc= mysql_query(mysql, query);
274 check_mysql_rc(rc, mysql);
275 result= mysql_store_result(mysql);
276 FAIL_IF(!result, "Invalid result set");
277 mysql_free_result(result);
278
279 sprintf(query, "DROP FUNCTION %s", (char*) utf8_func);
280 rc= mysql_query(mysql, query);
281 check_mysql_rc(rc, mysql);
282
283 rc= mysql_query(mysql, "set names default");
284 check_mysql_rc(rc, mysql);
285 return OK;
286 }
287
test_ps_i18n(MYSQL * mysql)288 static int test_ps_i18n(MYSQL *mysql)
289 {
290 MYSQL_STMT *stmt;
291 int rc;
292 const char *stmt_text;
293 MYSQL_BIND bind_array[2];
294
295 /* Represented as numbers to keep UTF8 tools from clobbering them. */
296 const char *koi8= "\xee\xd5\x2c\x20\xda\xc1\x20\xd2\xd9\xc2\xc1\xcc\xcb\xd5";
297 const char *cp1251= "\xcd\xf3\x2c\x20\xe7\xe0\x20\xf0\xfb\xe1\xe0\xeb\xea\xf3";
298 char buf1[16], buf2[16];
299 ulong buf1_len, buf2_len;
300
301 stmt_text= "DROP TABLE IF EXISTS t1";
302 rc= mysql_real_query(mysql, SL(stmt_text));
303 check_mysql_rc(rc, mysql);
304
305 /*
306 Create table with binary columns, set session character set to cp1251,
307 client character set to koi8, and make sure that there is conversion
308 on insert and no conversion on select
309 */
310
311 stmt_text= "CREATE TABLE t1 (c1 VARBINARY(255), c2 VARBINARY(255))";
312 rc= mysql_real_query(mysql, SL(stmt_text));
313 check_mysql_rc(rc, mysql);
314
315 stmt_text= "SET CHARACTER_SET_CLIENT=koi8r, "
316 "CHARACTER_SET_CONNECTION=cp1251, "
317 "CHARACTER_SET_RESULTS=koi8r";
318
319 rc= mysql_real_query(mysql, SL(stmt_text));
320 check_mysql_rc(rc, mysql);
321
322 memset(bind_array, '\0', sizeof(bind_array));
323 bind_array[0].buffer_type= MYSQL_TYPE_STRING;
324 bind_array[0].buffer= (void *) koi8;
325 bind_array[0].buffer_length= (unsigned long)strlen(koi8);
326
327 bind_array[1].buffer_type= MYSQL_TYPE_STRING;
328 bind_array[1].buffer= (void *) koi8;
329 bind_array[1].buffer_length= (unsigned long)strlen(koi8);
330
331 stmt= mysql_stmt_init(mysql);
332 check_stmt_rc(rc, stmt);
333
334 stmt_text= "INSERT INTO t1 (c1, c2) VALUES (?, ?)";
335
336 rc= mysql_stmt_prepare(stmt, SL(stmt_text));
337 check_stmt_rc(rc, stmt);
338 mysql_stmt_bind_param(stmt, bind_array);
339 check_stmt_rc(rc, stmt);
340
341 // mysql_stmt_send_long_data(stmt, 0, koi8, strlen(koi8));
342
343 rc= mysql_stmt_execute(stmt);
344 check_stmt_rc(rc, stmt);
345 stmt_text= "SELECT c1, c2 FROM t1";
346
347 /* c1 and c2 are binary so no conversion will be done on select */
348 rc= mysql_stmt_prepare(stmt, SL(stmt_text));
349 check_stmt_rc(rc, stmt);
350 rc= mysql_stmt_execute(stmt);
351 check_stmt_rc(rc, stmt);
352 bind_array[0].buffer= buf1;
353 bind_array[0].buffer_length= sizeof(buf1);
354 bind_array[0].length= &buf1_len;
355
356 bind_array[1].buffer= buf2;
357 bind_array[1].buffer_length= sizeof(buf2);
358 bind_array[1].length= &buf2_len;
359
360 mysql_stmt_bind_result(stmt, bind_array);
361
362 rc= mysql_stmt_fetch(stmt);
363 check_stmt_rc(rc, stmt);
364 FAIL_UNLESS(buf1_len == strlen(cp1251), "buf1_len != strlen(cp1251)");
365 FAIL_UNLESS(buf2_len == strlen(cp1251), "buf2_len != strlen(cp1251)");
366 FAIL_UNLESS(!memcmp(buf1, cp1251, buf1_len), "buf1 != cp1251");
367 FAIL_UNLESS(!memcmp(buf2, cp1251, buf1_len), "buf2 != cp1251");
368
369 rc= mysql_stmt_fetch(stmt);
370 FAIL_UNLESS(rc == MYSQL_NO_DATA, "rc != MYSQL_NO_DATA");
371
372 stmt_text= "DROP TABLE IF EXISTS t1";
373 rc= mysql_real_query(mysql, SL(stmt_text));
374 check_mysql_rc(rc, mysql);
375
376 /*
377 Now create table with two cp1251 columns, set client character
378 set to koi8 and supply columns of one row as string and another as
379 binary data. Binary data must not be converted on insert, and both
380 columns must be converted to client character set on select.
381 */
382
383 stmt_text= "CREATE TABLE t1 (c1 VARCHAR(255) CHARACTER SET cp1251, "
384 "c2 VARCHAR(255) CHARACTER SET cp1251)";
385
386 rc= mysql_real_query(mysql, SL(stmt_text));
387 check_mysql_rc(rc, mysql);
388
389 stmt_text= "INSERT INTO t1 (c1, c2) VALUES (?, ?)";
390
391 rc= mysql_stmt_prepare(stmt, SL(stmt_text));
392 check_stmt_rc(rc, stmt);
393 /* this data must be converted */
394 bind_array[0].buffer_type= MYSQL_TYPE_STRING;
395 bind_array[0].buffer= (void *) koi8;
396 bind_array[0].buffer_length= (unsigned long)strlen(koi8);
397
398 bind_array[1].buffer_type= MYSQL_TYPE_STRING;
399 bind_array[1].buffer= (void *) koi8;
400 bind_array[1].buffer_length= (unsigned long)strlen(koi8);
401
402 mysql_stmt_bind_param(stmt, bind_array);
403
404 // mysql_stmt_send_long_data(stmt, 0, koi8, strlen(koi8));
405
406 rc= mysql_stmt_execute(stmt);
407 check_stmt_rc(rc, stmt);
408 /* this data must not be converted */
409 bind_array[0].buffer_type= MYSQL_TYPE_BLOB;
410 bind_array[0].buffer= (void *) cp1251;
411 bind_array[0].buffer_length= (unsigned long)strlen(cp1251);
412
413 bind_array[1].buffer_type= MYSQL_TYPE_BLOB;
414 bind_array[1].buffer= (void *) cp1251;
415 bind_array[1].buffer_length= (unsigned long)strlen(cp1251);
416
417 mysql_stmt_bind_param(stmt, bind_array);
418
419 // mysql_stmt_send_long_data(stmt, 0, cp1251, strlen(cp1251));
420
421 rc= mysql_stmt_execute(stmt);
422 check_stmt_rc(rc, stmt);
423 /* Fetch data and verify that rows are in koi8 */
424
425 stmt_text= "SELECT c1, c2 FROM t1";
426
427 /* c1 and c2 are binary so no conversion will be done on select */
428 rc= mysql_stmt_prepare(stmt, SL(stmt_text));
429 check_stmt_rc(rc, stmt);
430 rc= mysql_stmt_execute(stmt);
431 check_stmt_rc(rc, stmt);
432 bind_array[0].buffer= buf1;
433 bind_array[0].buffer_length= sizeof(buf1);
434 bind_array[0].length= &buf1_len;
435
436 bind_array[1].buffer= buf2;
437 bind_array[1].buffer_length= sizeof(buf2);
438 bind_array[1].length= &buf2_len;
439
440 mysql_stmt_bind_result(stmt, bind_array);
441
442 while ((rc= mysql_stmt_fetch(stmt)) == 0)
443 {
444 FAIL_UNLESS(buf1_len == strlen(koi8), "buf1_len != strlen(koi8)");
445 FAIL_UNLESS(buf2_len == strlen(koi8), "buf2_len != strlen(koi8)");
446 FAIL_UNLESS(!memcmp(buf1, koi8, buf1_len), "buf1 != koi8");
447 FAIL_UNLESS(!memcmp(buf2, koi8, buf1_len), "buf2 != koi8");
448 }
449 FAIL_UNLESS(rc == MYSQL_NO_DATA, "rc != MYSQL_NO_DATA");
450 mysql_stmt_close(stmt);
451
452 stmt_text= "DROP TABLE t1";
453 rc= mysql_real_query(mysql, SL(stmt_text));
454 check_mysql_rc(rc, mysql);
455 stmt_text= "SET NAMES DEFAULT";
456 rc= mysql_real_query(mysql, SL(stmt_text));
457 check_mysql_rc(rc, mysql);
458 return OK;
459 }
460
461 /*
462 Bug#30472: libmysql doesn't reset charset, insert_id after succ.
463 mysql_change_user() call row insertions.
464 */
465
bug30472_retrieve_charset_info(MYSQL * con,char * character_set_name,char * character_set_client,char * character_set_results,char * collation_connection)466 static int bug30472_retrieve_charset_info(MYSQL *con,
467 char *character_set_name,
468 char *character_set_client,
469 char *character_set_results,
470 char *collation_connection)
471 {
472 MYSQL_RES *rs;
473 MYSQL_ROW row;
474 int rc;
475
476 /* Get the cached client character set name. */
477
478 strcpy(character_set_name, mysql_character_set_name(con));
479
480 /* Retrieve server character set information. */
481
482 rc= mysql_query(con, "SHOW VARIABLES LIKE 'character_set_client'");
483 check_mysql_rc(rc, con);
484
485 rs= mysql_store_result(con);
486 FAIL_IF(!rs, "Invalid result set");
487 row= mysql_fetch_row(rs);
488 FAIL_IF(!row, "Couldn't fetch row");
489 strcpy(character_set_client, row[1]);
490 mysql_free_result(rs);
491
492 rc= mysql_query(con, "SHOW VARIABLES LIKE 'character_set_results'");
493 check_mysql_rc(rc, con);
494 rs= mysql_store_result(con);
495 FAIL_IF(!rs, "Invalid result set");
496 row= mysql_fetch_row(rs);
497 FAIL_IF(!row, "Couldn't fetch row");
498 strcpy(character_set_results, row[1]);
499 mysql_free_result(rs);
500
501 rc= mysql_query(con, "SHOW VARIABLES LIKE 'collation_connection'");
502 check_mysql_rc(rc, con);
503 rs= mysql_store_result(con);
504 FAIL_IF(!rs, "Invalid result set");
505 row= mysql_fetch_row(rs);
506 FAIL_IF(!row, "Couldn't fetch row");
507 strcpy(collation_connection, row[1]);
508 mysql_free_result(rs);
509 return OK;
510 }
511
512 #define MY_CS_NAME_SIZE 32
513
test_bug30472(MYSQL * mysql)514 static int test_bug30472(MYSQL *mysql)
515 {
516 int rc;
517
518 char character_set_name_1[MY_CS_NAME_SIZE];
519 char character_set_client_1[MY_CS_NAME_SIZE];
520 char character_set_results_1[MY_CS_NAME_SIZE];
521 char collation_connnection_1[MY_CS_NAME_SIZE];
522
523 char character_set_name_2[MY_CS_NAME_SIZE];
524 char character_set_client_2[MY_CS_NAME_SIZE];
525 char character_set_results_2[MY_CS_NAME_SIZE];
526 char collation_connnection_2[MY_CS_NAME_SIZE];
527
528 char character_set_name_3[MY_CS_NAME_SIZE];
529 char character_set_client_3[MY_CS_NAME_SIZE];
530 char character_set_results_3[MY_CS_NAME_SIZE];
531 char collation_connnection_3[MY_CS_NAME_SIZE];
532
533 char character_set_name_4[MY_CS_NAME_SIZE];
534 char character_set_client_4[MY_CS_NAME_SIZE];
535 char character_set_results_4[MY_CS_NAME_SIZE];
536 char collation_connnection_4[MY_CS_NAME_SIZE];
537
538 SKIP_MAXSCALE;
539
540 if (mysql_get_server_version(mysql) < 50100 || !is_mariadb)
541 {
542 diag("Test requires MySQL Server version 5.1 or above");
543 return SKIP;
544 }
545 /* Retrieve character set information. */
546
547 mysql_set_character_set(mysql, "latin1");
548 bug30472_retrieve_charset_info(mysql,
549 character_set_name_1,
550 character_set_client_1,
551 character_set_results_1,
552 collation_connnection_1);
553
554 /* Switch client character set. */
555
556 FAIL_IF(mysql_set_character_set(mysql, "utf8"), "Setting cs to utf8 failed");
557
558 /* Retrieve character set information. */
559
560 bug30472_retrieve_charset_info(mysql,
561 character_set_name_2,
562 character_set_client_2,
563 character_set_results_2,
564 collation_connnection_2);
565
566 /*
567 Check that
568 1) character set has been switched and
569 2) new character set is different from the original one.
570 */
571
572 FAIL_UNLESS(strncmp(character_set_name_2, "utf8", 4) == 0, "cs_name != utf8");
573 FAIL_UNLESS(strncmp(character_set_client_2, "utf8", 4) == 0, "cs_client != utf8");
574 FAIL_UNLESS(strncmp(character_set_results_2, "utf8", 4) == 0, "cs_result != ut8");
575 if (mariadb_connection(mysql) && mysql_get_server_version(mysql) < 100600) {
576 FAIL_UNLESS(strcmp(collation_connnection_2, "utf8_general_ci") == 0, "collation != utf8_general_ci");
577 } else {
578 FAIL_UNLESS(strcmp(collation_connnection_2, "utf8mb3_general_ci") == 0, "collation != utf8_general_ci");
579 }
580
581 diag("%s %s", character_set_name_1, character_set_name_2);
582 FAIL_UNLESS(strcmp(character_set_name_1, character_set_name_2) != 0, "cs_name1 = cs_name2");
583 FAIL_UNLESS(strcmp(character_set_client_1, character_set_client_2) != 0, "cs_client1 = cs_client2");
584 FAIL_UNLESS(strcmp(character_set_results_1, character_set_results_2) != 0, "cs_result1 = cs_result2");
585 FAIL_UNLESS(strcmp(collation_connnection_1, collation_connnection_2) != 0, "collation1 = collation2");
586
587 /* Call mysql_change_user() with the same username, password, database. */
588
589 rc= mysql_change_user(mysql, username, password, (schema) ? schema : "test");
590 mysql_set_character_set(mysql, "latin1");
591 check_mysql_rc(rc, mysql);
592
593 /* Retrieve character set information. */
594
595 bug30472_retrieve_charset_info(mysql,
596 character_set_name_3,
597 character_set_client_3,
598 character_set_results_3,
599 collation_connnection_3);
600
601 /* Check that character set information has been reset. */
602
603 FAIL_UNLESS(strcmp(character_set_name_1, character_set_name_3) == 0, "cs_name1 != cs_name3");
604 FAIL_UNLESS(strcmp(character_set_client_1, character_set_client_3) == 0, "cs_client1 != cs_client3");
605 FAIL_UNLESS(strcmp(character_set_results_1, character_set_results_3) == 0, "cs_result1 != cs_result3");
606 FAIL_UNLESS(strcmp(collation_connnection_1, collation_connnection_3) == 0, "collation1 != collation3");
607
608 /* Change connection-default character set in the client. */
609
610 mysql_options(mysql, MYSQL_SET_CHARSET_NAME, "utf8");
611
612 /*
613 Call mysql_change_user() in order to check that new connection will
614 have UTF8 character set on the client and on the server.
615 */
616
617 rc= mysql_change_user(mysql, username, password, (schema) ? schema : "test");
618 check_mysql_rc(rc, mysql);
619
620 /* Retrieve character set information. */
621
622 bug30472_retrieve_charset_info(mysql,
623 character_set_name_4,
624 character_set_client_4,
625 character_set_results_4,
626 collation_connnection_4);
627
628 /* Check that we have UTF8 on the server and on the client. */
629 FAIL_UNLESS(strcmp(character_set_name_4, "utf8") == 0, "cs_name != utf8");
630 if (mariadb_connection(mysql) && mysql_get_server_version(mysql) < 100600) {
631 FAIL_UNLESS(strcmp(character_set_client_4, "utf8") == 0, "cs_client != utf8");
632 FAIL_UNLESS(strcmp(character_set_results_4, "utf8") == 0, "cs_result != utf8");
633 FAIL_UNLESS(strcmp(collation_connnection_4, "utf8_general_ci") == 0, "collation_connection != utf8_general_ci");
634 } else {
635 FAIL_UNLESS(strcmp(character_set_client_4, "utf8mb3") == 0, "cs_client != utf8");
636 FAIL_UNLESS(strcmp(character_set_results_4, "utf8mb3") == 0, "cs_result != utf8");
637 FAIL_UNLESS(strcmp(collation_connnection_4, "utf8mb3_general_ci") == 0, "collation_connection != utf8_general_ci");
638 }
639
640 /* That's it. Cleanup. */
641
642 return OK;
643 }
644
test_bug_54100(MYSQL * mysql)645 static int test_bug_54100(MYSQL *mysql)
646 {
647 MYSQL_RES *result;
648 MYSQL_ROW row;
649 int rc;
650
651 rc= mysql_query(mysql, "SHOW CHARACTER SET");
652 check_mysql_rc(rc, mysql);
653
654 result= mysql_store_result(mysql);
655
656 while ((row= mysql_fetch_row(result)))
657 {
658 /* ignore ucs2 */
659 if (strcmp(row[0], "ucs2")
660 && strcmp(row[0], "utf16le")
661 && (strcmp(row[0], "utf8mb4") && mariadb_connection(mysql) && mysql_get_server_version(mysql) < 100600)
662 && (strcmp(row[0], "utf8") && mariadb_connection(mysql) && mysql_get_server_version(mysql) >= 100600)
663 && strcmp(row[0], "utf16")
664 && strcmp(row[0], "utf32")) {
665 rc= mysql_set_character_set(mysql, row[0]);
666 check_mysql_rc(rc, mysql);
667 }
668 }
669 mysql_free_result(result);
670
671 return OK;
672 }
673
674
675 /* We need this internal function for the test */
676
test_utf16_utf32_noboms(MYSQL * mysql)677 static int test_utf16_utf32_noboms(MYSQL *mysql __attribute__((unused)))
678 {
679 #ifndef HAVE_ICONV
680 diag("MariaDB Connector/C was built without iconv support");
681 return SKIP;
682 #else
683 const char *csname[]= {"utf16", "utf16le", "utf32", "utf8"};
684 MARIADB_CHARSET_INFO *csinfo[sizeof(csname)/sizeof(char*)];
685
686 const int UTF8= sizeof(csname)/sizeof(char*) - 1;
687
688 unsigned char in_string[][8]= {"\xd8\x02\xdc\x60\0", /* utf16(be) */
689 "\x02\xd8\x60\xdc\0", /* utf16le */
690 "\x00\x01\x08\x60\0\0\0", /* utf32(be) */
691 "\xF0\x90\xA1\xA0" }; /* utf8 */
692 size_t in_oct_len[]= {6, 6, 8, 5};
693
694 char buffer[8], as_hex[16];
695 int i, error;
696 size_t rc, in_len, out_len;
697
698 for (i= 0; i < (int)(sizeof(csname)/sizeof(char*)); ++i)
699 {
700 csinfo[i]= mariadb_get_charset_by_name(csname[i]);
701
702 if (csinfo[i] == NULL)
703 {
704 diag("Could not get cs info for %s", csname[i]);
705 return FAIL;
706 }
707 }
708
709 for (i= 0; i < UTF8; ++i)
710 {
711 in_len= in_oct_len[i];
712 out_len= sizeof(buffer);
713
714 diag("Converting %s->%s", csname[i], csname[UTF8]);
715 rc= mariadb_convert_string((char *)in_string[i], &in_len, csinfo[i], buffer, &out_len, csinfo[UTF8], &error);
716
717 FAIL_IF(rc == (size_t)-1, "Conversion failed");
718 FAIL_IF(rc != in_oct_len[UTF8], "Incorrect number of written bytes");
719
720 if (memcmp(buffer, in_string[UTF8], rc) != 0)
721 {
722 mysql_hex_string(as_hex, buffer, (unsigned long)rc);
723 diag("Converted string(%s) does not match the expected one", as_hex);
724 return FAIL;
725 }
726
727 in_len= in_oct_len[UTF8];
728 out_len= sizeof(buffer);
729
730 diag("Converting %s->%s", csname[UTF8], csname[i]);
731 rc= mariadb_convert_string((char *)in_string[UTF8], &in_len, csinfo[UTF8], buffer, &out_len, csinfo[i], &error);
732
733 FAIL_IF(rc == (size_t)-1, "Conversion failed");
734 diag("rc=%lu oct_len: %lu", (unsigned long)rc, (unsigned long)in_oct_len[i]);
735 FAIL_IF(rc != in_oct_len[i], "Incorrect number of written bytes");
736
737 if (memcmp(buffer, in_string[i], rc) != 0)
738 {
739 mysql_hex_string(as_hex, buffer, (unsigned long)rc);
740 diag("Converted string(%s) does not match the expected one", as_hex);
741 return FAIL;
742 }
743 }
744
745 return OK;
746 #endif
747 }
748
charset_auto(MYSQL * my)749 static int charset_auto(MYSQL *my __attribute__((unused)))
750 {
751 const char *csname1, *csname2;
752 const char *osname;
753 MYSQL *mysql= mysql_init(NULL);
754 int rc;
755
756 osname= madb_get_os_character_set();
757
758 mysql_options(mysql, MYSQL_SET_CHARSET_NAME, "auto");
759
760 FAIL_IF(!my_test_connect(mysql, hostname, username,
761 password, schema, port, socketname, 0),
762 mysql_error(mysql));
763
764 csname1= mysql_character_set_name(mysql);
765 diag("Character set: %s os charset: %s", csname1, osname);
766
767 FAIL_IF(strcmp(osname, csname1), "character set is not os character set");
768
769 if (strcmp(osname, "utf8"))
770 {
771 rc= mysql_set_character_set(mysql, "utf8");
772 check_mysql_rc(rc, mysql);
773
774 csname2= mysql_character_set_name(mysql);
775 diag("Character set: %s", csname2);
776
777 FAIL_IF(!strcmp(csname2, csname1), "Wrong charset: expected utf8");
778
779 rc= mysql_set_character_set(mysql, "auto");
780 check_mysql_rc(rc, mysql);
781
782 csname2= mysql_character_set_name(mysql);
783 diag("Character set: %s", csname2);
784 FAIL_IF(strcmp(csname2, osname), "Wrong charset: expected os charset");
785 }
786 mysql_close(mysql);
787 return OK;
788 }
789
790 /* check if all server character sets are supported */
test_conc223(MYSQL * mysql)791 static int test_conc223(MYSQL *mysql)
792 {
793 int rc;
794 MYSQL_RES *res;
795 MYSQL_ROW row;
796 int found= 0;
797
798 SKIP_MYSQL(mysql);
799
800 rc= mysql_query(mysql, "SELECT ID, CHARACTER_SET_NAME, COLLATION_NAME FROM INFORMATION_SCHEMA.COLLATIONS");
801 check_mysql_rc(rc, mysql);
802
803 res= mysql_store_result(mysql);
804 while ((row = mysql_fetch_row(res)))
805 {
806 int id= atoi(row[0]);
807 if (!mariadb_get_charset_by_nr(id))
808 {
809 diag("%04d %s %s", id, row[1], row[2]);
810 found++;
811 }
812 }
813 mysql_free_result(res);
814 if (found)
815 {
816 diag("%d character sets/collations not found", found);
817 return FAIL;
818 }
819 return OK;
820 }
821
822 struct my_tests_st my_tests[] = {
823 {"test_conc223", test_conc223, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},
824 {"charset_auto", charset_auto, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},
825 {"bug_8378: mysql_real_escape with gbk", bug_8378, TEST_CONNECTION_NEW, 0, opt_bug8378, NULL},
826 {"test_client_character_set", test_client_character_set, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},
827 {"bug_10214: mysql_real_escape with NO_BACKSLASH_ESCAPES", bug_10214, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},
828 {"test_escaping", test_escaping, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},
829 {"test_conversion", test_conversion, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},
830 {"bug_41785", bug_41785, TEST_CONNECTION_DEFAULT, 0, NULL, "not fixed yet"},
831 {"test_bug27876", test_bug27876, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},
832 {"test_bug30472", test_bug30472, TEST_CONNECTION_NEW, 0, NULL, NULL},
833 {"test_ps_i18n", test_ps_i18n, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},
834 {"test_bug_54100", test_bug_54100, TEST_CONNECTION_NEW, 0, NULL, NULL},
835 {"test_utf16_utf32_noboms", test_utf16_utf32_noboms, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},
836 {NULL, NULL, 0, 0, NULL, 0}
837 };
838
839
main(int argc,char ** argv)840 int main(int argc, char **argv)
841 {
842 if (argc > 1)
843 get_options(argc, argv);
844
845 get_envvars();
846
847 run_tests(my_tests);
848
849 return(exit_status());
850 }
851