PageRenderTime 55ms CodeModel.GetById 15ms RepoModel.GetById 1ms app.codeStats 1ms

/tests/mysql_client_test.c

https://bitbucket.org/Habibutsu/mysql
C | 18448 lines | 13017 code | 4133 blank | 1298 comment | 1421 complexity | 0dc94f78e50517519d9da62efc6d9ba0 MD5 | raw file
Possible License(s): GPL-2.0, BSD-3-Clause

Large files files are truncated, but you can click here to view the full file

  1. /* Copyright (c) 2002, 2012, Oracle and/or its affiliates. All rights reserved.
  2. This program is free software; you can redistribute it and/or modify
  3. it under the terms of the GNU General Public License as published by
  4. the Free Software Foundation; version 2 of the License.
  5. This program is distributed in the hope that it will be useful,
  6. but WITHOUT ANY WARRANTY; without even the implied warranty of
  7. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  8. GNU General Public License for more details.
  9. You should have received a copy of the GNU General Public License
  10. along with this program; if not, write to the Free Software
  11. Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
  12. /***************************************************************************
  13. This is a test sample to test the new features in MySQL client-server
  14. protocol
  15. Main author: venu ( venu@mysql.com )
  16. ***************************************************************************/
  17. /*
  18. XXX: PLEASE RUN THIS PROGRAM UNDER VALGRIND AND VERIFY THAT YOUR TEST
  19. DOESN'T CONTAIN WARNINGS/ERRORS BEFORE YOU PUSH.
  20. */
  21. /*
  22. The fw.c file includes all the mysql_client_test framework; this file
  23. contains only the actual tests, plus the list of test functions to call.
  24. */
  25. #include "mysql_client_fw.c"
  26. /* Query processing */
  27. static void client_query()
  28. {
  29. int rc;
  30. myheader("client_query");
  31. rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1");
  32. myquery(rc);
  33. rc= mysql_query(mysql, "CREATE TABLE t1("
  34. "id int primary key auto_increment, "
  35. "name varchar(20))");
  36. myquery(rc);
  37. rc= mysql_query(mysql, "CREATE TABLE t1(id int, name varchar(20))");
  38. myquery_r(rc);
  39. rc= mysql_query(mysql, "INSERT INTO t1(name) VALUES('mysql')");
  40. myquery(rc);
  41. rc= mysql_query(mysql, "INSERT INTO t1(name) VALUES('monty')");
  42. myquery(rc);
  43. rc= mysql_query(mysql, "INSERT INTO t1(name) VALUES('venu')");
  44. myquery(rc);
  45. rc= mysql_query(mysql, "INSERT INTO t1(name) VALUES('deleted')");
  46. myquery(rc);
  47. rc= mysql_query(mysql, "INSERT INTO t1(name) VALUES('deleted')");
  48. myquery(rc);
  49. rc= mysql_query(mysql, "UPDATE t1 SET name= 'updated' "
  50. "WHERE name= 'deleted'");
  51. myquery(rc);
  52. rc= mysql_query(mysql, "UPDATE t1 SET id= 3 WHERE name= 'updated'");
  53. myquery_r(rc);
  54. myquery(mysql_query(mysql, "drop table t1"));
  55. }
  56. /* Store result processing */
  57. static void client_store_result()
  58. {
  59. MYSQL_RES *result;
  60. int rc;
  61. myheader("client_store_result");
  62. rc= mysql_query(mysql, "SELECT * FROM t1");
  63. myquery(rc);
  64. /* get the result */
  65. result= mysql_store_result(mysql);
  66. mytest(result);
  67. (void) my_process_result_set(result);
  68. mysql_free_result(result);
  69. }
  70. /* Fetch the results */
  71. static void client_use_result()
  72. {
  73. MYSQL_RES *result;
  74. int rc;
  75. myheader("client_use_result");
  76. rc= mysql_query(mysql, "SELECT * FROM t1");
  77. myquery(rc);
  78. /* get the result */
  79. result= mysql_use_result(mysql);
  80. mytest(result);
  81. (void) my_process_result_set(result);
  82. mysql_free_result(result);
  83. }
  84. /* Query processing */
  85. static void test_debug_example()
  86. {
  87. int rc;
  88. MYSQL_RES *result;
  89. myheader("test_debug_example");
  90. rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_debug_example");
  91. myquery(rc);
  92. rc= mysql_query(mysql, "CREATE TABLE test_debug_example("
  93. "id INT PRIMARY KEY AUTO_INCREMENT, "
  94. "name VARCHAR(20), xxx INT)");
  95. myquery(rc);
  96. rc= mysql_query(mysql, "INSERT INTO test_debug_example (name) "
  97. "VALUES ('mysql')");
  98. myquery(rc);
  99. rc= mysql_query(mysql, "UPDATE test_debug_example SET name='updated' "
  100. "WHERE name='deleted'");
  101. myquery(rc);
  102. rc= mysql_query(mysql, "SELECT * FROM test_debug_example where name='mysql'");
  103. myquery(rc);
  104. result= mysql_use_result(mysql);
  105. mytest(result);
  106. (void) my_process_result_set(result);
  107. mysql_free_result(result);
  108. rc= mysql_query(mysql, "DROP TABLE test_debug_example");
  109. myquery(rc);
  110. }
  111. /* Test autocommit feature for BDB tables */
  112. static void test_tran_bdb()
  113. {
  114. MYSQL_RES *result;
  115. MYSQL_ROW row;
  116. int rc;
  117. myheader("test_tran_bdb");
  118. /* set AUTOCOMMIT to OFF */
  119. rc= mysql_autocommit(mysql, FALSE);
  120. myquery(rc);
  121. rc= mysql_query(mysql, "DROP TABLE IF EXISTS my_demo_transaction");
  122. myquery(rc);
  123. /* create the table 'mytran_demo' of type BDB' or 'InnoDB' */
  124. rc= mysql_query(mysql, "CREATE TABLE my_demo_transaction( "
  125. "col1 int , col2 varchar(30)) ENGINE= BDB");
  126. myquery(rc);
  127. /* insert a row and commit the transaction */
  128. rc= mysql_query(mysql, "INSERT INTO my_demo_transaction VALUES(10, 'venu')");
  129. myquery(rc);
  130. rc= mysql_commit(mysql);
  131. myquery(rc);
  132. /* now insert the second row, and roll back the transaction */
  133. rc= mysql_query(mysql, "INSERT INTO my_demo_transaction VALUES(20, 'mysql')");
  134. myquery(rc);
  135. rc= mysql_rollback(mysql);
  136. myquery(rc);
  137. /* delete first row, and roll it back */
  138. rc= mysql_query(mysql, "DELETE FROM my_demo_transaction WHERE col1= 10");
  139. myquery(rc);
  140. rc= mysql_rollback(mysql);
  141. myquery(rc);
  142. /* test the results now, only one row should exist */
  143. rc= mysql_query(mysql, "SELECT * FROM my_demo_transaction");
  144. myquery(rc);
  145. /* get the result */
  146. result= mysql_store_result(mysql);
  147. mytest(result);
  148. (void) my_process_result_set(result);
  149. mysql_free_result(result);
  150. /* test the results now, only one row should exist */
  151. rc= mysql_query(mysql, "SELECT * FROM my_demo_transaction");
  152. myquery(rc);
  153. /* get the result */
  154. result= mysql_use_result(mysql);
  155. mytest(result);
  156. row= mysql_fetch_row(result);
  157. mytest(row);
  158. row= mysql_fetch_row(result);
  159. mytest_r(row);
  160. mysql_free_result(result);
  161. mysql_autocommit(mysql, TRUE);
  162. }
  163. /* Test autocommit feature for InnoDB tables */
  164. static void test_tran_innodb()
  165. {
  166. MYSQL_RES *result;
  167. MYSQL_ROW row;
  168. int rc;
  169. myheader("test_tran_innodb");
  170. /* set AUTOCOMMIT to OFF */
  171. rc= mysql_autocommit(mysql, FALSE);
  172. myquery(rc);
  173. rc= mysql_query(mysql, "DROP TABLE IF EXISTS my_demo_transaction");
  174. myquery(rc);
  175. /* create the table 'mytran_demo' of type BDB' or 'InnoDB' */
  176. rc= mysql_query(mysql, "CREATE TABLE my_demo_transaction(col1 int, "
  177. "col2 varchar(30)) ENGINE= InnoDB");
  178. myquery(rc);
  179. /* insert a row and commit the transaction */
  180. rc= mysql_query(mysql, "INSERT INTO my_demo_transaction VALUES(10, 'venu')");
  181. myquery(rc);
  182. rc= mysql_commit(mysql);
  183. myquery(rc);
  184. /* now insert the second row, and roll back the transaction */
  185. rc= mysql_query(mysql, "INSERT INTO my_demo_transaction VALUES(20, 'mysql')");
  186. myquery(rc);
  187. rc= mysql_rollback(mysql);
  188. myquery(rc);
  189. /* delete first row, and roll it back */
  190. rc= mysql_query(mysql, "DELETE FROM my_demo_transaction WHERE col1= 10");
  191. myquery(rc);
  192. rc= mysql_rollback(mysql);
  193. myquery(rc);
  194. /* test the results now, only one row should exist */
  195. rc= mysql_query(mysql, "SELECT * FROM my_demo_transaction");
  196. myquery(rc);
  197. /* get the result */
  198. result= mysql_store_result(mysql);
  199. mytest(result);
  200. (void) my_process_result_set(result);
  201. mysql_free_result(result);
  202. /* test the results now, only one row should exist */
  203. rc= mysql_query(mysql, "SELECT * FROM my_demo_transaction");
  204. myquery(rc);
  205. /* get the result */
  206. result= mysql_use_result(mysql);
  207. mytest(result);
  208. row= mysql_fetch_row(result);
  209. mytest(row);
  210. row= mysql_fetch_row(result);
  211. mytest_r(row);
  212. mysql_free_result(result);
  213. mysql_autocommit(mysql, TRUE);
  214. }
  215. /* Test for BUG#7242 */
  216. static void test_prepare_insert_update()
  217. {
  218. MYSQL_STMT *stmt;
  219. int rc;
  220. int i;
  221. const char *testcase[]= {
  222. "CREATE TABLE t1 (a INT, b INT, c INT, UNIQUE (A), UNIQUE(B))",
  223. "INSERT t1 VALUES (1,2,10), (3,4,20)",
  224. "INSERT t1 VALUES (5,6,30), (7,4,40), (8,9,60) ON DUPLICATE KEY UPDATE c=c+100",
  225. "SELECT * FROM t1",
  226. "INSERT t1 SET a=5 ON DUPLICATE KEY UPDATE b=0",
  227. "SELECT * FROM t1",
  228. "INSERT t1 VALUES (2,1,11), (7,4,40) ON DUPLICATE KEY UPDATE c=c+VALUES(a)",
  229. NULL};
  230. const char **cur_query;
  231. myheader("test_prepare_insert_update");
  232. for (cur_query= testcase; *cur_query; cur_query++)
  233. {
  234. char query[MAX_TEST_QUERY_LENGTH];
  235. printf("\nRunning query: %s", *cur_query);
  236. strmov(query, *cur_query);
  237. stmt= mysql_simple_prepare(mysql, query);
  238. check_stmt(stmt);
  239. verify_param_count(stmt, 0);
  240. rc= mysql_stmt_execute(stmt);
  241. check_execute(stmt, rc);
  242. /* try the last query several times */
  243. if (!cur_query[1])
  244. {
  245. for (i=0; i < 3;i++)
  246. {
  247. printf("\nExecuting last statement again");
  248. rc= mysql_stmt_execute(stmt);
  249. check_execute(stmt, rc);
  250. rc= mysql_stmt_execute(stmt);
  251. check_execute(stmt, rc);
  252. }
  253. }
  254. mysql_stmt_close(stmt);
  255. }
  256. rc= mysql_commit(mysql);
  257. myquery(rc);
  258. }
  259. /* Test simple prepares of all DML statements */
  260. static void test_prepare_simple()
  261. {
  262. MYSQL_STMT *stmt;
  263. int rc;
  264. char query[MAX_TEST_QUERY_LENGTH];
  265. myheader("test_prepare_simple");
  266. rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_prepare_simple");
  267. myquery(rc);
  268. rc= mysql_query(mysql, "CREATE TABLE test_prepare_simple("
  269. "id int, name varchar(50))");
  270. myquery(rc);
  271. /* insert */
  272. strmov(query, "INSERT INTO test_prepare_simple VALUES(?, ?)");
  273. stmt= mysql_simple_prepare(mysql, query);
  274. check_stmt(stmt);
  275. verify_param_count(stmt, 2);
  276. mysql_stmt_close(stmt);
  277. /* update */
  278. strmov(query, "UPDATE test_prepare_simple SET id=? "
  279. "WHERE id=? AND CONVERT(name USING utf8)= ?");
  280. stmt= mysql_simple_prepare(mysql, query);
  281. check_stmt(stmt);
  282. verify_param_count(stmt, 3);
  283. mysql_stmt_close(stmt);
  284. /* delete */
  285. strmov(query, "DELETE FROM test_prepare_simple WHERE id=10");
  286. stmt= mysql_simple_prepare(mysql, query);
  287. check_stmt(stmt);
  288. verify_param_count(stmt, 0);
  289. rc= mysql_stmt_execute(stmt);
  290. check_execute(stmt, rc);
  291. mysql_stmt_close(stmt);
  292. /* delete */
  293. strmov(query, "DELETE FROM test_prepare_simple WHERE id=?");
  294. stmt= mysql_simple_prepare(mysql, query);
  295. check_stmt(stmt);
  296. verify_param_count(stmt, 1);
  297. mysql_stmt_close(stmt);
  298. /* select */
  299. strmov(query, "SELECT * FROM test_prepare_simple WHERE id=? "
  300. "AND CONVERT(name USING utf8)= ?");
  301. stmt= mysql_simple_prepare(mysql, query);
  302. check_stmt(stmt);
  303. verify_param_count(stmt, 2);
  304. mysql_stmt_close(stmt);
  305. /* now fetch the results ..*/
  306. rc= mysql_commit(mysql);
  307. myquery(rc);
  308. }
  309. /************************************************************************/
  310. #define FILE_PATH_SIZE 4096
  311. char mct_log_file_path[FILE_PATH_SIZE];
  312. FILE *mct_log_file= NULL;
  313. void mct_start_logging(const char *test_case_name)
  314. {
  315. const char *tmp_dir= getenv("MYSQL_TMP_DIR");
  316. if (!tmp_dir)
  317. {
  318. printf("Warning: MYSQL_TMP_DIR is not set. Logging is disabled.\n");
  319. return;
  320. }
  321. if (mct_log_file)
  322. {
  323. printf("Warning: can not start logging for test case '%s' "
  324. "because log is already open\n",
  325. (const char *) test_case_name);
  326. return;
  327. }
  328. /*
  329. Path is: <tmp_dir>/<test_case_name>.out.log
  330. 10 is length of '/' + '.out.log' + \0
  331. */
  332. if (strlen(tmp_dir) + strlen(test_case_name) + 10 > FILE_PATH_SIZE)
  333. {
  334. printf("Warning: MYSQL_TMP_DIR is too long. Logging is disabled.\n");
  335. return;
  336. }
  337. my_snprintf(mct_log_file_path, FILE_PATH_SIZE,
  338. "%s/%s.out.log",
  339. (const char *) tmp_dir,
  340. (const char *) test_case_name);
  341. mct_log_file= my_fopen(mct_log_file_path, O_WRONLY | O_BINARY, MYF(MY_WME));
  342. if (!mct_log_file)
  343. {
  344. printf("Warning: can not open log file (%s): %s. Logging is disabled.\n",
  345. (const char *) mct_log_file_path,
  346. (const char *) strerror(errno));
  347. return;
  348. }
  349. }
  350. void mct_log(const char *format, ...)
  351. {
  352. va_list args;
  353. va_start(args, format);
  354. vprintf(format, args);
  355. va_end(args);
  356. if (mct_log_file)
  357. {
  358. va_list args;
  359. va_start(args, format);
  360. vfprintf(mct_log_file, format, args);
  361. va_end(args);
  362. }
  363. }
  364. void mct_close_log()
  365. {
  366. if (!mct_log_file)
  367. return;
  368. my_fclose(mct_log_file, MYF(0));
  369. mct_log_file= NULL;
  370. }
  371. #define WL4435_NUM_PARAMS 10
  372. #define WL4435_STRING_SIZE 30
  373. static void test_wl4435()
  374. {
  375. MYSQL_STMT *stmt;
  376. int rc;
  377. char query[MAX_TEST_QUERY_LENGTH];
  378. char str_data[20][WL4435_STRING_SIZE];
  379. double dbl_data[20];
  380. char dec_data[20][WL4435_STRING_SIZE];
  381. int int_data[20];
  382. ulong str_length= WL4435_STRING_SIZE;
  383. my_bool is_null;
  384. MYSQL_BIND ps_params[WL4435_NUM_PARAMS];
  385. int exec_counter;
  386. myheader("test_wl4435");
  387. mct_start_logging("test_wl4435");
  388. rc= mysql_query(mysql, "DROP PROCEDURE IF EXISTS p1");
  389. myquery(rc);
  390. rc= mysql_query(mysql, "DROP PROCEDURE IF EXISTS p2");
  391. myquery(rc);
  392. rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1");
  393. myquery(rc);
  394. rc= mysql_query(mysql, "DROP TABLE IF EXISTS t2");
  395. myquery(rc);
  396. rc= mysql_query(mysql, "CREATE TABLE t1(a1 INT, a2 CHAR(32), "
  397. " a3 DOUBLE(4, 2), a4 DECIMAL(3, 1))");
  398. myquery(rc);
  399. rc= mysql_query(mysql, "CREATE TABLE t2(b0 INT, b1 INT, b2 CHAR(32), "
  400. " b3 DOUBLE(4, 2), b4 DECIMAL(3, 1))");
  401. myquery(rc);
  402. rc= mysql_query(mysql, "INSERT INTO t1 VALUES"
  403. "(1, '11', 12.34, 56.7), "
  404. "(2, '12', 56.78, 90.1), "
  405. "(3, '13', 23.45, 67.8)");
  406. myquery(rc);
  407. rc= mysql_query(mysql, "INSERT INTO t2 VALUES"
  408. "(100, 10, '110', 70.70, 10.1), "
  409. "(200, 20, '120', 80.80, 20.2), "
  410. "(300, 30, '130', 90.90, 30.3)");
  411. myquery(rc);
  412. rc= mysql_query(mysql,
  413. "CREATE PROCEDURE p1("
  414. " IN v0 INT, "
  415. " OUT v_str_1 CHAR(32), "
  416. " OUT v_dbl_1 DOUBLE(4, 2), "
  417. " OUT v_dec_1 DECIMAL(6, 3), "
  418. " OUT v_int_1 INT, "
  419. " IN v1 INT, "
  420. " INOUT v_str_2 CHAR(64), "
  421. " INOUT v_dbl_2 DOUBLE(5, 3), "
  422. " INOUT v_dec_2 DECIMAL(7, 4), "
  423. " INOUT v_int_2 INT)"
  424. "BEGIN "
  425. " SET v0 = -1; "
  426. " SET v1 = -1; "
  427. " SET v_str_1 = 'test_1'; "
  428. " SET v_dbl_1 = 12.34; "
  429. " SET v_dec_1 = 567.891; "
  430. " SET v_int_1 = 2345; "
  431. " SET v_str_2 = 'test_2'; "
  432. " SET v_dbl_2 = 67.891; "
  433. " SET v_dec_2 = 234.6789; "
  434. " SET v_int_2 = 6789; "
  435. " SELECT * FROM t1; "
  436. " SELECT * FROM t2; "
  437. "END");
  438. myquery(rc);
  439. rc= mysql_query(mysql,
  440. "CREATE PROCEDURE p2("
  441. " IN i1 VARCHAR(255) CHARACTER SET koi8r, "
  442. " OUT o1 VARCHAR(255) CHARACTER SET cp1251, "
  443. " OUT o2 VARBINARY(255)) "
  444. "BEGIN "
  445. " SET o1 = i1; "
  446. " SET o2 = i1; "
  447. "END");
  448. myquery(rc);
  449. strmov(query, "CALL p1(?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
  450. stmt= mysql_simple_prepare(mysql, query);
  451. check_stmt(stmt);
  452. /* Init PS-parameters. */
  453. bzero((char *) ps_params, sizeof (ps_params));
  454. /* - v0 -- INT */
  455. ps_params[0].buffer_type= MYSQL_TYPE_LONG;
  456. ps_params[0].buffer= (char *) &int_data[0];
  457. ps_params[0].length= 0;
  458. ps_params[0].is_null= 0;
  459. /* - v_str_1 -- CHAR(32) */
  460. ps_params[1].buffer_type= MYSQL_TYPE_STRING;
  461. ps_params[1].buffer= (char *) str_data[0];
  462. ps_params[1].buffer_length= WL4435_STRING_SIZE;
  463. ps_params[1].length= &str_length;
  464. ps_params[1].is_null= 0;
  465. /* - v_dbl_1 -- DOUBLE */
  466. ps_params[2].buffer_type= MYSQL_TYPE_DOUBLE;
  467. ps_params[2].buffer= (char *) &dbl_data[0];
  468. ps_params[2].length= 0;
  469. ps_params[2].is_null= 0;
  470. /* - v_dec_1 -- DECIMAL */
  471. ps_params[3].buffer_type= MYSQL_TYPE_NEWDECIMAL;
  472. ps_params[3].buffer= (char *) dec_data[0];
  473. ps_params[3].buffer_length= WL4435_STRING_SIZE;
  474. ps_params[3].length= 0;
  475. ps_params[3].is_null= 0;
  476. /* - v_int_1 -- INT */
  477. ps_params[4].buffer_type= MYSQL_TYPE_LONG;
  478. ps_params[4].buffer= (char *) &int_data[0];
  479. ps_params[4].length= 0;
  480. ps_params[4].is_null= 0;
  481. /* - v1 -- INT */
  482. ps_params[5].buffer_type= MYSQL_TYPE_LONG;
  483. ps_params[5].buffer= (char *) &int_data[0];
  484. ps_params[5].length= 0;
  485. ps_params[5].is_null= 0;
  486. /* - v_str_2 -- CHAR(32) */
  487. ps_params[6].buffer_type= MYSQL_TYPE_STRING;
  488. ps_params[6].buffer= (char *) str_data[0];
  489. ps_params[6].buffer_length= WL4435_STRING_SIZE;
  490. ps_params[6].length= &str_length;
  491. ps_params[6].is_null= 0;
  492. /* - v_dbl_2 -- DOUBLE */
  493. ps_params[7].buffer_type= MYSQL_TYPE_DOUBLE;
  494. ps_params[7].buffer= (char *) &dbl_data[0];
  495. ps_params[7].length= 0;
  496. ps_params[7].is_null= 0;
  497. /* - v_dec_2 -- DECIMAL */
  498. ps_params[8].buffer_type= MYSQL_TYPE_DECIMAL;
  499. ps_params[8].buffer= (char *) dec_data[0];
  500. ps_params[8].buffer_length= WL4435_STRING_SIZE;
  501. ps_params[8].length= 0;
  502. ps_params[8].is_null= 0;
  503. /* - v_int_2 -- INT */
  504. ps_params[9].buffer_type= MYSQL_TYPE_LONG;
  505. ps_params[9].buffer= (char *) &int_data[0];
  506. ps_params[9].length= 0;
  507. ps_params[9].is_null= 0;
  508. /* Bind parameters. */
  509. rc= mysql_stmt_bind_param(stmt, ps_params);
  510. /* Execute! */
  511. for (exec_counter= 0; exec_counter < 3; ++exec_counter)
  512. {
  513. int i;
  514. int num_fields;
  515. MYSQL_BIND *rs_bind;
  516. mct_log("\nexec_counter: %d\n", (int) exec_counter);
  517. rc= mysql_stmt_execute(stmt);
  518. check_execute(stmt, rc);
  519. while (1)
  520. {
  521. MYSQL_FIELD *fields;
  522. MYSQL_RES *rs_metadata= mysql_stmt_result_metadata(stmt);
  523. num_fields= mysql_stmt_field_count(stmt);
  524. fields= mysql_fetch_fields(rs_metadata);
  525. rs_bind= (MYSQL_BIND *) malloc(sizeof (MYSQL_BIND) * num_fields);
  526. bzero(rs_bind, sizeof (MYSQL_BIND) * num_fields);
  527. mct_log("num_fields: %d\n", (int) num_fields);
  528. for (i = 0; i < num_fields; ++i)
  529. {
  530. mct_log(" - %d: name: '%s'/'%s'; table: '%s'/'%s'; "
  531. "db: '%s'; catalog: '%s'; length: %d; max_length: %d; "
  532. "type: %d; decimals: %d\n",
  533. (int) i,
  534. (const char *) fields[i].name,
  535. (const char *) fields[i].org_name,
  536. (const char *) fields[i].table,
  537. (const char *) fields[i].org_table,
  538. (const char *) fields[i].db,
  539. (const char *) fields[i].catalog,
  540. (int) fields[i].length,
  541. (int) fields[i].max_length,
  542. (int) fields[i].type,
  543. (int) fields[i].decimals);
  544. rs_bind[i].buffer_type= fields[i].type;
  545. rs_bind[i].is_null= &is_null;
  546. switch (fields[i].type)
  547. {
  548. case MYSQL_TYPE_LONG:
  549. rs_bind[i].buffer= (char *) &(int_data[i]);
  550. rs_bind[i].buffer_length= sizeof (int_data);
  551. break;
  552. case MYSQL_TYPE_STRING:
  553. rs_bind[i].buffer= (char *) str_data[i];
  554. rs_bind[i].buffer_length= WL4435_STRING_SIZE;
  555. rs_bind[i].length= &str_length;
  556. break;
  557. case MYSQL_TYPE_DOUBLE:
  558. rs_bind[i].buffer= (char *) &dbl_data[i];
  559. rs_bind[i].buffer_length= sizeof (dbl_data);
  560. break;
  561. case MYSQL_TYPE_NEWDECIMAL:
  562. rs_bind[i].buffer= (char *) dec_data[i];
  563. rs_bind[i].buffer_length= WL4435_STRING_SIZE;
  564. rs_bind[i].length= &str_length;
  565. break;
  566. default:
  567. fprintf(stderr, "ERROR: unexpected type: %d.\n", fields[i].type);
  568. exit(1);
  569. }
  570. }
  571. rc= mysql_stmt_bind_result(stmt, rs_bind);
  572. check_execute(stmt, rc);
  573. mct_log("Data:\n");
  574. while (1)
  575. {
  576. int rc= mysql_stmt_fetch(stmt);
  577. if (rc == 1 || rc == MYSQL_NO_DATA)
  578. break;
  579. mct_log(" ");
  580. for (i = 0; i < num_fields; ++i)
  581. {
  582. switch (rs_bind[i].buffer_type)
  583. {
  584. case MYSQL_TYPE_LONG:
  585. mct_log(" int: %ld;",
  586. (long) *((int *) rs_bind[i].buffer));
  587. break;
  588. case MYSQL_TYPE_STRING:
  589. mct_log(" str: '%s';",
  590. (char *) rs_bind[i].buffer);
  591. break;
  592. case MYSQL_TYPE_DOUBLE:
  593. mct_log(" dbl: %lf;",
  594. (double) *((double *) rs_bind[i].buffer));
  595. break;
  596. case MYSQL_TYPE_NEWDECIMAL:
  597. mct_log(" dec: '%s';",
  598. (char *) rs_bind[i].buffer);
  599. break;
  600. default:
  601. printf(" unexpected type (%d)\n",
  602. rs_bind[i].buffer_type);
  603. }
  604. }
  605. mct_log("\n");
  606. }
  607. mct_log("EOF\n");
  608. rc= mysql_stmt_next_result(stmt);
  609. mct_log("mysql_stmt_next_result(): %d; field_count: %d\n",
  610. (int) rc, (int) mysql->field_count);
  611. free(rs_bind);
  612. mysql_free_result(rs_metadata);
  613. if (rc > 0)
  614. {
  615. printf("Error: %s (errno: %d)\n",
  616. mysql_stmt_error(stmt), mysql_stmt_errno(stmt));
  617. DIE(rc > 0);
  618. }
  619. if (rc)
  620. break;
  621. if (!mysql->field_count)
  622. {
  623. /* This is the last OK-packet. No more resultsets. */
  624. break;
  625. }
  626. }
  627. }
  628. mysql_stmt_close(stmt);
  629. mct_close_log();
  630. rc= mysql_commit(mysql);
  631. myquery(rc);
  632. /* i18n part of test case. */
  633. {
  634. const char *str_koi8r= "\xee\xd5\x2c\x20\xda\xc1\x20\xd2\xd9\xc2\xc1\xcc\xcb\xd5";
  635. const char *str_cp1251= "\xcd\xf3\x2c\x20\xe7\xe0\x20\xf0\xfb\xe1\xe0\xeb\xea\xf3";
  636. char o1_buffer[255];
  637. ulong o1_length;
  638. char o2_buffer[255];
  639. ulong o2_length;
  640. MYSQL_BIND rs_bind[2];
  641. strmov(query, "CALL p2(?, ?, ?)");
  642. stmt= mysql_simple_prepare(mysql, query);
  643. check_stmt(stmt);
  644. /* Init PS-parameters. */
  645. bzero((char *) ps_params, sizeof (ps_params));
  646. ps_params[0].buffer_type= MYSQL_TYPE_STRING;
  647. ps_params[0].buffer= (char *) str_koi8r;
  648. ps_params[0].buffer_length= strlen(str_koi8r);
  649. ps_params[1].buffer_type= MYSQL_TYPE_STRING;
  650. ps_params[1].buffer= o1_buffer;
  651. ps_params[1].buffer_length= 0;
  652. ps_params[2].buffer_type= MYSQL_TYPE_STRING;
  653. ps_params[2].buffer= o2_buffer;
  654. ps_params[2].buffer_length= 0;
  655. /* Bind parameters. */
  656. rc= mysql_stmt_bind_param(stmt, ps_params);
  657. check_execute(stmt, rc);
  658. /* Prevent converting to character_set_results. */
  659. rc= mysql_query(mysql, "SET NAMES binary");
  660. myquery(rc);
  661. /* Execute statement. */
  662. rc= mysql_stmt_execute(stmt);
  663. check_execute(stmt, rc);
  664. /* Bind result. */
  665. bzero(rs_bind, sizeof (rs_bind));
  666. rs_bind[0].buffer_type= MYSQL_TYPE_STRING;
  667. rs_bind[0].buffer= o1_buffer;
  668. rs_bind[0].buffer_length= sizeof (o1_buffer);
  669. rs_bind[0].length= &o1_length;
  670. rs_bind[1].buffer_type= MYSQL_TYPE_BLOB;
  671. rs_bind[1].buffer= o2_buffer;
  672. rs_bind[1].buffer_length= sizeof (o2_buffer);
  673. rs_bind[1].length= &o2_length;
  674. rc= mysql_stmt_bind_result(stmt, rs_bind);
  675. check_execute(stmt, rc);
  676. /* Fetch result. */
  677. rc= mysql_stmt_fetch(stmt);
  678. check_execute(stmt, rc);
  679. /* Check result. */
  680. DIE_UNLESS(o1_length == strlen(str_cp1251));
  681. DIE_UNLESS(o2_length == strlen(str_koi8r));
  682. DIE_UNLESS(!memcmp(o1_buffer, str_cp1251, o1_length));
  683. DIE_UNLESS(!memcmp(o2_buffer, str_koi8r, o2_length));
  684. rc= mysql_stmt_fetch(stmt);
  685. DIE_UNLESS(rc == MYSQL_NO_DATA);
  686. rc= mysql_stmt_next_result(stmt);
  687. DIE_UNLESS(rc == 0 && mysql->field_count == 0);
  688. mysql_stmt_close(stmt);
  689. rc= mysql_commit(mysql);
  690. myquery(rc);
  691. }
  692. }
  693. static void test_wl4435_2()
  694. {
  695. MYSQL_STMT *stmt;
  696. int i;
  697. int rc;
  698. char query[MAX_TEST_QUERY_LENGTH];
  699. myheader("test_wl4435_2");
  700. mct_start_logging("test_wl4435_2");
  701. /*
  702. Do a few iterations so that we catch any problem with incorrect
  703. handling/flushing prepared statement results.
  704. */
  705. for (i= 0; i < 10; ++i)
  706. {
  707. /*
  708. Prepare a procedure. That can be moved out of the loop, but it was
  709. left in the loop for the sake of having as many statements as
  710. possible.
  711. */
  712. rc= mysql_query(mysql, "DROP PROCEDURE IF EXISTS p1");
  713. myquery(rc);
  714. rc= mysql_query(mysql,
  715. "CREATE PROCEDURE p1()"
  716. "BEGIN "
  717. " SELECT 1; "
  718. " SELECT 2, 3 UNION SELECT 4, 5; "
  719. " SELECT 6, 7, 8; "
  720. "END");
  721. myquery(rc);
  722. /* Invoke a procedure, that returns several result sets. */
  723. strmov(query, "CALL p1()");
  724. stmt= mysql_simple_prepare(mysql, query);
  725. check_stmt(stmt);
  726. /* Execute! */
  727. rc= mysql_stmt_execute(stmt);
  728. check_execute(stmt, rc);
  729. /* Flush all the results. */
  730. mysql_stmt_close(stmt);
  731. /* Clean up. */
  732. rc= mysql_commit(mysql);
  733. myquery(rc);
  734. rc= mysql_query(mysql, "DROP PROCEDURE p1");
  735. myquery(rc);
  736. }
  737. }
  738. #define WL4435_TEST(sql_type, sql_value, \
  739. c_api_in_type, c_api_out_type, \
  740. c_type, c_type_ext, \
  741. printf_args, assert_condition) \
  742. \
  743. do { \
  744. int rc; \
  745. MYSQL_STMT *ps; \
  746. MYSQL_BIND psp; \
  747. MYSQL_RES *rs_metadata; \
  748. MYSQL_FIELD *fields; \
  749. c_type pspv c_type_ext; \
  750. my_bool psp_null; \
  751. \
  752. bzero(&pspv, sizeof (pspv)); \
  753. \
  754. rc= mysql_query(mysql, "DROP PROCEDURE IF EXISTS p1"); \
  755. myquery(rc); \
  756. \
  757. rc= mysql_query(mysql, \
  758. "CREATE PROCEDURE p1(OUT v " sql_type ") SET v = " sql_value ";"); \
  759. myquery(rc); \
  760. \
  761. ps = mysql_simple_prepare(mysql, "CALL p1(?)"); \
  762. check_stmt(ps); \
  763. \
  764. bzero(&psp, sizeof (psp)); \
  765. psp.buffer_type= c_api_in_type; \
  766. psp.is_null= &psp_null; \
  767. psp.buffer= (char *) &pspv; \
  768. psp.buffer_length= sizeof (psp); \
  769. \
  770. rc= mysql_stmt_bind_param(ps, &psp); \
  771. check_execute(ps, rc); \
  772. \
  773. rc= mysql_stmt_execute(ps); \
  774. check_execute(ps, rc); \
  775. \
  776. DIE_UNLESS(mysql->server_status & SERVER_PS_OUT_PARAMS); \
  777. DIE_UNLESS(mysql_stmt_field_count(ps) == 1); \
  778. \
  779. rs_metadata= mysql_stmt_result_metadata(ps); \
  780. fields= mysql_fetch_fields(rs_metadata); \
  781. \
  782. rc= mysql_stmt_bind_result(ps, &psp); \
  783. check_execute(ps, rc); \
  784. \
  785. rc= mysql_stmt_fetch(ps); \
  786. DIE_UNLESS(rc == 0); \
  787. \
  788. DIE_UNLESS(fields[0].type == c_api_out_type); \
  789. printf printf_args; \
  790. printf("; in type: %d; out type: %d\n", \
  791. (int) c_api_in_type, (int) c_api_out_type); \
  792. \
  793. rc= mysql_stmt_fetch(ps); \
  794. DIE_UNLESS(rc == MYSQL_NO_DATA); \
  795. \
  796. rc= mysql_stmt_next_result(ps); \
  797. DIE_UNLESS(rc == 0); \
  798. \
  799. mysql_stmt_free_result(ps); \
  800. mysql_stmt_close(ps); \
  801. \
  802. DIE_UNLESS(assert_condition); \
  803. \
  804. } while (0)
  805. static void test_wl4435_3()
  806. {
  807. char tmp[255];
  808. puts("");
  809. // The following types are not supported:
  810. // - ENUM
  811. // - SET
  812. //
  813. // The following types are supported but can not be used for
  814. // OUT-parameters:
  815. // - MEDIUMINT;
  816. // - BIT(..);
  817. //
  818. // The problem is that those types are not supported for IN-parameters,
  819. // and OUT-parameters should be bound as IN-parameters before execution.
  820. //
  821. // The following types should not be used:
  822. // - MYSQL_TYPE_YEAR (use MYSQL_TYPE_SHORT instead);
  823. // - MYSQL_TYPE_TINY_BLOB, MYSQL_TYPE_MEDIUM_BLOB, MYSQL_TYPE_LONG_BLOB
  824. // (use MYSQL_TYPE_BLOB instead);
  825. WL4435_TEST("TINYINT", "127",
  826. MYSQL_TYPE_TINY, MYSQL_TYPE_TINY,
  827. char, ,
  828. (" - TINYINT / char / MYSQL_TYPE_TINY:\t\t\t %d", (int) pspv),
  829. pspv == 127);
  830. WL4435_TEST("SMALLINT", "32767",
  831. MYSQL_TYPE_SHORT, MYSQL_TYPE_SHORT,
  832. short, ,
  833. (" - SMALLINT / short / MYSQL_TYPE_SHORT:\t\t %d", (int) pspv),
  834. pspv == 32767);
  835. WL4435_TEST("INT", "2147483647",
  836. MYSQL_TYPE_LONG, MYSQL_TYPE_LONG,
  837. int, ,
  838. (" - INT / int / MYSQL_TYPE_LONG:\t\t\t %d", pspv),
  839. pspv == 2147483647l);
  840. WL4435_TEST("BIGINT", "9223372036854775807",
  841. MYSQL_TYPE_LONGLONG, MYSQL_TYPE_LONGLONG,
  842. long long, ,
  843. (" - BIGINT / long long / MYSQL_TYPE_LONGLONG:\t\t %lld", pspv),
  844. pspv == 9223372036854775807ll);
  845. WL4435_TEST("TIMESTAMP", "'2007-11-18 15:01:02'",
  846. MYSQL_TYPE_TIMESTAMP, MYSQL_TYPE_TIMESTAMP,
  847. MYSQL_TIME, ,
  848. (" - TIMESTAMP / MYSQL_TIME / MYSQL_TYPE_TIMESTAMP:\t "
  849. "%.4d-%.2d-%.2d %.2d:%.2d:%.2d",
  850. (int) pspv.year, (int) pspv.month, (int) pspv.day,
  851. (int) pspv.hour, (int) pspv.minute, (int) pspv.second),
  852. pspv.year == 2007 && pspv.month == 11 && pspv.day == 18 &&
  853. pspv.hour == 15 && pspv.minute == 1 && pspv.second == 2);
  854. WL4435_TEST("DATETIME", "'1234-11-12 12:34:59'",
  855. MYSQL_TYPE_DATETIME, MYSQL_TYPE_DATETIME,
  856. MYSQL_TIME, ,
  857. (" - DATETIME / MYSQL_TIME / MYSQL_TYPE_DATETIME:\t "
  858. "%.4d-%.2d-%.2d %.2d:%.2d:%.2d",
  859. (int) pspv.year, (int) pspv.month, (int) pspv.day,
  860. (int) pspv.hour, (int) pspv.minute, (int) pspv.second),
  861. pspv.year == 1234 && pspv.month == 11 && pspv.day == 12 &&
  862. pspv.hour == 12 && pspv.minute == 34 && pspv.second == 59);
  863. WL4435_TEST("TIME", "'123:45:01'",
  864. MYSQL_TYPE_TIME, MYSQL_TYPE_TIME,
  865. MYSQL_TIME, ,
  866. (" - TIME / MYSQL_TIME / MYSQL_TYPE_TIME:\t\t "
  867. "%.3d:%.2d:%.2d",
  868. (int) pspv.hour, (int) pspv.minute, (int) pspv.second),
  869. pspv.hour == 123 && pspv.minute == 45 && pspv.second == 1);
  870. WL4435_TEST("DATE", "'1234-11-12'",
  871. MYSQL_TYPE_DATE, MYSQL_TYPE_DATE,
  872. MYSQL_TIME, ,
  873. (" - DATE / MYSQL_TIME / MYSQL_TYPE_DATE:\t\t "
  874. "%.4d-%.2d-%.2d",
  875. (int) pspv.year, (int) pspv.month, (int) pspv.day),
  876. pspv.year == 1234 && pspv.month == 11 && pspv.day == 12);
  877. WL4435_TEST("YEAR", "'2010'",
  878. MYSQL_TYPE_SHORT, MYSQL_TYPE_YEAR,
  879. short, ,
  880. (" - YEAR / short / MYSQL_TYPE_SHORT:\t\t\t %.4d", (int) pspv),
  881. pspv == 2010);
  882. WL4435_TEST("FLOAT(7, 4)", "123.4567",
  883. MYSQL_TYPE_FLOAT, MYSQL_TYPE_FLOAT,
  884. float, ,
  885. (" - FLOAT / float / MYSQL_TYPE_FLOAT:\t\t\t %g", (double) pspv),
  886. pspv - 123.4567 < 0.0001);
  887. WL4435_TEST("DOUBLE(8, 5)", "123.45678",
  888. MYSQL_TYPE_DOUBLE, MYSQL_TYPE_DOUBLE,
  889. double, ,
  890. (" - DOUBLE / double / MYSQL_TYPE_DOUBLE:\t\t %g", (double) pspv),
  891. pspv - 123.45678 < 0.00001);
  892. WL4435_TEST("DECIMAL(9, 6)", "123.456789",
  893. MYSQL_TYPE_NEWDECIMAL, MYSQL_TYPE_NEWDECIMAL,
  894. char, [255],
  895. (" - DECIMAL / char[] / MYSQL_TYPE_NEWDECIMAL:\t\t '%s'", (char *) pspv),
  896. !strcmp(pspv, "123.456789"));
  897. WL4435_TEST("CHAR(32)", "REPEAT('C', 16)",
  898. MYSQL_TYPE_STRING, MYSQL_TYPE_STRING,
  899. char, [255],
  900. (" - CHAR(32) / char[] / MYSQL_TYPE_STRING:\t\t '%s'", (char *) pspv),
  901. !strcmp(pspv, "CCCCCCCCCCCCCCCC"));
  902. WL4435_TEST("VARCHAR(32)", "REPEAT('V', 16)",
  903. MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_VAR_STRING,
  904. char, [255],
  905. (" - VARCHAR(32) / char[] / MYSQL_TYPE_VAR_STRING:\t '%s'", (char *) pspv),
  906. !strcmp(pspv, "VVVVVVVVVVVVVVVV"));
  907. WL4435_TEST("TINYTEXT", "REPEAT('t', 16)",
  908. MYSQL_TYPE_TINY_BLOB, MYSQL_TYPE_BLOB,
  909. char, [255],
  910. (" - TINYTEXT / char[] / MYSQL_TYPE_TINY_BLOB:\t\t '%s'", (char *) pspv),
  911. !strcmp(pspv, "tttttttttttttttt"));
  912. WL4435_TEST("TEXT", "REPEAT('t', 16)",
  913. MYSQL_TYPE_BLOB, MYSQL_TYPE_BLOB,
  914. char, [255],
  915. (" - TEXT / char[] / MYSQL_TYPE_BLOB:\t\t\t '%s'", (char *) pspv),
  916. !strcmp(pspv, "tttttttttttttttt"));
  917. WL4435_TEST("MEDIUMTEXT", "REPEAT('t', 16)",
  918. MYSQL_TYPE_MEDIUM_BLOB, MYSQL_TYPE_BLOB,
  919. char, [255],
  920. (" - MEDIUMTEXT / char[] / MYSQL_TYPE_MEDIUM_BLOB:\t '%s'", (char *) pspv),
  921. !strcmp(pspv, "tttttttttttttttt"));
  922. WL4435_TEST("LONGTEXT", "REPEAT('t', 16)",
  923. MYSQL_TYPE_LONG_BLOB, MYSQL_TYPE_BLOB,
  924. char, [255],
  925. (" - LONGTEXT / char[] / MYSQL_TYPE_LONG_BLOB:\t\t '%s'", (char *) pspv),
  926. !strcmp(pspv, "tttttttttttttttt"));
  927. WL4435_TEST("BINARY(32)", "REPEAT('\1', 16)",
  928. MYSQL_TYPE_STRING, MYSQL_TYPE_STRING,
  929. char, [255],
  930. (" - BINARY(32) / char[] / MYSQL_TYPE_STRING:\t\t '%s'", (char *) pspv),
  931. memset(tmp, 1, 16) && !memcmp(tmp, pspv, 16));
  932. WL4435_TEST("VARBINARY(32)", "REPEAT('\1', 16)",
  933. MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_VAR_STRING,
  934. char, [255],
  935. (" - VARBINARY(32) / char[] / MYSQL_TYPE_VAR_STRING:\t '%s'", (char *) pspv),
  936. memset(tmp, 1, 16) && !memcmp(tmp, pspv, 16));
  937. WL4435_TEST("TINYBLOB", "REPEAT('\2', 16)",
  938. MYSQL_TYPE_TINY_BLOB, MYSQL_TYPE_BLOB,
  939. char, [255],
  940. (" - TINYBLOB / char[] / MYSQL_TYPE_TINY_BLOB:\t\t '%s'", (char *) pspv),
  941. memset(tmp, 2, 16) && !memcmp(tmp, pspv, 16));
  942. WL4435_TEST("BLOB", "REPEAT('\2', 16)",
  943. MYSQL_TYPE_BLOB, MYSQL_TYPE_BLOB,
  944. char, [255],
  945. (" - BLOB / char[] / MYSQL_TYPE_BLOB:\t\t\t '%s'", (char *) pspv),
  946. memset(tmp, 2, 16) && !memcmp(tmp, pspv, 16));
  947. WL4435_TEST("MEDIUMBLOB", "REPEAT('\2', 16)",
  948. MYSQL_TYPE_MEDIUM_BLOB, MYSQL_TYPE_BLOB,
  949. char, [255],
  950. (" - MEDIUMBLOB / char[] / MYSQL_TYPE_MEDIUM_BLOB:\t '%s'", (char *) pspv),
  951. memset(tmp, 2, 16) && !memcmp(tmp, pspv, 16));
  952. WL4435_TEST("LONGBLOB", "REPEAT('\2', 16)",
  953. MYSQL_TYPE_LONG_BLOB, MYSQL_TYPE_BLOB,
  954. char, [255],
  955. (" - LONGBLOB / char[] / MYSQL_TYPE_LONG_BLOB:\t\t '%s'", (char *) pspv),
  956. memset(tmp, 2, 16) && !memcmp(tmp, pspv, 16));
  957. }
  958. /* Test simple prepare field results */
  959. static void test_prepare_field_result()
  960. {
  961. MYSQL_STMT *stmt;
  962. MYSQL_RES *result;
  963. int rc;
  964. char query[MAX_TEST_QUERY_LENGTH];
  965. myheader("test_prepare_field_result");
  966. rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_prepare_field_result");
  967. myquery(rc);
  968. rc= mysql_query(mysql, "CREATE TABLE test_prepare_field_result(int_c int, "
  969. "var_c varchar(50), ts_c timestamp, "
  970. "char_c char(4), date_c date, extra tinyint)");
  971. myquery(rc);
  972. /* insert */
  973. strmov(query, "SELECT int_c, var_c, date_c as date, ts_c, char_c FROM "
  974. " test_prepare_field_result as t1 WHERE int_c=?");
  975. stmt= mysql_simple_prepare(mysql, query);
  976. check_stmt(stmt);
  977. verify_param_count(stmt, 1);
  978. result= mysql_stmt_result_metadata(stmt);
  979. mytest(result);
  980. my_print_result_metadata(result);
  981. if (!opt_silent)
  982. fprintf(stdout, "\n\n field attributes:\n");
  983. verify_prepare_field(result, 0, "int_c", "int_c", MYSQL_TYPE_LONG,
  984. "t1", "test_prepare_field_result", current_db, 11, 0);
  985. verify_prepare_field(result, 1, "var_c", "var_c", MYSQL_TYPE_VAR_STRING,
  986. "t1", "test_prepare_field_result", current_db, 50, 0);
  987. verify_prepare_field(result, 2, "date", "date_c", MYSQL_TYPE_DATE,
  988. "t1", "test_prepare_field_result", current_db, 10, 0);
  989. verify_prepare_field(result, 3, "ts_c", "ts_c", MYSQL_TYPE_TIMESTAMP,
  990. "t1", "test_prepare_field_result", current_db, 19, 0);
  991. verify_prepare_field(result, 4, "char_c", "char_c",
  992. (mysql_get_server_version(mysql) <= 50000 ?
  993. MYSQL_TYPE_VAR_STRING : MYSQL_TYPE_STRING),
  994. "t1", "test_prepare_field_result", current_db, 4, 0);
  995. verify_field_count(result, 5);
  996. mysql_free_result(result);
  997. mysql_stmt_close(stmt);
  998. }
  999. /* Test simple prepare field results */
  1000. static void test_prepare_syntax()
  1001. {
  1002. MYSQL_STMT *stmt;
  1003. int rc;
  1004. char query[MAX_TEST_QUERY_LENGTH];
  1005. myheader("test_prepare_syntax");
  1006. rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_prepare_syntax");
  1007. myquery(rc);
  1008. rc= mysql_query(mysql, "CREATE TABLE test_prepare_syntax("
  1009. "id int, name varchar(50), extra int)");
  1010. myquery(rc);
  1011. strmov(query, "INSERT INTO test_prepare_syntax VALUES(?");
  1012. stmt= mysql_simple_prepare(mysql, query);
  1013. check_stmt_r(stmt);
  1014. strmov(query, "SELECT id, name FROM test_prepare_syntax WHERE id=? AND WHERE");
  1015. stmt= mysql_simple_prepare(mysql, query);
  1016. check_stmt_r(stmt);
  1017. /* now fetch the results ..*/
  1018. rc= mysql_commit(mysql);
  1019. myquery(rc);
  1020. }
  1021. /* Test a simple prepare */
  1022. static void test_prepare()
  1023. {
  1024. MYSQL_STMT *stmt;
  1025. int rc, i;
  1026. int int_data, o_int_data;
  1027. char str_data[50], data[50];
  1028. char tiny_data, o_tiny_data;
  1029. short small_data, o_small_data;
  1030. longlong big_data, o_big_data;
  1031. float real_data, o_real_data;
  1032. double double_data, o_double_data;
  1033. ulong length[7], len;
  1034. my_bool is_null[7];
  1035. char llbuf[22];
  1036. MYSQL_BIND my_bind[7];
  1037. char query[MAX_TEST_QUERY_LENGTH];
  1038. myheader("test_prepare");
  1039. rc= mysql_autocommit(mysql, TRUE);
  1040. myquery(rc);
  1041. rc= mysql_query(mysql, "DROP TABLE IF EXISTS my_prepare");
  1042. myquery(rc);
  1043. rc= mysql_query(mysql, "CREATE TABLE my_prepare(col1 tinyint, "
  1044. "col2 varchar(15), col3 int, "
  1045. "col4 smallint, col5 bigint, "
  1046. "col6 float, col7 double )");
  1047. myquery(rc);
  1048. /* insert by prepare */
  1049. strxmov(query, "INSERT INTO my_prepare VALUES(?, ?, ?, ?, ?, ?, ?)", NullS);
  1050. stmt= mysql_simple_prepare(mysql, query);
  1051. check_stmt(stmt);
  1052. verify_param_count(stmt, 7);
  1053. bzero((char*) my_bind, sizeof(my_bind));
  1054. /* tinyint */
  1055. my_bind[0].buffer_type= MYSQL_TYPE_TINY;
  1056. my_bind[0].buffer= (void *)&tiny_data;
  1057. /* string */
  1058. my_bind[1].buffer_type= MYSQL_TYPE_STRING;
  1059. my_bind[1].buffer= (void *)str_data;
  1060. my_bind[1].buffer_length= 1000; /* Max string length */
  1061. /* integer */
  1062. my_bind[2].buffer_type= MYSQL_TYPE_LONG;
  1063. my_bind[2].buffer= (void *)&int_data;
  1064. /* short */
  1065. my_bind[3].buffer_type= MYSQL_TYPE_SHORT;
  1066. my_bind[3].buffer= (void *)&small_data;
  1067. /* bigint */
  1068. my_bind[4].buffer_type= MYSQL_TYPE_LONGLONG;
  1069. my_bind[4].buffer= (void *)&big_data;
  1070. /* float */
  1071. my_bind[5].buffer_type= MYSQL_TYPE_FLOAT;
  1072. my_bind[5].buffer= (void *)&real_data;
  1073. /* double */
  1074. my_bind[6].buffer_type= MYSQL_TYPE_DOUBLE;
  1075. my_bind[6].buffer= (void *)&double_data;
  1076. for (i= 0; i < (int) array_elements(my_bind); i++)
  1077. {
  1078. my_bind[i].length= &length[i];
  1079. my_bind[i].is_null= &is_null[i];
  1080. is_null[i]= 0;
  1081. }
  1082. rc= mysql_stmt_bind_param(stmt, my_bind);
  1083. check_execute(stmt, rc);
  1084. int_data= 320;
  1085. small_data= 1867;
  1086. big_data= 1000;
  1087. real_data= 2;
  1088. double_data= 6578.001;
  1089. /* now, execute the prepared statement to insert 10 records.. */
  1090. for (tiny_data= 0; tiny_data < 100; tiny_data++)
  1091. {
  1092. length[1]= sprintf(str_data, "MySQL%d", int_data);
  1093. rc= mysql_stmt_execute(stmt);
  1094. check_execute(stmt, rc);
  1095. int_data += 25;
  1096. small_data += 10;
  1097. big_data += 100;
  1098. real_data += 1;
  1099. double_data += 10.09;
  1100. }
  1101. mysql_stmt_close(stmt);
  1102. /* now fetch the results ..*/
  1103. rc= mysql_commit(mysql);
  1104. myquery(rc);
  1105. /* test the results now, only one row should exist */
  1106. rc= my_stmt_result("SELECT * FROM my_prepare");
  1107. DIE_UNLESS(tiny_data == (char) rc);
  1108. stmt= mysql_simple_prepare(mysql, "SELECT * FROM my_prepare");
  1109. check_stmt(stmt);
  1110. rc= mysql_stmt_bind_result(stmt, my_bind);
  1111. check_execute(stmt, rc);
  1112. /* get the result */
  1113. rc= mysql_stmt_execute(stmt);
  1114. check_execute(stmt, rc);
  1115. o_int_data= 320;
  1116. o_small_data= 1867;
  1117. o_big_data= 1000;
  1118. o_real_data= 2;
  1119. o_double_data= 6578.001;
  1120. /* now, execute the prepared statement to insert 10 records.. */
  1121. for (o_tiny_data= 0; o_tiny_data < 100; o_tiny_data++)
  1122. {
  1123. len= sprintf(data, "MySQL%d", o_int_data);
  1124. rc= mysql_stmt_fetch(stmt);
  1125. check_execute(stmt, rc);
  1126. if (!opt_silent)
  1127. {
  1128. fprintf(stdout, "\n");
  1129. fprintf(stdout, "\n\t tiny : %d (%lu)", tiny_data, length[0]);
  1130. fprintf(stdout, "\n\t short : %d (%lu)", small_data, length[3]);
  1131. fprintf(stdout, "\n\t int : %d (%lu)", int_data, length[2]);
  1132. fprintf(stdout, "\n\t big : %s (%lu)", llstr(big_data, llbuf),
  1133. length[4]);
  1134. fprintf(stdout, "\n\t float : %f (%lu)", real_data, length[5]);
  1135. fprintf(stdout, "\n\t double : %f (%lu)", double_data, length[6]);
  1136. fprintf(stdout, "\n\t str : %s (%lu)", str_data, length[1]);
  1137. }
  1138. DIE_UNLESS(tiny_data == o_tiny_data);
  1139. DIE_UNLESS(is_null[0] == 0);
  1140. DIE_UNLESS(length[0] == 1);
  1141. DIE_UNLESS(int_data == o_int_data);
  1142. DIE_UNLESS(length[2] == 4);
  1143. DIE_UNLESS(small_data == o_small_data);
  1144. DIE_UNLESS(length[3] == 2);
  1145. DIE_UNLESS(big_data == o_big_data);
  1146. DIE_UNLESS(length[4] == 8);
  1147. DIE_UNLESS(real_data == o_real_data);
  1148. DIE_UNLESS(length[5] == 4);
  1149. DIE_UNLESS(cmp_double(&double_data, &o_double_data));
  1150. DIE_UNLESS(length[6] == 8);
  1151. DIE_UNLESS(strcmp(data, str_data) == 0);
  1152. DIE_UNLESS(length[1] == len);
  1153. o_int_data += 25;
  1154. o_small_data += 10;
  1155. o_big_data += 100;
  1156. o_real_data += 1;
  1157. o_double_data += 10.09;
  1158. }
  1159. rc= mysql_stmt_fetch(stmt);
  1160. DIE_UNLESS(rc == MYSQL_NO_DATA);
  1161. mysql_stmt_close(stmt);
  1162. }
  1163. /* Test double comparision */
  1164. static void test_double_compare()
  1165. {
  1166. MYSQL_STMT *stmt;
  1167. int rc;
  1168. char real_data[10], tiny_data;
  1169. double double_data;
  1170. MYSQL_RES *result;
  1171. MYSQL_BIND my_bind[3];
  1172. ulong length[3];
  1173. char query[MAX_TEST_QUERY_LENGTH];
  1174. myheader("test_double_compare");
  1175. rc= mysql_autocommit(mysql, TRUE);
  1176. myquery(rc);
  1177. rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_double_compare");
  1178. myquery(rc);
  1179. rc= mysql_query(mysql, "CREATE TABLE test_double_compare(col1 tinyint, "
  1180. " col2 float, col3 double )");
  1181. myquery(rc);
  1182. rc= mysql_query(mysql, "INSERT INTO test_double_compare "
  1183. "VALUES (1, 10.2, 34.5)");
  1184. myquery(rc);
  1185. strmov(query, "UPDATE test_double_compare SET col1=100 "
  1186. "WHERE col1 = ? AND col2 = ? AND COL3 = ?");
  1187. stmt= mysql_simple_prepare(mysql, query);
  1188. check_stmt(stmt);
  1189. verify_param_count(stmt, 3);
  1190. /* Always bzero bind array because there can be internal members */
  1191. bzero((char*) my_bind, sizeof(my_bind));
  1192. /* tinyint */
  1193. my_bind[0].buffer_type= MYSQL_TYPE_TINY;
  1194. my_bind[0].buffer= (void *)&tiny_data;
  1195. /* string->float */
  1196. my_bind[1].buffer_type= MYSQL_TYPE_STRING;
  1197. my_bind[1].buffer= (void *)&real_data;
  1198. my_bind[1].buffer_length= sizeof(real_data);
  1199. my_bind[1].length= &length[1];
  1200. length[1]= 10;
  1201. /* double */
  1202. my_bind[2].buffer_type= MYSQL_TYPE_DOUBLE;
  1203. my_bind[2].buffer= (void *)&double_data;
  1204. tiny_data= 1;
  1205. strmov(real_data, "10.2");
  1206. double_data= 34.5;
  1207. rc= mysql_stmt_bind_param(stmt, my_bind);
  1208. check_execute(stmt, rc);
  1209. rc= mysql_stmt_execute(stmt);
  1210. check_execute(stmt, rc);
  1211. verify_affected_rows(0);
  1212. mysql_stmt_close(stmt);
  1213. /* now fetch the results ..*/
  1214. rc= mysql_commit(mysql);
  1215. myquery(rc);
  1216. /* test the results now, only one row should exist */
  1217. rc= mysql_query(mysql, "SELECT * FROM test_double_compare");
  1218. myquery(rc);
  1219. /* get the result */
  1220. result= mysql_store_result(mysql);
  1221. mytest(result);
  1222. rc= my_process_result_set(result);
  1223. DIE_UNLESS((int)tiny_data == rc);
  1224. mysql_free_result(result);
  1225. }
  1226. /* Test simple null */
  1227. static void test_null()
  1228. {
  1229. MYSQL_STMT *stmt;
  1230. int rc;
  1231. uint nData;
  1232. MYSQL_BIND my_bind[2];
  1233. my_bool is_null[2];
  1234. char query[MAX_TEST_QUERY_LENGTH];
  1235. myheader("test_null");
  1236. rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_null");
  1237. myquery(rc);
  1238. rc= mysql_query(mysql, "CREATE TABLE test_null(col1 int, col2 varchar(50))");
  1239. myquery(rc);
  1240. /* insert by prepare, wrong column name */
  1241. strmov(query, "INSERT INTO test_null(col3, col2) VALUES(?, ?)");
  1242. stmt= mysql_simple_prepare(mysql, query);
  1243. check_stmt_r(stmt);
  1244. strmov(query, "INSERT INTO test_null(col1, col2) VALUES(?, ?)");
  1245. stmt= mysql_simple_prepare(mysql, query);
  1246. check_stmt(stmt);
  1247. verify_param_count(stmt, 2);
  1248. /* Always bzero all members of bind parameter */
  1249. bzero((char*) my_bind, sizeof(my_bind));
  1250. my_bind[0].buffer_type= MYSQL_TYPE_LONG;
  1251. my_bind[0].is_null= &is_null[0];
  1252. is_null[0]= 1;
  1253. my_bind[1]= my_bind[0];
  1254. rc= mysql_stmt_bind_param(stmt, my_bind);
  1255. check_execute(stmt, rc);
  1256. /* now, execute the prepared statement to insert 10 records.. */
  1257. for (nData= 0; nData<10; nData++)
  1258. {
  1259. rc= mysql_stmt_execute(stmt);
  1260. check_execute(stmt, rc);
  1261. }
  1262. /* Re-bind with MYSQL_TYPE_NULL */
  1263. my_bind[0].buffer_type= MYSQL_TYPE_NULL;
  1264. is_null[0]= 0; /* reset */
  1265. my_bind[1]= my_bind[0];
  1266. rc= mysql_stmt_bind_param(stmt, my_bind);
  1267. check_execute(stmt, rc);
  1268. for (nData= 0; nData<10; nData++)
  1269. {
  1270. rc= mysql_stmt_execute(stmt);
  1271. check_execute(stmt, rc);
  1272. }
  1273. mysql_stmt_close(stmt);
  1274. /* now fetch the results ..*/
  1275. rc= mysql_commit(mysql);
  1276. myquery(rc);
  1277. nData*= 2;
  1278. rc= my_stmt_result("SELECT * FROM test_null");;
  1279. DIE_UNLESS((int) nData == rc);
  1280. /* Fetch results */
  1281. my_bind[0].buffer_type= MYSQL_TYPE_LONG;
  1282. my_bind[0].buffer= (void *)&nData; /* this buffer won't be altered */
  1283. my_bind[0].length= 0;
  1284. my_bind[1]= my_bind[0];
  1285. my_bind[0].is_null= &is_null[0];
  1286. my_bind[1].is_null= &is_null[1];
  1287. stmt= mysql_simple_prepare(mysql, "SELECT * FROM test_null");
  1288. check_stmt(stmt);
  1289. rc= mysql_stmt_execute(stmt);
  1290. check_execute(stmt, rc);
  1291. rc= mysql_stmt_bind_result(stmt, my_bind);
  1292. check_execute(stmt, rc);
  1293. rc= 0;
  1294. is_null[0]= is_null[1]= 0;
  1295. while (mysql_stmt_fetch(stmt) != MYSQL_NO_DATA)
  1296. {
  1297. DIE_UNLESS(is_null[0]);
  1298. DIE_UNLESS(is_null[1]);
  1299. rc++;
  1300. is_null[0]= is_null[1]= 0;
  1301. }
  1302. DIE_UNLESS(rc == (int) nData);
  1303. mysql_stmt_close(stmt);
  1304. }
  1305. /* Test for NULL as PS parameter (BUG#3367, BUG#3371) */
  1306. static void test_ps_null_param()
  1307. {
  1308. MYSQL_STMT *stmt;
  1309. int rc;
  1310. MYSQL_BIND in_bind;
  1311. my_bool in_is_null;
  1312. long int in_long;
  1313. MYSQL_BIND out_bind;
  1314. ulong out_length;
  1315. my_bool out_is_null;
  1316. char out_str_data[20];
  1317. const char *queries[]= {"select ?", "select ?+1",
  1318. "select col1 from test_ps_nulls where col1 <=> ?",
  1319. NULL
  1320. };
  1321. const char **cur_query= queries;
  1322. myheader("test_null_ps_param_in_result");
  1323. rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_ps_nulls");
  1324. myquery(rc);
  1325. rc= mysql_query(mysql, "CREATE TABLE test_ps_nulls(col1 int)");
  1326. myquery(rc);
  1327. rc= mysql_query(mysql, "INSERT INTO test_ps_nulls values (1), (null)");
  1328. myquery(rc);
  1329. /* Always bzero all members of bind parameter */
  1330. bzero((char*) &in_bind, sizeof(in_bind));
  1331. bzero((char*) &out_bind, sizeof(out_bind));
  1332. in_bind.buffer_type= MYSQL_TYPE_LONG;
  1333. in_bind.is_null= &in_is_null;
  1334. in_bind.length= 0;
  1335. in_bind.buffer= (void *)&in_long;
  1336. in_is_null= 1;
  1337. in_long= 1;
  1338. out_bind.buffer_type= MYSQL_TYPE_STRING;
  1339. out_bind.is_null= &out_is_null;
  1340. out_bind.length= &out_length;
  1341. out_bind.buffer= out_str_data;
  1342. out_bind.buffer_length= array_elements(out_str_data);
  1343. /* Execute several queries, all returning NULL in result. */
  1344. for(cur_query= queries; *cur_query; cur_query++)
  1345. {
  1346. char query[MAX_TEST_QUERY_LENGTH];
  1347. strmov(query, *cur_query);
  1348. stmt= mysql_simple_prepare(mysql, query);
  1349. check_stmt(stmt);
  1350. verify_param_count(stmt, 1);
  1351. rc= mysql_stmt_bind_param(stmt, &in_bind);
  1352. check_execute(stmt, rc);
  1353. rc= mysql_stmt_bind_result(stmt, &out_bind);
  1354. check_execute(stmt, rc);
  1355. rc= mysql_stmt_execute(stmt);
  1356. check_execute(stmt, rc);
  1357. rc= mysql_stmt_fetch(stmt);
  1358. DIE_UNLESS(rc != MYSQL_NO_DATA);
  1359. DIE_UNLESS(out_is_null);
  1360. rc= mysql_stmt_fetch(stmt);
  1361. DIE_UNLESS(rc == MYSQL_NO_DATA);
  1362. mysql_stmt_close(stmt);
  1363. }
  1364. }
  1365. /* Test fetch null */
  1366. static void test_fetch_null()
  1367. {
  1368. MYSQL_STMT *stmt;
  1369. int rc;
  1370. int i, nData;
  1371. MYSQL_BIND my_bind[11];
  1372. ulong length[11];
  1373. my_bool is_null[11];
  1374. char query[MAX_TEST_QUERY_LENGTH];
  1375. myheader("test_fetch_null");
  1376. rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_fetch_null");
  1377. myquery(rc);
  1378. rc= mysql_query(mysql, "CREATE TABLE test_fetch_null("
  1379. " col1 tinyint, col2 smallint, "
  1380. " col3 int, col4 bigint, "
  1381. " col5 float, col6 double, "
  1382. " col7 date, col8 time, "
  1383. " col9 varbinary(10), "
  1384. " col10 varchar(50), "
  1385. " col11 char(20))");
  1386. myquery(rc);
  1387. rc= mysql_query(mysql, "INSERT INTO test_fetch_null (col11) "
  1388. "VALUES (1000), (88), (389789)");
  1389. myquery(rc);
  1390. rc= mysql_commit(mysql);
  1391. myquery(rc);
  1392. /* fetch */
  1393. bzero((char*) my_bind, sizeof(my_bind));
  1394. for (i= 0; i < (int) array_elements(my_bind); i++)
  1395. {
  1396. my_bind[i].buffer_type= MYSQL_TYPE_LONG;
  1397. my_bind[i].is_null= &is_null[i];
  1398. my_bind[i].length= &length[i];
  1399. }
  1400. my_bind[i-1].buffer= (void *)&nData; /* Last column is not null */
  1401. strmov((char *)query , "SELECT * FROM test_fetch_null");
  1402. rc= my_stmt_result(query);
  1403. DIE_UNLESS(rc == 3);
  1404. stmt= mysql_simple_prepare(mysql, query);
  1405. check_stmt(stmt);
  1406. rc= mysql_stmt_bind_result(stmt, my_bind);
  1407. check_execute(stmt, rc);
  1408. rc= mysql_stmt_execute(stmt);
  1409. check_execute(stmt, rc);
  1410. rc= 0;
  1411. while (mysql_stmt_fetch(stmt) != MYSQL_NO_DATA)
  1412. {
  1413. rc++;
  1414. for (i= 0; i < 10; i++)
  1415. {
  1416. if (!opt_silent)
  1417. fprintf(stdout, "\n data[%d] : %s", i,
  1418. is_null[i] ? "NULL" : "NOT NULL");
  1419. DIE_UNLESS(is_null[i]);
  1420. }
  1421. if (!opt_silent)

Large files files are truncated, but you can click here to view the full file