1/*
2Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
3
4The 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
6MySQL Connectors. There are special exceptions to the terms and
7conditions of the GPLv2 as it is applied to this software, see the
8FLOSS License Exception
9<http://www.mysql.com/about/legal/licensing/foss-exception.html>.
10
11This program is free software; you can redistribute it and/or modify
12it under the terms of the GNU General Public License as published
13by the Free Software Foundation; version 2 of the License.
14
15This program is distributed in the hope that it will be useful, but
16WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
17or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
18for more details.
19
20You should have received a copy of the GNU General Public License along
21with this program; if not, write to the Free Software Foundation, Inc.,
2251 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 */
39struct my_option_st opt_bug8378[] = {
40 {MYSQL_SET_CHARSET_NAME, (char *) "gbk"},
41 {0, NULL}
42};
43
44int 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
71int 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 */
93int 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), NULL);
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 */
119int 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 */
141int 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
162static 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
229static 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
288static 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
466static 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 diag("cs: %s", row[1]);
491 mysql_free_result(rs);
492
493 rc= mysql_query(con, "SHOW VARIABLES LIKE 'character_set_results'");
494 check_mysql_rc(rc, con);
495 rs= mysql_store_result(con);
496 FAIL_IF(!rs, "Invalid result set");
497 row= mysql_fetch_row(rs);
498 FAIL_IF(!row, "Couldn't fetch row");
499 strcpy(character_set_results, row[1]);
500 mysql_free_result(rs);
501
502 rc= mysql_query(con, "SHOW VARIABLES LIKE 'collation_connection'");
503 check_mysql_rc(rc, con);
504 rs= mysql_store_result(con);
505 FAIL_IF(!rs, "Invalid result set");
506 row= mysql_fetch_row(rs);
507 FAIL_IF(!row, "Couldn't fetch row");
508 strcpy(collation_connection, row[1]);
509 mysql_free_result(rs);
510 return OK;
511}
512
513#define MY_CS_NAME_SIZE 32
514
515static int test_bug30472(MYSQL *mysql)
516{
517 int rc;
518
519 char character_set_name_1[MY_CS_NAME_SIZE];
520 char character_set_client_1[MY_CS_NAME_SIZE];
521 char character_set_results_1[MY_CS_NAME_SIZE];
522 char collation_connnection_1[MY_CS_NAME_SIZE];
523
524 char character_set_name_2[MY_CS_NAME_SIZE];
525 char character_set_client_2[MY_CS_NAME_SIZE];
526 char character_set_results_2[MY_CS_NAME_SIZE];
527 char collation_connnection_2[MY_CS_NAME_SIZE];
528
529 char character_set_name_3[MY_CS_NAME_SIZE];
530 char character_set_client_3[MY_CS_NAME_SIZE];
531 char character_set_results_3[MY_CS_NAME_SIZE];
532 char collation_connnection_3[MY_CS_NAME_SIZE];
533
534 char character_set_name_4[MY_CS_NAME_SIZE];
535 char character_set_client_4[MY_CS_NAME_SIZE];
536 char character_set_results_4[MY_CS_NAME_SIZE];
537 char collation_connnection_4[MY_CS_NAME_SIZE];
538
539 if (mysql_get_server_version(mysql) < 50100 || !is_mariadb)
540 {
541 diag("Test requires MySQL Server version 5.1 or above");
542 return SKIP;
543 }
544 /* Retrieve character set information. */
545
546 mysql_set_character_set(mysql, "latin1");
547 bug30472_retrieve_charset_info(mysql,
548 character_set_name_1,
549 character_set_client_1,
550 character_set_results_1,
551 collation_connnection_1);
552
553 /* Switch client character set. */
554
555 FAIL_IF(mysql_set_character_set(mysql, "utf8"), "Setting cs to utf8 failed");
556
557 /* Retrieve character set information. */
558
559 bug30472_retrieve_charset_info(mysql,
560 character_set_name_2,
561 character_set_client_2,
562 character_set_results_2,
563 collation_connnection_2);
564
565 /*
566 Check that
567 1) character set has been switched and
568 2) new character set is different from the original one.
569 */
570
571 FAIL_UNLESS(strcmp(character_set_name_2, "utf8") == 0, "cs_name != utf8");
572 FAIL_UNLESS(strcmp(character_set_client_2, "utf8") == 0, "cs_client != utf8");
573 FAIL_UNLESS(strcmp(character_set_results_2, "utf8") == 0, "cs_result != ut8");
574 FAIL_UNLESS(strcmp(collation_connnection_2, "utf8_general_ci") == 0, "collation != utf8_general_ci");
575
576 diag("%s %s", character_set_name_1, character_set_name_2);
577 FAIL_UNLESS(strcmp(character_set_name_1, character_set_name_2) != 0, "cs_name1 = cs_name2");
578 FAIL_UNLESS(strcmp(character_set_client_1, character_set_client_2) != 0, "cs_client1 = cs_client2");
579 FAIL_UNLESS(strcmp(character_set_results_1, character_set_results_2) != 0, "cs_result1 = cs_result2");
580 FAIL_UNLESS(strcmp(collation_connnection_1, collation_connnection_2) != 0, "collation1 = collation2");
581
582 /* Call mysql_change_user() with the same username, password, database. */
583
584 rc= mysql_change_user(mysql, username, password, (schema) ? schema : "test");
585 mysql_set_character_set(mysql, "latin1");
586 check_mysql_rc(rc, mysql);
587
588 /* Retrieve character set information. */
589
590 bug30472_retrieve_charset_info(mysql,
591 character_set_name_3,
592 character_set_client_3,
593 character_set_results_3,
594 collation_connnection_3);
595
596 /* Check that character set information has been reset. */
597
598 FAIL_UNLESS(strcmp(character_set_name_1, character_set_name_3) == 0, "cs_name1 != cs_name3");
599 FAIL_UNLESS(strcmp(character_set_client_1, character_set_client_3) == 0, "cs_client1 != cs_client3");
600 FAIL_UNLESS(strcmp(character_set_results_1, character_set_results_3) == 0, "cs_result1 != cs_result3");
601 FAIL_UNLESS(strcmp(collation_connnection_1, collation_connnection_3) == 0, "collation1 != collation3");
602
603 /* Change connection-default character set in the client. */
604
605 mysql_options(mysql, MYSQL_SET_CHARSET_NAME, "utf8");
606
607 /*
608 Call mysql_change_user() in order to check that new connection will
609 have UTF8 character set on the client and on the server.
610 */
611
612 rc= mysql_change_user(mysql, username, password, (schema) ? schema : "test");
613 check_mysql_rc(rc, mysql);
614
615 /* Retrieve character set information. */
616
617 bug30472_retrieve_charset_info(mysql,
618 character_set_name_4,
619 character_set_client_4,
620 character_set_results_4,
621 collation_connnection_4);
622
623 /* Check that we have UTF8 on the server and on the client. */
624
625 FAIL_UNLESS(strcmp(character_set_name_4, "utf8") == 0, "cs_name != utf8");
626 FAIL_UNLESS(strcmp(character_set_client_4, "utf8") == 0, "cs_client != utf8");
627 FAIL_UNLESS(strcmp(character_set_results_4, "utf8") == 0, "cs_result != utf8");
628 FAIL_UNLESS(strcmp(collation_connnection_4, "utf8_general_ci") == 0, "collation_connection != utf8_general_ci");
629
630 /* That's it. Cleanup. */
631
632 return OK;
633}
634
635static int test_bug_54100(MYSQL *mysql)
636{
637 MYSQL_RES *result;
638 MYSQL_ROW row;
639 int rc;
640
641 rc= mysql_query(mysql, "SHOW CHARACTER SET");
642 check_mysql_rc(rc, mysql);
643
644 result= mysql_store_result(mysql);
645
646 while ((row= mysql_fetch_row(result)))
647 {
648 /* ignore ucs2 */
649 if (strcmp(row[0], "ucs2") && strcmp(row[0], "utf16le") && strcmp(row[0], "utf8mb4") &&
650 strcmp(row[0], "utf16") && strcmp(row[0], "utf32")) {
651 rc= mysql_set_character_set(mysql, row[0]);
652 check_mysql_rc(rc, mysql);
653 }
654 }
655 mysql_free_result(result);
656
657 return OK;
658}
659
660
661/* We need this internal function for the test */
662
663static int test_utf16_utf32_noboms(MYSQL *mysql __attribute__((unused)))
664{
665 const char *csname[]= {"utf16", "utf16le", "utf32", "utf8"};
666 MARIADB_CHARSET_INFO *csinfo[sizeof(csname)/sizeof(char*)];
667
668 const int UTF8= sizeof(csname)/sizeof(char*) - 1;
669
670 unsigned char in_string[][8]= {"\xd8\x02\xdc\x60\0", /* utf16(be) */
671 "\x02\xd8\x60\xdc\0", /* utf16le */
672 "\x00\x01\x08\x60\0\0\0", /* utf32(be) */
673 "\xF0\x90\xA1\xA0" }; /* utf8 */
674 size_t in_oct_len[]= {6, 6, 8, 5};
675
676 char buffer[8], as_hex[16];
677 int i, error;
678 size_t rc, in_len, out_len;
679
680 for (i= 0; i < (int)(sizeof(csname)/sizeof(char*)); ++i)
681 {
682 csinfo[i]= mariadb_get_charset_by_name(csname[i]);
683
684 if (csinfo[i] == NULL)
685 {
686 diag("Could not get cs info for %s", csname[i]);
687 return FAIL;
688 }
689 }
690
691 for (i= 0; i < UTF8; ++i)
692 {
693 in_len= in_oct_len[i];
694 out_len= sizeof(buffer);
695
696 diag("Converting %s->%s", csname[i], csname[UTF8]);
697 rc= mariadb_convert_string((char *)in_string[i], &in_len, csinfo[i], buffer, &out_len, csinfo[UTF8], &error);
698
699 FAIL_IF(rc == (size_t)-1, "Conversion failed");
700 FAIL_IF(rc != in_oct_len[UTF8], "Incorrect number of written bytes");
701
702 if (memcmp(buffer, in_string[UTF8], rc) != 0)
703 {
704 mysql_hex_string(as_hex, buffer, (unsigned long)rc);
705 diag("Converted string(%s) does not match the expected one", as_hex);
706 return FAIL;
707 }
708
709 in_len= in_oct_len[UTF8];
710 out_len= sizeof(buffer);
711
712 diag("Converting %s->%s", csname[UTF8], csname[i]);
713 rc= mariadb_convert_string((char *)in_string[UTF8], &in_len, csinfo[UTF8], buffer, &out_len, csinfo[i], &error);
714
715 FAIL_IF(rc == (size_t)-1, "Conversion failed");
716 diag("rc=%lu oct_len: %lu", (unsigned long)rc, (unsigned long)in_oct_len[i]);
717 FAIL_IF(rc != in_oct_len[i], "Incorrect number of written bytes");
718
719 if (memcmp(buffer, in_string[i], rc) != 0)
720 {
721 mysql_hex_string(as_hex, buffer, (unsigned long)rc);
722 diag("Converted string(%s) does not match the expected one", as_hex);
723 return FAIL;
724 }
725 }
726
727 return OK;
728}
729
730static int charset_auto(MYSQL *my __attribute__((unused)))
731{
732 const char *csname1, *csname2;
733 const char *osname;
734 MYSQL *mysql= mysql_init(NULL);
735 int rc;
736
737 osname= madb_get_os_character_set();
738
739 mysql_options(mysql, MYSQL_SET_CHARSET_NAME, "auto");
740
741 FAIL_IF(!my_test_connect(mysql, hostname, username,
742 password, schema, port, socketname, 0),
743 mysql_error(mysql));
744
745 csname1= mysql_character_set_name(mysql);
746 diag("Character set: %s os charset: %s", csname1, osname);
747
748 FAIL_IF(strcmp(osname, csname1), "character set is not os character set");
749
750 if (strcmp(osname, "utf8"))
751 {
752 rc= mysql_set_character_set(mysql, "utf8");
753 check_mysql_rc(rc, mysql);
754
755 csname2= mysql_character_set_name(mysql);
756 diag("Character set: %s", csname2);
757
758 FAIL_IF(!strcmp(csname2, csname1), "Wrong charset: expected utf8");
759
760 rc= mysql_set_character_set(mysql, "auto");
761 check_mysql_rc(rc, mysql);
762
763 csname2= mysql_character_set_name(mysql);
764 diag("Character set: %s", csname2);
765 FAIL_IF(strcmp(csname2, osname), "Wrong charset: expected os charset");
766 }
767 mysql_close(mysql);
768 return OK;
769}
770
771/* check if all server character sets are supported */
772static int test_conc223(MYSQL *mysql)
773{
774 int rc;
775 MYSQL_RES *res;
776 MYSQL_ROW row;
777 int found= 0;
778
779 rc= mysql_query(mysql, "SELECT ID, CHARACTER_SET_NAME, COLLATION_NAME FROM INFORMATION_SCHEMA.COLLATIONS");
780 check_mysql_rc(rc, mysql);
781
782 res= mysql_store_result(mysql);
783 while ((row = mysql_fetch_row(res)))
784 {
785 int id= atoi(row[0]);
786 if (!mariadb_get_charset_by_nr(id))
787 {
788 diag("%04d %s %s", id, row[1], row[2]);
789 found++;
790 }
791 }
792 mysql_free_result(res);
793 if (found)
794 {
795 diag("%d character sets/collations not found", found);
796 return FAIL;
797 }
798 return OK;
799}
800
801struct my_tests_st my_tests[] = {
802 {"test_conc223", test_conc223, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},
803 {"charset_auto", charset_auto, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},
804 {"bug_8378: mysql_real_escape with gbk", bug_8378, TEST_CONNECTION_NEW, 0, opt_bug8378, NULL},
805 {"test_client_character_set", test_client_character_set, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},
806 {"bug_10214: mysql_real_escape with NO_BACKSLASH_ESCAPES", bug_10214, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},
807 {"test_escaping", test_escaping, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},
808 {"test_conversion", test_conversion, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},
809 {"bug_41785", bug_41785, TEST_CONNECTION_DEFAULT, 0, NULL, "not fixed yet"},
810 {"test_bug27876", test_bug27876, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},
811 {"test_bug30472", test_bug30472, TEST_CONNECTION_NEW, 0, NULL, NULL},
812 {"test_ps_i18n", test_ps_i18n, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},
813 {"test_bug_54100", test_bug_54100, TEST_CONNECTION_NEW, 0, NULL, NULL},
814 {"test_utf16_utf32_noboms", test_utf16_utf32_noboms, TEST_CONNECTION_DEFAULT, 0, NULL, NULL},
815 {NULL, NULL, 0, 0, NULL, 0}
816};
817
818
819int main(int argc, char **argv)
820{
821 if (argc > 1)
822 get_options(argc, argv);
823
824 get_envvars();
825
826 run_tests(my_tests);
827
828 return(exit_status());
829}
830