mirror of
				https://github.com/MariaDB/server.git
				synced 2025-10-31 02:46:29 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			23344 lines
		
	
	
	
		
			621 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			23344 lines
		
	
	
	
		
			621 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /* Copyright (c) 2002, 2014, Oracle and/or its affiliates.
 | |
|    Copyright (c) 2008, 2022, MariaDB
 | |
| 
 | |
|    This program is free software; you can redistribute it and/or modify
 | |
|    it under the terms of the GNU General Public License as published by
 | |
|    the Free Software Foundation; version 2 of the License.
 | |
| 
 | |
|    This program is distributed in the hope that it will be useful,
 | |
|    but WITHOUT ANY WARRANTY; without even the implied warranty of
 | |
|    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | |
|    GNU General Public License for more details.
 | |
| 
 | |
|    You should have received a copy of the GNU General Public License
 | |
|    along with this program; if not, write to the Free Software
 | |
|    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1335  USA */
 | |
| 
 | |
| /***************************************************************************
 | |
|  This is a test sample to test the new features in MySQL client-server
 | |
|  protocol
 | |
| 
 | |
|  Main author: venu ( venu@mysql.com )
 | |
| ***************************************************************************/
 | |
| 
 | |
| /*
 | |
|   XXX: PLEASE RUN THIS PROGRAM UNDER VALGRIND AND VERIFY THAT YOUR TEST
 | |
|   DOESN'T CONTAIN WARNINGS/ERRORS BEFORE YOU PUSH.
 | |
| */
 | |
| 
 | |
| 
 | |
| /*
 | |
|   The fw.c file includes all the mysql_client_test framework; this file
 | |
|   contains only the actual tests, plus the list of test functions to call.
 | |
| */
 | |
| #ifdef _MSC_VER
 | |
| #pragma warning (disable : 4267)
 | |
| #endif
 | |
| 
 | |
| #include "mysql_client_fw.c"
 | |
| #ifndef _WIN32
 | |
| #include <arpa/inet.h>
 | |
| #endif
 | |
| 
 | |
| #include "my_valgrind.h"
 | |
| 
 | |
| static const my_bool my_true= 1;
 | |
| 
 | |
| 
 | |
| /* Query processing */
 | |
| 
 | |
| static my_bool get_reconnect(MYSQL *mysql)
 | |
| {
 | |
| #ifdef EMBEDDED_LIBRARY
 | |
|   return mysql->reconnect;
 | |
| #else
 | |
|   my_bool reconnect;
 | |
|   mysql_get_option(mysql, MYSQL_OPT_RECONNECT, &reconnect);
 | |
|   return reconnect;
 | |
| #endif
 | |
| }
 | |
| 
 | |
| static void client_query()
 | |
| {
 | |
|   int rc;
 | |
| 
 | |
|   myheader("client_query");
 | |
| 
 | |
|   rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "CREATE TABLE t1("
 | |
|                          "id int primary key auto_increment, "
 | |
|                          "name varchar(20))");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "CREATE TABLE t1(id int, name varchar(20))");
 | |
|   myquery_r(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "INSERT INTO t1(name) VALUES('mysql')");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "INSERT INTO t1(name) VALUES('monty')");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "INSERT INTO t1(name) VALUES('venu')");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "INSERT INTO t1(name) VALUES('deleted')");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "INSERT INTO t1(name) VALUES('deleted')");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "UPDATE t1 SET name= 'updated' "
 | |
|                           "WHERE name= 'deleted'");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "UPDATE t1 SET id= 3 WHERE name= 'updated'");
 | |
|   myquery_r(rc);
 | |
| 
 | |
|   myquery(mysql_query(mysql, "drop table t1"));
 | |
| }
 | |
| 
 | |
| 
 | |
| /* Store result processing */
 | |
| 
 | |
| static void client_store_result()
 | |
| {
 | |
|   MYSQL_RES *result;
 | |
|   int       rc;
 | |
| 
 | |
|   myheader("client_store_result");
 | |
| 
 | |
|   rc= mysql_query(mysql, "SELECT * FROM t1");
 | |
|   myquery(rc);
 | |
| 
 | |
|   /* get the result */
 | |
|   result= mysql_store_result(mysql);
 | |
|   mytest(result);
 | |
| 
 | |
|   (void) my_process_result_set(result);
 | |
|   mysql_free_result(result);
 | |
| }
 | |
| 
 | |
| 
 | |
| /* Fetch the results */
 | |
| 
 | |
| static void client_use_result()
 | |
| {
 | |
|   MYSQL_RES *result;
 | |
|   int       rc;
 | |
|   myheader("client_use_result");
 | |
| 
 | |
|   rc= mysql_query(mysql, "SELECT * FROM t1");
 | |
|   myquery(rc);
 | |
| 
 | |
|   /* get the result */
 | |
|   result= mysql_use_result(mysql);
 | |
|   mytest(result);
 | |
| 
 | |
|   (void) my_process_result_set(result);
 | |
|   mysql_free_result(result);
 | |
| }
 | |
| 
 | |
| 
 | |
| /* Query processing */
 | |
| 
 | |
| static void test_debug_example()
 | |
| {
 | |
|   int rc;
 | |
|   MYSQL_RES *result;
 | |
| 
 | |
|   myheader("test_debug_example");
 | |
| 
 | |
|   rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_debug_example");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "CREATE TABLE test_debug_example("
 | |
|                          "id INT PRIMARY KEY AUTO_INCREMENT, "
 | |
|                          "name VARCHAR(20), xxx INT)");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "INSERT INTO test_debug_example (name) "
 | |
|                          "VALUES ('mysql')");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "UPDATE test_debug_example SET name='updated' "
 | |
|                          "WHERE name='deleted'");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "SELECT * FROM test_debug_example where name='mysql'");
 | |
|   myquery(rc);
 | |
| 
 | |
|   result= mysql_use_result(mysql);
 | |
|   mytest(result);
 | |
| 
 | |
|   (void) my_process_result_set(result);
 | |
|   mysql_free_result(result);
 | |
| 
 | |
|   rc= mysql_query(mysql, "DROP TABLE test_debug_example");
 | |
|   myquery(rc);
 | |
| }
 | |
| 
 | |
| 
 | |
| /* Test autocommit feature for BDB tables */
 | |
| 
 | |
| static void test_tran_bdb()
 | |
| {
 | |
|   MYSQL_RES *result;
 | |
|   MYSQL_ROW row;
 | |
|   int       rc;
 | |
| 
 | |
|   myheader("test_tran_bdb");
 | |
| 
 | |
|   /* set AUTOCOMMIT to OFF */
 | |
|   rc= mysql_autocommit(mysql, FALSE);
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "DROP TABLE IF EXISTS my_demo_transaction");
 | |
|   myquery(rc);
 | |
| 
 | |
| 
 | |
|   /* create the table 'mytran_demo' of type BDB' or 'InnoDB' */
 | |
|   rc= mysql_query(mysql, "CREATE TABLE my_demo_transaction( "
 | |
|                          "col1 int , col2 varchar(30)) ENGINE= BDB");
 | |
|   myquery(rc);
 | |
| 
 | |
|   /* insert a row and commit the transaction */
 | |
|   rc= mysql_query(mysql, "INSERT INTO my_demo_transaction VALUES(10, 'venu')");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_commit(mysql);
 | |
|   myquery(rc);
 | |
| 
 | |
|   /* now insert the second row, and roll back the transaction */
 | |
|   rc= mysql_query(mysql, "INSERT INTO my_demo_transaction VALUES(20, 'mysql')");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_rollback(mysql);
 | |
|   myquery(rc);
 | |
| 
 | |
|   /* delete first row, and roll it back */
 | |
|   rc= mysql_query(mysql, "DELETE FROM my_demo_transaction WHERE col1= 10");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_rollback(mysql);
 | |
|   myquery(rc);
 | |
| 
 | |
|   /* test the results now, only one row should exist */
 | |
|   rc= mysql_query(mysql, "SELECT * FROM my_demo_transaction");
 | |
|   myquery(rc);
 | |
| 
 | |
|   /* get the result */
 | |
|   result= mysql_store_result(mysql);
 | |
|   mytest(result);
 | |
| 
 | |
|   (void) my_process_result_set(result);
 | |
|   mysql_free_result(result);
 | |
| 
 | |
|   /* test the results now, only one row should exist */
 | |
|   rc= mysql_query(mysql, "SELECT * FROM my_demo_transaction");
 | |
|   myquery(rc);
 | |
| 
 | |
|   /* get the result */
 | |
|   result= mysql_use_result(mysql);
 | |
|   mytest(result);
 | |
| 
 | |
|   row= mysql_fetch_row(result);
 | |
|   mytest(row);
 | |
| 
 | |
|   row= mysql_fetch_row(result);
 | |
|   mytest_r(row);
 | |
| 
 | |
|   mysql_free_result(result);
 | |
|   mysql_autocommit(mysql, TRUE);
 | |
| }
 | |
| 
 | |
| 
 | |
| /* Test autocommit feature for InnoDB tables */
 | |
| 
 | |
| static void test_tran_innodb()
 | |
| {
 | |
|   MYSQL_RES *result;
 | |
|   MYSQL_ROW row;
 | |
|   int       rc;
 | |
| 
 | |
|   myheader("test_tran_innodb");
 | |
| 
 | |
|   /* set AUTOCOMMIT to OFF */
 | |
|   rc= mysql_autocommit(mysql, FALSE);
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "DROP TABLE IF EXISTS my_demo_transaction");
 | |
|   myquery(rc);
 | |
| 
 | |
|   /* create the table 'mytran_demo' of type BDB' or 'InnoDB' */
 | |
|   rc= mysql_query(mysql, "CREATE TABLE my_demo_transaction(col1 int, "
 | |
|                          "col2 varchar(30)) ENGINE= InnoDB");
 | |
|   myquery(rc);
 | |
| 
 | |
|   /* insert a row and commit the transaction */
 | |
|   rc= mysql_query(mysql, "INSERT INTO my_demo_transaction VALUES(10, 'venu')");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_commit(mysql);
 | |
|   myquery(rc);
 | |
| 
 | |
|   /* now insert the second row, and roll back the transaction */
 | |
|   rc= mysql_query(mysql, "INSERT INTO my_demo_transaction VALUES(20, 'mysql')");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_rollback(mysql);
 | |
|   myquery(rc);
 | |
| 
 | |
|   /* delete first row, and roll it back */
 | |
|   rc= mysql_query(mysql, "DELETE FROM my_demo_transaction WHERE col1= 10");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_rollback(mysql);
 | |
|   myquery(rc);
 | |
| 
 | |
|   /* test the results now, only one row should exist */
 | |
|   rc= mysql_query(mysql, "SELECT * FROM my_demo_transaction");
 | |
|   myquery(rc);
 | |
| 
 | |
|   /* get the result */
 | |
|   result= mysql_store_result(mysql);
 | |
|   mytest(result);
 | |
| 
 | |
|   (void) my_process_result_set(result);
 | |
|   mysql_free_result(result);
 | |
| 
 | |
|   /* test the results now, only one row should exist */
 | |
|   rc= mysql_query(mysql, "SELECT * FROM my_demo_transaction");
 | |
|   myquery(rc);
 | |
| 
 | |
|   /* get the result */
 | |
|   result= mysql_use_result(mysql);
 | |
|   mytest(result);
 | |
| 
 | |
|   row= mysql_fetch_row(result);
 | |
|   mytest(row);
 | |
| 
 | |
|   row= mysql_fetch_row(result);
 | |
|   mytest_r(row);
 | |
| 
 | |
|   mysql_free_result(result);
 | |
|   mysql_autocommit(mysql, TRUE);
 | |
| }
 | |
| 
 | |
| 
 | |
| /* Test for BUG#7242 */
 | |
| 
 | |
| static void test_prepare_insert_update()
 | |
| {
 | |
|   MYSQL_STMT *stmt;
 | |
|   int        rc;
 | |
|   int        i;
 | |
|   const char *testcase[]= {
 | |
|     "CREATE TABLE t1 (a INT, b INT, c INT, UNIQUE (A), UNIQUE(B))",
 | |
|     "INSERT t1 VALUES (1,2,10), (3,4,20)",
 | |
|     "INSERT t1 VALUES (5,6,30), (7,4,40), (8,9,60) ON DUPLICATE KEY UPDATE c=c+100",
 | |
|     "SELECT * FROM t1",
 | |
|     "INSERT t1 SET a=5 ON DUPLICATE KEY UPDATE b=0",
 | |
|     "SELECT * FROM t1",
 | |
|     "INSERT t1 VALUES (2,1,11), (7,4,40) ON DUPLICATE KEY UPDATE c=c+VALUES(a)",
 | |
|     NULL};
 | |
|   const char **cur_query;
 | |
| 
 | |
|   myheader("test_prepare_insert_update");
 | |
|   
 | |
|   for (cur_query= testcase; *cur_query; cur_query++)
 | |
|   {
 | |
|     char query[MAX_TEST_QUERY_LENGTH];
 | |
|     printf("\nRunning query: %s", *cur_query);
 | |
|     strmov(query, *cur_query);
 | |
|     stmt= mysql_simple_prepare(mysql, query);
 | |
|     check_stmt(stmt);
 | |
| 
 | |
|     verify_param_count(stmt, 0);
 | |
|     rc= mysql_stmt_execute(stmt);
 | |
| 
 | |
|     check_execute(stmt, rc);
 | |
|     /* try the last query several times */
 | |
|     if (!cur_query[1])
 | |
|     {
 | |
|       for (i=0; i < 3;i++)
 | |
|       {
 | |
|         printf("\nExecuting last statement again");
 | |
|         rc= mysql_stmt_execute(stmt);
 | |
|         check_execute(stmt, rc);
 | |
|         rc= mysql_stmt_execute(stmt);
 | |
|         check_execute(stmt, rc);
 | |
|       }
 | |
|     }
 | |
|     mysql_stmt_close(stmt);
 | |
|   }
 | |
| 
 | |
|   rc= mysql_commit(mysql);
 | |
|   myquery(rc);
 | |
| }
 | |
| 
 | |
| 
 | |
| /* Test simple prepares of all DML statements */
 | |
| 
 | |
| static void test_prepare_simple()
 | |
| {
 | |
|   MYSQL_STMT *stmt;
 | |
|   int        rc;
 | |
|   char query[MAX_TEST_QUERY_LENGTH];
 | |
| 
 | |
|   myheader("test_prepare_simple");
 | |
| 
 | |
|   rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_prepare_simple");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "CREATE TABLE test_prepare_simple("
 | |
|                          "id int, name varchar(50))");
 | |
|   myquery(rc);
 | |
| 
 | |
|   /* insert */
 | |
|   strmov(query, "INSERT INTO test_prepare_simple VALUES(?, ?)");
 | |
|   stmt= mysql_simple_prepare(mysql, query);
 | |
|   check_stmt(stmt);
 | |
| 
 | |
|   verify_param_count(stmt, 2);
 | |
|   mysql_stmt_close(stmt);
 | |
| 
 | |
|   /* update */
 | |
|   strmov(query, "UPDATE test_prepare_simple SET id=? "
 | |
|                 "WHERE id=? AND CONVERT(name USING utf8)= ?");
 | |
|   stmt= mysql_simple_prepare(mysql, query);
 | |
|   check_stmt(stmt);
 | |
| 
 | |
|   verify_param_count(stmt, 3);
 | |
|   mysql_stmt_close(stmt);
 | |
| 
 | |
|   /* delete */
 | |
|   strmov(query, "DELETE FROM test_prepare_simple WHERE id=10");
 | |
|   stmt= mysql_simple_prepare(mysql, query);
 | |
|   check_stmt(stmt);
 | |
| 
 | |
|   verify_param_count(stmt, 0);
 | |
| 
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
|   mysql_stmt_close(stmt);
 | |
| 
 | |
|   /* delete */
 | |
|   strmov(query, "DELETE FROM test_prepare_simple WHERE id=?");
 | |
|   stmt= mysql_simple_prepare(mysql, query);
 | |
|   check_stmt(stmt);
 | |
| 
 | |
|   verify_param_count(stmt, 1);
 | |
| 
 | |
|   mysql_stmt_close(stmt);
 | |
| 
 | |
|   /* select */
 | |
|   strmov(query, "SELECT * FROM test_prepare_simple WHERE id=? "
 | |
|                 "AND CONVERT(name USING utf8)= ?");
 | |
|   stmt= mysql_simple_prepare(mysql, query);
 | |
|   check_stmt(stmt);
 | |
| 
 | |
|   verify_param_count(stmt, 2);
 | |
| 
 | |
|   mysql_stmt_close(stmt);
 | |
| 
 | |
|   /* show create */
 | |
|   strmov(query, "SHOW CREATE TABLE test_prepare_simple");
 | |
|   stmt= mysql_simple_prepare(mysql, query);
 | |
|   check_stmt(stmt);
 | |
|   DIE_UNLESS(mysql_stmt_field_count(stmt) == 2);
 | |
|   mysql_stmt_close(stmt);
 | |
| 
 | |
|   /* show create database */
 | |
|   strmov(query, "SHOW CREATE DATABASE test");
 | |
|   stmt= mysql_simple_prepare(mysql, query);
 | |
|   check_stmt(stmt);
 | |
|   DIE_UNLESS(mysql_stmt_field_count(stmt) == 2);
 | |
|   mysql_stmt_close(stmt);
 | |
| 
 | |
|   /* show grants */
 | |
|   strmov(query, "SHOW GRANTS");
 | |
|   stmt= mysql_simple_prepare(mysql, query);
 | |
|   check_stmt(stmt);
 | |
|   DIE_UNLESS(mysql_stmt_field_count(stmt) == 1);
 | |
|   mysql_stmt_close(stmt);
 | |
| 
 | |
|   /* show slave status */
 | |
|   strmov(query, "SHOW SLAVE STATUS");
 | |
|   stmt= mysql_simple_prepare(mysql, query);
 | |
|   check_stmt(stmt);
 | |
|   DIE_UNLESS(mysql_stmt_field_count(stmt) == 56);
 | |
|   mysql_stmt_close(stmt);
 | |
| 
 | |
|   /* show master status */
 | |
|   strmov(query, "SHOW MASTER STATUS");
 | |
|   stmt= mysql_simple_prepare(mysql, query);
 | |
|   check_stmt(stmt);
 | |
|   DIE_UNLESS(mysql_stmt_field_count(stmt) == 4);
 | |
|   mysql_stmt_close(stmt);
 | |
| 
 | |
|   /* show create procedure */
 | |
|   strmov(query, "SHOW CREATE PROCEDURE e1;");
 | |
|   stmt= mysql_simple_prepare(mysql, query);
 | |
|   check_stmt(stmt);
 | |
|   DIE_UNLESS(mysql_stmt_field_count(stmt) == 6);
 | |
|   mysql_stmt_close(stmt);
 | |
| 
 | |
|   /* show create function */
 | |
|   strmov(query, "SHOW CREATE FUNCTION e1;");
 | |
|   stmt= mysql_simple_prepare(mysql, query);
 | |
|   check_stmt(stmt);
 | |
|   DIE_UNLESS(mysql_stmt_field_count(stmt) == 6);
 | |
|   mysql_stmt_close(stmt);
 | |
| 
 | |
|   /* now fetch the results ..*/
 | |
|   rc= mysql_commit(mysql);
 | |
|   myquery(rc);
 | |
| }
 | |
| 
 | |
| /************************************************************************/
 | |
| 
 | |
| #define FILE_PATH_SIZE 4096
 | |
| 
 | |
| char mct_log_file_path[FILE_PATH_SIZE];
 | |
| FILE *mct_log_file= NULL;
 | |
| 
 | |
| void mct_start_logging(const char *test_case_name)
 | |
| {
 | |
|   const char *tmp_dir= getenv("MYSQL_TMP_DIR");
 | |
| 
 | |
|   if (!tmp_dir)
 | |
|   {
 | |
|     printf("Warning: MYSQL_TMP_DIR is not set. Logging is disabled.\n");
 | |
|     return;
 | |
|   }
 | |
| 
 | |
|   if (mct_log_file)
 | |
|   {
 | |
|     printf("Warning: can not start logging for test case '%s' "
 | |
|            "because log is already open\n",
 | |
|            (const char *) test_case_name);
 | |
|     return;
 | |
|   }
 | |
| 
 | |
|   /*
 | |
|     Path is: <tmp_dir>/<test_case_name>.out.log
 | |
|     10 is length of '/' + '.out.log' + \0
 | |
|   */
 | |
| 
 | |
|   if (strlen(tmp_dir) + strlen(test_case_name) + 10 > FILE_PATH_SIZE)
 | |
|   {
 | |
|     printf("Warning: MYSQL_TMP_DIR is too long. Logging is disabled.\n");
 | |
|     return;
 | |
|   }
 | |
| 
 | |
|   my_snprintf(mct_log_file_path, FILE_PATH_SIZE,
 | |
|               "%s/%s.out.log",
 | |
|               (const char *) tmp_dir,
 | |
|               (const char *) test_case_name);
 | |
| 
 | |
|   mct_log_file= my_fopen(mct_log_file_path, O_WRONLY | O_BINARY, MYF(MY_WME));
 | |
| 
 | |
|   if (!mct_log_file)
 | |
|   {
 | |
|     printf("Warning: can not open log file (%s): %s. Logging is disabled.\n",
 | |
|         (const char *) mct_log_file_path,
 | |
|         (const char *) strerror(errno));
 | |
|     return;
 | |
|   }
 | |
| }
 | |
| 
 | |
| void mct_log(const char *format, ...)
 | |
| {
 | |
|   va_list args;
 | |
|   va_start(args, format);
 | |
|   vprintf(format, args);
 | |
|   va_end(args);
 | |
| 
 | |
|   if (mct_log_file)
 | |
|   {
 | |
|     va_list args;
 | |
|     va_start(args, format);
 | |
|     vfprintf(mct_log_file, format, args);
 | |
|     va_end(args);
 | |
|   }
 | |
| }
 | |
| 
 | |
| void mct_close_log()
 | |
| {
 | |
|   if (!mct_log_file)
 | |
|     return;
 | |
| 
 | |
|   my_fclose(mct_log_file, MYF(0));
 | |
|   mct_log_file= NULL;
 | |
| }
 | |
| 
 | |
| #define WL4435_NUM_PARAMS 10
 | |
| #define WL4435_STRING_SIZE 30
 | |
| 
 | |
| static void test_wl4435()
 | |
| {
 | |
|   MYSQL_STMT *stmt;
 | |
|   int        rc;
 | |
|   char query[MAX_TEST_QUERY_LENGTH];
 | |
| 
 | |
|   char       str_data[20][WL4435_STRING_SIZE];
 | |
|   double     dbl_data[20];
 | |
|   char       dec_data[20][WL4435_STRING_SIZE];
 | |
|   int        int_data[20];
 | |
|   ulong      str_length= WL4435_STRING_SIZE;
 | |
|   my_bool    is_null;
 | |
|   MYSQL_BIND ps_params[WL4435_NUM_PARAMS];
 | |
| 
 | |
|   int exec_counter;
 | |
| 
 | |
|   myheader("test_wl4435");
 | |
|   mct_start_logging("test_wl4435");
 | |
| 
 | |
|   rc= mysql_query(mysql, "DROP PROCEDURE IF EXISTS p1");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "DROP PROCEDURE IF EXISTS p2");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "DROP TABLE IF EXISTS t2");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "CREATE TABLE t1(a1 INT, a2 CHAR(32), "
 | |
|                        "  a3 DOUBLE(4, 2), a4 DECIMAL(3, 1))");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "CREATE TABLE t2(b0 INT, b1 INT, b2 CHAR(32), "
 | |
|                        "  b3 DOUBLE(4, 2), b4 DECIMAL(3, 1))");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "INSERT INTO t1 VALUES"
 | |
|     "(1, '11', 12.34, 56.7), "
 | |
|     "(2, '12', 56.78, 90.1), "
 | |
|     "(3, '13', 23.45, 67.8)");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "INSERT INTO t2 VALUES"
 | |
|     "(100, 10, '110', 70.70, 10.1), "
 | |
|     "(200, 20, '120', 80.80, 20.2), "
 | |
|     "(300, 30, '130', 90.90, 30.3)");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql,
 | |
|     "CREATE PROCEDURE p1("
 | |
|     "   IN v0 INT, "
 | |
|     "   OUT v_str_1 CHAR(32), "
 | |
|     "   OUT v_dbl_1 DOUBLE(4, 2), "
 | |
|     "   OUT v_dec_1 DECIMAL(6, 3), "
 | |
|     "   OUT v_int_1 INT, "
 | |
|     "   IN v1 INT, "
 | |
|     "   INOUT v_str_2 CHAR(64), "
 | |
|     "   INOUT v_dbl_2 DOUBLE(5, 3), "
 | |
|     "   INOUT v_dec_2 DECIMAL(7, 4), "
 | |
|     "   INOUT v_int_2 INT)"
 | |
|     "BEGIN "
 | |
|     "   SET v0 = -1; "
 | |
|     "   SET v1 = -1; "
 | |
|     "   SET v_str_1 = 'test_1'; "
 | |
|     "   SET v_dbl_1 = 12.34; "
 | |
|     "   SET v_dec_1 = 567.891; "
 | |
|     "   SET v_int_1 = 2345; "
 | |
|     "   SET v_str_2 = 'test_2'; "
 | |
|     "   SET v_dbl_2 = 67.891; "
 | |
|     "   SET v_dec_2 = 234.6789; "
 | |
|     "   SET v_int_2 = 6789; "
 | |
|     "   SELECT * FROM t1; "
 | |
|     "   SELECT * FROM t2; "
 | |
|     "END");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql,
 | |
|     "CREATE PROCEDURE p2("
 | |
|     "   IN i1 VARCHAR(255) CHARACTER SET koi8r, "
 | |
|     "   OUT o1 VARCHAR(255) CHARACTER SET cp1251, "
 | |
|     "   OUT o2 VARBINARY(255)) "
 | |
|     "BEGIN "
 | |
|     "   SET o1 = i1; "
 | |
|     "   SET o2 = i1; "
 | |
|     "END");
 | |
|   myquery(rc);
 | |
| 
 | |
|   strmov(query, "CALL p1(?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
 | |
|   stmt= mysql_simple_prepare(mysql, query);
 | |
|   check_stmt(stmt);
 | |
| 
 | |
|   /* Init PS-parameters. */
 | |
| 
 | |
|   memset(str_data, 0, sizeof str_data);
 | |
|   memset(dbl_data, 0, sizeof dbl_data);
 | |
|   memset(dec_data, 0, sizeof dec_data);
 | |
|   memset(int_data, 0, sizeof int_data);
 | |
| 
 | |
|   bzero((char *) ps_params, sizeof (ps_params));
 | |
| 
 | |
|   /* - v0 -- INT */
 | |
| 
 | |
|   ps_params[0].buffer_type= MYSQL_TYPE_LONG;
 | |
|   ps_params[0].buffer= (char *) &int_data[0];
 | |
|   ps_params[0].length= 0;
 | |
|   ps_params[0].is_null= 0;
 | |
| 
 | |
|   /* - v_str_1 -- CHAR(32) */
 | |
| 
 | |
|   ps_params[1].buffer_type= MYSQL_TYPE_STRING;
 | |
|   ps_params[1].buffer= (char *) str_data[0];
 | |
|   ps_params[1].buffer_length= WL4435_STRING_SIZE;
 | |
|   ps_params[1].length= &str_length;
 | |
|   ps_params[1].is_null= 0;
 | |
| 
 | |
|   /* - v_dbl_1 -- DOUBLE */
 | |
| 
 | |
|   ps_params[2].buffer_type= MYSQL_TYPE_DOUBLE;
 | |
|   ps_params[2].buffer= (char *) &dbl_data[0];
 | |
|   ps_params[2].length= 0;
 | |
|   ps_params[2].is_null= 0;
 | |
| 
 | |
|   /* - v_dec_1 -- DECIMAL */
 | |
| 
 | |
|   ps_params[3].buffer_type= MYSQL_TYPE_NEWDECIMAL;
 | |
|   ps_params[3].buffer= (char *) dec_data[0];
 | |
|   ps_params[3].buffer_length= WL4435_STRING_SIZE;
 | |
|   ps_params[3].length= 0;
 | |
|   ps_params[3].is_null= 0;
 | |
| 
 | |
|   /* - v_int_1 -- INT */
 | |
| 
 | |
|   ps_params[4].buffer_type= MYSQL_TYPE_LONG;
 | |
|   ps_params[4].buffer= (char *) &int_data[0];
 | |
|   ps_params[4].length= 0;
 | |
|   ps_params[4].is_null= 0;
 | |
| 
 | |
|   /* - v1 -- INT */
 | |
| 
 | |
|   ps_params[5].buffer_type= MYSQL_TYPE_LONG;
 | |
|   ps_params[5].buffer= (char *) &int_data[0];
 | |
|   ps_params[5].length= 0;
 | |
|   ps_params[5].is_null= 0;
 | |
| 
 | |
|   /* - v_str_2 -- CHAR(32) */
 | |
| 
 | |
|   ps_params[6].buffer_type= MYSQL_TYPE_STRING;
 | |
|   ps_params[6].buffer= (char *) str_data[0];
 | |
|   ps_params[6].buffer_length= WL4435_STRING_SIZE;
 | |
|   ps_params[6].length= &str_length;
 | |
|   ps_params[6].is_null= 0;
 | |
| 
 | |
|   /* - v_dbl_2 -- DOUBLE */
 | |
| 
 | |
|   ps_params[7].buffer_type= MYSQL_TYPE_DOUBLE;
 | |
|   ps_params[7].buffer= (char *) &dbl_data[0];
 | |
|   ps_params[7].length= 0;
 | |
|   ps_params[7].is_null= 0;
 | |
| 
 | |
|   /* - v_dec_2 -- DECIMAL */
 | |
| 
 | |
|   ps_params[8].buffer_type= MYSQL_TYPE_DECIMAL;
 | |
|   ps_params[8].buffer= (char *) dec_data[0];
 | |
|   ps_params[8].buffer_length= WL4435_STRING_SIZE;
 | |
|   ps_params[8].length= 0;
 | |
|   ps_params[8].is_null= 0;
 | |
| 
 | |
|   /* - v_int_2 -- INT */
 | |
| 
 | |
|   ps_params[9].buffer_type= MYSQL_TYPE_LONG;
 | |
|   ps_params[9].buffer= (char *) &int_data[0];
 | |
|   ps_params[9].length= 0;
 | |
|   ps_params[9].is_null= 0;
 | |
| 
 | |
|   /* Bind parameters. */
 | |
| 
 | |
|   rc= mysql_stmt_bind_param(stmt, ps_params);
 | |
| 
 | |
|   /* Execute! */
 | |
| 
 | |
|   for (exec_counter= 0; exec_counter < 3; ++exec_counter)
 | |
|   {
 | |
|     int i;
 | |
|     int num_fields;
 | |
|     MYSQL_BIND *rs_bind;
 | |
| 
 | |
|     mct_log("\nexec_counter: %d\n", (int) exec_counter);
 | |
| 
 | |
|     rc= mysql_stmt_execute(stmt);
 | |
|     check_execute(stmt, rc);
 | |
| 
 | |
|     while (1)
 | |
|     {
 | |
|       MYSQL_FIELD *fields;
 | |
| 
 | |
|       MYSQL_RES *rs_metadata= mysql_stmt_result_metadata(stmt);
 | |
| 
 | |
|       num_fields= mysql_stmt_field_count(stmt);
 | |
|       fields= mysql_fetch_fields(rs_metadata);
 | |
| 
 | |
|       rs_bind= (MYSQL_BIND *) malloc(sizeof (MYSQL_BIND) * num_fields);
 | |
|       bzero(rs_bind, sizeof (MYSQL_BIND) * num_fields);
 | |
| 
 | |
|       mct_log("num_fields: %d\n", (int) num_fields);
 | |
| 
 | |
|       for (i = 0; i < num_fields; ++i)
 | |
|       {
 | |
|         mct_log("  - %d: name: '%s'/'%s'; table: '%s'/'%s'; "
 | |
|                 "db: '%s'; catalog: '%s'; length: %d; max_length: %d; "
 | |
|                 "type: %d; decimals: %d\n",
 | |
|                 (int) i,
 | |
|                 (const char *) fields[i].name,
 | |
|                 (const char *) fields[i].org_name,
 | |
|                 (const char *) fields[i].table,
 | |
|                 (const char *) fields[i].org_table,
 | |
|                 (const char *) fields[i].db,
 | |
|                 (const char *) fields[i].catalog,
 | |
|                 (int) fields[i].length,
 | |
|                 (int) fields[i].max_length,
 | |
|                 (int) fields[i].type,
 | |
|                 (int) fields[i].decimals);
 | |
| 
 | |
|         rs_bind[i].buffer_type= fields[i].type;
 | |
|         rs_bind[i].is_null= &is_null;
 | |
| 
 | |
|         switch (fields[i].type)
 | |
|         {
 | |
|           case MYSQL_TYPE_LONG:
 | |
|             rs_bind[i].buffer= (char *) &(int_data[i]);
 | |
|             rs_bind[i].buffer_length= sizeof (int_data);
 | |
|             break;
 | |
| 
 | |
|           case MYSQL_TYPE_STRING:
 | |
|             rs_bind[i].buffer= (char *) str_data[i];
 | |
|             rs_bind[i].buffer_length= WL4435_STRING_SIZE;
 | |
|             rs_bind[i].length= &str_length;
 | |
|             break;
 | |
| 
 | |
|           case MYSQL_TYPE_DOUBLE:
 | |
|             rs_bind[i].buffer= (char *) &dbl_data[i];
 | |
|             rs_bind[i].buffer_length= sizeof (dbl_data);
 | |
|             break;
 | |
| 
 | |
|           case MYSQL_TYPE_NEWDECIMAL:
 | |
|             rs_bind[i].buffer= (char *) dec_data[i];
 | |
|             rs_bind[i].buffer_length= WL4435_STRING_SIZE;
 | |
|             rs_bind[i].length= &str_length;
 | |
|             break;
 | |
| 
 | |
|           default:
 | |
|             fprintf(stderr, "ERROR: unexpected type: %d.\n", fields[i].type);
 | |
|             exit(1);
 | |
|         }
 | |
|       }
 | |
| 
 | |
|       rc= mysql_stmt_bind_result(stmt, rs_bind);
 | |
|       check_execute(stmt, rc);
 | |
| 
 | |
|       mct_log("Data:\n");
 | |
| 
 | |
|       while (1)
 | |
|       {
 | |
|         int rc= mysql_stmt_fetch(stmt);
 | |
| 
 | |
|         if (rc == 1 || rc == MYSQL_NO_DATA)
 | |
|           break;
 | |
| 
 | |
|         mct_log(" ");
 | |
| 
 | |
|         for (i = 0; i < num_fields; ++i)
 | |
|         {
 | |
|           switch (rs_bind[i].buffer_type)
 | |
|           {
 | |
|             case MYSQL_TYPE_LONG:
 | |
|               mct_log(" int: %ld;",
 | |
|                       (long) *((int *) rs_bind[i].buffer));
 | |
|               break;
 | |
| 
 | |
|             case MYSQL_TYPE_STRING:
 | |
|               mct_log(" str: '%s';",
 | |
|                       (char *) rs_bind[i].buffer);
 | |
|               break;
 | |
| 
 | |
|             case MYSQL_TYPE_DOUBLE:
 | |
|               mct_log(" dbl: %lf;",
 | |
|                       (double) *((double *) rs_bind[i].buffer));
 | |
|               break;
 | |
| 
 | |
|             case MYSQL_TYPE_NEWDECIMAL:
 | |
|               mct_log(" dec: '%s';",
 | |
|                       (char *) rs_bind[i].buffer);
 | |
|               break;
 | |
| 
 | |
|             default:
 | |
|               printf("  unexpected type (%d)\n",
 | |
|                 rs_bind[i].buffer_type);
 | |
|           }
 | |
|         }
 | |
|         mct_log("\n");
 | |
|       }
 | |
| 
 | |
|       mct_log("EOF\n");
 | |
| 
 | |
|       rc= mysql_stmt_next_result(stmt);
 | |
|       mct_log("mysql_stmt_next_result(): %d; field_count: %d\n",
 | |
|               (int) rc, (int) mysql->field_count);
 | |
| 
 | |
|       free(rs_bind);
 | |
|       mysql_free_result(rs_metadata);
 | |
| 
 | |
|       if (rc > 0)
 | |
|       {
 | |
|         printf("Error: %s (errno: %d)\n",
 | |
|                mysql_stmt_error(stmt), mysql_stmt_errno(stmt));
 | |
|         DIE(rc > 0);
 | |
|       }
 | |
| 
 | |
|       if (rc)
 | |
|         break;
 | |
| 
 | |
|       if (!mysql->field_count)
 | |
|       {
 | |
|         /* This is the last OK-packet. No more resultsets. */
 | |
|         break;
 | |
|       }
 | |
|     }
 | |
| 
 | |
|   }
 | |
| 
 | |
|   mysql_stmt_close(stmt);
 | |
| 
 | |
|   mct_close_log();
 | |
| 
 | |
|   rc= mysql_commit(mysql);
 | |
|   myquery(rc);
 | |
| 
 | |
|   /* i18n part of test case. */
 | |
| 
 | |
|   {
 | |
|     const char *str_koi8r= "\xee\xd5\x2c\x20\xda\xc1\x20\xd2\xd9\xc2\xc1\xcc\xcb\xd5";
 | |
|     const char *str_cp1251= "\xcd\xf3\x2c\x20\xe7\xe0\x20\xf0\xfb\xe1\xe0\xeb\xea\xf3";
 | |
|     char o1_buffer[255];
 | |
|     ulong o1_length;
 | |
|     char o2_buffer[255];
 | |
|     ulong o2_length;
 | |
| 
 | |
|     MYSQL_BIND rs_bind[2];
 | |
| 
 | |
|     strmov(query, "CALL p2(?, ?, ?)");
 | |
|     stmt= mysql_simple_prepare(mysql, query);
 | |
|     check_stmt(stmt);
 | |
| 
 | |
|     /* Init PS-parameters. */
 | |
| 
 | |
|     bzero((char *) ps_params, sizeof (ps_params));
 | |
| 
 | |
|     ps_params[0].buffer_type= MYSQL_TYPE_STRING;
 | |
|     ps_params[0].buffer= (char *) str_koi8r;
 | |
|     ps_params[0].buffer_length= strlen(str_koi8r);
 | |
| 
 | |
|     ps_params[1].buffer_type= MYSQL_TYPE_STRING;
 | |
|     ps_params[1].buffer= o1_buffer;
 | |
|     ps_params[1].buffer_length= 0;
 | |
| 
 | |
|     ps_params[2].buffer_type= MYSQL_TYPE_STRING;
 | |
|     ps_params[2].buffer= o2_buffer;
 | |
|     ps_params[2].buffer_length= 0;
 | |
| 
 | |
|     /* Bind parameters. */
 | |
| 
 | |
|     rc= mysql_stmt_bind_param(stmt, ps_params);
 | |
|     check_execute(stmt, rc);
 | |
| 
 | |
|     /* Prevent converting to character_set_results. */
 | |
| 
 | |
|     rc= mysql_query(mysql, "SET NAMES binary");
 | |
|     myquery(rc);
 | |
| 
 | |
|     /* Execute statement. */
 | |
| 
 | |
|     rc= mysql_stmt_execute(stmt);
 | |
|     check_execute(stmt, rc);
 | |
| 
 | |
|     /* Bind result. */
 | |
| 
 | |
|     bzero(rs_bind, sizeof (rs_bind));
 | |
| 
 | |
|     rs_bind[0].buffer_type= MYSQL_TYPE_STRING;
 | |
|     rs_bind[0].buffer= o1_buffer;
 | |
|     rs_bind[0].buffer_length= sizeof (o1_buffer);
 | |
|     rs_bind[0].length= &o1_length;
 | |
| 
 | |
|     rs_bind[1].buffer_type= MYSQL_TYPE_BLOB;
 | |
|     rs_bind[1].buffer= o2_buffer;
 | |
|     rs_bind[1].buffer_length= sizeof (o2_buffer);
 | |
|     rs_bind[1].length= &o2_length;
 | |
| 
 | |
|     rc= mysql_stmt_bind_result(stmt, rs_bind);
 | |
|     check_execute(stmt, rc);
 | |
| 
 | |
|     /* Fetch result. */
 | |
| 
 | |
|     rc= mysql_stmt_fetch(stmt);
 | |
|     check_execute(stmt, rc);
 | |
| 
 | |
|     /* Check result. */
 | |
| 
 | |
|     DIE_UNLESS(o1_length == strlen(str_cp1251));
 | |
|     DIE_UNLESS(o2_length == strlen(str_koi8r));
 | |
|     DIE_UNLESS(!memcmp(o1_buffer, str_cp1251, o1_length));
 | |
|     DIE_UNLESS(!memcmp(o2_buffer, str_koi8r, o2_length));
 | |
| 
 | |
|     rc= mysql_stmt_fetch(stmt);
 | |
|     DIE_UNLESS(rc == MYSQL_NO_DATA);
 | |
| 
 | |
|     rc= mysql_stmt_next_result(stmt);
 | |
|     DIE_UNLESS(rc == 0 && mysql->field_count == 0);
 | |
| 
 | |
|     mysql_stmt_close(stmt);
 | |
| 
 | |
|     rc= mysql_commit(mysql);
 | |
|     myquery(rc);
 | |
|   }
 | |
| }
 | |
| 
 | |
| static void test_wl4435_2()
 | |
| {
 | |
|   MYSQL_STMT *stmt;
 | |
|   int  i;
 | |
|   int  rc;
 | |
|   char query[MAX_TEST_QUERY_LENGTH];
 | |
| 
 | |
|   myheader("test_wl4435_2");
 | |
|   mct_start_logging("test_wl4435_2");
 | |
| 
 | |
|   /*
 | |
|     Do a few iterations so that we catch any problem with incorrect
 | |
|     handling/flushing prepared statement results.
 | |
|   */
 | |
| 
 | |
|   for (i= 0; i < 10; ++i)
 | |
|   {
 | |
|     /*
 | |
|       Prepare a procedure. That can be moved out of the loop, but it was
 | |
|       left in the loop for the sake of having as many statements as
 | |
|       possible.
 | |
|     */
 | |
| 
 | |
|     rc= mysql_query(mysql, "DROP PROCEDURE IF EXISTS p1");
 | |
|     myquery(rc);
 | |
| 
 | |
|     rc= mysql_query(mysql,
 | |
|       "CREATE PROCEDURE p1()"
 | |
|       "BEGIN "
 | |
|       "  SELECT 1; "
 | |
|       "  SELECT 2, 3 UNION SELECT 4, 5; "
 | |
|       "  SELECT 6, 7, 8; "
 | |
|       "END");
 | |
|     myquery(rc);
 | |
| 
 | |
|     /* Invoke a procedure, that returns several result sets. */
 | |
| 
 | |
|     strmov(query, "CALL p1()");
 | |
|     stmt= mysql_simple_prepare(mysql, query);
 | |
|     check_stmt(stmt);
 | |
| 
 | |
|     /* Execute! */
 | |
| 
 | |
|     rc= mysql_stmt_execute(stmt);
 | |
|     check_execute(stmt, rc);
 | |
| 
 | |
|     /* Flush all the results. */
 | |
| 
 | |
|     mysql_stmt_close(stmt);
 | |
| 
 | |
|     /* Clean up. */
 | |
|     rc= mysql_commit(mysql);
 | |
|     myquery(rc);
 | |
| 
 | |
|     rc= mysql_query(mysql, "DROP PROCEDURE p1");
 | |
|     myquery(rc);
 | |
|   }
 | |
|   mct_close_log();
 | |
| }
 | |
| 
 | |
| 
 | |
| #define WL4435_TEST(sql_type, sql_value, \
 | |
|                     c_api_in_type, c_api_out_type, \
 | |
|                     c_type, c_type_ext, \
 | |
|                     printf_args, assert_condition) \
 | |
| \
 | |
|   do { \
 | |
|   int rc; \
 | |
|   MYSQL_STMT *ps; \
 | |
|   MYSQL_BIND psp; \
 | |
|   MYSQL_RES *rs_metadata; \
 | |
|   MYSQL_FIELD *fields; \
 | |
|   c_type pspv c_type_ext; \
 | |
|   my_bool psp_null= FALSE; \
 | |
|   \
 | |
|   bzero(&pspv, sizeof (pspv)); \
 | |
|   \
 | |
|   rc= mysql_query(mysql, "DROP PROCEDURE IF EXISTS p1"); \
 | |
|   myquery(rc); \
 | |
|   \
 | |
|   rc= mysql_query(mysql, \
 | |
|     "CREATE PROCEDURE p1(OUT v " sql_type ") SET v = " sql_value ";"); \
 | |
|   myquery(rc); \
 | |
|   \
 | |
|   ps = mysql_simple_prepare(mysql, "CALL p1(?)"); \
 | |
|   check_stmt(ps); \
 | |
|   \
 | |
|   bzero(&psp, sizeof (psp)); \
 | |
|   psp.buffer_type= c_api_in_type; \
 | |
|   psp.is_null= &psp_null; \
 | |
|   psp.buffer= (char *) &pspv; \
 | |
|   psp.buffer_length= sizeof (psp); \
 | |
|   \
 | |
|   rc= mysql_stmt_bind_param(ps, &psp); \
 | |
|   check_execute(ps, rc); \
 | |
|   \
 | |
|   rc= mysql_stmt_execute(ps); \
 | |
|   check_execute(ps, rc); \
 | |
|   \
 | |
|   DIE_UNLESS(mysql->server_status & SERVER_PS_OUT_PARAMS); \
 | |
|   DIE_UNLESS(mysql_stmt_field_count(ps) == 1); \
 | |
|   \
 | |
|   rs_metadata= mysql_stmt_result_metadata(ps); \
 | |
|   fields= mysql_fetch_fields(rs_metadata); \
 | |
|   mysql_free_result(rs_metadata);               \
 | |
|   \
 | |
|   rc= mysql_stmt_bind_result(ps, &psp); \
 | |
|   check_execute(ps, rc); \
 | |
|   \
 | |
|   rc= mysql_stmt_fetch(ps); \
 | |
|   DIE_UNLESS(rc == 0); \
 | |
|   \
 | |
|   DIE_UNLESS(fields[0].type == c_api_out_type); \
 | |
|   printf printf_args; \
 | |
|   printf("; in type: %d; out type: %d\n", \
 | |
|          (int) c_api_in_type, (int) c_api_out_type); \
 | |
|   \
 | |
|   rc= mysql_stmt_fetch(ps); \
 | |
|   DIE_UNLESS(rc == MYSQL_NO_DATA); \
 | |
|   \
 | |
|   rc= mysql_stmt_next_result(ps); \
 | |
|   DIE_UNLESS(rc == 0); \
 | |
|   \
 | |
|   mysql_stmt_free_result(ps); \
 | |
|   mysql_stmt_close(ps); \
 | |
|   \
 | |
|   DIE_UNLESS(assert_condition); \
 | |
|   \
 | |
|   } while (0)
 | |
| 
 | |
| static void test_wl4435_3()
 | |
| {
 | |
|   char tmp[255];
 | |
| 
 | |
|   memset(tmp, 0, sizeof tmp);
 | |
|   puts("");
 | |
| 
 | |
|   /*
 | |
|   // The following types are not supported:
 | |
|   //   - ENUM
 | |
|   //   - SET
 | |
|   //
 | |
|   // The following types are supported but can not be used for
 | |
|   // OUT-parameters:
 | |
|   //   - MEDIUMINT;
 | |
|   //   - BIT(..);
 | |
|   //
 | |
|   // The problem is that those types are not supported for IN-parameters,
 | |
|   // and OUT-parameters should be bound as IN-parameters before execution.
 | |
|   //
 | |
|   // The following types should not be used:
 | |
|   //   - MYSQL_TYPE_YEAR (use MYSQL_TYPE_SHORT instead);
 | |
|   //   - MYSQL_TYPE_TINY_BLOB, MYSQL_TYPE_MEDIUM_BLOB, MYSQL_TYPE_LONG_BLOB
 | |
|   //     (use MYSQL_TYPE_BLOB instead);
 | |
|   */
 | |
| 
 | |
|   WL4435_TEST("TINYINT", "127",
 | |
|               MYSQL_TYPE_TINY, MYSQL_TYPE_TINY,
 | |
|               char, ,
 | |
|               ("  - TINYINT / char / MYSQL_TYPE_TINY:\t\t\t %d", (int) pspv),
 | |
|               pspv == 127);
 | |
| 
 | |
|   WL4435_TEST("SMALLINT", "32767",
 | |
|               MYSQL_TYPE_SHORT, MYSQL_TYPE_SHORT,
 | |
|               short, ,
 | |
|               ("  - SMALLINT / short / MYSQL_TYPE_SHORT:\t\t %d", (int) pspv),
 | |
|               pspv == 32767);
 | |
| 
 | |
|   WL4435_TEST("INT", "2147483647",
 | |
|               MYSQL_TYPE_LONG, MYSQL_TYPE_LONG,
 | |
|               int, ,
 | |
|               ("  - INT / int / MYSQL_TYPE_LONG:\t\t\t %d", pspv),
 | |
|               pspv == 2147483647l);
 | |
| 
 | |
|   WL4435_TEST("BIGINT", "9223372036854775807",
 | |
|               MYSQL_TYPE_LONGLONG, MYSQL_TYPE_LONGLONG,
 | |
|               long long, ,
 | |
|               ("  - BIGINT / long long / MYSQL_TYPE_LONGLONG:\t\t %lld", pspv),
 | |
|               pspv == 9223372036854775807ll);
 | |
| 
 | |
|   WL4435_TEST("TIMESTAMP", "'2007-11-18 15:01:02'",
 | |
|               MYSQL_TYPE_TIMESTAMP, MYSQL_TYPE_TIMESTAMP,
 | |
|               MYSQL_TIME, ,
 | |
|               ("  - TIMESTAMP / MYSQL_TIME / MYSQL_TYPE_TIMESTAMP:\t "
 | |
|                "%.4d-%.2d-%.2d %.2d:%.2d:%.2d",
 | |
|                (int) pspv.year, (int) pspv.month, (int) pspv.day,
 | |
|                (int) pspv.hour, (int) pspv.minute, (int) pspv.second),
 | |
|               pspv.year == 2007 && pspv.month == 11 && pspv.day == 18 &&
 | |
|               pspv.hour == 15 && pspv.minute == 1 && pspv.second == 2);
 | |
| 
 | |
|   WL4435_TEST("DATETIME", "'1234-11-12 12:34:59'",
 | |
|               MYSQL_TYPE_DATETIME, MYSQL_TYPE_DATETIME,
 | |
|               MYSQL_TIME, ,
 | |
|               ("  - DATETIME / MYSQL_TIME / MYSQL_TYPE_DATETIME:\t "
 | |
|                "%.4d-%.2d-%.2d %.2d:%.2d:%.2d",
 | |
|                (int) pspv.year, (int) pspv.month, (int) pspv.day,
 | |
|                (int) pspv.hour, (int) pspv.minute, (int) pspv.second),
 | |
|               pspv.year == 1234 && pspv.month == 11 && pspv.day == 12 &&
 | |
|               pspv.hour == 12 && pspv.minute == 34 && pspv.second == 59);
 | |
| 
 | |
|   WL4435_TEST("TIME", "'123:45:01'",
 | |
|               MYSQL_TYPE_TIME, MYSQL_TYPE_TIME,
 | |
|               MYSQL_TIME, ,
 | |
|               ("  - TIME / MYSQL_TIME / MYSQL_TYPE_TIME:\t\t "
 | |
|                "%.3d:%.2d:%.2d",
 | |
|                (int) pspv.hour, (int) pspv.minute, (int) pspv.second),
 | |
|               pspv.hour == 123 && pspv.minute == 45 && pspv.second == 1);
 | |
| 
 | |
|   WL4435_TEST("DATE", "'1234-11-12'",
 | |
|               MYSQL_TYPE_DATE, MYSQL_TYPE_DATE,
 | |
|               MYSQL_TIME, ,
 | |
|               ("  - DATE / MYSQL_TIME / MYSQL_TYPE_DATE:\t\t "
 | |
|                "%.4d-%.2d-%.2d",
 | |
|                (int) pspv.year, (int) pspv.month, (int) pspv.day),
 | |
|               pspv.year == 1234 && pspv.month == 11 && pspv.day == 12);
 | |
| 
 | |
|   WL4435_TEST("YEAR", "'2010'",
 | |
|               MYSQL_TYPE_SHORT, MYSQL_TYPE_YEAR,
 | |
|               short, ,
 | |
|               ("  - YEAR / short / MYSQL_TYPE_SHORT:\t\t\t %.4d", (int) pspv),
 | |
|               pspv == 2010);
 | |
| 
 | |
|   WL4435_TEST("FLOAT(7, 4)", "123.4567",
 | |
|               MYSQL_TYPE_FLOAT, MYSQL_TYPE_FLOAT,
 | |
|               float, ,
 | |
|               ("  - FLOAT / float / MYSQL_TYPE_FLOAT:\t\t\t %g", (double) pspv),
 | |
|               pspv - 123.4567 < 0.0001);
 | |
| 
 | |
|   WL4435_TEST("DOUBLE(8, 5)", "123.45678",
 | |
|               MYSQL_TYPE_DOUBLE, MYSQL_TYPE_DOUBLE,
 | |
|               double, ,
 | |
|               ("  - DOUBLE / double / MYSQL_TYPE_DOUBLE:\t\t %g", (double) pspv),
 | |
|               pspv - 123.45678 < 0.00001);
 | |
| 
 | |
|   WL4435_TEST("DECIMAL(9, 6)", "123.456789",
 | |
|               MYSQL_TYPE_NEWDECIMAL, MYSQL_TYPE_NEWDECIMAL,
 | |
|               char, [255],
 | |
|               ("  - DECIMAL / char[] / MYSQL_TYPE_NEWDECIMAL:\t\t '%s'", (char *) pspv),
 | |
|               !strcmp(pspv, "123.456789"));
 | |
| 
 | |
|   WL4435_TEST("CHAR(32)", "REPEAT('C', 16)",
 | |
|               MYSQL_TYPE_STRING, MYSQL_TYPE_STRING,
 | |
|               char, [255],
 | |
|               ("  - CHAR(32) / char[] / MYSQL_TYPE_STRING:\t\t '%s'", (char *) pspv),
 | |
|               !strcmp(pspv, "CCCCCCCCCCCCCCCC"));
 | |
| 
 | |
|   WL4435_TEST("VARCHAR(32)", "REPEAT('V', 16)",
 | |
|               MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_VAR_STRING,
 | |
|               char, [255],
 | |
|               ("  - VARCHAR(32) / char[] / MYSQL_TYPE_VAR_STRING:\t '%s'", (char *) pspv),
 | |
|               !strcmp(pspv, "VVVVVVVVVVVVVVVV"));
 | |
| 
 | |
|   WL4435_TEST("TINYTEXT", "REPEAT('t', 16)",
 | |
|               MYSQL_TYPE_TINY_BLOB, MYSQL_TYPE_BLOB,
 | |
|               char, [255],
 | |
|               ("  - TINYTEXT / char[] / MYSQL_TYPE_TINY_BLOB:\t\t '%s'", (char *) pspv),
 | |
|               !strcmp(pspv, "tttttttttttttttt"));
 | |
| 
 | |
|   WL4435_TEST("TEXT", "REPEAT('t', 16)",
 | |
|               MYSQL_TYPE_BLOB, MYSQL_TYPE_BLOB,
 | |
|               char, [255],
 | |
|               ("  - TEXT / char[] / MYSQL_TYPE_BLOB:\t\t\t '%s'", (char *) pspv),
 | |
|               !strcmp(pspv, "tttttttttttttttt"));
 | |
| 
 | |
|   WL4435_TEST("MEDIUMTEXT", "REPEAT('t', 16)",
 | |
|               MYSQL_TYPE_MEDIUM_BLOB, MYSQL_TYPE_BLOB,
 | |
|               char, [255],
 | |
|               ("  - MEDIUMTEXT / char[] / MYSQL_TYPE_MEDIUM_BLOB:\t '%s'", (char *) pspv),
 | |
|               !strcmp(pspv, "tttttttttttttttt"));
 | |
| 
 | |
|   WL4435_TEST("LONGTEXT", "REPEAT('t', 16)",
 | |
|               MYSQL_TYPE_LONG_BLOB, MYSQL_TYPE_BLOB,
 | |
|               char, [255],
 | |
|               ("  - LONGTEXT / char[] / MYSQL_TYPE_LONG_BLOB:\t\t '%s'", (char *) pspv),
 | |
|               !strcmp(pspv, "tttttttttttttttt"));
 | |
| 
 | |
|   WL4435_TEST("BINARY(32)", "REPEAT('\1', 16)",
 | |
|               MYSQL_TYPE_STRING, MYSQL_TYPE_STRING,
 | |
|               char, [255],
 | |
|               ("  - BINARY(32) / char[] / MYSQL_TYPE_STRING:\t\t '%s'", (char *) pspv),
 | |
|               memset(tmp, 1, 16) && !memcmp(tmp, pspv, 16));
 | |
| 
 | |
|   WL4435_TEST("VARBINARY(32)", "REPEAT('\1', 16)",
 | |
|               MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_VAR_STRING,
 | |
|               char, [255],
 | |
|               ("  - VARBINARY(32) / char[] / MYSQL_TYPE_VAR_STRING:\t '%s'", (char *) pspv),
 | |
|               memset(tmp, 1, 16) && !memcmp(tmp, pspv, 16));
 | |
| 
 | |
|   WL4435_TEST("TINYBLOB", "REPEAT('\2', 16)",
 | |
|               MYSQL_TYPE_TINY_BLOB, MYSQL_TYPE_BLOB,
 | |
|               char, [255],
 | |
|               ("  - TINYBLOB / char[] / MYSQL_TYPE_TINY_BLOB:\t\t '%s'", (char *) pspv),
 | |
|               memset(tmp, 2, 16) && !memcmp(tmp, pspv, 16));
 | |
| 
 | |
|   WL4435_TEST("BLOB", "REPEAT('\2', 16)",
 | |
|               MYSQL_TYPE_BLOB, MYSQL_TYPE_BLOB,
 | |
|               char, [255],
 | |
|               ("  - BLOB / char[] / MYSQL_TYPE_BLOB:\t\t\t '%s'", (char *) pspv),
 | |
|               memset(tmp, 2, 16) && !memcmp(tmp, pspv, 16));
 | |
| 
 | |
|   WL4435_TEST("MEDIUMBLOB", "REPEAT('\2', 16)",
 | |
|               MYSQL_TYPE_MEDIUM_BLOB, MYSQL_TYPE_BLOB,
 | |
|               char, [255],
 | |
|               ("  - MEDIUMBLOB / char[] / MYSQL_TYPE_MEDIUM_BLOB:\t '%s'", (char *) pspv),
 | |
|               memset(tmp, 2, 16) && !memcmp(tmp, pspv, 16));
 | |
| 
 | |
|   WL4435_TEST("LONGBLOB", "REPEAT('\2', 16)",
 | |
|               MYSQL_TYPE_LONG_BLOB, MYSQL_TYPE_BLOB,
 | |
|               char, [255],
 | |
|               ("  - LONGBLOB / char[] / MYSQL_TYPE_LONG_BLOB:\t\t '%s'", (char *) pspv),
 | |
|               memset(tmp, 2, 16) && !memcmp(tmp, pspv, 16));
 | |
| }
 | |
| 
 | |
| 
 | |
| /* Test simple prepare field results */
 | |
| 
 | |
| static void test_prepare_field_result()
 | |
| {
 | |
|   MYSQL_STMT *stmt;
 | |
|   MYSQL_RES  *result;
 | |
|   int        rc;
 | |
|   char query[MAX_TEST_QUERY_LENGTH];
 | |
| 
 | |
|   myheader("test_prepare_field_result");
 | |
| 
 | |
|   rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_prepare_field_result");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "CREATE TABLE test_prepare_field_result(int_c int, "
 | |
|                          "var_c varchar(50), ts_c timestamp, "
 | |
|                          "char_c char(4), date_c date, extra tinyint)");
 | |
|   myquery(rc);
 | |
| 
 | |
|   /* insert */
 | |
|   strmov(query, "SELECT int_c, var_c, date_c as date, ts_c, char_c FROM "
 | |
|                 " test_prepare_field_result as t1 WHERE int_c=?");
 | |
|   stmt= mysql_simple_prepare(mysql, query);
 | |
|   check_stmt(stmt);
 | |
| 
 | |
|   verify_param_count(stmt, 1);
 | |
| 
 | |
|   result= mysql_stmt_result_metadata(stmt);
 | |
|   mytest(result);
 | |
| 
 | |
|   my_print_result_metadata(result);
 | |
| 
 | |
|   if (!opt_silent)
 | |
|     fprintf(stdout, "\n\n field attributes:\n");
 | |
|   verify_prepare_field(result, 0, "int_c", "int_c", MYSQL_TYPE_LONG,
 | |
|                        "t1", "test_prepare_field_result", current_db, 11, 0);
 | |
|   verify_prepare_field(result, 1, "var_c", "var_c", MYSQL_TYPE_VAR_STRING,
 | |
|                        "t1", "test_prepare_field_result", current_db, 50, 0);
 | |
|   verify_prepare_field(result, 2, "date", "date_c", MYSQL_TYPE_DATE,
 | |
|                        "t1", "test_prepare_field_result", current_db, 10, 0);
 | |
|   verify_prepare_field(result, 3, "ts_c", "ts_c", MYSQL_TYPE_TIMESTAMP,
 | |
|                        "t1", "test_prepare_field_result", current_db, 19, 0);
 | |
|   verify_prepare_field(result, 4, "char_c", "char_c",
 | |
|                        (mysql_get_server_version(mysql) <= 50000 ?
 | |
|                         MYSQL_TYPE_VAR_STRING : MYSQL_TYPE_STRING),
 | |
|                        "t1", "test_prepare_field_result", current_db, 4, 0);
 | |
| 
 | |
|   verify_field_count(result, 5);
 | |
|   mysql_free_result(result);
 | |
|   mysql_stmt_close(stmt);
 | |
| }
 | |
| 
 | |
| 
 | |
| /* Test simple prepare field results */
 | |
| 
 | |
| static void test_prepare_syntax()
 | |
| {
 | |
|   MYSQL_STMT *stmt;
 | |
|   int        rc;
 | |
|   char query[MAX_TEST_QUERY_LENGTH];
 | |
| 
 | |
|   myheader("test_prepare_syntax");
 | |
| 
 | |
|   rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_prepare_syntax");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "CREATE TABLE test_prepare_syntax("
 | |
|                          "id int, name varchar(50), extra int)");
 | |
|   myquery(rc);
 | |
| 
 | |
|   strmov(query, "INSERT INTO test_prepare_syntax VALUES(?");
 | |
|   stmt= mysql_simple_prepare(mysql, query);
 | |
|   check_stmt_r(stmt);
 | |
| 
 | |
|   strmov(query, "SELECT id, name FROM test_prepare_syntax WHERE id=? AND WHERE");
 | |
|   stmt= mysql_simple_prepare(mysql, query);
 | |
|   check_stmt_r(stmt);
 | |
| 
 | |
|   /* now fetch the results ..*/
 | |
|   rc= mysql_commit(mysql);
 | |
|   myquery(rc);
 | |
| }
 | |
| 
 | |
| 
 | |
| /* Test a simple prepare */
 | |
| 
 | |
| static void test_prepare()
 | |
| {
 | |
|   MYSQL_STMT *stmt;
 | |
|   int        rc, i;
 | |
|   int        int_data, o_int_data;
 | |
|   char       str_data[50], data[50];
 | |
|   char       tiny_data, o_tiny_data;
 | |
|   short      small_data, o_small_data;
 | |
|   longlong   big_data, o_big_data;
 | |
|   float      real_data, o_real_data;
 | |
|   double     double_data, o_double_data;
 | |
|   ulong      length[7], len;
 | |
|   my_bool    is_null[7];
 | |
|   char	     llbuf[22];
 | |
|   MYSQL_BIND my_bind[7];
 | |
|   char query[MAX_TEST_QUERY_LENGTH];
 | |
| 
 | |
|   myheader("test_prepare");
 | |
| 
 | |
|   rc= mysql_autocommit(mysql, TRUE);
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "DROP TABLE IF EXISTS my_prepare");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "CREATE TABLE my_prepare(col1 tinyint, "
 | |
|                          "col2 varchar(15), col3 int, "
 | |
|                          "col4 smallint, col5 bigint, "
 | |
|                          "col6 float, col7 double )");
 | |
|   myquery(rc);
 | |
| 
 | |
|   /* insert by prepare */
 | |
|   strxmov(query, "INSERT INTO my_prepare VALUES(?, ?, ?, ?, ?, ?, ?)", NullS);
 | |
|   stmt= mysql_simple_prepare(mysql, query);
 | |
|   check_stmt(stmt);
 | |
| 
 | |
|   verify_param_count(stmt, 7);
 | |
| 
 | |
|   bzero((char*) my_bind, sizeof(my_bind));
 | |
| 
 | |
|   /* tinyint */
 | |
|   my_bind[0].buffer_type= MYSQL_TYPE_TINY;
 | |
|   my_bind[0].buffer= (void *)&tiny_data;
 | |
|   /* string */
 | |
|   my_bind[1].buffer_type= MYSQL_TYPE_STRING;
 | |
|   my_bind[1].buffer= (void *)str_data;
 | |
|   my_bind[1].buffer_length= 1000;                  /* Max string length */
 | |
|   /* integer */
 | |
|   my_bind[2].buffer_type= MYSQL_TYPE_LONG;
 | |
|   my_bind[2].buffer= (void *)&int_data;
 | |
|   /* short */
 | |
|   my_bind[3].buffer_type= MYSQL_TYPE_SHORT;
 | |
|   my_bind[3].buffer= (void *)&small_data;
 | |
|   /* bigint */
 | |
|   my_bind[4].buffer_type= MYSQL_TYPE_LONGLONG;
 | |
|   my_bind[4].buffer= (void *)&big_data;
 | |
|   /* float */
 | |
|   my_bind[5].buffer_type= MYSQL_TYPE_FLOAT;
 | |
|   my_bind[5].buffer= (void *)&real_data;
 | |
|   /* double */
 | |
|   my_bind[6].buffer_type= MYSQL_TYPE_DOUBLE;
 | |
|   my_bind[6].buffer= (void *)&double_data;
 | |
| 
 | |
|   for (i= 0; i < (int) array_elements(my_bind); i++)
 | |
|   {
 | |
|     my_bind[i].length= &length[i];
 | |
|     my_bind[i].is_null= &is_null[i];
 | |
|     is_null[i]= 0;
 | |
|   }
 | |
| 
 | |
|   rc= mysql_stmt_bind_param(stmt, my_bind);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   int_data= 320;
 | |
|   small_data= 1867;
 | |
|   big_data= 1000;
 | |
|   real_data= 2;
 | |
|   double_data= 6578.001;
 | |
| 
 | |
|   /* now, execute the prepared statement to insert 10 records.. */
 | |
|   for (tiny_data= 0; tiny_data < 100; tiny_data++)
 | |
|   {
 | |
|     length[1]= sprintf(str_data, "MySQL%d", int_data);
 | |
|     rc= mysql_stmt_execute(stmt);
 | |
|     check_execute(stmt, rc);
 | |
|     int_data += 25;
 | |
|     small_data += 10;
 | |
|     big_data += 100;
 | |
|     real_data += 1;
 | |
|     double_data += 10.09;
 | |
|   }
 | |
| 
 | |
|   mysql_stmt_close(stmt);
 | |
| 
 | |
|   /* now fetch the results ..*/
 | |
|   rc= mysql_commit(mysql);
 | |
|   myquery(rc);
 | |
| 
 | |
|   /* test the results now, only one row should exist */
 | |
|   rc= my_stmt_result("SELECT * FROM my_prepare");
 | |
|   DIE_UNLESS(tiny_data == (char) rc);
 | |
| 
 | |
|   stmt= mysql_simple_prepare(mysql, "SELECT * FROM my_prepare");
 | |
|   check_stmt(stmt);
 | |
| 
 | |
|   rc= mysql_stmt_bind_result(stmt, my_bind);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   /* get the result */
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   o_int_data= 320;
 | |
|   o_small_data= 1867;
 | |
|   o_big_data= 1000;
 | |
|   o_real_data= 2;
 | |
|   o_double_data= 6578.001;
 | |
| 
 | |
|   /* now, execute the prepared statement to insert 10 records.. */
 | |
|   for (o_tiny_data= 0; o_tiny_data < 100; o_tiny_data++)
 | |
|   {
 | |
|     len= sprintf(data, "MySQL%d", o_int_data);
 | |
| 
 | |
|     rc= mysql_stmt_fetch(stmt);
 | |
|     check_execute(stmt, rc);
 | |
| 
 | |
|     if (!opt_silent)
 | |
|     {
 | |
|       fprintf(stdout, "\n");
 | |
|       fprintf(stdout, "\n\t tiny   : %d (%lu)", tiny_data, length[0]);
 | |
|       fprintf(stdout, "\n\t short  : %d (%lu)", small_data, length[3]);
 | |
|       fprintf(stdout, "\n\t int    : %d (%lu)", int_data, length[2]);
 | |
|       fprintf(stdout, "\n\t big    : %s (%lu)", llstr(big_data, llbuf),
 | |
|               length[4]);
 | |
| 
 | |
|       fprintf(stdout, "\n\t float  : %f (%lu)", real_data, length[5]);
 | |
|       fprintf(stdout, "\n\t double : %f (%lu)", double_data, length[6]);
 | |
| 
 | |
|       fprintf(stdout, "\n\t str    : %s (%lu)", str_data, length[1]);
 | |
|     }
 | |
| 
 | |
|     DIE_UNLESS(tiny_data == o_tiny_data);
 | |
|     DIE_UNLESS(is_null[0] == 0);
 | |
|     DIE_UNLESS(length[0] == 1);
 | |
| 
 | |
|     DIE_UNLESS(int_data == o_int_data);
 | |
|     DIE_UNLESS(length[2] == 4);
 | |
| 
 | |
|     DIE_UNLESS(small_data == o_small_data);
 | |
|     DIE_UNLESS(length[3] == 2);
 | |
| 
 | |
|     DIE_UNLESS(big_data == o_big_data);
 | |
|     DIE_UNLESS(length[4] == 8);
 | |
| 
 | |
|     DIE_UNLESS(real_data == o_real_data);
 | |
|     DIE_UNLESS(length[5] == 4);
 | |
| 
 | |
|     DIE_UNLESS(cmp_double(&double_data, &o_double_data));
 | |
|     DIE_UNLESS(length[6] == 8);
 | |
| 
 | |
|     DIE_UNLESS(strcmp(data, str_data) == 0);
 | |
|     DIE_UNLESS(length[1] == len);
 | |
| 
 | |
|     o_int_data += 25;
 | |
|     o_small_data += 10;
 | |
|     o_big_data += 100;
 | |
|     o_real_data += 1;
 | |
|     o_double_data += 10.09;
 | |
|   }
 | |
| 
 | |
|   rc= mysql_stmt_fetch(stmt);
 | |
|   DIE_UNLESS(rc == MYSQL_NO_DATA);
 | |
| 
 | |
|   mysql_stmt_close(stmt);
 | |
| 
 | |
| }
 | |
| 
 | |
| 
 | |
| /* Test double comparision */
 | |
| 
 | |
| static void test_double_compare()
 | |
| {
 | |
|   MYSQL_STMT *stmt;
 | |
|   int        rc;
 | |
|   char       real_data[10], tiny_data;
 | |
|   double     double_data;
 | |
|   MYSQL_RES  *result;
 | |
|   MYSQL_BIND my_bind[3];
 | |
|   ulong      length[3];
 | |
|   char query[MAX_TEST_QUERY_LENGTH];
 | |
| 
 | |
|   myheader("test_double_compare");
 | |
| 
 | |
|   rc= mysql_autocommit(mysql, TRUE);
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_double_compare");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "CREATE TABLE test_double_compare(col1 tinyint, "
 | |
|                          " col2 float, col3 double )");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "INSERT INTO test_double_compare "
 | |
|                          "VALUES (1, 10.2, 34.5)");
 | |
|   myquery(rc);
 | |
| 
 | |
|   strmov(query, "UPDATE test_double_compare SET col1=100 "
 | |
|                 "WHERE col1 = ? AND col2 = ? AND COL3 = ?");
 | |
|   stmt= mysql_simple_prepare(mysql, query);
 | |
|   check_stmt(stmt);
 | |
| 
 | |
|   verify_param_count(stmt, 3);
 | |
| 
 | |
|   /* Always bzero bind array because there can be internal members */
 | |
|   bzero((char*) my_bind, sizeof(my_bind));
 | |
| 
 | |
|   /* tinyint */
 | |
|   my_bind[0].buffer_type= MYSQL_TYPE_TINY;
 | |
|   my_bind[0].buffer= (void *)&tiny_data;
 | |
| 
 | |
|   /* string->float */
 | |
|   my_bind[1].buffer_type= MYSQL_TYPE_STRING;
 | |
|   my_bind[1].buffer= (void *)&real_data;
 | |
|   my_bind[1].buffer_length= sizeof(real_data);
 | |
|   my_bind[1].length= &length[1];
 | |
|   length[1]= 10;
 | |
| 
 | |
|   /* double */
 | |
|   my_bind[2].buffer_type= MYSQL_TYPE_DOUBLE;
 | |
|   my_bind[2].buffer= (void *)&double_data;
 | |
| 
 | |
|   tiny_data= 1;
 | |
|   memset(real_data, 0, sizeof real_data);
 | |
|   strmov(real_data, "10.2");
 | |
|   double_data= 34.5;
 | |
|   rc= mysql_stmt_bind_param(stmt, my_bind);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   verify_affected_rows(0);
 | |
| 
 | |
|   mysql_stmt_close(stmt);
 | |
| 
 | |
|   /* now fetch the results ..*/
 | |
|   rc= mysql_commit(mysql);
 | |
|   myquery(rc);
 | |
| 
 | |
|   /* test the results now, only one row should exist */
 | |
|   rc= mysql_query(mysql, "SELECT * FROM test_double_compare");
 | |
|   myquery(rc);
 | |
| 
 | |
|   /* get the result */
 | |
|   result= mysql_store_result(mysql);
 | |
|   mytest(result);
 | |
| 
 | |
|   rc= my_process_result_set(result);
 | |
|   DIE_UNLESS((int)tiny_data == rc);
 | |
|   mysql_free_result(result);
 | |
| }
 | |
| 
 | |
| 
 | |
| /* Test simple null */
 | |
| 
 | |
| static void test_null()
 | |
| {
 | |
|   MYSQL_STMT *stmt;
 | |
|   int        rc;
 | |
|   uint       nData;
 | |
|   MYSQL_BIND my_bind[2];
 | |
|   my_bool    is_null[2];
 | |
|   char query[MAX_TEST_QUERY_LENGTH];
 | |
| 
 | |
|   myheader("test_null");
 | |
| 
 | |
|   rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_null");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "CREATE TABLE test_null(col1 int, col2 varchar(50))");
 | |
|   myquery(rc);
 | |
| 
 | |
|   /* insert by prepare, wrong column name */
 | |
|   strmov(query, "INSERT INTO test_null(col3, col2) VALUES(?, ?)");
 | |
|   stmt= mysql_simple_prepare(mysql, query);
 | |
|   check_stmt_r(stmt);
 | |
| 
 | |
|   strmov(query, "INSERT INTO test_null(col1, col2) VALUES(?, ?)");
 | |
|   stmt= mysql_simple_prepare(mysql, query);
 | |
|   check_stmt(stmt);
 | |
| 
 | |
|   verify_param_count(stmt, 2);
 | |
| 
 | |
|   /* Always bzero all members of bind parameter */
 | |
|   bzero((char*) my_bind, sizeof(my_bind));
 | |
| 
 | |
|   my_bind[0].buffer_type= MYSQL_TYPE_LONG;
 | |
|   my_bind[0].is_null= &is_null[0];
 | |
|   is_null[0]= 1;
 | |
|   my_bind[1]= my_bind[0];
 | |
| 
 | |
|   rc= mysql_stmt_bind_param(stmt, my_bind);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   /* now, execute the prepared statement to insert 10 records.. */
 | |
|   for (nData= 0; nData<10; nData++)
 | |
|   {
 | |
|     rc= mysql_stmt_execute(stmt);
 | |
|     check_execute(stmt, rc);
 | |
|   }
 | |
| 
 | |
|   /* Re-bind with MYSQL_TYPE_NULL */
 | |
|   my_bind[0].buffer_type= MYSQL_TYPE_NULL;
 | |
|   is_null[0]= 0; /* reset */
 | |
|   my_bind[1]= my_bind[0];
 | |
| 
 | |
|   rc= mysql_stmt_bind_param(stmt, my_bind);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   for (nData= 0; nData<10; nData++)
 | |
|   {
 | |
|     rc= mysql_stmt_execute(stmt);
 | |
|     check_execute(stmt, rc);
 | |
|   }
 | |
| 
 | |
|   mysql_stmt_close(stmt);
 | |
| 
 | |
|   /* now fetch the results ..*/
 | |
|   rc= mysql_commit(mysql);
 | |
|   myquery(rc);
 | |
| 
 | |
|   nData*= 2;
 | |
|   rc= my_stmt_result("SELECT * FROM test_null");;
 | |
|   DIE_UNLESS((int) nData == rc);
 | |
| 
 | |
|   /* Fetch results */
 | |
|   my_bind[0].buffer_type= MYSQL_TYPE_LONG;
 | |
|   my_bind[0].buffer= (void *)&nData; /* this buffer won't be altered */
 | |
|   my_bind[0].length= 0;
 | |
|   my_bind[1]= my_bind[0];
 | |
|   my_bind[0].is_null= &is_null[0];
 | |
|   my_bind[1].is_null= &is_null[1];
 | |
| 
 | |
|   stmt= mysql_simple_prepare(mysql, "SELECT * FROM test_null");
 | |
|   check_stmt(stmt);
 | |
| 
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= mysql_stmt_bind_result(stmt, my_bind);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= 0;
 | |
|   is_null[0]= is_null[1]= 0;
 | |
|   while (mysql_stmt_fetch(stmt) != MYSQL_NO_DATA)
 | |
|   {
 | |
|     DIE_UNLESS(is_null[0]);
 | |
|     DIE_UNLESS(is_null[1]);
 | |
|     rc++;
 | |
|     is_null[0]= is_null[1]= 0;
 | |
|   }
 | |
|   DIE_UNLESS(rc == (int) nData);
 | |
|   mysql_stmt_close(stmt);
 | |
| }
 | |
| 
 | |
| 
 | |
| /* Test for NULL as PS parameter (BUG#3367, BUG#3371) */
 | |
| 
 | |
| static void test_ps_null_param()
 | |
| {
 | |
|   MYSQL_STMT *stmt;
 | |
|   int        rc;
 | |
| 
 | |
|   MYSQL_BIND in_bind;
 | |
|   my_bool    in_is_null;
 | |
|   long int   in_long;
 | |
| 
 | |
|   MYSQL_BIND out_bind;
 | |
|   ulong      out_length;
 | |
|   my_bool    out_is_null;
 | |
|   char       out_str_data[20];
 | |
| 
 | |
|   const char *queries[]= {"select ?", "select ?+1",
 | |
|                     "select col1 from test_ps_nulls where col1 <=> ?",
 | |
|                     NULL
 | |
|                     };
 | |
|   const char **cur_query= queries;
 | |
| 
 | |
|   myheader("test_null_ps_param_in_result");
 | |
| 
 | |
|   rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_ps_nulls");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "CREATE TABLE test_ps_nulls(col1 int)");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "INSERT INTO test_ps_nulls values (1), (null)");
 | |
|   myquery(rc);
 | |
| 
 | |
|   /* Always bzero all members of bind parameter */
 | |
|   bzero((char*) &in_bind, sizeof(in_bind));
 | |
|   bzero((char*) &out_bind, sizeof(out_bind));
 | |
| 
 | |
|   in_bind.buffer_type= MYSQL_TYPE_LONG;
 | |
|   in_bind.is_null= &in_is_null;
 | |
|   in_bind.length= 0;
 | |
|   in_bind.buffer= (void *)&in_long;
 | |
|   in_is_null= 1;
 | |
|   in_long= 1;
 | |
| 
 | |
|   out_bind.buffer_type= MYSQL_TYPE_STRING;
 | |
|   out_bind.is_null= &out_is_null;
 | |
|   out_bind.length= &out_length;
 | |
|   out_bind.buffer= out_str_data;
 | |
|   out_bind.buffer_length= array_elements(out_str_data);
 | |
| 
 | |
|   /* Execute several queries, all returning NULL in result. */
 | |
|   for(cur_query= queries; *cur_query; cur_query++)
 | |
|   {
 | |
|     char query[MAX_TEST_QUERY_LENGTH];
 | |
|     strmov(query, *cur_query);
 | |
|     stmt= mysql_simple_prepare(mysql, query);
 | |
|     check_stmt(stmt);
 | |
|     verify_param_count(stmt, 1);
 | |
| 
 | |
|     rc= mysql_stmt_bind_param(stmt, &in_bind);
 | |
|     check_execute(stmt, rc);
 | |
|     rc= mysql_stmt_bind_result(stmt, &out_bind);
 | |
|     check_execute(stmt, rc);
 | |
|     rc= mysql_stmt_execute(stmt);
 | |
|     check_execute(stmt, rc);
 | |
|     rc= mysql_stmt_fetch(stmt);
 | |
|     DIE_UNLESS(rc != MYSQL_NO_DATA);
 | |
|     DIE_UNLESS(out_is_null);
 | |
|     rc= mysql_stmt_fetch(stmt);
 | |
|     DIE_UNLESS(rc == MYSQL_NO_DATA);
 | |
|     mysql_stmt_close(stmt);
 | |
|   }
 | |
| }
 | |
| 
 | |
| 
 | |
| /* Test fetch null */
 | |
| 
 | |
| static void test_fetch_null()
 | |
| {
 | |
|   MYSQL_STMT *stmt;
 | |
|   int        rc;
 | |
|   int        i, nData;
 | |
|   MYSQL_BIND my_bind[11];
 | |
|   ulong      length[11];
 | |
|   my_bool    is_null[11];
 | |
|   char query[MAX_TEST_QUERY_LENGTH];
 | |
| 
 | |
|   myheader("test_fetch_null");
 | |
| 
 | |
|   rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_fetch_null");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "CREATE TABLE test_fetch_null("
 | |
|                          " col1 tinyint, col2 smallint, "
 | |
|                          " col3 int, col4 bigint, "
 | |
|                          " col5 float, col6 double, "
 | |
|                          " col7 date, col8 time, "
 | |
|                          " col9 varbinary(10), "
 | |
|                          " col10 varchar(50), "
 | |
|                          " col11 char(20))");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "INSERT INTO test_fetch_null (col11) "
 | |
|                          "VALUES (1000), (88), (389789)");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_commit(mysql);
 | |
|   myquery(rc);
 | |
| 
 | |
|   /* fetch */
 | |
|   bzero((char*) my_bind, sizeof(my_bind));
 | |
|   for (i= 0; i < (int) array_elements(my_bind); i++)
 | |
|   {
 | |
|     my_bind[i].buffer_type= MYSQL_TYPE_LONG;
 | |
|     my_bind[i].is_null= &is_null[i];
 | |
|     my_bind[i].length= &length[i];
 | |
|   }
 | |
|   my_bind[i-1].buffer= (void *)&nData;              /* Last column is not null */
 | |
| 
 | |
|   strmov((char *)query , "SELECT * FROM test_fetch_null");
 | |
| 
 | |
|   rc= my_stmt_result(query);
 | |
|   DIE_UNLESS(rc == 3);
 | |
| 
 | |
|   stmt= mysql_simple_prepare(mysql, query);
 | |
|   check_stmt(stmt);
 | |
| 
 | |
|   rc= mysql_stmt_bind_result(stmt, my_bind);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= 0;
 | |
|   while (mysql_stmt_fetch(stmt) != MYSQL_NO_DATA)
 | |
|   {
 | |
|     rc++;
 | |
|     for (i= 0; i < 10; i++)
 | |
|     {
 | |
|       if (!opt_silent)
 | |
|         fprintf(stdout, "\n data[%d] : %s", i,
 | |
|                 is_null[i] ? "NULL" : "NOT NULL");
 | |
|       DIE_UNLESS(is_null[i]);
 | |
|     }
 | |
|     if (!opt_silent)
 | |
|       fprintf(stdout, "\n data[%d]: %d", i, nData);
 | |
|     DIE_UNLESS(nData == 1000 || nData == 88 || nData == 389789);
 | |
|     DIE_UNLESS(is_null[i] == 0);
 | |
|     DIE_UNLESS(length[i] == 4);
 | |
|   }
 | |
|   DIE_UNLESS(rc == 3);
 | |
|   mysql_stmt_close(stmt);
 | |
| }
 | |
| 
 | |
| 
 | |
| /* Test simple select */
 | |
| 
 | |
| static void test_select_version()
 | |
| {
 | |
|   MYSQL_STMT *stmt;
 | |
|   int        rc;
 | |
| 
 | |
|   myheader("test_select_version");
 | |
| 
 | |
|   stmt= mysql_simple_prepare(mysql, "SELECT @@version");
 | |
|   check_stmt(stmt);
 | |
| 
 | |
|   verify_param_count(stmt, 0);
 | |
| 
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   my_process_stmt_result(stmt);
 | |
|   mysql_stmt_close(stmt);
 | |
| }
 | |
| 
 | |
| 
 | |
| /* Test simple show */
 | |
| 
 | |
| static void test_select_show_table()
 | |
| {
 | |
|   MYSQL_STMT *stmt;
 | |
|   int        rc, i;
 | |
| 
 | |
|   myheader("test_select_show_table");
 | |
| 
 | |
|   stmt= mysql_simple_prepare(mysql, "SHOW TABLES FROM mysql");
 | |
|   check_stmt(stmt);
 | |
| 
 | |
|   verify_param_count(stmt, 0);
 | |
| 
 | |
|   for (i= 1; i < 3; i++)
 | |
|   {
 | |
|     rc= mysql_stmt_execute(stmt);
 | |
|     check_execute(stmt, rc);
 | |
|   }
 | |
| 
 | |
|   my_process_stmt_result(stmt);
 | |
|   mysql_stmt_close(stmt);
 | |
| }
 | |
| 
 | |
| 
 | |
| /* Test simple select to debug */
 | |
| 
 | |
| static void test_select_direct()
 | |
| {
 | |
|   int        rc;
 | |
|   MYSQL_RES  *result;
 | |
| 
 | |
|   myheader("test_select_direct");
 | |
| 
 | |
|   rc= mysql_autocommit(mysql, TRUE);
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_select");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "CREATE TABLE test_select(id int, id1 tinyint, "
 | |
|                                                  " id2 float, "
 | |
|                                                  " id3 double, "
 | |
|                                                  " name varchar(50))");
 | |
|   myquery(rc);
 | |
| 
 | |
|   /* insert a row and commit the transaction */
 | |
|   rc= mysql_query(mysql, "INSERT INTO test_select VALUES(10, 5, 2.3, 4.5, 'venu')");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_commit(mysql);
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "SELECT * FROM test_select");
 | |
|   myquery(rc);
 | |
| 
 | |
|   /* get the result */
 | |
|   result= mysql_store_result(mysql);
 | |
|   mytest(result);
 | |
| 
 | |
|   (void) my_process_result_set(result);
 | |
|   mysql_free_result(result);
 | |
| }
 | |
| 
 | |
| 
 | |
| /* Test simple select with prepare */
 | |
| 
 | |
| static void test_select_prepare()
 | |
| {
 | |
|   int        rc;
 | |
|   MYSQL_STMT *stmt;
 | |
| 
 | |
|   myheader("test_select_prepare");
 | |
| 
 | |
|   rc= mysql_autocommit(mysql, TRUE);
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_select");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "CREATE TABLE test_select(id int, name varchar(50))");
 | |
|   myquery(rc);
 | |
| 
 | |
|   /* insert a row and commit the transaction */
 | |
|   rc= mysql_query(mysql, "INSERT INTO test_select VALUES(10, 'venu')");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_commit(mysql);
 | |
|   myquery(rc);
 | |
| 
 | |
|   stmt= mysql_simple_prepare(mysql, "SELECT * FROM test_select");
 | |
|   check_stmt(stmt);
 | |
| 
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= my_process_stmt_result(stmt);
 | |
|   DIE_UNLESS(rc == 1);
 | |
|   mysql_stmt_close(stmt);
 | |
| 
 | |
|   rc= mysql_query(mysql, "DROP TABLE test_select");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "CREATE TABLE test_select(id tinyint, id1 int, "
 | |
|                                                 "  id2 float, id3 float, "
 | |
|                                                 "  name varchar(50))");
 | |
|   myquery(rc);
 | |
| 
 | |
|   /* insert a row and commit the transaction */
 | |
|   rc= mysql_query(mysql, "INSERT INTO test_select(id, id1, id2, name) VALUES(10, 5, 2.3, 'venu')");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_commit(mysql);
 | |
|   myquery(rc);
 | |
| 
 | |
|   stmt= mysql_simple_prepare(mysql, "SELECT * FROM test_select");
 | |
|   check_stmt(stmt);
 | |
| 
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= my_process_stmt_result(stmt);
 | |
|   DIE_UNLESS(rc == 1);
 | |
|   mysql_stmt_close(stmt);
 | |
| }
 | |
| 
 | |
| 
 | |
| /* Test simple select */
 | |
| 
 | |
| static void test_select()
 | |
| {
 | |
|   MYSQL_STMT *stmt;
 | |
|   int        rc;
 | |
|   char       szData[25];
 | |
|   int        nData= 1;
 | |
|   MYSQL_BIND my_bind[2];
 | |
|   ulong length[2];
 | |
|   char query[MAX_TEST_QUERY_LENGTH];
 | |
| 
 | |
|   myheader("test_select");
 | |
| 
 | |
|   rc= mysql_autocommit(mysql, TRUE);
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_select");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "CREATE TABLE test_select(id int, name varchar(50))");
 | |
|   myquery(rc);
 | |
| 
 | |
|   /* insert a row and commit the transaction */
 | |
|   rc= mysql_query(mysql, "INSERT INTO test_select VALUES(10, 'venu')");
 | |
|   myquery(rc);
 | |
| 
 | |
|   /* now insert the second row, and roll back the transaction */
 | |
|   rc= mysql_query(mysql, "INSERT INTO test_select VALUES(20, 'mysql')");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_commit(mysql);
 | |
|   myquery(rc);
 | |
| 
 | |
|   strmov(query, "SELECT * FROM test_select WHERE id= ? "
 | |
|                 "AND CONVERT(name USING utf8) =?");
 | |
|   stmt= mysql_simple_prepare(mysql, query);
 | |
|   check_stmt(stmt);
 | |
| 
 | |
|   verify_param_count(stmt, 2);
 | |
| 
 | |
|   /* Always bzero all members of bind parameter */
 | |
|   bzero((char*) my_bind, sizeof(my_bind));
 | |
| 
 | |
|   /* string data */
 | |
|   nData= 10;
 | |
|   strmov(szData, (char *)"venu");
 | |
|   my_bind[1].buffer_type= MYSQL_TYPE_STRING;
 | |
|   my_bind[1].buffer= (void *)szData;
 | |
|   my_bind[1].buffer_length= 4;
 | |
|   my_bind[1].length= &length[1];
 | |
|   length[1]= 4;
 | |
| 
 | |
|   my_bind[0].buffer= (void *)&nData;
 | |
|   my_bind[0].buffer_type= MYSQL_TYPE_LONG;
 | |
| 
 | |
|   rc= mysql_stmt_bind_param(stmt, my_bind);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= my_process_stmt_result(stmt);
 | |
|   DIE_UNLESS(rc == 1);
 | |
| 
 | |
|   mysql_stmt_close(stmt);
 | |
| }
 | |
| 
 | |
| 
 | |
| /*
 | |
|   Test for BUG#3420 ("select id1, value1 from t where id= ? or value= ?"
 | |
|   returns all rows in the table)
 | |
| */
 | |
| 
 | |
| static void test_ps_conj_select()
 | |
| {
 | |
|   MYSQL_STMT *stmt;
 | |
|   int        rc;
 | |
|   MYSQL_BIND my_bind[2];
 | |
|   int32      int_data;
 | |
|   char       str_data[32];
 | |
|   unsigned long str_length;
 | |
|   char query[MAX_TEST_QUERY_LENGTH];
 | |
|   myheader("test_ps_conj_select");
 | |
| 
 | |
|   rc= mysql_query(mysql, "drop table if exists t1");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "create table t1 (id1 int(11) NOT NULL default '0', "
 | |
|                          "value2 varchar(100), value1 varchar(100))");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "insert into t1 values (1, 'hh', 'hh'), "
 | |
|                           "(2, 'hh', 'hh'), (1, 'ii', 'ii'), (2, 'ii', 'ii')");
 | |
|   myquery(rc);
 | |
| 
 | |
|   strmov(query, "SELECT id1, value1 from t1 where id1= ? or "
 | |
|                 "CONVERT(value1 USING utf8)= ?");
 | |
|   stmt= mysql_simple_prepare(mysql, query);
 | |
|   check_stmt(stmt);
 | |
| 
 | |
|   verify_param_count(stmt, 2);
 | |
| 
 | |
|   /* Always bzero all members of bind parameter */
 | |
|   bzero((char*) my_bind, sizeof(my_bind));
 | |
| 
 | |
|   my_bind[0].buffer_type= MYSQL_TYPE_LONG;
 | |
|   my_bind[0].buffer= (void *)&int_data;
 | |
| 
 | |
|   my_bind[1].buffer_type= MYSQL_TYPE_VAR_STRING;
 | |
|   my_bind[1].buffer= (void *)str_data;
 | |
|   my_bind[1].buffer_length= array_elements(str_data);
 | |
|   my_bind[1].length= &str_length;
 | |
| 
 | |
|   rc= mysql_stmt_bind_param(stmt, my_bind);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   int_data= 1;
 | |
|   strmov(str_data, "hh");
 | |
|   str_length= strlen(str_data);
 | |
| 
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= my_process_stmt_result(stmt);
 | |
|   DIE_UNLESS(rc == 3);
 | |
| 
 | |
|   mysql_stmt_close(stmt);
 | |
| }
 | |
| 
 | |
| 
 | |
| /* reads Qcache_hits from server and returns its value */
 | |
| static uint query_cache_hits(MYSQL *conn)
 | |
| {
 | |
|   MYSQL_RES *res;
 | |
|   MYSQL_ROW row;
 | |
|   int rc;
 | |
|   uint result;
 | |
| 
 | |
|   rc= mysql_query(conn, "show status like 'qcache_hits'");
 | |
|   myquery(rc);
 | |
|   res= mysql_use_result(conn);
 | |
|   DIE_UNLESS(res);
 | |
| 
 | |
|   row= mysql_fetch_row(res);
 | |
|   DIE_UNLESS(row);
 | |
| 
 | |
|   result= atoi(row[1]);
 | |
|   mysql_free_result(res);
 | |
|   return result;
 | |
| }
 | |
| 
 | |
| 
 | |
| /*
 | |
|   utility for the next test; expects 3 rows in the result from a SELECT,
 | |
|   compares each row/field with an expected value.
 | |
|  */
 | |
| #define test_ps_query_cache_result(i1,s1,l1,i2,s2,l2,i3,s3,l3)    \
 | |
|   r_metadata= mysql_stmt_result_metadata(stmt);                   \
 | |
|   DIE_UNLESS(r_metadata != NULL);                                 \
 | |
|   rc= mysql_stmt_fetch(stmt);                                     \
 | |
|   check_execute(stmt, rc);                                        \
 | |
|   if (!opt_silent)                                                \
 | |
|     fprintf(stdout, "\n row 1: %d, %s(%lu)", r_int_data,          \
 | |
|             r_str_data, r_str_length);                            \
 | |
|   DIE_UNLESS((r_int_data == i1) && (r_str_length == l1) &&        \
 | |
|              (strcmp(r_str_data, s1) == 0));                      \
 | |
|   rc= mysql_stmt_fetch(stmt);                                     \
 | |
|   check_execute(stmt, rc);                                        \
 | |
|   if (!opt_silent)                                                \
 | |
|     fprintf(stdout, "\n row 2: %d, %s(%lu)", r_int_data,          \
 | |
|             r_str_data, r_str_length);                            \
 | |
|   DIE_UNLESS((r_int_data == i2) && (r_str_length == l2) &&        \
 | |
|              (strcmp(r_str_data, s2) == 0));                      \
 | |
|   rc= mysql_stmt_fetch(stmt);                                     \
 | |
|   check_execute(stmt, rc);                                        \
 | |
|   if (!opt_silent)                                                \
 | |
|     fprintf(stdout, "\n row 3: %d, %s(%lu)", r_int_data,          \
 | |
|             r_str_data, r_str_length);                            \
 | |
|   DIE_UNLESS((r_int_data == i3) && (r_str_length == l3) &&        \
 | |
|              (strcmp(r_str_data, s3) == 0));                      \
 | |
|   rc= mysql_stmt_fetch(stmt);                                     \
 | |
|   DIE_UNLESS(rc == MYSQL_NO_DATA);                                \
 | |
|   mysql_free_result(r_metadata);
 | |
| 
 | |
| 
 | |
| /*
 | |
|   Check that query cache is available in server.
 | |
| */
 | |
| static my_bool is_query_cache_available()
 | |
| {
 | |
|   int rc;
 | |
|   MYSQL_RES *result;
 | |
|   MYSQL_ROW row;
 | |
|   int res= -1;
 | |
| 
 | |
|   rc= mysql_query(mysql, "SHOW VARIABLES LIKE 'have_query_cache'");
 | |
|   myquery(rc);
 | |
| 
 | |
|   result= mysql_store_result(mysql);
 | |
|   DIE_UNLESS(result);
 | |
| 
 | |
|   row= mysql_fetch_row(result);
 | |
|   DIE_UNLESS(row != NULL);
 | |
|   if (strcmp(row[1], "YES") == 0)
 | |
|     res= 1;
 | |
|   else if (strcmp(row[1], "NO") == 0)
 | |
|     res= 0;
 | |
|   mysql_free_result(result);
 | |
| 
 | |
|   DIE_UNLESS(res == 0 || res == 1);
 | |
|   return res;
 | |
| }
 | |
| 
 | |
| /*
 | |
|   Test that prepared statements make use of the query cache just as normal
 | |
|   statements (BUG#735).
 | |
| */
 | |
| static void test_ps_query_cache()
 | |
| {
 | |
|   MYSQL      *lmysql= mysql;
 | |
|   MYSQL_STMT *stmt;
 | |
|   int        rc;
 | |
|   MYSQL_BIND p_bind[2],r_bind[2]; /* p: param bind; r: result bind */
 | |
|   int32      p_int_data, r_int_data;
 | |
|   char       p_str_data[32], r_str_data[32];
 | |
|   unsigned long p_str_length, r_str_length;
 | |
|   MYSQL_RES  *r_metadata;
 | |
|   char       query[MAX_TEST_QUERY_LENGTH];
 | |
|   uint       hits1, hits2;
 | |
|   enum enum_test_ps_query_cache
 | |
|   {
 | |
|     /*
 | |
|       We iterate the same prepare/executes block, but have iterations where
 | |
|       we vary the query cache conditions.
 | |
|     */
 | |
|     /* the query cache is enabled for the duration of prep&execs: */
 | |
|     TEST_QCACHE_ON= 0,
 | |
|     /*
 | |
|       same but using a new connection (to see if qcache serves results from
 | |
|       the previous connection as it should):
 | |
|     */
 | |
|     TEST_QCACHE_ON_WITH_OTHER_CONN,
 | |
|     /*
 | |
|       First border case: disables the query cache before prepare and
 | |
|       re-enables it before execution (to test if we have no bug then):
 | |
|     */
 | |
|     TEST_QCACHE_OFF_ON,
 | |
|     /*
 | |
|       Second border case: enables the query cache before prepare and
 | |
|       disables it before execution:
 | |
|     */
 | |
|     TEST_QCACHE_ON_OFF
 | |
|   };
 | |
|   enum enum_test_ps_query_cache iteration;
 | |
| 
 | |
|   myheader("test_ps_query_cache");
 | |
| 
 | |
|   if (! is_query_cache_available())
 | |
|   {
 | |
|     fprintf(stdout, "Skipping test_ps_query_cache: Query cache not available.\n");
 | |
|     return;
 | |
|   }
 | |
| 
 | |
|   rc= mysql_set_character_set(mysql, "utf8");
 | |
|   myquery(rc);
 | |
| 
 | |
|   /* prepare the table */
 | |
| 
 | |
|   rc= mysql_query(mysql, "drop table if exists t1");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "create table t1 (id1 int(11) NOT NULL default '0', "
 | |
|                          "value2 varchar(100), value1 varchar(100))");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "insert into t1 values (1, 'hh', 'hh'), "
 | |
|                           "(2, 'hh', 'hh'), (1, 'ii', 'ii'), (2, 'ii', 'ii')");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql,
 | |
|                   "set @save_query_cache_type="
 | |
|                   "@@global.query_cache_type,"
 | |
|                   "@save_query_cache_size="
 | |
|                   "@@global.query_cache_size");
 | |
|   myquery(rc);
 | |
|   rc= mysql_query(lmysql, "set global query_cache_type=ON");
 | |
|   myquery(rc);
 | |
|   rc= mysql_query(lmysql, "set local query_cache_type=ON");
 | |
|   myquery(rc);
 | |
| 
 | |
|   for (iteration= TEST_QCACHE_ON; iteration <= TEST_QCACHE_ON_OFF; iteration++)
 | |
|   {
 | |
| 
 | |
|     switch (iteration) {
 | |
|     case TEST_QCACHE_ON:
 | |
|     case TEST_QCACHE_ON_OFF:
 | |
|       rc= mysql_query(lmysql, "set global query_cache_size=1000000");
 | |
|       myquery(rc);
 | |
|       break;
 | |
|     case TEST_QCACHE_OFF_ON:
 | |
|       rc= mysql_query(lmysql, "set global query_cache_size=0");
 | |
|       myquery(rc);
 | |
|       break;
 | |
|     case TEST_QCACHE_ON_WITH_OTHER_CONN:
 | |
|       if (!opt_silent)
 | |
|         fprintf(stdout, "\n Establishing a test connection ...");
 | |
|       if (!(lmysql= mysql_client_init(NULL)))
 | |
|       {
 | |
|         printf("mysql_client_init() failed");
 | |
|         DIE_UNLESS(0);
 | |
|       }
 | |
|       if (!(mysql_real_connect(lmysql, opt_host, opt_user,
 | |
|                                opt_password, current_db, opt_port,
 | |
|                                opt_unix_socket, 0)))
 | |
|       {
 | |
|         printf("connection failed");
 | |
|         mysql_close(lmysql);
 | |
|         DIE_UNLESS(0);
 | |
|       }
 | |
|       rc= mysql_query(lmysql, "SET SQL_MODE=''");
 | |
|       myquery(rc);
 | |
|       rc= mysql_set_character_set(lmysql, "utf8");
 | |
|       myquery(rc);
 | |
| 
 | |
|       if (!opt_silent)
 | |
|         fprintf(stdout, "OK");
 | |
|       break;
 | |
|     }
 | |
| 
 | |
|     strmov(query, "select id1, value1 from t1 where id1= ? or "
 | |
|            "CONVERT(value1 USING utf8)= ?");
 | |
|     stmt= mysql_simple_prepare(lmysql, query);
 | |
|     check_stmt(stmt);
 | |
| 
 | |
|     verify_param_count(stmt, 2);
 | |
| 
 | |
|     switch (iteration) {
 | |
|     case TEST_QCACHE_OFF_ON:
 | |
|       rc= mysql_query(lmysql, "set global query_cache_size=1000000");
 | |
|       myquery(rc);
 | |
|       break;
 | |
|     case TEST_QCACHE_ON_OFF:
 | |
|       rc= mysql_query(lmysql, "set global query_cache_size=0");
 | |
|       myquery(rc);
 | |
|     default:
 | |
|       break;
 | |
|     }
 | |
| 
 | |
|     bzero((char*) p_bind, sizeof(p_bind));
 | |
|     p_bind[0].buffer_type= MYSQL_TYPE_LONG;
 | |
|     p_bind[0].buffer= (void *)&p_int_data;
 | |
|     p_bind[1].buffer_type= MYSQL_TYPE_VAR_STRING;
 | |
|     p_bind[1].buffer= (void *)p_str_data;
 | |
|     p_bind[1].buffer_length= array_elements(p_str_data);
 | |
|     p_bind[1].length= &p_str_length;
 | |
| 
 | |
|     rc= mysql_stmt_bind_param(stmt, p_bind);
 | |
|     check_execute(stmt, rc);
 | |
| 
 | |
|     p_int_data= 1;
 | |
|     strmov(p_str_data, "hh");
 | |
|     p_str_length= strlen(p_str_data);
 | |
| 
 | |
|     bzero((char*) r_bind, sizeof(r_bind));
 | |
|     r_bind[0].buffer_type= MYSQL_TYPE_LONG;
 | |
|     r_bind[0].buffer= (void *)&r_int_data;
 | |
|     r_bind[1].buffer_type= MYSQL_TYPE_VAR_STRING;
 | |
|     r_bind[1].buffer= (void *)r_str_data;
 | |
|     r_bind[1].buffer_length= array_elements(r_str_data);
 | |
|     r_bind[1].length= &r_str_length;
 | |
| 
 | |
|     rc= mysql_stmt_bind_result(stmt, r_bind);
 | |
|     check_execute(stmt, rc);
 | |
| 
 | |
|     rc= mysql_stmt_execute(stmt);
 | |
|     check_execute(stmt, rc);
 | |
| 
 | |
|     test_ps_query_cache_result(1, "hh", 2, 2, "hh", 2, 1, "ii", 2);
 | |
| 
 | |
|     /* now retry with the same parameter values and see qcache hits */
 | |
|     hits1= query_cache_hits(lmysql);
 | |
|     rc= mysql_stmt_execute(stmt);
 | |
|     check_execute(stmt, rc);
 | |
|     test_ps_query_cache_result(1, "hh", 2, 2, "hh", 2, 1, "ii", 2);
 | |
|     hits2= query_cache_hits(lmysql);
 | |
|     switch(iteration) {
 | |
|     case TEST_QCACHE_ON_WITH_OTHER_CONN:
 | |
|     case TEST_QCACHE_ON:                 /* should have hit */
 | |
|       DIE_UNLESS(hits2-hits1 == 1);
 | |
|       break;
 | |
|     case TEST_QCACHE_OFF_ON:
 | |
|     case TEST_QCACHE_ON_OFF:             /* should not have hit */
 | |
|       DIE_UNLESS(hits2-hits1 == 0);
 | |
|       break;
 | |
|     }
 | |
| 
 | |
|     /* now modify parameter values and see qcache hits */
 | |
|     strmov(p_str_data, "ii");
 | |
|     p_str_length= strlen(p_str_data);
 | |
|     rc= mysql_stmt_execute(stmt);
 | |
|     check_execute(stmt, rc);
 | |
|     test_ps_query_cache_result(1, "hh", 2, 1, "ii", 2, 2, "ii", 2);
 | |
|     hits1= query_cache_hits(lmysql);
 | |
| 
 | |
|     switch(iteration) {
 | |
|     case TEST_QCACHE_ON:
 | |
|     case TEST_QCACHE_OFF_ON:
 | |
|     case TEST_QCACHE_ON_OFF:             /* should not have hit */
 | |
|       DIE_UNLESS(hits2-hits1 == 0);
 | |
|       break;
 | |
|     case TEST_QCACHE_ON_WITH_OTHER_CONN: /* should have hit */
 | |
|       DIE_UNLESS(hits1-hits2 == 1);
 | |
|       break;
 | |
|     }
 | |
| 
 | |
|     rc= mysql_stmt_execute(stmt);
 | |
|     check_execute(stmt, rc);
 | |
| 
 | |
|     test_ps_query_cache_result(1, "hh", 2, 1, "ii", 2, 2, "ii", 2);
 | |
|     hits2= query_cache_hits(lmysql);
 | |
| 
 | |
|     mysql_stmt_close(stmt);
 | |
| 
 | |
|     switch(iteration) {
 | |
|     case TEST_QCACHE_ON:                 /* should have hit */
 | |
|       DIE_UNLESS(hits2-hits1 == 1);
 | |
|       break;
 | |
|     case TEST_QCACHE_OFF_ON:
 | |
|     case TEST_QCACHE_ON_OFF:             /* should not have hit */
 | |
|       DIE_UNLESS(hits2-hits1 == 0);
 | |
|       break;
 | |
|     case TEST_QCACHE_ON_WITH_OTHER_CONN: /* should have hit */
 | |
|       DIE_UNLESS(hits2-hits1 == 1);
 | |
|       break;
 | |
|     }
 | |
| 
 | |
|   } /* for(iteration=...) */
 | |
| 
 | |
|   if (lmysql != mysql)
 | |
|     mysql_close(lmysql);
 | |
| 
 | |
|   rc= mysql_query(mysql, "set global query_cache_size=@save_query_cache_size");
 | |
|   myquery(rc);
 | |
|   rc= mysql_query(mysql, "set global query_cache_type=@save_query_cache_type");
 | |
|   myquery(rc);
 | |
| }
 | |
| 
 | |
| 
 | |
| /* Test BUG#1115 (incorrect string parameter value allocation) */
 | |
| 
 | |
| static void test_bug1115()
 | |
| {
 | |
|   MYSQL_STMT *stmt;
 | |
|   int rc;
 | |
|   MYSQL_BIND my_bind[1];
 | |
|   ulong length[1];
 | |
|   char szData[11];
 | |
|   char query[MAX_TEST_QUERY_LENGTH];
 | |
| 
 | |
|   myheader("test_bug1115");
 | |
| 
 | |
|   rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_select");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "CREATE TABLE test_select(\
 | |
| session_id  char(9) NOT NULL, \
 | |
|     a       int(8) unsigned NOT NULL, \
 | |
|     b        int(5) NOT NULL, \
 | |
|     c      int(5) NOT NULL, \
 | |
|     d  datetime NOT NULL)");
 | |
|   myquery(rc);
 | |
|   rc= mysql_query(mysql, "INSERT INTO test_select VALUES "
 | |
|                          "(\"abc\", 1, 2, 3, 2003-08-30), "
 | |
|                          "(\"abd\", 1, 2, 3, 2003-08-30), "
 | |
|                          "(\"abf\", 1, 2, 3, 2003-08-30), "
 | |
|                          "(\"abg\", 1, 2, 3, 2003-08-30), "
 | |
|                          "(\"abh\", 1, 2, 3, 2003-08-30), "
 | |
|                          "(\"abj\", 1, 2, 3, 2003-08-30), "
 | |
|                          "(\"abk\", 1, 2, 3, 2003-08-30), "
 | |
|                          "(\"abl\", 1, 2, 3, 2003-08-30), "
 | |
|                          "(\"abq\", 1, 2, 3, 2003-08-30) ");
 | |
|   myquery(rc);
 | |
|   rc= mysql_query(mysql, "INSERT INTO test_select VALUES "
 | |
|                          "(\"abw\", 1, 2, 3, 2003-08-30), "
 | |
|                          "(\"abe\", 1, 2, 3, 2003-08-30), "
 | |
|                          "(\"abr\", 1, 2, 3, 2003-08-30), "
 | |
|                          "(\"abt\", 1, 2, 3, 2003-08-30), "
 | |
|                          "(\"aby\", 1, 2, 3, 2003-08-30), "
 | |
|                          "(\"abu\", 1, 2, 3, 2003-08-30), "
 | |
|                          "(\"abi\", 1, 2, 3, 2003-08-30), "
 | |
|                          "(\"abo\", 1, 2, 3, 2003-08-30), "
 | |
|                          "(\"abp\", 1, 2, 3, 2003-08-30), "
 | |
|                          "(\"abz\", 1, 2, 3, 2003-08-30), "
 | |
|                          "(\"abx\", 1, 2, 3, 2003-08-30)");
 | |
|   myquery(rc);
 | |
| 
 | |
|   strmov(query, "SELECT * FROM test_select WHERE "
 | |
|                 "CONVERT(session_id USING utf8)= ?");
 | |
|   stmt= mysql_simple_prepare(mysql, query);
 | |
|   check_stmt(stmt);
 | |
| 
 | |
|   verify_param_count(stmt, 1);
 | |
| 
 | |
|   /* Always bzero all members of bind parameter */
 | |
|   bzero((char*) my_bind, sizeof(my_bind));
 | |
| 
 | |
|   strmov(szData, (char *)"abc");
 | |
|   my_bind[0].buffer_type= MYSQL_TYPE_STRING;
 | |
|   my_bind[0].buffer= (void *)szData;
 | |
|   my_bind[0].buffer_length= 10;
 | |
|   my_bind[0].length= &length[0];
 | |
|   length[0]= 3;
 | |
| 
 | |
|   rc= mysql_stmt_bind_param(stmt, my_bind);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= my_process_stmt_result(stmt);
 | |
|   DIE_UNLESS(rc == 1);
 | |
| 
 | |
|   strmov(szData, (char *)"venu");
 | |
|   my_bind[0].buffer_type= MYSQL_TYPE_STRING;
 | |
|   my_bind[0].buffer= (void *)szData;
 | |
|   my_bind[0].buffer_length= 10;
 | |
|   my_bind[0].length= &length[0];
 | |
|   length[0]= 4;
 | |
|   my_bind[0].is_null= 0;
 | |
| 
 | |
|   rc= mysql_stmt_bind_param(stmt, my_bind);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= my_process_stmt_result(stmt);
 | |
|   DIE_UNLESS(rc == 0);
 | |
| 
 | |
|   strmov(szData, (char *)"abc");
 | |
|   my_bind[0].buffer_type= MYSQL_TYPE_STRING;
 | |
|   my_bind[0].buffer= (void *)szData;
 | |
|   my_bind[0].buffer_length= 10;
 | |
|   my_bind[0].length= &length[0];
 | |
|   length[0]= 3;
 | |
|   my_bind[0].is_null= 0;
 | |
| 
 | |
|   rc= mysql_stmt_bind_param(stmt, my_bind);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= my_process_stmt_result(stmt);
 | |
|   DIE_UNLESS(rc == 1);
 | |
| 
 | |
|   mysql_stmt_close(stmt);
 | |
| }
 | |
| 
 | |
| 
 | |
| /* Test BUG#1180 (optimized away part of WHERE clause) */
 | |
| 
 | |
| static void test_bug1180()
 | |
| {
 | |
|   MYSQL_STMT *stmt;
 | |
|   int rc;
 | |
|   MYSQL_BIND my_bind[1];
 | |
|   ulong length[1];
 | |
|   char szData[11];
 | |
|   char query[MAX_TEST_QUERY_LENGTH];
 | |
| 
 | |
|   myheader("test_select_bug");
 | |
| 
 | |
|   rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_select");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "CREATE TABLE test_select(session_id  char(9) NOT NULL)");
 | |
|   myquery(rc);
 | |
|   rc= mysql_query(mysql, "INSERT INTO test_select VALUES (\"abc\")");
 | |
|   myquery(rc);
 | |
| 
 | |
|   strmov(query, "SELECT * FROM test_select WHERE ?= \"1111\" and "
 | |
|                 "session_id= \"abc\"");
 | |
|   stmt= mysql_simple_prepare(mysql, query);
 | |
|   check_stmt(stmt);
 | |
| 
 | |
|   verify_param_count(stmt, 1);
 | |
| 
 | |
|   /* Always bzero all members of bind parameter */
 | |
|   bzero((char*) my_bind, sizeof(my_bind));
 | |
| 
 | |
|   strmov(szData, (char *)"abc");
 | |
|   my_bind[0].buffer_type= MYSQL_TYPE_STRING;
 | |
|   my_bind[0].buffer= (void *)szData;
 | |
|   my_bind[0].buffer_length= 10;
 | |
|   my_bind[0].length= &length[0];
 | |
|   length[0]= 3;
 | |
|   my_bind[0].is_null= 0;
 | |
| 
 | |
|   rc= mysql_stmt_bind_param(stmt, my_bind);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= my_process_stmt_result(stmt);
 | |
|   DIE_UNLESS(rc == 0);
 | |
| 
 | |
|   strmov(szData, (char *)"1111");
 | |
|   my_bind[0].buffer_type= MYSQL_TYPE_STRING;
 | |
|   my_bind[0].buffer= (void *)szData;
 | |
|   my_bind[0].buffer_length= 10;
 | |
|   my_bind[0].length= &length[0];
 | |
|   length[0]= 4;
 | |
|   my_bind[0].is_null= 0;
 | |
| 
 | |
|   rc= mysql_stmt_bind_param(stmt, my_bind);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= my_process_stmt_result(stmt);
 | |
|   DIE_UNLESS(rc == 1);
 | |
| 
 | |
|   strmov(szData, (char *)"abc");
 | |
|   my_bind[0].buffer_type= MYSQL_TYPE_STRING;
 | |
|   my_bind[0].buffer= (void *)szData;
 | |
|   my_bind[0].buffer_length= 10;
 | |
|   my_bind[0].length= &length[0];
 | |
|   length[0]= 3;
 | |
|   my_bind[0].is_null= 0;
 | |
| 
 | |
|   rc= mysql_stmt_bind_param(stmt, my_bind);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= my_process_stmt_result(stmt);
 | |
|   DIE_UNLESS(rc == 0);
 | |
| 
 | |
|   mysql_stmt_close(stmt);
 | |
| }
 | |
| 
 | |
| 
 | |
| /*
 | |
|   Test BUG#1644 (Insertion of more than 3 NULL columns with parameter
 | |
|   binding fails)
 | |
| */
 | |
| 
 | |
| static void test_bug1644()
 | |
| {
 | |
|   MYSQL_STMT *stmt;
 | |
|   MYSQL_RES *result;
 | |
|   MYSQL_ROW row;
 | |
|   MYSQL_BIND my_bind[4];
 | |
|   int num;
 | |
|   my_bool isnull;
 | |
|   int rc, i;
 | |
|   char query[MAX_TEST_QUERY_LENGTH];
 | |
| 
 | |
|   myheader("test_bug1644");
 | |
| 
 | |
|   rc= mysql_query(mysql, "DROP TABLE IF EXISTS foo_dfr");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql,
 | |
|            "CREATE TABLE foo_dfr(col1 int, col2 int, col3 int, col4 int);");
 | |
|   myquery(rc);
 | |
| 
 | |
|   strmov(query, "INSERT INTO foo_dfr VALUES (?, ?, ?, ? )");
 | |
|   stmt= mysql_simple_prepare(mysql, query);
 | |
|   check_stmt(stmt);
 | |
| 
 | |
|   verify_param_count(stmt, 4);
 | |
| 
 | |
|   /* Always bzero all members of bind parameter */
 | |
|   bzero((char*) my_bind, sizeof(my_bind));
 | |
| 
 | |
|   num= 22;
 | |
|   isnull= 0;
 | |
|   for (i= 0 ; i < 4 ; i++)
 | |
|   {
 | |
|     my_bind[i].buffer_type= MYSQL_TYPE_LONG;
 | |
|     my_bind[i].buffer= (void *)#
 | |
|     my_bind[i].is_null= &isnull;
 | |
|   }
 | |
| 
 | |
|   rc= mysql_stmt_bind_param(stmt, my_bind);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   isnull= 1;
 | |
|   for (i= 0 ; i < 4 ; i++)
 | |
|     my_bind[i].is_null= &isnull;
 | |
| 
 | |
|   rc= mysql_stmt_bind_param(stmt, my_bind);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   isnull= 0;
 | |
|   num= 88;
 | |
|   for (i= 0 ; i < 4 ; i++)
 | |
|     my_bind[i].is_null= &isnull;
 | |
| 
 | |
|   rc= mysql_stmt_bind_param(stmt, my_bind);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   mysql_stmt_close(stmt);
 | |
| 
 | |
|   rc= mysql_query(mysql, "SELECT * FROM foo_dfr");
 | |
|   myquery(rc);
 | |
| 
 | |
|   result= mysql_store_result(mysql);
 | |
|   mytest(result);
 | |
| 
 | |
|   rc= my_process_result_set(result);
 | |
|   DIE_UNLESS(rc == 3);
 | |
| 
 | |
|   mysql_data_seek(result, 0);
 | |
| 
 | |
|   row= mysql_fetch_row(result);
 | |
|   mytest(row);
 | |
|   for (i= 0 ; i < 4 ; i++)
 | |
|   {
 | |
|     DIE_UNLESS(strcmp(row[i], "22") == 0);
 | |
|   }
 | |
|   row= mysql_fetch_row(result);
 | |
|   mytest(row);
 | |
|   for (i= 0 ; i < 4 ; i++)
 | |
|   {
 | |
|     DIE_UNLESS(row[i] == 0);
 | |
|   }
 | |
|   row= mysql_fetch_row(result);
 | |
|   mytest(row);
 | |
|   for (i= 0 ; i < 4 ; i++)
 | |
|   {
 | |
|     DIE_UNLESS(strcmp(row[i], "88") == 0);
 | |
|   }
 | |
|   row= mysql_fetch_row(result);
 | |
|   mytest_r(row);
 | |
| 
 | |
|   mysql_free_result(result);
 | |
| }
 | |
| 
 | |
| 
 | |
| /* Test simple select show */
 | |
| 
 | |
| static void test_select_show()
 | |
| {
 | |
|   MYSQL_STMT *stmt;
 | |
|   int        rc;
 | |
|   char query[MAX_TEST_QUERY_LENGTH];
 | |
| 
 | |
|   myheader("test_select_show");
 | |
| 
 | |
|   mysql_autocommit(mysql, TRUE);
 | |
| 
 | |
|   rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_show");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "CREATE TABLE test_show(id int(4) NOT NULL primary "
 | |
|                          " key, name char(2))");
 | |
|   myquery(rc);
 | |
| 
 | |
|   stmt= mysql_simple_prepare(mysql, "show columns from test_show");
 | |
|   check_stmt(stmt);
 | |
| 
 | |
|   verify_param_count(stmt, 0);
 | |
| 
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   my_process_stmt_result(stmt);
 | |
|   mysql_stmt_close(stmt);
 | |
| 
 | |
|   stmt= mysql_simple_prepare(mysql, "show tables from mysql like ?");
 | |
|   check_stmt_r(stmt);
 | |
| 
 | |
|   strxmov(query, "show tables from ", current_db, " like \'test_show\'", NullS);
 | |
|   stmt= mysql_simple_prepare(mysql, query);
 | |
|   check_stmt(stmt);
 | |
| 
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   my_process_stmt_result(stmt);
 | |
|   mysql_stmt_close(stmt);
 | |
| 
 | |
|   stmt= mysql_simple_prepare(mysql, "describe test_show");
 | |
|   check_stmt(stmt);
 | |
| 
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   my_process_stmt_result(stmt);
 | |
|   mysql_stmt_close(stmt);
 | |
| 
 | |
|   stmt= mysql_simple_prepare(mysql, "show keys from test_show");
 | |
|   check_stmt(stmt);
 | |
| 
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= my_process_stmt_result(stmt);
 | |
|   DIE_UNLESS(rc == 1);
 | |
|   mysql_stmt_close(stmt);
 | |
| }
 | |
| 
 | |
| 
 | |
| /* Test simple update */
 | |
| 
 | |
| static void test_simple_update()
 | |
| {
 | |
|   MYSQL_STMT *stmt;
 | |
|   int        rc;
 | |
|   char       szData[25];
 | |
|   int        nData= 1;
 | |
|   MYSQL_RES  *result;
 | |
|   MYSQL_BIND my_bind[2];
 | |
|   ulong      length[2];
 | |
|   char query[MAX_TEST_QUERY_LENGTH];
 | |
| 
 | |
|   myheader("test_simple_update");
 | |
| 
 | |
|   rc= mysql_autocommit(mysql, TRUE);
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_update");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "CREATE TABLE test_update(col1 int, "
 | |
|                          " col2 varchar(50), col3 int )");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "INSERT INTO test_update VALUES(1, 'MySQL', 100)");
 | |
|   myquery(rc);
 | |
| 
 | |
|   verify_affected_rows(1);
 | |
| 
 | |
|   rc= mysql_commit(mysql);
 | |
|   myquery(rc);
 | |
| 
 | |
|   /* insert by prepare */
 | |
|   strmov(query, "UPDATE test_update SET col2= ? WHERE col1= ?");
 | |
|   stmt= mysql_simple_prepare(mysql, query);
 | |
|   check_stmt(stmt);
 | |
| 
 | |
|   verify_param_count(stmt, 2);
 | |
| 
 | |
|   /* Always bzero all members of bind parameter */
 | |
|   bzero((char*) my_bind, sizeof(my_bind));
 | |
| 
 | |
|   nData= 1;
 | |
|   my_bind[0].buffer_type= MYSQL_TYPE_STRING;
 | |
|   my_bind[0].buffer= szData;                /* string data */
 | |
|   my_bind[0].buffer_length= sizeof(szData);
 | |
|   my_bind[0].length= &length[0];
 | |
|   length[0]= sprintf(szData, "updated-data");
 | |
| 
 | |
|   my_bind[1].buffer= (void *) &nData;
 | |
|   my_bind[1].buffer_type= MYSQL_TYPE_LONG;
 | |
| 
 | |
|   rc= mysql_stmt_bind_param(stmt, my_bind);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
|   verify_affected_rows(1);
 | |
| 
 | |
|   mysql_stmt_close(stmt);
 | |
| 
 | |
|   /* now fetch the results ..*/
 | |
|   rc= mysql_commit(mysql);
 | |
|   myquery(rc);
 | |
| 
 | |
|   /* test the results now, only one row should exist */
 | |
|   rc= mysql_query(mysql, "SELECT * FROM test_update");
 | |
|   myquery(rc);
 | |
| 
 | |
|   /* get the result */
 | |
|   result= mysql_store_result(mysql);
 | |
|   mytest(result);
 | |
| 
 | |
|   rc= my_process_result_set(result);
 | |
|   DIE_UNLESS(rc == 1);
 | |
|   mysql_free_result(result);
 | |
| }
 | |
| 
 | |
| 
 | |
| /* Test simple long data handling */
 | |
| 
 | |
| static void test_long_data()
 | |
| {
 | |
|   MYSQL_STMT *stmt;
 | |
|   int        rc, int_data;
 | |
|   char       *data= NullS;
 | |
|   MYSQL_RES  *result;
 | |
|   MYSQL_BIND my_bind[3];
 | |
|   char query[MAX_TEST_QUERY_LENGTH];
 | |
| 
 | |
|   myheader("test_long_data");
 | |
| 
 | |
|   rc= mysql_autocommit(mysql, TRUE);
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_long_data");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "CREATE TABLE test_long_data(col1 int, "
 | |
|                          "      col2 long varchar, col3 long varbinary)");
 | |
|   myquery(rc);
 | |
| 
 | |
|   strmov(query, "INSERT INTO test_long_data(col1, col2) VALUES(?)");
 | |
|   stmt= mysql_simple_prepare(mysql, query);
 | |
|   check_stmt_r(stmt);
 | |
| 
 | |
|   strmov(query, "INSERT INTO test_long_data(col1, col2, col3) VALUES(?, ?, ?)");
 | |
|   stmt= mysql_simple_prepare(mysql, query);
 | |
|   check_stmt(stmt);
 | |
| 
 | |
|   verify_param_count(stmt, 3);
 | |
| 
 | |
|   /* Always bzero all members of bind parameter */
 | |
|   bzero((char*) my_bind, sizeof(my_bind));
 | |
| 
 | |
|   my_bind[0].buffer= (void *)&int_data;
 | |
|   my_bind[0].buffer_type= MYSQL_TYPE_LONG;
 | |
| 
 | |
|   my_bind[1].buffer_type= MYSQL_TYPE_STRING;
 | |
| 
 | |
|   my_bind[2]= my_bind[1];
 | |
|   rc= mysql_stmt_bind_param(stmt, my_bind);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   int_data= 999;
 | |
|   data= (char *)"Michael";
 | |
| 
 | |
|   /* supply data in pieces */
 | |
|   rc= mysql_stmt_send_long_data(stmt, 1, data, strlen(data));
 | |
|   data= (char *)" 'Monty' Widenius";
 | |
|   rc= mysql_stmt_send_long_data(stmt, 1, data, strlen(data));
 | |
|   check_execute(stmt, rc);
 | |
|   rc= mysql_stmt_send_long_data(stmt, 2, "Venu (venu@mysql.com)", 4);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   /* execute */
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   if (!opt_silent)
 | |
|     fprintf(stdout, " mysql_stmt_execute() returned %d\n", rc);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= mysql_commit(mysql);
 | |
|   myquery(rc);
 | |
| 
 | |
|   /* now fetch the results ..*/
 | |
|   rc= mysql_query(mysql, "SELECT * FROM test_long_data");
 | |
|   myquery(rc);
 | |
| 
 | |
|   /* get the result */
 | |
|   result= mysql_store_result(mysql);
 | |
|   mytest(result);
 | |
| 
 | |
|   rc= my_process_result_set(result);
 | |
|   DIE_UNLESS(rc == 1);
 | |
|   mysql_free_result(result);
 | |
| 
 | |
|   verify_col_data("test_long_data", "col1", "999");
 | |
|   verify_col_data("test_long_data", "col2", "Michael 'Monty' Widenius");
 | |
|   verify_col_data("test_long_data", "col3", "Venu");
 | |
|   mysql_stmt_close(stmt);
 | |
| }
 | |
| 
 | |
| 
 | |
| /* Test long data (string) handling */
 | |
| 
 | |
| static void test_long_data_str()
 | |
| {
 | |
|   MYSQL_STMT *stmt;
 | |
|   int        rc, i;
 | |
|   char       data[255];
 | |
|   long       length;
 | |
|   ulong      length1;
 | |
|   MYSQL_RES  *result;
 | |
|   MYSQL_BIND my_bind[2];
 | |
|   my_bool    is_null[2];
 | |
|   char query[MAX_TEST_QUERY_LENGTH];
 | |
| 
 | |
|   myheader("test_long_data_str");
 | |
| 
 | |
|   rc= mysql_autocommit(mysql, TRUE);
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_long_data_str");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "CREATE TABLE test_long_data_str(id int, longstr long varchar)");
 | |
|   myquery(rc);
 | |
| 
 | |
|   strmov(query, "INSERT INTO test_long_data_str VALUES(?, ?)");
 | |
|   stmt= mysql_simple_prepare(mysql, query);
 | |
|   check_stmt(stmt);
 | |
| 
 | |
|   verify_param_count(stmt, 2);
 | |
| 
 | |
|   /* Always bzero all members of bind parameter */
 | |
|   bzero((char*) my_bind, sizeof(my_bind));
 | |
| 
 | |
|   my_bind[0].buffer= (void *)&length;
 | |
|   my_bind[0].buffer_type= MYSQL_TYPE_LONG;
 | |
|   my_bind[0].is_null= &is_null[0];
 | |
|   is_null[0]= 0;
 | |
|   length= 0;
 | |
| 
 | |
|   my_bind[1].buffer= data;                          /* string data */
 | |
|   my_bind[1].buffer_type= MYSQL_TYPE_STRING;
 | |
|   my_bind[1].length= &length1;
 | |
|   my_bind[1].is_null= &is_null[1];
 | |
|   is_null[1]= 0;
 | |
|   rc= mysql_stmt_bind_param(stmt, my_bind);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   length= 40;
 | |
|   strmov(data, "MySQL AB");
 | |
| 
 | |
|   /* supply data in pieces */
 | |
|   for(i= 0; i < 4; i++)
 | |
|   {
 | |
|     rc= mysql_stmt_send_long_data(stmt, 1, (char *)data, 5);
 | |
|     check_execute(stmt, rc);
 | |
|   }
 | |
|   /* execute */
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   if (!opt_silent)
 | |
|     fprintf(stdout, " mysql_stmt_execute() returned %d\n", rc);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   mysql_stmt_close(stmt);
 | |
| 
 | |
|   rc= mysql_commit(mysql);
 | |
|   myquery(rc);
 | |
| 
 | |
|   /* now fetch the results ..*/
 | |
|   rc= mysql_query(mysql, "SELECT LENGTH(longstr), longstr FROM test_long_data_str");
 | |
|   myquery(rc);
 | |
| 
 | |
|   /* get the result */
 | |
|   result= mysql_store_result(mysql);
 | |
|   mytest(result);
 | |
| 
 | |
|   rc= my_process_result_set(result);
 | |
|   DIE_UNLESS(rc == 1);
 | |
|   mysql_free_result(result);
 | |
| 
 | |
|   sprintf(data, "%d", i*5);
 | |
|   verify_col_data("test_long_data_str", "LENGTH(longstr)", data);
 | |
|   data[0]= '\0';
 | |
|   while (i--)
 | |
|    strxmov(data, data, "MySQL", NullS);
 | |
|   verify_col_data("test_long_data_str", "longstr", data);
 | |
| 
 | |
|   rc= mysql_query(mysql, "DROP TABLE test_long_data_str");
 | |
|   myquery(rc);
 | |
| }
 | |
| 
 | |
| 
 | |
| /* Test long data (string) handling */
 | |
| 
 | |
| static void test_long_data_str1()
 | |
| {
 | |
|   MYSQL_STMT *stmt;
 | |
|   int        rc, i;
 | |
|   char       data[255];
 | |
|   long       length;
 | |
|   ulong      max_blob_length, blob_length= 0, length1;
 | |
|   my_bool    true_value;
 | |
|   MYSQL_RES  *result;
 | |
|   MYSQL_BIND my_bind[2];
 | |
|   MYSQL_FIELD *field;
 | |
|   char query[MAX_TEST_QUERY_LENGTH];
 | |
| 
 | |
|   myheader("test_long_data_str1");
 | |
| 
 | |
|   rc= mysql_autocommit(mysql, TRUE);
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_long_data_str");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "CREATE TABLE test_long_data_str(longstr long varchar, blb long varbinary)");
 | |
|   myquery(rc);
 | |
| 
 | |
|   strmov(query, "INSERT INTO test_long_data_str VALUES(?, ?)");
 | |
|   stmt= mysql_simple_prepare(mysql, query);
 | |
|   check_stmt(stmt);
 | |
| 
 | |
|   verify_param_count(stmt, 2);
 | |
| 
 | |
|   /* Always bzero all members of bind parameter */
 | |
|   bzero((char*) my_bind, sizeof(my_bind));
 | |
| 
 | |
|   my_bind[0].buffer= data;            /* string data */
 | |
|   my_bind[0].buffer_length= sizeof(data);
 | |
|   my_bind[0].length= &length1;
 | |
|   my_bind[0].buffer_type= MYSQL_TYPE_STRING;
 | |
|   length1= 0;
 | |
| 
 | |
|   my_bind[1]= my_bind[0];
 | |
|   my_bind[1].buffer_type= MYSQL_TYPE_BLOB;
 | |
| 
 | |
|   rc= mysql_stmt_bind_param(stmt, my_bind);
 | |
|   check_execute(stmt, rc);
 | |
|   length= sprintf(data, "MySQL AB");
 | |
| 
 | |
|   /* supply data in pieces */
 | |
|   for (i= 0; i < 3; i++)
 | |
|   {
 | |
|     rc= mysql_stmt_send_long_data(stmt, 0, data, length);
 | |
|     check_execute(stmt, rc);
 | |
| 
 | |
|     rc= mysql_stmt_send_long_data(stmt, 1, data, 2);
 | |
|     check_execute(stmt, rc);
 | |
|   }
 | |
| 
 | |
|   /* execute */
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   if (!opt_silent)
 | |
|     fprintf(stdout, " mysql_stmt_execute() returned %d\n", rc);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   mysql_stmt_close(stmt);
 | |
| 
 | |
|   rc= mysql_commit(mysql);
 | |
|   myquery(rc);
 | |
| 
 | |
|   /* now fetch the results ..*/
 | |
|   rc= mysql_query(mysql, "SELECT LENGTH(longstr), longstr, LENGTH(blb), blb FROM test_long_data_str");
 | |
|   myquery(rc);
 | |
| 
 | |
|   /* get the result */
 | |
|   result= mysql_store_result(mysql);
 | |
| 
 | |
|   mysql_field_seek(result, 1);
 | |
|   field= mysql_fetch_field(result);
 | |
|   max_blob_length= field->max_length;
 | |
| 
 | |
|   mytest(result);
 | |
| 
 | |
|   rc= my_process_result_set(result);
 | |
|   DIE_UNLESS(rc == 1);
 | |
|   mysql_free_result(result);
 | |
| 
 | |
|   sprintf(data, "%ld", (long)i*length);
 | |
|   verify_col_data("test_long_data_str", "length(longstr)", data);
 | |
| 
 | |
|   sprintf(data, "%d", i*2);
 | |
|   verify_col_data("test_long_data_str", "length(blb)", data);
 | |
| 
 | |
|   /* Test length of field->max_length */
 | |
|   stmt= mysql_simple_prepare(mysql, "SELECT * from test_long_data_str");
 | |
|   check_stmt(stmt);
 | |
|   verify_param_count(stmt, 0);
 | |
| 
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= mysql_stmt_store_result(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   result= mysql_stmt_result_metadata(stmt);
 | |
|   field= mysql_fetch_fields(result);
 | |
| 
 | |
|   /* First test what happens if STMT_ATTR_UPDATE_MAX_LENGTH is not used */
 | |
|   DIE_UNLESS(field->max_length == 0);
 | |
|   mysql_free_result(result);
 | |
| 
 | |
|   /* Enable updating of field->max_length */
 | |
|   true_value= 1;
 | |
|   mysql_stmt_attr_set(stmt, STMT_ATTR_UPDATE_MAX_LENGTH, (void*) &true_value);
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= mysql_stmt_store_result(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   result= mysql_stmt_result_metadata(stmt);
 | |
|   field= mysql_fetch_fields(result);
 | |
| 
 | |
|   DIE_UNLESS(field->max_length == max_blob_length);
 | |
| 
 | |
|   /* Fetch results into a data buffer that is smaller than data */
 | |
|   bzero((char*) my_bind, sizeof(*my_bind));
 | |
|   my_bind[0].buffer_type= MYSQL_TYPE_BLOB;
 | |
|   my_bind[0].buffer= (void *) &data; /* this buffer won't be altered */
 | |
|   my_bind[0].buffer_length= 16;
 | |
|   my_bind[0].length= &blob_length;
 | |
|   my_bind[0].error= &my_bind[0].error_value;
 | |
|   rc= mysql_stmt_bind_result(stmt, my_bind);
 | |
|   data[16]= 0;
 | |
| 
 | |
|   rc= mysql_stmt_fetch(stmt);
 | |
|   DIE_UNLESS(rc == MYSQL_DATA_TRUNCATED);
 | |
|   DIE_UNLESS(my_bind[0].error_value);
 | |
|   DIE_UNLESS(strlen(data) == 16);
 | |
|   DIE_UNLESS(blob_length == max_blob_length);
 | |
| 
 | |
|   /* Fetch all data */
 | |
|   bzero((char*) (my_bind+1), sizeof(*my_bind));
 | |
|   my_bind[1].buffer_type= MYSQL_TYPE_BLOB;
 | |
|   my_bind[1].buffer= (void *) &data; /* this buffer won't be altered */
 | |
|   my_bind[1].buffer_length= sizeof(data);
 | |
|   my_bind[1].length= &blob_length;
 | |
|   bzero(data, sizeof(data));
 | |
|   mysql_stmt_fetch_column(stmt, my_bind+1, 0, 0);
 | |
|   DIE_UNLESS(strlen(data) == max_blob_length);
 | |
| 
 | |
|   mysql_free_result(result);
 | |
|   mysql_stmt_close(stmt);
 | |
| 
 | |
|   /* Drop created table */
 | |
|   rc= mysql_query(mysql, "DROP TABLE test_long_data_str");
 | |
|   myquery(rc);
 | |
| }
 | |
| 
 | |
| 
 | |
| /* Test long data (binary) handling */
 | |
| 
 | |
| static void test_long_data_bin()
 | |
| {
 | |
|   MYSQL_STMT *stmt;
 | |
|   int        rc;
 | |
|   char       data[255];
 | |
|   long       length;
 | |
|   MYSQL_RES  *result;
 | |
|   MYSQL_BIND my_bind[2];
 | |
|   char query[MAX_TEST_QUERY_LENGTH];
 | |
| 
 | |
| 
 | |
|   myheader("test_long_data_bin");
 | |
| 
 | |
|   rc= mysql_autocommit(mysql, TRUE);
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_long_data_bin");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "CREATE TABLE test_long_data_bin(id int, longbin long varbinary)");
 | |
|   myquery(rc);
 | |
| 
 | |
|   strmov(query, "INSERT INTO test_long_data_bin VALUES(?, ?)");
 | |
|   stmt= mysql_simple_prepare(mysql, query);
 | |
|   check_stmt(stmt);
 | |
| 
 | |
|   verify_param_count(stmt, 2);
 | |
| 
 | |
|   /* Always bzero all members of bind parameter */
 | |
|   bzero((char*) my_bind, sizeof(my_bind));
 | |
| 
 | |
|   my_bind[0].buffer= (void *)&length;
 | |
|   my_bind[0].buffer_type= MYSQL_TYPE_LONG;
 | |
|   length= 0;
 | |
| 
 | |
|   my_bind[1].buffer= data;           /* string data */
 | |
|   my_bind[1].buffer_type= MYSQL_TYPE_LONG_BLOB;
 | |
|   rc= mysql_stmt_bind_param(stmt, my_bind);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   length= 10;
 | |
|   strmov(data, "MySQL AB");
 | |
| 
 | |
|   /* supply data in pieces */
 | |
|   {
 | |
|     int i;
 | |
|     for (i= 0; i < 100; i++)
 | |
|     {
 | |
|       rc= mysql_stmt_send_long_data(stmt, 1, (char *)data, 4);
 | |
|       check_execute(stmt, rc);
 | |
|     }
 | |
|   }
 | |
|   /* execute */
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   if (!opt_silent)
 | |
|     fprintf(stdout, " mysql_stmt_execute() returned %d\n", rc);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   mysql_stmt_close(stmt);
 | |
| 
 | |
|   rc= mysql_commit(mysql);
 | |
|   myquery(rc);
 | |
| 
 | |
|   /* now fetch the results ..*/
 | |
|   rc= mysql_query(mysql, "SELECT LENGTH(longbin), longbin FROM test_long_data_bin");
 | |
|   myquery(rc);
 | |
| 
 | |
|   /* get the result */
 | |
|   result= mysql_store_result(mysql);
 | |
|   mytest(result);
 | |
| 
 | |
|   rc= my_process_result_set(result);
 | |
|   DIE_UNLESS(rc == 1);
 | |
|   mysql_free_result(result);
 | |
| }
 | |
| 
 | |
| 
 | |
| /* Test simple delete */
 | |
| 
 | |
| static void test_simple_delete()
 | |
| {
 | |
|   MYSQL_STMT *stmt;
 | |
|   int        rc;
 | |
|   char       szData[30]= {0};
 | |
|   int        nData= 1;
 | |
|   MYSQL_RES  *result;
 | |
|   MYSQL_BIND my_bind[2];
 | |
|   ulong length[2];
 | |
|   char query[MAX_TEST_QUERY_LENGTH];
 | |
| 
 | |
|   myheader("test_simple_delete");
 | |
| 
 | |
|   rc= mysql_autocommit(mysql, TRUE);
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_simple_delete");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "CREATE TABLE test_simple_delete(col1 int, \
 | |
|                                 col2 varchar(50), col3 int )");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "INSERT INTO test_simple_delete VALUES(1, 'MySQL', 100)");
 | |
|   myquery(rc);
 | |
| 
 | |
|   verify_affected_rows(1);
 | |
| 
 | |
|   rc= mysql_commit(mysql);
 | |
|   myquery(rc);
 | |
| 
 | |
|   /* insert by prepare */
 | |
|   strmov(query, "DELETE FROM test_simple_delete WHERE col1= ? AND "
 | |
|                 "CONVERT(col2 USING utf8)= ? AND col3= 100");
 | |
|   stmt= mysql_simple_prepare(mysql, query);
 | |
|   check_stmt(stmt);
 | |
| 
 | |
|   verify_param_count(stmt, 2);
 | |
| 
 | |
|   /* Always bzero all members of bind parameter */
 | |
|   bzero((char*) my_bind, sizeof(my_bind));
 | |
| 
 | |
|   nData= 1;
 | |
|   strmov(szData, "MySQL");
 | |
|   my_bind[1].buffer_type= MYSQL_TYPE_STRING;
 | |
|   my_bind[1].buffer= szData;               /* string data */
 | |
|   my_bind[1].buffer_length= sizeof(szData);
 | |
|   my_bind[1].length= &length[1];
 | |
|   length[1]= 5;
 | |
| 
 | |
|   my_bind[0].buffer= (void *)&nData;
 | |
|   my_bind[0].buffer_type= MYSQL_TYPE_LONG;
 | |
| 
 | |
|   rc= mysql_stmt_bind_param(stmt, my_bind);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   verify_affected_rows(1);
 | |
| 
 | |
|   mysql_stmt_close(stmt);
 | |
| 
 | |
|   /* now fetch the results ..*/
 | |
|   rc= mysql_commit(mysql);
 | |
|   myquery(rc);
 | |
| 
 | |
|   /* test the results now, only one row should exist */
 | |
|   rc= mysql_query(mysql, "SELECT * FROM test_simple_delete");
 | |
|   myquery(rc);
 | |
| 
 | |
|   /* get the result */
 | |
|   result= mysql_store_result(mysql);
 | |
|   mytest(result);
 | |
| 
 | |
|   rc= my_process_result_set(result);
 | |
|   DIE_UNLESS(rc == 0);
 | |
|   mysql_free_result(result);
 | |
| }
 | |
| 
 | |
| 
 | |
| /* Test simple update */
 | |
| 
 | |
| static void test_update()
 | |
| {
 | |
|   MYSQL_STMT *stmt;
 | |
|   int        rc;
 | |
|   char       szData[25];
 | |
|   int        nData= 1;
 | |
|   MYSQL_RES  *result;
 | |
|   MYSQL_BIND my_bind[2];
 | |
|   ulong length[2];
 | |
|   char query[MAX_TEST_QUERY_LENGTH];
 | |
| 
 | |
|   myheader("test_update");
 | |
| 
 | |
|   rc= mysql_autocommit(mysql, TRUE);
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_update");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "CREATE TABLE test_update("
 | |
|                                "col1 int primary key auto_increment, "
 | |
|                                "col2 varchar(50), col3 int )");
 | |
|   myquery(rc);
 | |
| 
 | |
|   strmov(query, "INSERT INTO test_update(col2, col3) VALUES(?, ?)");
 | |
|   stmt= mysql_simple_prepare(mysql, query);
 | |
|   check_stmt(stmt);
 | |
| 
 | |
|   verify_param_count(stmt, 2);
 | |
| 
 | |
|   /* Always bzero all members of bind parameter */
 | |
|   bzero((char*) my_bind, sizeof(my_bind));
 | |
| 
 | |
|   /* string data */
 | |
|   my_bind[0].buffer_type= MYSQL_TYPE_STRING;
 | |
|   my_bind[0].buffer= szData;
 | |
|   my_bind[0].buffer_length= sizeof(szData);
 | |
|   my_bind[0].length= &length[0];
 | |
|   length[0]= sprintf(szData, "inserted-data");
 | |
| 
 | |
|   my_bind[1].buffer= (void *)&nData;
 | |
|   my_bind[1].buffer_type= MYSQL_TYPE_LONG;
 | |
| 
 | |
|   rc= mysql_stmt_bind_param(stmt, my_bind);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   nData= 100;
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   verify_affected_rows(1);
 | |
|   mysql_stmt_close(stmt);
 | |
| 
 | |
|   strmov(query, "UPDATE test_update SET col2= ? WHERE col3= ?");
 | |
|   stmt= mysql_simple_prepare(mysql, query);
 | |
|   check_stmt(stmt);
 | |
| 
 | |
|   verify_param_count(stmt, 2);
 | |
|   nData= 100;
 | |
| 
 | |
|   /* Always bzero all members of bind parameter */
 | |
|   bzero((char*) my_bind, sizeof(my_bind));
 | |
| 
 | |
|   my_bind[0].buffer_type= MYSQL_TYPE_STRING;
 | |
|   my_bind[0].buffer= szData;
 | |
|   my_bind[0].buffer_length= sizeof(szData);
 | |
|   my_bind[0].length= &length[0];
 | |
|   length[0]= sprintf(szData, "updated-data");
 | |
| 
 | |
|   my_bind[1].buffer= (void *)&nData;
 | |
|   my_bind[1].buffer_type= MYSQL_TYPE_LONG;
 | |
| 
 | |
|   rc= mysql_stmt_bind_param(stmt, my_bind);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
|   verify_affected_rows(1);
 | |
| 
 | |
|   mysql_stmt_close(stmt);
 | |
| 
 | |
|   /* now fetch the results ..*/
 | |
|   rc= mysql_commit(mysql);
 | |
|   myquery(rc);
 | |
| 
 | |
|   /* test the results now, only one row should exist */
 | |
|   rc= mysql_query(mysql, "SELECT * FROM test_update");
 | |
|   myquery(rc);
 | |
| 
 | |
|   /* get the result */
 | |
|   result= mysql_store_result(mysql);
 | |
|   mytest(result);
 | |
| 
 | |
|   rc= my_process_result_set(result);
 | |
|   DIE_UNLESS(rc == 1);
 | |
|   mysql_free_result(result);
 | |
| }
 | |
| 
 | |
| 
 | |
| /* Test prepare without parameters */
 | |
| 
 | |
| static void test_prepare_noparam()
 | |
| {
 | |
|   MYSQL_STMT *stmt;
 | |
|   int        rc;
 | |
|   MYSQL_RES  *result;
 | |
|   char query[MAX_TEST_QUERY_LENGTH];
 | |
| 
 | |
|   myheader("test_prepare_noparam");
 | |
| 
 | |
|   rc= mysql_query(mysql, "DROP TABLE IF EXISTS my_prepare");
 | |
|   myquery(rc);
 | |
| 
 | |
| 
 | |
|   rc= mysql_query(mysql, "CREATE TABLE my_prepare(col1 int, col2 varchar(50))");
 | |
|   myquery(rc);
 | |
| 
 | |
|   /* insert by prepare */
 | |
|   strmov(query, "INSERT INTO my_prepare VALUES(10, 'venu')");
 | |
|   stmt= mysql_simple_prepare(mysql, query);
 | |
|   check_stmt(stmt);
 | |
| 
 | |
|   verify_param_count(stmt, 0);
 | |
| 
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   mysql_stmt_close(stmt);
 | |
| 
 | |
|   /* now fetch the results ..*/
 | |
|   rc= mysql_commit(mysql);
 | |
|   myquery(rc);
 | |
| 
 | |
|   /* test the results now, only one row should exist */
 | |
|   rc= mysql_query(mysql, "SELECT * FROM my_prepare");
 | |
|   myquery(rc);
 | |
| 
 | |
|   /* get the result */
 | |
|   result= mysql_store_result(mysql);
 | |
|   mytest(result);
 | |
| 
 | |
|   rc= my_process_result_set(result);
 | |
|   DIE_UNLESS(rc == 1);
 | |
|   mysql_free_result(result);
 | |
| }
 | |
| 
 | |
| 
 | |
| /* Test simple bind result */
 | |
| 
 | |
| static void test_bind_result()
 | |
| {
 | |
|   MYSQL_STMT *stmt;
 | |
|   int        rc;
 | |
|   int        nData;
 | |
|   ulong      length1;
 | |
|   char       szData[100];
 | |
|   MYSQL_BIND my_bind[2];
 | |
|   my_bool    is_null[2];
 | |
| 
 | |
|   myheader("test_bind_result");
 | |
| 
 | |
|   rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_bind_result");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "CREATE TABLE test_bind_result(col1 int , col2 varchar(50))");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "INSERT INTO test_bind_result VALUES(10, 'venu')");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "INSERT INTO test_bind_result VALUES(20, 'MySQL')");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "INSERT INTO test_bind_result(col2) VALUES('monty')");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_commit(mysql);
 | |
|   myquery(rc);
 | |
| 
 | |
|   /* fetch */
 | |
| 
 | |
|   bzero((char*) my_bind, sizeof(my_bind));
 | |
|   my_bind[0].buffer_type= MYSQL_TYPE_LONG;
 | |
|   my_bind[0].buffer= (void *) &nData;      /* integer data */
 | |
|   my_bind[0].is_null= &is_null[0];
 | |
| 
 | |
|   my_bind[1].buffer_type= MYSQL_TYPE_STRING;
 | |
|   my_bind[1].buffer= szData;                /* string data */
 | |
|   my_bind[1].buffer_length= sizeof(szData);
 | |
|   my_bind[1].length= &length1;
 | |
|   my_bind[1].is_null= &is_null[1];
 | |
| 
 | |
|   stmt= mysql_simple_prepare(mysql, "SELECT * FROM test_bind_result");
 | |
|   check_stmt(stmt);
 | |
| 
 | |
|   rc= mysql_stmt_bind_result(stmt, my_bind);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= mysql_stmt_fetch(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   if (!opt_silent)
 | |
|     fprintf(stdout, "\n row 1: %d, %s(%lu)", nData, szData, length1);
 | |
|   DIE_UNLESS(nData == 10);
 | |
|   DIE_UNLESS(strcmp(szData, "venu") == 0);
 | |
|   DIE_UNLESS(length1 == 4);
 | |
| 
 | |
|   rc= mysql_stmt_fetch(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   if (!opt_silent)
 | |
|     fprintf(stdout, "\n row 2: %d, %s(%lu)", nData, szData, length1);
 | |
|   DIE_UNLESS(nData == 20);
 | |
|   DIE_UNLESS(strcmp(szData, "MySQL") == 0);
 | |
|   DIE_UNLESS(length1 == 5);
 | |
| 
 | |
|   rc= mysql_stmt_fetch(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   if (!opt_silent && is_null[0])
 | |
|     fprintf(stdout, "\n row 3: NULL, %s(%lu)", szData, length1);
 | |
|   DIE_UNLESS(is_null[0]);
 | |
|   DIE_UNLESS(strcmp(szData, "monty") == 0);
 | |
|   DIE_UNLESS(length1 == 5);
 | |
| 
 | |
|   rc= mysql_stmt_fetch(stmt);
 | |
|   DIE_UNLESS(rc == MYSQL_NO_DATA);
 | |
| 
 | |
|   mysql_stmt_close(stmt);
 | |
| }
 | |
| 
 | |
| 
 | |
| /* Test ext bind result */
 | |
| 
 | |
| static void test_bind_result_ext()
 | |
| {
 | |
|   MYSQL_STMT *stmt;
 | |
|   int        rc, i;
 | |
|   uchar      t_data;
 | |
|   short      s_data;
 | |
|   int        i_data;
 | |
|   longlong   b_data;
 | |
|   float      f_data;
 | |
|   double     d_data;
 | |
|   char       szData[20], bData[20];
 | |
|   ulong       szLength, bLength;
 | |
|   MYSQL_BIND my_bind[8];
 | |
|   ulong      length[8];
 | |
|   my_bool    is_null[8];
 | |
|   char	     llbuf[22];
 | |
|   myheader("test_bind_result_ext");
 | |
| 
 | |
|   rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_bind_result");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "CREATE TABLE test_bind_result(c1 tinyint, "
 | |
|                                                       " c2 smallint, "
 | |
|                                                       " c3 int, c4 bigint, "
 | |
|                                                       " c5 float, c6 double, "
 | |
|                                                       " c7 varbinary(10), "
 | |
|                                                       " c8 varchar(50))");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "INSERT INTO test_bind_result "
 | |
|                          "VALUES (19, 2999, 3999, 4999999, "
 | |
|                          " 2345.6, 5678.89563, 'venu', 'mysql')");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_commit(mysql);
 | |
|   myquery(rc);
 | |
| 
 | |
|   bzero((char*) my_bind, sizeof(my_bind));
 | |
|   for (i= 0; i < (int) array_elements(my_bind); i++)
 | |
|   {
 | |
|     my_bind[i].length=  &length[i];
 | |
|     my_bind[i].is_null= &is_null[i];
 | |
|   }
 | |
| 
 | |
|   my_bind[0].buffer_type= MYSQL_TYPE_TINY;
 | |
|   my_bind[0].buffer= (void *)&t_data;
 | |
| 
 | |
|   my_bind[1].buffer_type= MYSQL_TYPE_SHORT;
 | |
|   my_bind[2].buffer_type= MYSQL_TYPE_LONG;
 | |
| 
 | |
|   my_bind[3].buffer_type= MYSQL_TYPE_LONGLONG;
 | |
|   my_bind[1].buffer= (void *)&s_data;
 | |
| 
 | |
|   my_bind[2].buffer= (void *)&i_data;
 | |
|   my_bind[3].buffer= (void *)&b_data;
 | |
| 
 | |
|   my_bind[4].buffer_type= MYSQL_TYPE_FLOAT;
 | |
|   my_bind[4].buffer= (void *)&f_data;
 | |
| 
 | |
|   my_bind[5].buffer_type= MYSQL_TYPE_DOUBLE;
 | |
|   my_bind[5].buffer= (void *)&d_data;
 | |
| 
 | |
|   my_bind[6].buffer_type= MYSQL_TYPE_STRING;
 | |
|   my_bind[6].buffer= (void *)szData;
 | |
|   my_bind[6].buffer_length= sizeof(szData);
 | |
|   my_bind[6].length= &szLength;
 | |
| 
 | |
|   my_bind[7].buffer_type= MYSQL_TYPE_TINY_BLOB;
 | |
|   my_bind[7].buffer= (void *)&bData;
 | |
|   my_bind[7].length= &bLength;
 | |
|   my_bind[7].buffer_length= sizeof(bData);
 | |
| 
 | |
|   stmt= mysql_simple_prepare(mysql, "select * from test_bind_result");
 | |
|   check_stmt(stmt);
 | |
| 
 | |
|   rc= mysql_stmt_bind_result(stmt, my_bind);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= mysql_stmt_fetch(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   if (!opt_silent)
 | |
|   {
 | |
|     fprintf(stdout, "\n data (tiny)   : %d", t_data);
 | |
|     fprintf(stdout, "\n data (short)  : %d", s_data);
 | |
|     fprintf(stdout, "\n data (int)    : %d", i_data);
 | |
|     fprintf(stdout, "\n data (big)    : %s", llstr(b_data, llbuf));
 | |
| 
 | |
|     fprintf(stdout, "\n data (float)  : %f", f_data);
 | |
|     fprintf(stdout, "\n data (double) : %f", d_data);
 | |
| 
 | |
|     fprintf(stdout, "\n data (str)    : %s(%lu)", szData, szLength);
 | |
| 
 | |
|     bData[bLength]= '\0';                         /* bData is binary */
 | |
|     fprintf(stdout, "\n data (bin)    : %s(%lu)", bData, bLength);
 | |
|   }
 | |
| 
 | |
|   DIE_UNLESS(t_data == 19);
 | |
|   DIE_UNLESS(s_data == 2999);
 | |
|   DIE_UNLESS(i_data == 3999);
 | |
|   DIE_UNLESS(b_data == 4999999);
 | |
|   /*DIE_UNLESS(f_data == 2345.60);*/
 | |
|   /*DIE_UNLESS(d_data == 5678.89563);*/
 | |
|   DIE_UNLESS(strcmp(szData, "venu") == 0);
 | |
|   DIE_UNLESS(strncmp(bData, "mysql", 5) == 0);
 | |
|   DIE_UNLESS(szLength == 4);
 | |
|   DIE_UNLESS(bLength == 5);
 | |
| 
 | |
|   rc= mysql_stmt_fetch(stmt);
 | |
|   DIE_UNLESS(rc == MYSQL_NO_DATA);
 | |
| 
 | |
|   mysql_stmt_close(stmt);
 | |
| }
 | |
| 
 | |
| 
 | |
| /* Test ext bind result */
 | |
| 
 | |
| static void test_bind_result_ext1()
 | |
| {
 | |
|   MYSQL_STMT *stmt;
 | |
|   uint       i;
 | |
|   int        rc;
 | |
|   char       t_data[20];
 | |
|   float      s_data;
 | |
|   short      i_data;
 | |
|   uchar      b_data;
 | |
|   int        f_data;
 | |
|   int        bData;
 | |
|   char       d_data[20];
 | |
|   double     szData;
 | |
|   MYSQL_BIND my_bind[8];
 | |
|   ulong      length[8];
 | |
|   my_bool    is_null[8];
 | |
|   myheader("test_bind_result_ext1");
 | |
| 
 | |
|   rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_bind_result");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "CREATE TABLE test_bind_result(c1 tinyint, c2 smallint, \
 | |
|                                                         c3 int, c4 bigint, \
 | |
|                                                         c5 float, c6 double, \
 | |
|                                                         c7 varbinary(10), \
 | |
|                                                         c8 varchar(10))");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "INSERT INTO test_bind_result VALUES(120, 2999, 3999, 54, \
 | |
|                                                               2.6, 58.89, \
 | |
|                                                               '206', '6.7')");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_commit(mysql);
 | |
|   myquery(rc);
 | |
| 
 | |
|   bzero((char*) my_bind, sizeof(my_bind));
 | |
|   my_bind[0].buffer_type= MYSQL_TYPE_STRING;
 | |
|   my_bind[0].buffer= (void *) t_data;
 | |
|   my_bind[0].buffer_length= sizeof(t_data);
 | |
|   my_bind[0].error= &my_bind[0].error_value;
 | |
| 
 | |
|   my_bind[1].buffer_type= MYSQL_TYPE_FLOAT;
 | |
|   my_bind[1].buffer= (void *)&s_data;
 | |
|   my_bind[1].buffer_length= 0;
 | |
|   my_bind[1].error= &my_bind[1].error_value;
 | |
| 
 | |
|   my_bind[2].buffer_type= MYSQL_TYPE_SHORT;
 | |
|   my_bind[2].buffer= (void *)&i_data;
 | |
|   my_bind[2].buffer_length= 0;
 | |
|   my_bind[2].error= &my_bind[2].error_value;
 | |
| 
 | |
|   my_bind[3].buffer_type= MYSQL_TYPE_TINY;
 | |
|   my_bind[3].buffer= (void *)&b_data;
 | |
|   my_bind[3].buffer_length= 0;
 | |
|   my_bind[3].error= &my_bind[3].error_value;
 | |
| 
 | |
|   my_bind[4].buffer_type= MYSQL_TYPE_LONG;
 | |
|   my_bind[4].buffer= (void *)&f_data;
 | |
|   my_bind[4].buffer_length= 0;
 | |
|   my_bind[4].error= &my_bind[4].error_value;
 | |
| 
 | |
|   my_bind[5].buffer_type= MYSQL_TYPE_STRING;
 | |
|   my_bind[5].buffer= (void *)d_data;
 | |
|   my_bind[5].buffer_length= sizeof(d_data);
 | |
|   my_bind[5].error= &my_bind[5].error_value;
 | |
| 
 | |
|   my_bind[6].buffer_type= MYSQL_TYPE_LONG;
 | |
|   my_bind[6].buffer= (void *)&bData;
 | |
|   my_bind[6].buffer_length= 0;
 | |
|   my_bind[6].error= &my_bind[6].error_value;
 | |
| 
 | |
|   my_bind[7].buffer_type= MYSQL_TYPE_DOUBLE;
 | |
|   my_bind[7].buffer= (void *)&szData;
 | |
|   my_bind[7].buffer_length= 0;
 | |
|   my_bind[7].error= &my_bind[7].error_value;
 | |
| 
 | |
|   for (i= 0; i < array_elements(my_bind); i++)
 | |
|   {
 | |
|     my_bind[i].is_null= &is_null[i];
 | |
|     my_bind[i].length= &length[i];
 | |
|   }
 | |
| 
 | |
|   stmt= mysql_simple_prepare(mysql, "select * from test_bind_result");
 | |
|   check_stmt(stmt);
 | |
| 
 | |
|   rc= mysql_stmt_bind_result(stmt, my_bind);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= mysql_stmt_fetch(stmt);
 | |
|   printf("rc=%d\n", rc);
 | |
|   DIE_UNLESS(rc == 0);
 | |
| 
 | |
|   if (!opt_silent)
 | |
|   {
 | |
|     fprintf(stdout, "\n data (tiny)   : %s(%lu)", t_data, length[0]);
 | |
|     fprintf(stdout, "\n data (short)  : %f(%lu)", s_data, length[1]);
 | |
|     fprintf(stdout, "\n data (int)    : %d(%lu)", i_data, length[2]);
 | |
|     fprintf(stdout, "\n data (big)    : %d(%lu)", b_data, length[3]);
 | |
| 
 | |
|     fprintf(stdout, "\n data (float)  : %d(%lu)", f_data, length[4]);
 | |
|     fprintf(stdout, "\n data (double) : %s(%lu)", d_data, length[5]);
 | |
| 
 | |
|     fprintf(stdout, "\n data (bin)    : %d(%lu)", bData, length[6]);
 | |
|     fprintf(stdout, "\n data (str)    : %g(%lu)", szData, length[7]);
 | |
|   }
 | |
| 
 | |
|   DIE_UNLESS(strcmp(t_data, "120") == 0);
 | |
|   DIE_UNLESS(i_data == 3999);
 | |
|   DIE_UNLESS(f_data == 2);
 | |
|   DIE_UNLESS(strcmp(d_data, "58.89") == 0);
 | |
|   DIE_UNLESS(b_data == 54);
 | |
| 
 | |
|   DIE_UNLESS(length[0] == 3);
 | |
|   DIE_UNLESS(length[1] == 4);
 | |
|   DIE_UNLESS(length[2] == 2);
 | |
|   DIE_UNLESS(length[3] == 1);
 | |
|   DIE_UNLESS(length[4] == 4);
 | |
|   DIE_UNLESS(length[5] == 5);
 | |
|   DIE_UNLESS(length[6] == 4);
 | |
|   DIE_UNLESS(length[7] == 8);
 | |
| 
 | |
|   rc= mysql_stmt_fetch(stmt);
 | |
|   DIE_UNLESS(rc == MYSQL_NO_DATA);
 | |
| 
 | |
|   mysql_stmt_close(stmt);
 | |
| }
 | |
| 
 | |
| 
 | |
| /* Generalized fetch conversion routine for all basic types */
 | |
| 
 | |
| static void bind_fetch(int row_count)
 | |
| {
 | |
|   MYSQL_STMT   *stmt;
 | |
|   int          rc, i, count= row_count;
 | |
|   int32        data[10];
 | |
|   int8         i8_data;
 | |
|   int16        i16_data;
 | |
|   int32        i32_data;
 | |
|   longlong     i64_data;
 | |
|   float        f_data;
 | |
|   double       d_data;
 | |
|   char         s_data[10];
 | |
|   ulong        length[10];
 | |
|   MYSQL_BIND   my_bind[7];
 | |
|   my_bool      is_null[7];
 | |
| 
 | |
|   stmt= mysql_simple_prepare(mysql, "INSERT INTO test_bind_fetch VALUES "
 | |
|                                     "(?, ?, ?, ?, ?, ?, ?)");
 | |
|   check_stmt(stmt);
 | |
| 
 | |
|   verify_param_count(stmt, 7);
 | |
| 
 | |
|   /* Always bzero all members of bind parameter */
 | |
|   bzero((char*) my_bind, sizeof(my_bind));
 | |
| 
 | |
|   for (i= 0; i < (int) array_elements(my_bind); i++)
 | |
|   {
 | |
|     my_bind[i].buffer_type= MYSQL_TYPE_LONG;
 | |
|     my_bind[i].buffer= (void *) &data[i];
 | |
|   }
 | |
|   rc= mysql_stmt_bind_param(stmt, my_bind);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   while (count--)
 | |
|   {
 | |
|     rc= 10+count;
 | |
|     for (i= 0; i < (int) array_elements(my_bind); i++)
 | |
|     {
 | |
|       data[i]= rc+i;
 | |
|       rc+= 12;
 | |
|     }
 | |
|     rc= mysql_stmt_execute(stmt);
 | |
|     check_execute(stmt, rc);
 | |
|   }
 | |
| 
 | |
|   rc= mysql_commit(mysql);
 | |
|   myquery(rc);
 | |
| 
 | |
|   mysql_stmt_close(stmt);
 | |
| 
 | |
|   rc= my_stmt_result("SELECT * FROM test_bind_fetch");
 | |
|   DIE_UNLESS(row_count == rc);
 | |
| 
 | |
|   stmt= mysql_simple_prepare(mysql, "SELECT * FROM test_bind_fetch");
 | |
|   check_stmt(stmt);
 | |
| 
 | |
|   for (i= 0; i < (int) array_elements(my_bind); i++)
 | |
|   {
 | |
|     my_bind[i].buffer= (void *) &data[i];
 | |
|     my_bind[i].length= &length[i];
 | |
|     my_bind[i].is_null= &is_null[i];
 | |
|   }
 | |
| 
 | |
|   my_bind[0].buffer_type= MYSQL_TYPE_TINY;
 | |
|   my_bind[0].buffer= (void *)&i8_data;
 | |
| 
 | |
|   my_bind[1].buffer_type= MYSQL_TYPE_SHORT;
 | |
|   my_bind[1].buffer= (void *)&i16_data;
 | |
| 
 | |
|   my_bind[2].buffer_type= MYSQL_TYPE_LONG;
 | |
|   my_bind[2].buffer= (void *)&i32_data;
 | |
| 
 | |
|   my_bind[3].buffer_type= MYSQL_TYPE_LONGLONG;
 | |
|   my_bind[3].buffer= (void *)&i64_data;
 | |
| 
 | |
|   my_bind[4].buffer_type= MYSQL_TYPE_FLOAT;
 | |
|   my_bind[4].buffer= (void *)&f_data;
 | |
| 
 | |
|   my_bind[5].buffer_type= MYSQL_TYPE_DOUBLE;
 | |
|   my_bind[5].buffer= (void *)&d_data;
 | |
| 
 | |
|   my_bind[6].buffer_type= MYSQL_TYPE_STRING;
 | |
|   my_bind[6].buffer= (void *)&s_data;
 | |
|   my_bind[6].buffer_length= sizeof(s_data);
 | |
| 
 | |
|   rc= mysql_stmt_bind_result(stmt, my_bind);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= mysql_stmt_store_result(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   while (row_count--)
 | |
|   {
 | |
|     rc= mysql_stmt_fetch(stmt);
 | |
|     check_execute(stmt, rc);
 | |
| 
 | |
|     if (!opt_silent)
 | |
|     {
 | |
|       fprintf(stdout, "\n");
 | |
|       fprintf(stdout, "\n tiny     : %ld(%lu)", (ulong) i8_data, length[0]);
 | |
|       fprintf(stdout, "\n short    : %ld(%lu)", (ulong) i16_data, length[1]);
 | |
|       fprintf(stdout, "\n int      : %ld(%lu)", (ulong) i32_data, length[2]);
 | |
|       fprintf(stdout, "\n longlong : %ld(%lu)", (ulong) i64_data, length[3]);
 | |
|       fprintf(stdout, "\n float    : %f(%lu)",  f_data,  length[4]);
 | |
|       fprintf(stdout, "\n double   : %g(%lu)",  d_data,  length[5]);
 | |
|       fprintf(stdout, "\n char     : %s(%lu)",  s_data,  length[6]);
 | |
|     }
 | |
|     rc= 10+row_count;
 | |
| 
 | |
|     /* TINY */
 | |
|     DIE_UNLESS((int) i8_data == rc);
 | |
|     DIE_UNLESS(length[0] == 1);
 | |
|     rc+= 13;
 | |
| 
 | |
|     /* SHORT */
 | |
|     DIE_UNLESS((int) i16_data == rc);
 | |
|     DIE_UNLESS(length[1] == 2);
 | |
|     rc+= 13;
 | |
| 
 | |
|     /* LONG */
 | |
|     DIE_UNLESS((int) i32_data == rc);
 | |
|     DIE_UNLESS(length[2] == 4);
 | |
|     rc+= 13;
 | |
| 
 | |
|     /* LONGLONG */
 | |
|     DIE_UNLESS((int) i64_data == rc);
 | |
|     DIE_UNLESS(length[3] == 8);
 | |
|     rc+= 13;
 | |
| 
 | |
|     /* FLOAT */
 | |
|     DIE_UNLESS((int)f_data == rc);
 | |
|     DIE_UNLESS(length[4] == 4);
 | |
|     rc+= 13;
 | |
| 
 | |
|     /* DOUBLE */
 | |
|     DIE_UNLESS((int)d_data == rc);
 | |
|     DIE_UNLESS(length[5] == 8);
 | |
|     rc+= 13;
 | |
| 
 | |
|     /* CHAR */
 | |
|     {
 | |
|       char buff[20];
 | |
|       long len= sprintf(buff, "%d", rc);
 | |
|       DIE_UNLESS(strcmp(s_data, buff) == 0);
 | |
|       DIE_UNLESS(length[6] == (ulong) len);
 | |
|     }
 | |
|   }
 | |
|   rc= mysql_stmt_fetch(stmt);
 | |
|   DIE_UNLESS(rc == MYSQL_NO_DATA);
 | |
| 
 | |
|   mysql_stmt_close(stmt);
 | |
| }
 | |
| 
 | |
| 
 | |
| /* Test fetching of date, time and ts */
 | |
| 
 | |
| static void test_fetch_date()
 | |
| {
 | |
|   MYSQL_STMT *stmt;
 | |
|   uint       i;
 | |
|   int        rc, year;
 | |
|   char       date[25], my_time[25], ts[25], ts_4[25], ts_6[20], dt[20];
 | |
|   ulong      d_length, t_length, ts_length, ts4_length, ts6_length,
 | |
|              dt_length, y_length;
 | |
|   MYSQL_BIND my_bind[8];
 | |
|   my_bool    is_null[8];
 | |
|   ulong      length[8];
 | |
| 
 | |
|   myheader("test_fetch_date");
 | |
| 
 | |
|   /* Will not work if sql_mode is NO_ZERO_DATE (implicit if TRADITIONAL) */
 | |
|   rc= mysql_query(mysql, "SET SQL_MODE=''");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_bind_result");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "CREATE TABLE test_bind_result(c1 date, c2 time, \
 | |
|                                                         c3 timestamp, \
 | |
|                                                         c4 year, \
 | |
|                                                         c5 datetime, \
 | |
|                                                         c6 timestamp, \
 | |
|                                                         c7 timestamp)");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "SET SQL_MODE=''");
 | |
|   rc= mysql_query(mysql, "INSERT INTO test_bind_result VALUES('2002-01-02', \
 | |
|                                                               '12:49:00', \
 | |
|                                                               '2002-01-02 17:46:59', \
 | |
|                                                               2010, \
 | |
|                                                               '2010-07-10', \
 | |
|                                                               '2020', '1999-12-29')");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_commit(mysql);
 | |
|   myquery(rc);
 | |
| 
 | |
|   bzero((char*) my_bind, sizeof(my_bind));
 | |
|   for (i= 0; i < array_elements(my_bind); i++)
 | |
|   {
 | |
|     my_bind[i].is_null= &is_null[i];
 | |
|     my_bind[i].length= &length[i];
 | |
|   }
 | |
| 
 | |
|   my_bind[0].buffer_type= MYSQL_TYPE_STRING;
 | |
|   my_bind[1]= my_bind[2]= my_bind[0];
 | |
| 
 | |
|   my_bind[0].buffer= (void *)&date;
 | |
|   my_bind[0].buffer_length= sizeof(date);
 | |
|   my_bind[0].length= &d_length;
 | |
| 
 | |
|   my_bind[1].buffer= (void *)&my_time;
 | |
|   my_bind[1].buffer_length= sizeof(my_time);
 | |
|   my_bind[1].length= &t_length;
 | |
| 
 | |
|   my_bind[2].buffer= (void *)&ts;
 | |
|   my_bind[2].buffer_length= sizeof(ts);
 | |
|   my_bind[2].length= &ts_length;
 | |
| 
 | |
|   my_bind[3].buffer_type= MYSQL_TYPE_LONG;
 | |
|   my_bind[3].buffer= (void *)&year;
 | |
|   my_bind[3].length= &y_length;
 | |
| 
 | |
|   my_bind[4].buffer_type= MYSQL_TYPE_STRING;
 | |
|   my_bind[4].buffer= (void *)&dt;
 | |
|   my_bind[4].buffer_length= sizeof(dt);
 | |
|   my_bind[4].length= &dt_length;
 | |
| 
 | |
|   my_bind[5].buffer_type= MYSQL_TYPE_STRING;
 | |
|   my_bind[5].buffer= (void *)&ts_4;
 | |
|   my_bind[5].buffer_length= sizeof(ts_4);
 | |
|   my_bind[5].length= &ts4_length;
 | |
| 
 | |
|   my_bind[6].buffer_type= MYSQL_TYPE_STRING;
 | |
|   my_bind[6].buffer= (void *)&ts_6;
 | |
|   my_bind[6].buffer_length= sizeof(ts_6);
 | |
|   my_bind[6].length= &ts6_length;
 | |
| 
 | |
|   rc= my_stmt_result("SELECT * FROM test_bind_result");
 | |
|   DIE_UNLESS(rc == 1);
 | |
| 
 | |
|   stmt= mysql_simple_prepare(mysql, "SELECT * FROM test_bind_result");
 | |
|   check_stmt(stmt);
 | |
| 
 | |
|   rc= mysql_stmt_bind_result(stmt, my_bind);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   ts_4[0]= '\0';
 | |
|   rc= mysql_stmt_fetch(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   if (!opt_silent)
 | |
|   {
 | |
|     fprintf(stdout, "\n date   : %s(%lu)", date, d_length);
 | |
|     fprintf(stdout, "\n time   : %s(%lu)", my_time, t_length);
 | |
|     fprintf(stdout, "\n ts     : %s(%lu)", ts, ts_length);
 | |
|     fprintf(stdout, "\n year   : %d(%lu)", year, y_length);
 | |
|     fprintf(stdout, "\n dt     : %s(%lu)", dt,  dt_length);
 | |
|     fprintf(stdout, "\n ts(4)  : %s(%lu)", ts_4, ts4_length);
 | |
|     fprintf(stdout, "\n ts(6)  : %s(%lu)", ts_6, ts6_length);
 | |
|   }
 | |
| 
 | |
|   DIE_UNLESS(strcmp(date, "2002-01-02") == 0);
 | |
|   DIE_UNLESS(d_length == 10);
 | |
| 
 | |
|   DIE_UNLESS(strcmp(my_time, "12:49:00") == 0);
 | |
|   DIE_UNLESS(t_length == 8);
 | |
| 
 | |
|   DIE_UNLESS(strcmp(ts, "2002-01-02 17:46:59") == 0);
 | |
|   DIE_UNLESS(ts_length == 19);
 | |
| 
 | |
|   DIE_UNLESS(year == 2010);
 | |
|   DIE_UNLESS(y_length == 4);
 | |
| 
 | |
|   DIE_UNLESS(strcmp(dt, "2010-07-10 00:00:00") == 0);
 | |
|   DIE_UNLESS(dt_length == 19);
 | |
| 
 | |
|   DIE_UNLESS(strcmp(ts_4, "0000-00-00 00:00:00") == 0);
 | |
|   DIE_UNLESS(ts4_length == strlen("0000-00-00 00:00:00"));
 | |
| 
 | |
|   DIE_UNLESS(strcmp(ts_6, "1999-12-29 00:00:00") == 0);
 | |
|   DIE_UNLESS(ts6_length == 19);
 | |
| 
 | |
|   rc= mysql_stmt_fetch(stmt);
 | |
|   DIE_UNLESS(rc == MYSQL_NO_DATA);
 | |
| 
 | |
|   mysql_stmt_close(stmt);
 | |
| }
 | |
| 
 | |
| 
 | |
| /* Test fetching of str to all types */
 | |
| 
 | |
| static void test_fetch_str()
 | |
| {
 | |
|   int rc;
 | |
| 
 | |
|   myheader("test_fetch_str");
 | |
| 
 | |
|   rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_bind_fetch");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "CREATE TABLE test_bind_fetch(c1 char(10), \
 | |
|                                                      c2 char(10), \
 | |
|                                                      c3 char(20), \
 | |
|                                                      c4 char(20), \
 | |
|                                                      c5 char(30), \
 | |
|                                                      c6 char(40), \
 | |
|                                                      c7 char(20))");
 | |
|   myquery(rc);
 | |
| 
 | |
|   bind_fetch(3);
 | |
| }
 | |
| 
 | |
| 
 | |
| /* Test fetching of long to all types */
 | |
| 
 | |
| static void test_fetch_long()
 | |
| {
 | |
|   int rc;
 | |
| 
 | |
|   myheader("test_fetch_long");
 | |
| 
 | |
|   rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_bind_fetch");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "CREATE TABLE test_bind_fetch(c1 int unsigned, \
 | |
|                                                      c2 int unsigned, \
 | |
|                                                      c3 int, \
 | |
|                                                      c4 int, \
 | |
|                                                      c5 int, \
 | |
|                                                      c6 int unsigned, \
 | |
|                                                      c7 int)");
 | |
|   myquery(rc);
 | |
| 
 | |
|   bind_fetch(4);
 | |
| }
 | |
| 
 | |
| 
 | |
| /* Test fetching of short to all types */
 | |
| 
 | |
| static void test_fetch_short()
 | |
| {
 | |
|   int rc;
 | |
| 
 | |
|   myheader("test_fetch_short");
 | |
| 
 | |
|   rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_bind_fetch");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "CREATE TABLE test_bind_fetch(c1 smallint unsigned, \
 | |
|                                                      c2 smallint, \
 | |
|                                                      c3 smallint unsigned, \
 | |
|                                                      c4 smallint, \
 | |
|                                                      c5 smallint, \
 | |
|                                                      c6 smallint, \
 | |
|                                                      c7 smallint unsigned)");
 | |
|   myquery(rc);
 | |
| 
 | |
|   bind_fetch(5);
 | |
| }
 | |
| 
 | |
| 
 | |
| /* Test fetching of tiny to all types */
 | |
| 
 | |
| static void test_fetch_tiny()
 | |
| {
 | |
|   int rc;
 | |
| 
 | |
|   myheader("test_fetch_tiny");
 | |
| 
 | |
|   rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_bind_fetch");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "CREATE TABLE test_bind_fetch(c1 tinyint unsigned, \
 | |
|                                                      c2 tinyint, \
 | |
|                                                      c3 tinyint unsigned, \
 | |
|                                                      c4 tinyint, \
 | |
|                                                      c5 tinyint, \
 | |
|                                                      c6 tinyint, \
 | |
|                                                      c7 tinyint unsigned)");
 | |
|   myquery(rc);
 | |
| 
 | |
|   bind_fetch(3);
 | |
| 
 | |
| }
 | |
| 
 | |
| 
 | |
| /* Test fetching of longlong to all types */
 | |
| 
 | |
| static void test_fetch_bigint()
 | |
| {
 | |
|   int rc;
 | |
| 
 | |
|   myheader("test_fetch_bigint");
 | |
| 
 | |
|   rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_bind_fetch");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "CREATE TABLE test_bind_fetch(c1 bigint, \
 | |
|                                                      c2 bigint, \
 | |
|                                                      c3 bigint unsigned, \
 | |
|                                                      c4 bigint unsigned, \
 | |
|                                                      c5 bigint unsigned, \
 | |
|                                                      c6 bigint unsigned, \
 | |
|                                                      c7 bigint unsigned)");
 | |
|   myquery(rc);
 | |
| 
 | |
|   bind_fetch(2);
 | |
| 
 | |
| }
 | |
| 
 | |
| 
 | |
| /* Test fetching of float to all types */
 | |
| 
 | |
| static void test_fetch_float()
 | |
| {
 | |
|   int rc;
 | |
| 
 | |
|   myheader("test_fetch_float");
 | |
| 
 | |
|   rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_bind_fetch");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "CREATE TABLE test_bind_fetch(c1 float(3), \
 | |
|                                                      c2 float, \
 | |
|                                                      c3 float unsigned, \
 | |
|                                                      c4 float, \
 | |
|                                                      c5 float, \
 | |
|                                                      c6 float, \
 | |
|                                                      c7 float(10) unsigned)");
 | |
|   myquery(rc);
 | |
| 
 | |
|   bind_fetch(2);
 | |
| 
 | |
| }
 | |
| 
 | |
| 
 | |
| /* Test fetching of double to all types */
 | |
| 
 | |
| static void test_fetch_double()
 | |
| {
 | |
|   int rc;
 | |
| 
 | |
|   myheader("test_fetch_double");
 | |
| 
 | |
|   rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_bind_fetch");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "CREATE TABLE test_bind_fetch(c1 double(5, 2), "
 | |
|                          "c2 double unsigned, c3 double unsigned, "
 | |
|                          "c4 double unsigned, c5 double unsigned, "
 | |
|                          "c6 double unsigned, c7 double unsigned)");
 | |
|   myquery(rc);
 | |
| 
 | |
|   bind_fetch(3);
 | |
| 
 | |
| }
 | |
| 
 | |
| 
 | |
| /* Test simple prepare with all possible types */
 | |
| 
 | |
| static void test_prepare_ext()
 | |
| {
 | |
|   MYSQL_STMT *stmt;
 | |
|   int        rc;
 | |
|   char       *sql;
 | |
|   int        nData= 1;
 | |
|   char       tData= 1;
 | |
|   short      sData= 10;
 | |
|   longlong   bData= 20;
 | |
|   MYSQL_BIND my_bind[6];
 | |
|   char query[MAX_TEST_QUERY_LENGTH];
 | |
|   myheader("test_prepare_ext");
 | |
| 
 | |
|   rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_prepare_ext");
 | |
|   myquery(rc);
 | |
| 
 | |
|   sql= (char *)"CREATE TABLE test_prepare_ext"
 | |
|                "("
 | |
|                " c1  tinyint,"
 | |
|                " c2  smallint,"
 | |
|                " c3  mediumint,"
 | |
|                " c4  int,"
 | |
|                " c5  integer,"
 | |
|                " c6  bigint,"
 | |
|                " c7  float,"
 | |
|                " c8  double,"
 | |
|                " c9  double precision,"
 | |
|                " c10 real,"
 | |
|                " c11 decimal(7, 4),"
 | |
|                " c12 numeric(8, 4),"
 | |
|                " c13 date,"
 | |
|                " c14 datetime,"
 | |
|                " c15 timestamp,"
 | |
|                " c16 time,"
 | |
|                " c17 year,"
 | |
|                " c18 bit,"
 | |
|                " c19 bool,"
 | |
|                " c20 char,"
 | |
|                " c21 char(10),"
 | |
|                " c22 varchar(30),"
 | |
|                " c23 tinyblob,"
 | |
|                " c24 tinytext,"
 | |
|                " c25 blob,"
 | |
|                " c26 text,"
 | |
|                " c27 mediumblob,"
 | |
|                " c28 mediumtext,"
 | |
|                " c29 longblob,"
 | |
|                " c30 longtext,"
 | |
|                " c31 enum('one', 'two', 'three'),"
 | |
|                " c32 set('monday', 'tuesday', 'wednesday'))";
 | |
| 
 | |
|   rc= mysql_query(mysql, sql);
 | |
|   myquery(rc);
 | |
| 
 | |
|   /* insert by prepare - all integers */
 | |
|   strmov(query, (char *)"INSERT INTO test_prepare_ext(c1, c2, c3, c4, c5, c6) VALUES(?, ?, ?, ?, ?, ?)");
 | |
|   stmt= mysql_simple_prepare(mysql, query);
 | |
|   check_stmt(stmt);
 | |
| 
 | |
|   verify_param_count(stmt, 6);
 | |
| 
 | |
|   /* Always bzero all members of bind parameter */
 | |
|   bzero((char*) my_bind, sizeof(my_bind));
 | |
| 
 | |
|   /*tinyint*/
 | |
|   my_bind[0].buffer_type= MYSQL_TYPE_TINY;
 | |
|   my_bind[0].buffer= (void *)&tData;
 | |
| 
 | |
|   /*smallint*/
 | |
|   my_bind[1].buffer_type= MYSQL_TYPE_SHORT;
 | |
|   my_bind[1].buffer= (void *)&sData;
 | |
| 
 | |
|   /*mediumint*/
 | |
|   my_bind[2].buffer_type= MYSQL_TYPE_LONG;
 | |
|   my_bind[2].buffer= (void *)&nData;
 | |
| 
 | |
|   /*int*/
 | |
|   my_bind[3].buffer_type= MYSQL_TYPE_LONG;
 | |
|   my_bind[3].buffer= (void *)&nData;
 | |
| 
 | |
|   /*integer*/
 | |
|   my_bind[4].buffer_type= MYSQL_TYPE_LONG;
 | |
|   my_bind[4].buffer= (void *)&nData;
 | |
| 
 | |
|   /*bigint*/
 | |
|   my_bind[5].buffer_type= MYSQL_TYPE_LONGLONG;
 | |
|   my_bind[5].buffer= (void *)&bData;
 | |
| 
 | |
|   rc= mysql_stmt_bind_param(stmt, my_bind);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   /*
 | |
|   *  integer to integer
 | |
|   */
 | |
|   for (nData= 0; nData<10; nData++, tData++, sData++, bData++)
 | |
|   {
 | |
|     rc= mysql_stmt_execute(stmt);
 | |
|     check_execute(stmt, rc);
 | |
|   }
 | |
|   mysql_stmt_close(stmt);
 | |
| 
 | |
|   /* now fetch the results ..*/
 | |
| 
 | |
|   stmt= mysql_simple_prepare(mysql, "SELECT c1, c2, c3, c4, c5, c6 "
 | |
|                                     "FROM test_prepare_ext");
 | |
|   check_stmt(stmt);
 | |
| 
 | |
|   /* get the result */
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= my_process_stmt_result(stmt);
 | |
|   DIE_UNLESS(nData == rc);
 | |
| 
 | |
|   mysql_stmt_close(stmt);
 | |
| }
 | |
| 
 | |
| 
 | |
| /* Test real and alias names */
 | |
| 
 | |
| static void test_field_names()
 | |
| {
 | |
|   int        rc;
 | |
|   MYSQL_RES  *result;
 | |
| 
 | |
|   myheader("test_field_names");
 | |
| 
 | |
|   if (!opt_silent)
 | |
|     fprintf(stdout, "\n %d, %d, %d", MYSQL_TYPE_DECIMAL, MYSQL_TYPE_NEWDATE, MYSQL_TYPE_ENUM);
 | |
|   rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_field_names1");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_field_names2");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "CREATE TABLE test_field_names1(id int, name varchar(50))");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "CREATE TABLE test_field_names2(id int, name varchar(50))");
 | |
|   myquery(rc);
 | |
| 
 | |
|   /* with table name included with TRUE column name */
 | |
|   rc= mysql_query(mysql, "SELECT id as 'id-alias' FROM test_field_names1");
 | |
|   myquery(rc);
 | |
| 
 | |
|   result= mysql_use_result(mysql);
 | |
|   mytest(result);
 | |
| 
 | |
|   rc= my_process_result_set(result);
 | |
|   DIE_UNLESS(rc == 0);
 | |
|   mysql_free_result(result);
 | |
| 
 | |
|   /* with table name included with TRUE column name */
 | |
|   rc= mysql_query(mysql, "SELECT t1.id as 'id-alias', test_field_names2.name FROM test_field_names1 t1, test_field_names2");
 | |
|   myquery(rc);
 | |
| 
 | |
|   result= mysql_use_result(mysql);
 | |
|   mytest(result);
 | |
| 
 | |
|   rc= my_process_result_set(result);
 | |
|   DIE_UNLESS(rc == 0);
 | |
|   mysql_free_result(result);
 | |
| }
 | |
| 
 | |
| 
 | |
| /* Test warnings */
 | |
| 
 | |
| static void test_warnings()
 | |
| {
 | |
|   int        rc;
 | |
|   MYSQL_RES  *result;
 | |
| 
 | |
|   myheader("test_warnings");
 | |
| 
 | |
|   mysql_query(mysql, "DROP TABLE if exists test_non_exists");
 | |
| 
 | |
|   rc= mysql_query(mysql, "DROP TABLE if exists test_non_exists");
 | |
|   myquery(rc);
 | |
| 
 | |
|   if (!opt_silent)
 | |
|     fprintf(stdout, "\n total warnings: %d", mysql_warning_count(mysql));
 | |
|   rc= mysql_query(mysql, "SHOW WARNINGS");
 | |
|   myquery(rc);
 | |
| 
 | |
|   result= mysql_store_result(mysql);
 | |
|   mytest(result);
 | |
| 
 | |
|   rc= my_process_result_set(result);
 | |
|   DIE_UNLESS(rc == 1);
 | |
|   mysql_free_result(result);
 | |
| }
 | |
| 
 | |
| 
 | |
| /* Test errors */
 | |
| 
 | |
| static void test_errors()
 | |
| {
 | |
|   int        rc;
 | |
|   MYSQL_RES  *result;
 | |
| 
 | |
|   myheader("test_errors");
 | |
| 
 | |
|   mysql_query(mysql, "DROP TABLE if exists test_non_exists");
 | |
| 
 | |
|   rc= mysql_query(mysql, "DROP TABLE test_non_exists");
 | |
|   myquery_r(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "SHOW ERRORS");
 | |
|   myquery(rc);
 | |
| 
 | |
|   result= mysql_store_result(mysql);
 | |
|   mytest(result);
 | |
| 
 | |
|   (void) my_process_result_set(result);
 | |
|   mysql_free_result(result);
 | |
| }
 | |
| 
 | |
| 
 | |
| /* Test simple prepare-insert */
 | |
| 
 | |
| static void test_insert()
 | |
| {
 | |
|   MYSQL_STMT *stmt;
 | |
|   int        rc;
 | |
|   char       str_data[50];
 | |
|   char       tiny_data;
 | |
|   MYSQL_RES  *result;
 | |
|   MYSQL_BIND my_bind[2];
 | |
|   ulong      length;
 | |
| 
 | |
|   myheader("test_insert");
 | |
| 
 | |
|   rc= mysql_autocommit(mysql, TRUE);
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_prep_insert");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "CREATE TABLE test_prep_insert(col1 tinyint, \
 | |
|                                 col2 varchar(50))");
 | |
|   myquery(rc);
 | |
| 
 | |
|   /* insert by prepare */
 | |
|   stmt= mysql_simple_prepare(mysql,
 | |
|                              "INSERT INTO test_prep_insert VALUES(?, ?)");
 | |
|   check_stmt(stmt);
 | |
| 
 | |
|   verify_param_count(stmt, 2);
 | |
| 
 | |
|   /*
 | |
|     We need to bzero bind structure because mysql_stmt_bind_param checks all
 | |
|     its members.
 | |
|   */
 | |
|   bzero((char*) my_bind, sizeof(my_bind));
 | |
| 
 | |
|   /* tinyint */
 | |
|   my_bind[0].buffer_type= MYSQL_TYPE_TINY;
 | |
|   my_bind[0].buffer= (void *)&tiny_data;
 | |
| 
 | |
|   /* string */
 | |
|   my_bind[1].buffer_type= MYSQL_TYPE_STRING;
 | |
|   my_bind[1].buffer= str_data;
 | |
|   my_bind[1].buffer_length= sizeof(str_data);;
 | |
|   my_bind[1].length= &length;
 | |
| 
 | |
|   rc= mysql_stmt_bind_param(stmt, my_bind);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   /* now, execute the prepared statement to insert 10 records.. */
 | |
|   for (tiny_data= 0; tiny_data < 3; tiny_data++)
 | |
|   {
 | |
|     length= sprintf(str_data, "MySQL%d", tiny_data);
 | |
|     rc= mysql_stmt_execute(stmt);
 | |
|     check_execute(stmt, rc);
 | |
|   }
 | |
| 
 | |
|   mysql_stmt_close(stmt);
 | |
| 
 | |
|   /* now fetch the results ..*/
 | |
|   rc= mysql_commit(mysql);
 | |
|   myquery(rc);
 | |
| 
 | |
|   /* test the results now, only one row should exist */
 | |
|   rc= mysql_query(mysql, "SELECT * FROM test_prep_insert");
 | |
|   myquery(rc);
 | |
| 
 | |
|   /* get the result */
 | |
|   result= mysql_store_result(mysql);
 | |
|   mytest(result);
 | |
| 
 | |
|   rc= my_process_result_set(result);
 | |
|   DIE_UNLESS((int) tiny_data == rc);
 | |
|   mysql_free_result(result);
 | |
| 
 | |
| }
 | |
| 
 | |
| 
 | |
| /* Test simple prepare-resultset info */
 | |
| 
 | |
| static void test_prepare_resultset()
 | |
| {
 | |
|   MYSQL_STMT *stmt;
 | |
|   int        rc;
 | |
|   MYSQL_RES  *result;
 | |
| 
 | |
|   myheader("test_prepare_resultset");
 | |
| 
 | |
|   rc= mysql_autocommit(mysql, TRUE);
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_prepare_resultset");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "CREATE TABLE test_prepare_resultset(id int, \
 | |
|                                 name varchar(50), extra double)");
 | |
|   myquery(rc);
 | |
| 
 | |
|   stmt= mysql_simple_prepare(mysql, "SELECT * FROM test_prepare_resultset");
 | |
|   check_stmt(stmt);
 | |
| 
 | |
|   verify_param_count(stmt, 0);
 | |
| 
 | |
|   result= mysql_stmt_result_metadata(stmt);
 | |
|   mytest(result);
 | |
|   my_print_result_metadata(result);
 | |
|   mysql_free_result(result);
 | |
|   mysql_stmt_close(stmt);
 | |
| }
 | |
| 
 | |
| 
 | |
| /* Test field flags (verify .NET provider) */
 | |
| 
 | |
| static void test_field_flags()
 | |
| {
 | |
|   int          rc;
 | |
|   MYSQL_RES    *result;
 | |
|   MYSQL_FIELD  *field;
 | |
|   unsigned int i;
 | |
| 
 | |
| 
 | |
|   myheader("test_field_flags");
 | |
| 
 | |
|   rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_field_flags");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "CREATE TABLE test_field_flags(id int NOT NULL AUTO_INCREMENT PRIMARY KEY, \
 | |
|                                                         id1 int NOT NULL, \
 | |
|                                                         id2 int UNIQUE, \
 | |
|                                                         id3 int, \
 | |
|                                                         id4 int NOT NULL, \
 | |
|                                                         id5 int, \
 | |
|                                                         KEY(id3, id4))");
 | |
|   myquery(rc);
 | |
| 
 | |
|   /* with table name included with TRUE column name */
 | |
|   rc= mysql_query(mysql, "SELECT * FROM test_field_flags");
 | |
|   myquery(rc);
 | |
| 
 | |
|   result= mysql_use_result(mysql);
 | |
|   mytest(result);
 | |
| 
 | |
|   mysql_field_seek(result, 0);
 | |
|   if (!opt_silent)
 | |
|     fputc('\n', stdout);
 | |
| 
 | |
|   for(i= 0; i< mysql_num_fields(result); i++)
 | |
|   {
 | |
|     field= mysql_fetch_field(result);
 | |
|     if (!opt_silent)
 | |
|     {
 | |
|       fprintf(stdout, "\n field:%d", i);
 | |
|       if (field->flags & NOT_NULL_FLAG)
 | |
|         fprintf(stdout, "\n  NOT_NULL_FLAG");
 | |
|       if (field->flags & PRI_KEY_FLAG)
 | |
|         fprintf(stdout, "\n  PRI_KEY_FLAG");
 | |
|       if (field->flags & UNIQUE_KEY_FLAG)
 | |
|         fprintf(stdout, "\n  UNIQUE_KEY_FLAG");
 | |
|       if (field->flags & MULTIPLE_KEY_FLAG)
 | |
|         fprintf(stdout, "\n  MULTIPLE_KEY_FLAG");
 | |
|       if (field->flags & AUTO_INCREMENT_FLAG)
 | |
|         fprintf(stdout, "\n  AUTO_INCREMENT_FLAG");
 | |
| 
 | |
|     }
 | |
|   }
 | |
|   mysql_free_result(result);
 | |
| }
 | |
| 
 | |
| 
 | |
| /* Test mysql_stmt_close for open stmts */
 | |
| 
 | |
| static void test_stmt_close()
 | |
| {
 | |
|   MYSQL *lmysql;
 | |
|   MYSQL_STMT *stmt1, *stmt2, *stmt3, *stmt_x;
 | |
|   MYSQL_BIND  my_bind[1];
 | |
|   MYSQL_RES   *result;
 | |
|   unsigned int  count;
 | |
|   int   rc;
 | |
|   char query[MAX_TEST_QUERY_LENGTH];
 | |
| 
 | |
|   myheader("test_stmt_close");
 | |
| 
 | |
|   if (!opt_silent)
 | |
|     fprintf(stdout, "\n Establishing a test connection ...");
 | |
|   if (!(lmysql= mysql_client_init(NULL)))
 | |
|   {
 | |
|     myerror("mysql_client_init() failed");
 | |
|     exit(1);
 | |
|   }
 | |
|   if (!(mysql_real_connect(lmysql, opt_host, opt_user,
 | |
|                            opt_password, current_db, opt_port,
 | |
|                            opt_unix_socket, 0)))
 | |
|   {
 | |
|     myerror("connection failed");
 | |
|     exit(1);
 | |
|   }
 | |
|   mysql_options(lmysql, MYSQL_OPT_RECONNECT, &my_true);
 | |
|   if (!opt_silent)
 | |
|     fprintf(stdout, "OK");
 | |
| 
 | |
| 
 | |
|   /* set AUTOCOMMIT to ON*/
 | |
|   mysql_autocommit(lmysql, TRUE);
 | |
| 
 | |
|   rc= mysql_query(lmysql, "SET SQL_MODE = ''");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(lmysql, "DROP TABLE IF EXISTS test_stmt_close");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(lmysql, "CREATE TABLE test_stmt_close(id int)");
 | |
|   myquery(rc);
 | |
| 
 | |
|   strmov(query, "DO \"nothing\"");
 | |
|   stmt1= mysql_simple_prepare(lmysql, query);
 | |
|   check_stmt(stmt1);
 | |
| 
 | |
|   verify_param_count(stmt1, 0);
 | |
| 
 | |
|   strmov(query, "INSERT INTO test_stmt_close(id) VALUES(?)");
 | |
|   stmt_x= mysql_simple_prepare(mysql, query);
 | |
|   check_stmt(stmt_x);
 | |
| 
 | |
|   verify_param_count(stmt_x, 1);
 | |
| 
 | |
|   strmov(query, "UPDATE test_stmt_close SET id= ? WHERE id= ?");
 | |
|   stmt3= mysql_simple_prepare(lmysql, query);
 | |
|   check_stmt(stmt3);
 | |
| 
 | |
|   verify_param_count(stmt3, 2);
 | |
| 
 | |
|   strmov(query, "SELECT * FROM test_stmt_close WHERE id= ?");
 | |
|   stmt2= mysql_simple_prepare(lmysql, query);
 | |
|   check_stmt(stmt2);
 | |
| 
 | |
|   verify_param_count(stmt2, 1);
 | |
| 
 | |
|   rc= mysql_stmt_close(stmt1);
 | |
|   if (!opt_silent)
 | |
|     fprintf(stdout, "\n mysql_close_stmt(1) returned: %d", rc);
 | |
|   DIE_UNLESS(rc == 0);
 | |
| 
 | |
|   /*
 | |
|     Originally we were going to close all statements automatically in
 | |
|     mysql_close(). This proved to not work well - users weren't able to
 | |
|     close statements by hand once mysql_close() had been called.
 | |
|     Now mysql_close() doesn't free any statements, so this test doesn't
 | |
|     serve its original designation any more.
 | |
|     Here we free stmt2 and stmt3 by hand to avoid memory leaks.
 | |
|   */
 | |
|   mysql_stmt_close(stmt2);
 | |
|   mysql_stmt_close(stmt3);
 | |
|   mysql_close(lmysql);
 | |
| 
 | |
|   /*
 | |
|     We need to bzero bind structure because mysql_stmt_bind_param checks all
 | |
|     its members.
 | |
|   */
 | |
|   bzero((char*) my_bind, sizeof(my_bind));
 | |
| 
 | |
|   my_bind[0].buffer= (void *)&count;
 | |
|   my_bind[0].buffer_type= MYSQL_TYPE_LONG;
 | |
|   count= 100;
 | |
| 
 | |
|   rc= mysql_stmt_bind_param(stmt_x, my_bind);
 | |
|   check_execute(stmt_x, rc);
 | |
| 
 | |
|   rc= mysql_stmt_execute(stmt_x);
 | |
|   check_execute(stmt_x, rc);
 | |
| 
 | |
|   verify_st_affected_rows(stmt_x, 1);
 | |
| 
 | |
|   rc= mysql_stmt_close(stmt_x);
 | |
|   if (!opt_silent)
 | |
|     fprintf(stdout, "\n mysql_close_stmt(x) returned: %d", rc);
 | |
|   DIE_UNLESS( rc == 0);
 | |
| 
 | |
|   rc= mysql_query(mysql, "SELECT id FROM test_stmt_close");
 | |
|   myquery(rc);
 | |
| 
 | |
|   result= mysql_store_result(mysql);
 | |
|   mytest(result);
 | |
| 
 | |
|   rc= my_process_result_set(result);
 | |
|   DIE_UNLESS(rc == 1);
 | |
|   mysql_free_result(result);
 | |
| }
 | |
| 
 | |
| 
 | |
| /* Test simple set variable prepare */
 | |
| 
 | |
| static void test_set_variable()
 | |
| {
 | |
|   MYSQL_STMT *stmt, *stmt1;
 | |
|   int        rc;
 | |
|   int        set_count, def_count, get_count;
 | |
|   ulong      length;
 | |
|   char       var[NAME_LEN+1];
 | |
|   MYSQL_BIND set_bind[1], get_bind[2];
 | |
| 
 | |
|   myheader("test_set_variable");
 | |
| 
 | |
|   mysql_autocommit(mysql, TRUE);
 | |
| 
 | |
|   stmt1= mysql_simple_prepare(mysql, "show variables like 'max_error_count'");
 | |
|   check_stmt(stmt1);
 | |
| 
 | |
|   /*
 | |
|     We need to bzero bind structure because mysql_stmt_bind_param checks all
 | |
|     its members.
 | |
|   */
 | |
|   bzero((char*) get_bind, sizeof(get_bind));
 | |
| 
 | |
|   get_bind[0].buffer_type= MYSQL_TYPE_STRING;
 | |
|   get_bind[0].buffer= (void *)var;
 | |
|   get_bind[0].length= &length;
 | |
|   get_bind[0].buffer_length= (int)NAME_LEN;
 | |
|   length= NAME_LEN;
 | |
| 
 | |
|   get_bind[1].buffer_type= MYSQL_TYPE_LONG;
 | |
|   get_bind[1].buffer= (void *)&get_count;
 | |
| 
 | |
|   rc= mysql_stmt_execute(stmt1);
 | |
|   check_execute(stmt1, rc);
 | |
| 
 | |
|   rc= mysql_stmt_bind_result(stmt1, get_bind);
 | |
|   check_execute(stmt1, rc);
 | |
| 
 | |
|   rc= mysql_stmt_fetch(stmt1);
 | |
|   check_execute(stmt1, rc);
 | |
| 
 | |
|   if (!opt_silent)
 | |
|     fprintf(stdout, "\n max_error_count(default): %d", get_count);
 | |
|   def_count= get_count;
 | |
| 
 | |
|   DIE_UNLESS(strcmp(var, "max_error_count") == 0);
 | |
|   rc= mysql_stmt_fetch(stmt1);
 | |
|   DIE_UNLESS(rc == MYSQL_NO_DATA);
 | |
| 
 | |
|   stmt= mysql_simple_prepare(mysql, "set max_error_count= ?");
 | |
|   check_stmt(stmt);
 | |
| 
 | |
|   bzero((char*) set_bind, sizeof(set_bind));
 | |
| 
 | |
|   set_bind[0].buffer_type= MYSQL_TYPE_LONG;
 | |
|   set_bind[0].buffer= (void *)&set_count;
 | |
| 
 | |
|   rc= mysql_stmt_bind_param(stmt, set_bind);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   set_count= 31;
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   mysql_commit(mysql);
 | |
| 
 | |
|   rc= mysql_stmt_execute(stmt1);
 | |
|   check_execute(stmt1, rc);
 | |
| 
 | |
|   rc= mysql_stmt_fetch(stmt1);
 | |
|   check_execute(stmt1, rc);
 | |
| 
 | |
|   if (!opt_silent)
 | |
|     fprintf(stdout, "\n max_error_count         : %d", get_count);
 | |
|   DIE_UNLESS(get_count == set_count);
 | |
| 
 | |
|   rc= mysql_stmt_fetch(stmt1);
 | |
|   DIE_UNLESS(rc == MYSQL_NO_DATA);
 | |
| 
 | |
|   /* restore back to default */
 | |
|   set_count= def_count;
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= mysql_stmt_execute(stmt1);
 | |
|   check_execute(stmt1, rc);
 | |
| 
 | |
|   rc= mysql_stmt_fetch(stmt1);
 | |
|   check_execute(stmt1, rc);
 | |
| 
 | |
|   if (!opt_silent)
 | |
|     fprintf(stdout, "\n max_error_count(default): %d", get_count);
 | |
|   DIE_UNLESS(get_count == set_count);
 | |
| 
 | |
|   rc= mysql_stmt_fetch(stmt1);
 | |
|   DIE_UNLESS(rc == MYSQL_NO_DATA);
 | |
| 
 | |
|   mysql_stmt_close(stmt);
 | |
|   mysql_stmt_close(stmt1);
 | |
| }
 | |
| 
 | |
| /* Test FUNCTION field info / DATE_FORMAT() table_name . */
 | |
| 
 | |
| static void test_func_fields()
 | |
| {
 | |
|   int        rc;
 | |
|   MYSQL_RES  *result;
 | |
|   MYSQL_FIELD *field;
 | |
| 
 | |
|   myheader("test_func_fields");
 | |
| 
 | |
|   rc= mysql_autocommit(mysql, TRUE);
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_dateformat");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "CREATE TABLE test_dateformat(id int, \
 | |
|                                                        ts timestamp)");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "INSERT INTO test_dateformat(id) values(10)");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "SELECT ts FROM test_dateformat");
 | |
|   myquery(rc);
 | |
| 
 | |
|   result= mysql_store_result(mysql);
 | |
|   mytest(result);
 | |
| 
 | |
|   field= mysql_fetch_field(result);
 | |
|   mytest(field);
 | |
|   if (!opt_silent)
 | |
|     fprintf(stdout, "\n table name: `%s` (expected: `%s`)", field->table,
 | |
|             "test_dateformat");
 | |
|   DIE_UNLESS(strcmp(field->table, "test_dateformat") == 0);
 | |
| 
 | |
|   field= mysql_fetch_field(result);
 | |
|   mytest_r(field); /* no more fields */
 | |
| 
 | |
|   mysql_free_result(result);
 | |
| 
 | |
|   /* DATE_FORMAT */
 | |
|   rc= mysql_query(mysql, "SELECT DATE_FORMAT(ts, '%Y') AS 'venu' FROM test_dateformat");
 | |
|   myquery(rc);
 | |
| 
 | |
|   result= mysql_store_result(mysql);
 | |
|   mytest(result);
 | |
| 
 | |
|   field= mysql_fetch_field(result);
 | |
|   mytest(field);
 | |
|   if (!opt_silent)
 | |
|     fprintf(stdout, "\n table name: `%s` (expected: `%s`)", field->table, "");
 | |
|   DIE_UNLESS(field->table[0] == '\0');
 | |
| 
 | |
|   field= mysql_fetch_field(result);
 | |
|   mytest_r(field); /* no more fields */
 | |
| 
 | |
|   mysql_free_result(result);
 | |
| 
 | |
|   /* FIELD ALIAS TEST */
 | |
|   rc= mysql_query(mysql, "SELECT DATE_FORMAT(ts, '%Y')  AS 'YEAR' FROM test_dateformat");
 | |
|   myquery(rc);
 | |
| 
 | |
|   result= mysql_store_result(mysql);
 | |
|   mytest(result);
 | |
| 
 | |
|   field= mysql_fetch_field(result);
 | |
|   mytest(field);
 | |
|   if (!opt_silent)
 | |
|   {
 | |
|     printf("\n field name: `%s` (expected: `%s`)", field->name, "YEAR");
 | |
|     printf("\n field org name: `%s` (expected: `%s`)", field->org_name, "");
 | |
|   }
 | |
|   DIE_UNLESS(strcmp(field->name, "YEAR") == 0);
 | |
|   DIE_UNLESS(field->org_name[0] == '\0');
 | |
| 
 | |
|   field= mysql_fetch_field(result);
 | |
|   mytest_r(field); /* no more fields */
 | |
| 
 | |
|   mysql_free_result(result);
 | |
| }
 | |
| 
 | |
| 
 | |
| /* Multiple stmts .. */
 | |
| 
 | |
| static void test_multi_stmt()
 | |
| {
 | |
| 
 | |
|   MYSQL_STMT  *stmt, *stmt1, *stmt2;
 | |
|   int         rc;
 | |
|   uint32      id;
 | |
|   char        name[50];
 | |
|   MYSQL_BIND  my_bind[2];
 | |
|   ulong       length[2];
 | |
|   my_bool     is_null[2];
 | |
|   myheader("test_multi_stmt");
 | |
| 
 | |
|   rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_multi_table");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "CREATE TABLE test_multi_table(id int, name char(20))");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "INSERT INTO test_multi_table values(10, 'mysql')");
 | |
|   myquery(rc);
 | |
| 
 | |
|   stmt= mysql_simple_prepare(mysql, "SELECT * FROM test_multi_table "
 | |
|                                     "WHERE id= ?");
 | |
|   check_stmt(stmt);
 | |
| 
 | |
|   stmt2= mysql_simple_prepare(mysql, "UPDATE test_multi_table "
 | |
|                                      "SET name='updated' WHERE id=10");
 | |
|   check_stmt(stmt2);
 | |
| 
 | |
|   verify_param_count(stmt, 1);
 | |
| 
 | |
|   /*
 | |
|     We need to bzero bind structure because mysql_stmt_bind_param checks all
 | |
|     its members.
 | |
|   */
 | |
|   bzero((char*) my_bind, sizeof(my_bind));
 | |
| 
 | |
|   my_bind[0].buffer_type= MYSQL_TYPE_LONG;
 | |
|   my_bind[0].buffer= (void *)&id;
 | |
|   my_bind[0].is_null= &is_null[0];
 | |
|   my_bind[0].length= &length[0];
 | |
|   is_null[0]= 0;
 | |
|   length[0]= 0;
 | |
| 
 | |
|   my_bind[1].buffer_type= MYSQL_TYPE_STRING;
 | |
|   my_bind[1].buffer= (void *)name;
 | |
|   my_bind[1].buffer_length= sizeof(name);
 | |
|   my_bind[1].length= &length[1];
 | |
|   my_bind[1].is_null= &is_null[1];
 | |
| 
 | |
|   rc= mysql_stmt_bind_param(stmt, my_bind);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= mysql_stmt_bind_result(stmt, my_bind);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   id= 10;
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   id= 999;
 | |
|   rc= mysql_stmt_fetch(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   if (!opt_silent)
 | |
|   {
 | |
|     fprintf(stdout, "\n int_data: %lu(%lu)", (ulong) id, length[0]);
 | |
|     fprintf(stdout, "\n str_data: %s(%lu)", name, length[1]);
 | |
|   }
 | |
|   DIE_UNLESS(id == 10);
 | |
|   DIE_UNLESS(strcmp(name, "mysql") == 0);
 | |
| 
 | |
|   rc= mysql_stmt_fetch(stmt);
 | |
|   DIE_UNLESS(rc == MYSQL_NO_DATA);
 | |
| 
 | |
|   /* alter the table schema now */
 | |
|   stmt1= mysql_simple_prepare(mysql, "DELETE FROM test_multi_table "
 | |
|                                      "WHERE id= ? AND "
 | |
|                                      "CONVERT(name USING utf8)=?");
 | |
|   check_stmt(stmt1);
 | |
| 
 | |
|   verify_param_count(stmt1, 2);
 | |
| 
 | |
|   rc= mysql_stmt_bind_param(stmt1, my_bind);
 | |
|   check_execute(stmt1, rc);
 | |
| 
 | |
|   rc= mysql_stmt_execute(stmt2);
 | |
|   check_execute(stmt2, rc);
 | |
| 
 | |
|   verify_st_affected_rows(stmt2, 1);
 | |
| 
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= mysql_stmt_fetch(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   if (!opt_silent)
 | |
|   {
 | |
|     fprintf(stdout, "\n int_data: %lu(%lu)", (ulong) id, length[0]);
 | |
|     fprintf(stdout, "\n str_data: %s(%lu)", name, length[1]);
 | |
|   }
 | |
|   DIE_UNLESS(id == 10);
 | |
|   DIE_UNLESS(strcmp(name, "updated") == 0);
 | |
| 
 | |
|   rc= mysql_stmt_fetch(stmt);
 | |
|   DIE_UNLESS(rc == MYSQL_NO_DATA);
 | |
| 
 | |
|   rc= mysql_stmt_execute(stmt1);
 | |
|   check_execute(stmt1, rc);
 | |
| 
 | |
|   verify_st_affected_rows(stmt1, 1);
 | |
| 
 | |
|   mysql_stmt_close(stmt1);
 | |
| 
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= mysql_stmt_fetch(stmt);
 | |
|   DIE_UNLESS(rc == MYSQL_NO_DATA);
 | |
| 
 | |
|   rc= my_stmt_result("SELECT * FROM test_multi_table");
 | |
|   DIE_UNLESS(rc == 0);
 | |
| 
 | |
|   mysql_stmt_close(stmt);
 | |
|   mysql_stmt_close(stmt2);
 | |
| 
 | |
| }
 | |
| 
 | |
| 
 | |
| /* Test simple sample - manual */
 | |
| 
 | |
| static void test_manual_sample()
 | |
| {
 | |
|   unsigned int param_count;
 | |
|   MYSQL_STMT   *stmt;
 | |
|   short        small_data= 1;
 | |
|   int          int_data= 2;
 | |
|   int          rc;
 | |
|   char         str_data[50]= "std_data";
 | |
|   ulonglong    affected_rows;
 | |
|   MYSQL_BIND   my_bind[3];
 | |
|   my_bool      is_null;
 | |
|   char query[MAX_TEST_QUERY_LENGTH];
 | |
| 
 | |
|   myheader("test_manual_sample");
 | |
| 
 | |
|   /*
 | |
|     Sample which is incorporated directly in the manual under Prepared
 | |
|     statements section (Example from mysql_stmt_execute()
 | |
|   */
 | |
| 
 | |
|   mysql_autocommit(mysql, 1);
 | |
|   if (mysql_query(mysql, "DROP TABLE IF EXISTS test_table"))
 | |
|   {
 | |
|     fprintf(stderr, "\n drop table failed");
 | |
|     fprintf(stderr, "\n %s", mysql_error(mysql));
 | |
|     exit(1);
 | |
|   }
 | |
|   if (mysql_query(mysql, "CREATE TABLE test_table(col1 int, col2 varchar(50), \
 | |
|                                                  col3 smallint, \
 | |
|                                                  col4 timestamp)"))
 | |
|   {
 | |
|     fprintf(stderr, "\n create table failed");
 | |
|     fprintf(stderr, "\n %s", mysql_error(mysql));
 | |
|     exit(1);
 | |
|   }
 | |
| 
 | |
|   /* Prepare a insert query with 3 parameters */
 | |
|   strmov(query, "INSERT INTO test_table(col1, col2, col3) values(?, ?, ?)");
 | |
|   if (!(stmt= mysql_simple_prepare(mysql, query)))
 | |
|   {
 | |
|     fprintf(stderr, "\n prepare, insert failed");
 | |
|     fprintf(stderr, "\n %s", mysql_error(mysql));
 | |
|     exit(1);
 | |
|   }
 | |
|   if (!opt_silent)
 | |
|     fprintf(stdout, "\n prepare, insert successful");
 | |
| 
 | |
|   /* Get the parameter count from the statement */
 | |
|   param_count= mysql_stmt_param_count(stmt);
 | |
| 
 | |
|   if (!opt_silent)
 | |
|     fprintf(stdout, "\n total parameters in insert: %d", param_count);
 | |
|   if (param_count != 3) /* validate parameter count */
 | |
|   {
 | |
|     fprintf(stderr, "\n invalid parameter count returned by MySQL");
 | |
|     exit(1);
 | |
|   }
 | |
| 
 | |
|   /* Bind the data for the parameters */
 | |
| 
 | |
|   /*
 | |
|     We need to bzero bind structure because mysql_stmt_bind_param checks all
 | |
|     its members.
 | |
|   */
 | |
|   bzero((char*) my_bind, sizeof(my_bind));
 | |
| 
 | |
|   /* INTEGER PART */
 | |
|   my_bind[0].buffer_type= MYSQL_TYPE_LONG;
 | |
|   my_bind[0].buffer= (void *)&int_data;
 | |
| 
 | |
|   /* STRING PART */
 | |
|   my_bind[1].buffer_type= MYSQL_TYPE_VAR_STRING;
 | |
|   my_bind[1].buffer= (void *)str_data;
 | |
|   my_bind[1].buffer_length= sizeof(str_data);
 | |
| 
 | |
|   /* SMALLINT PART */
 | |
|   my_bind[2].buffer_type= MYSQL_TYPE_SHORT;
 | |
|   my_bind[2].buffer= (void *)&small_data;
 | |
|   my_bind[2].is_null= &is_null;
 | |
|   is_null= 0;
 | |
| 
 | |
|   /* Bind the buffers */
 | |
|   if (mysql_stmt_bind_param(stmt, my_bind))
 | |
|   {
 | |
|     fprintf(stderr, "\n param bind failed");
 | |
|     fprintf(stderr, "\n %s", mysql_stmt_error(stmt));
 | |
|     exit(1);
 | |
|   }
 | |
| 
 | |
|   /* Specify the data */
 | |
|   int_data= 10;             /* integer */
 | |
|   strmov(str_data, "MySQL"); /* string  */
 | |
| 
 | |
|   /* INSERT SMALLINT data as NULL */
 | |
|   is_null= 1;
 | |
| 
 | |
|   /* Execute the insert statement - 1*/
 | |
|   if (mysql_stmt_execute(stmt))
 | |
|   {
 | |
|     fprintf(stderr, "\n execute 1 failed");
 | |
|     fprintf(stderr, "\n %s", mysql_stmt_error(stmt));
 | |
|     exit(1);
 | |
|   }
 | |
| 
 | |
|   /* Get the total rows affected */
 | |
|   affected_rows= mysql_stmt_affected_rows(stmt);
 | |
| 
 | |
|   if (!opt_silent)
 | |
|     fprintf(stdout, "\n total affected rows: %ld", (ulong) affected_rows);
 | |
|   if (affected_rows != 1) /* validate affected rows */
 | |
|   {
 | |
|     fprintf(stderr, "\n invalid affected rows by MySQL");
 | |
|     exit(1);
 | |
|   }
 | |
| 
 | |
|   /* Re-execute the insert, by changing the values */
 | |
|   int_data= 1000;
 | |
|   strmov(str_data, "The most popular open source database");
 | |
|   small_data= 1000;         /* smallint */
 | |
|   is_null= 0;               /* reset */
 | |
| 
 | |
|   /* Execute the insert statement - 2*/
 | |
|   if (mysql_stmt_execute(stmt))
 | |
|   {
 | |
|     fprintf(stderr, "\n execute 2 failed");
 | |
|     fprintf(stderr, "\n %s", mysql_stmt_error(stmt));
 | |
|     exit(1);
 | |
|   }
 | |
| 
 | |
|   /* Get the total rows affected */
 | |
|   affected_rows= mysql_stmt_affected_rows(stmt);
 | |
| 
 | |
|   if (!opt_silent)
 | |
|     fprintf(stdout, "\n total affected rows: %ld", (ulong) affected_rows);
 | |
|   if (affected_rows != 1) /* validate affected rows */
 | |
|   {
 | |
|     fprintf(stderr, "\n invalid affected rows by MySQL");
 | |
|     exit(1);
 | |
|   }
 | |
| 
 | |
|   /* Close the statement */
 | |
|   if (mysql_stmt_close(stmt))
 | |
|   {
 | |
|     fprintf(stderr, "\n failed while closing the statement");
 | |
|     fprintf(stderr, "\n %s", mysql_stmt_error(stmt));
 | |
|     exit(1);
 | |
|   }
 | |
|   rc= my_stmt_result("SELECT * FROM test_table");
 | |
|   DIE_UNLESS(rc == 2);
 | |
| 
 | |
|   /* DROP THE TABLE */
 | |
|   if (mysql_query(mysql, "DROP TABLE test_table"))
 | |
|   {
 | |
|     fprintf(stderr, "\n drop table failed");
 | |
|     fprintf(stderr, "\n %s", mysql_error(mysql));
 | |
|     exit(1);
 | |
|   }
 | |
|   if (!opt_silent)
 | |
|     fprintf(stdout, "Success !!!");
 | |
| }
 | |
| 
 | |
| 
 | |
| /* Test alter table scenario in the middle of prepare */
 | |
| 
 | |
| static void test_prepare_alter()
 | |
| {
 | |
|   MYSQL_STMT  *stmt;
 | |
|   int         rc, id;
 | |
|   MYSQL_BIND  my_bind[1];
 | |
|   my_bool     is_null;
 | |
| 
 | |
|   myheader("test_prepare_alter");
 | |
| 
 | |
|   rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_prep_alter");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "CREATE TABLE test_prep_alter(id int, name char(20))");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "INSERT INTO test_prep_alter values(10, 'venu'), (20, 'mysql')");
 | |
|   myquery(rc);
 | |
| 
 | |
|   stmt= mysql_simple_prepare(mysql, "INSERT INTO test_prep_alter VALUES(?, 'monty')");
 | |
|   check_stmt(stmt);
 | |
| 
 | |
|   verify_param_count(stmt, 1);
 | |
| 
 | |
|   /*
 | |
|     We need to bzero bind structure because mysql_stmt_bind_param checks all
 | |
|     its members.
 | |
|   */
 | |
|   bzero((char*) my_bind, sizeof(my_bind));
 | |
| 
 | |
|   is_null= 0;
 | |
|   my_bind[0].buffer_type= MYSQL_TYPE_SHORT;
 | |
|   my_bind[0].buffer= (void *)&id;
 | |
|   my_bind[0].is_null= &is_null;
 | |
| 
 | |
|   rc= mysql_stmt_bind_param(stmt, my_bind);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   id= 30;
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   if (thread_query("ALTER TABLE test_prep_alter change id id_new varchar(20)"))
 | |
|     exit(1);
 | |
| 
 | |
|   is_null= 1;
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= my_stmt_result("SELECT * FROM test_prep_alter");
 | |
|   DIE_UNLESS(rc == 4);
 | |
| 
 | |
|   mysql_stmt_close(stmt);
 | |
| }
 | |
| 
 | |
| 
 | |
| /* Test the support of multi-statement executions */
 | |
| 
 | |
| static void test_multi_statements()
 | |
| {
 | |
|   MYSQL *mysql_local;
 | |
|   MYSQL_RES *result;
 | |
|   int    rc;
 | |
| 
 | |
|   const char *query= "\
 | |
| DROP TABLE IF EXISTS test_multi_tab;\
 | |
| CREATE TABLE test_multi_tab(id int, name char(20));\
 | |
| INSERT INTO test_multi_tab(id) VALUES(10), (20);\
 | |
| INSERT INTO test_multi_tab VALUES(20, 'insert;comma');\
 | |
| SELECT * FROM test_multi_tab;\
 | |
| UPDATE test_multi_tab SET name='new;name' WHERE id=20;\
 | |
| DELETE FROM test_multi_tab WHERE name='new;name';\
 | |
| SELECT * FROM test_multi_tab;\
 | |
| DELETE FROM test_multi_tab WHERE id=10;\
 | |
| SELECT * FROM test_multi_tab;\
 | |
| DROP TABLE test_multi_tab;\
 | |
| select 1;\
 | |
| DROP TABLE IF EXISTS test_multi_tab";
 | |
|   uint count, exp_value;
 | |
|   uint rows[]= {0, 0, 2, 1, 3, 2, 2, 1, 1, 0, 0, 1, 0};
 | |
| 
 | |
|   myheader("test_multi_statements");
 | |
| 
 | |
|   /*
 | |
|     First test that we get an error for multi statements
 | |
|     (Because default connection is not opened with CLIENT_MULTI_STATEMENTS)
 | |
|   */
 | |
|   rc= mysql_query(mysql, query); /* syntax error */
 | |
|   myquery_r(rc);
 | |
| 
 | |
|   rc= mysql_next_result(mysql);
 | |
|   DIE_UNLESS(rc == -1);
 | |
|   rc= mysql_more_results(mysql);
 | |
|   DIE_UNLESS(rc == 0);
 | |
| 
 | |
|   if (!(mysql_local= mysql_client_init(NULL)))
 | |
|   {
 | |
|     fprintf(stdout, "\n mysql_client_init() failed");
 | |
|     exit(1);
 | |
|   }
 | |
| 
 | |
|   /* Create connection that supports multi statements */
 | |
|   if (!(mysql_real_connect(mysql_local, opt_host, opt_user,
 | |
|                            opt_password, current_db, opt_port,
 | |
|                            opt_unix_socket, CLIENT_MULTI_STATEMENTS)))
 | |
|   {
 | |
|     fprintf(stdout, "\n connection failed(%s)", mysql_error(mysql_local));
 | |
|     exit(1);
 | |
|   }
 | |
|   mysql_options(mysql_local, MYSQL_OPT_RECONNECT, &my_true);
 | |
| 
 | |
|   rc= mysql_query(mysql_local, query);
 | |
|   myquery(rc);
 | |
| 
 | |
|   for (count= 0 ; count < array_elements(rows) ; count++)
 | |
|   {
 | |
|     if (!opt_silent)
 | |
|       fprintf(stdout, "\n Query %d: ", count);
 | |
|     if ((result= mysql_store_result(mysql_local)))
 | |
|     {
 | |
|       (void) my_process_result_set(result);
 | |
|       mysql_free_result(result);
 | |
|     }
 | |
|     else if (!opt_silent)
 | |
|       fprintf(stdout, "OK, %ld row(s) affected, %ld warning(s)\n",
 | |
|               (ulong) mysql_affected_rows(mysql_local),
 | |
|               (ulong) mysql_warning_count(mysql_local));
 | |
| 
 | |
|     exp_value= (uint) mysql_affected_rows(mysql_local);
 | |
|     if (rows[count] !=  exp_value)
 | |
|     {
 | |
|       fprintf(stderr, "row %d  had affected rows: %d, should be %d\n",
 | |
|               count, exp_value, rows[count]);
 | |
|       exit(1);
 | |
|     }
 | |
|     if (count != array_elements(rows) -1)
 | |
|     {
 | |
|       if (!(rc= mysql_more_results(mysql_local)))
 | |
|       {
 | |
|         fprintf(stdout,
 | |
|                 "mysql_more_result returned wrong value: %d for row %d\n",
 | |
|                 rc, count);
 | |
|         exit(1);
 | |
|       }
 | |
|       if ((rc= mysql_next_result(mysql_local)))
 | |
|       {
 | |
|         exp_value= mysql_errno(mysql_local);
 | |
| 
 | |
|         exit(1);
 | |
|       }
 | |
|     }
 | |
|     else
 | |
|     {
 | |
|       rc= mysql_more_results(mysql_local);
 | |
|       DIE_UNLESS(rc == 0);
 | |
|       rc= mysql_next_result(mysql_local);
 | |
|       DIE_UNLESS(rc == -1);
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   /* check that errors abort multi statements */
 | |
| 
 | |
|   rc= mysql_query(mysql_local, "select 1+1+a;select 1+1");
 | |
|   myquery_r(rc);
 | |
|   rc= mysql_more_results(mysql_local);
 | |
|   DIE_UNLESS(rc == 0);
 | |
|   rc= mysql_next_result(mysql_local);
 | |
|   DIE_UNLESS(rc == -1);
 | |
| 
 | |
|   rc= mysql_query(mysql_local, "select 1+1;select 1+1+a;select 1");
 | |
|   myquery(rc);
 | |
|   result= mysql_store_result(mysql_local);
 | |
|   mytest(result);
 | |
|   mysql_free_result(result);
 | |
|   rc= mysql_more_results(mysql_local);
 | |
|   DIE_UNLESS(rc == 1);
 | |
|   rc= mysql_next_result(mysql_local);
 | |
|   DIE_UNLESS(rc > 0);
 | |
| 
 | |
|   /*
 | |
|     Ensure that we can now do a simple query (this checks that the server is
 | |
|     not trying to send us the results for the last 'select 1'
 | |
|   */
 | |
|   rc= mysql_query(mysql_local, "select 1+1+1");
 | |
|   myquery(rc);
 | |
|   result= mysql_store_result(mysql_local);
 | |
|   mytest(result);
 | |
|   (void) my_process_result_set(result);
 | |
|   mysql_free_result(result);
 | |
| 
 | |
|   /*
 | |
|     Check if errors in one of the queries handled properly.
 | |
|   */
 | |
|   rc= mysql_query(mysql_local, "select 1; select * from not_existing_table");
 | |
|   myquery(rc);
 | |
|   result= mysql_store_result(mysql_local);
 | |
|   mysql_free_result(result);
 | |
| 
 | |
|   rc= mysql_next_result(mysql_local);
 | |
|   DIE_UNLESS(rc > 0);
 | |
| 
 | |
|   rc= mysql_next_result(mysql_local);
 | |
|   DIE_UNLESS(rc < 0);
 | |
| 
 | |
|   mysql_close(mysql_local);
 | |
| }
 | |
| 
 | |
| 
 | |
| /*
 | |
|   Check that Prepared statement cannot contain several
 | |
|   SQL statements
 | |
| */
 | |
| 
 | |
| static void test_prepare_multi_statements()
 | |
| {
 | |
|   MYSQL *mysql_local;
 | |
|   MYSQL_STMT *stmt;
 | |
|   char query[MAX_TEST_QUERY_LENGTH];
 | |
|   myheader("test_prepare_multi_statements");
 | |
| 
 | |
|   if (!(mysql_local= mysql_client_init(NULL)))
 | |
|   {
 | |
|     fprintf(stderr, "\n mysql_client_init() failed");
 | |
|     exit(1);
 | |
|   }
 | |
| 
 | |
|   if (!(mysql_real_connect(mysql_local, opt_host, opt_user,
 | |
|                            opt_password, current_db, opt_port,
 | |
|                            opt_unix_socket, CLIENT_MULTI_STATEMENTS)))
 | |
|   {
 | |
|     fprintf(stderr, "\n connection failed(%s)", mysql_error(mysql_local));
 | |
|     exit(1);
 | |
|   }
 | |
|   mysql_options(mysql_local, MYSQL_OPT_RECONNECT, &my_true);
 | |
|   strmov(query, "select 1; select 'another value'");
 | |
|   stmt= mysql_simple_prepare(mysql_local, query);
 | |
|   check_stmt_r(stmt);
 | |
|   mysql_close(mysql_local);
 | |
| }
 | |
| 
 | |
| 
 | |
| /* Test simple bind store result */
 | |
| 
 | |
| static void test_store_result()
 | |
| {
 | |
|   MYSQL_STMT *stmt;
 | |
|   int        rc;
 | |
|   int32      nData;
 | |
|   char       szData[100];
 | |
|   MYSQL_BIND my_bind[2];
 | |
|   ulong      length, length1;
 | |
|   my_bool    is_null[2];
 | |
| 
 | |
|   myheader("test_store_result");
 | |
| 
 | |
|   rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_store_result");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "CREATE TABLE test_store_result(col1 int , col2 varchar(50))");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "INSERT INTO test_store_result VALUES(10, 'venu'), (20, 'mysql')");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "INSERT INTO test_store_result(col2) VALUES('monty')");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_commit(mysql);
 | |
|   myquery(rc);
 | |
| 
 | |
|   /* fetch */
 | |
|   bzero((char*) my_bind, sizeof(my_bind));
 | |
|   my_bind[0].buffer_type= MYSQL_TYPE_LONG;
 | |
|   my_bind[0].buffer= (void *) &nData;       /* integer data */
 | |
|   my_bind[0].length= &length;
 | |
|   my_bind[0].is_null= &is_null[0];
 | |
| 
 | |
|   length= 0;
 | |
|   my_bind[1].buffer_type= MYSQL_TYPE_STRING;
 | |
|   my_bind[1].buffer= szData;                /* string data */
 | |
|   my_bind[1].buffer_length= sizeof(szData);
 | |
|   my_bind[1].length= &length1;
 | |
|   my_bind[1].is_null= &is_null[1];
 | |
|   length1= 0;
 | |
| 
 | |
|   stmt= mysql_simple_prepare(mysql, "SELECT * FROM test_store_result");
 | |
|   check_stmt(stmt);
 | |
| 
 | |
|   rc= mysql_stmt_bind_result(stmt, my_bind);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= mysql_stmt_store_result(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= mysql_stmt_fetch(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   if (!opt_silent)
 | |
|     fprintf(stdout, "\n row 1: %ld, %s(%lu)", (long) nData, szData, length1);
 | |
|   DIE_UNLESS(nData == 10);
 | |
|   DIE_UNLESS(strcmp(szData, "venu") == 0);
 | |
|   DIE_UNLESS(length1 == 4);
 | |
| 
 | |
|   rc= mysql_stmt_fetch(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   if (!opt_silent)
 | |
|     fprintf(stdout, "\n row 2: %ld, %s(%lu)", (long) nData, szData, length1);
 | |
|   DIE_UNLESS(nData == 20);
 | |
|   DIE_UNLESS(strcmp(szData, "mysql") == 0);
 | |
|   DIE_UNLESS(length1 == 5);
 | |
| 
 | |
|   length= 99;
 | |
|   rc= mysql_stmt_fetch(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   if (!opt_silent && is_null[0])
 | |
|     fprintf(stdout, "\n row 3: NULL, %s(%lu)", szData, length1);
 | |
|   DIE_UNLESS(is_null[0]);
 | |
|   DIE_UNLESS(strcmp(szData, "monty") == 0);
 | |
|   DIE_UNLESS(length1 == 5);
 | |
| 
 | |
|   rc= mysql_stmt_fetch(stmt);
 | |
|   DIE_UNLESS(rc == MYSQL_NO_DATA);
 | |
| 
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= mysql_stmt_store_result(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= mysql_stmt_fetch(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   if (!opt_silent)
 | |
|     fprintf(stdout, "\n row 1: %ld, %s(%lu)", (long) nData, szData, length1);
 | |
|   DIE_UNLESS(nData == 10);
 | |
|   DIE_UNLESS(strcmp(szData, "venu") == 0);
 | |
|   DIE_UNLESS(length1 == 4);
 | |
| 
 | |
|   rc= mysql_stmt_fetch(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   if (!opt_silent)
 | |
|     fprintf(stdout, "\n row 2: %ld, %s(%lu)", (long) nData, szData, length1);
 | |
|   DIE_UNLESS(nData == 20);
 | |
|   DIE_UNLESS(strcmp(szData, "mysql") == 0);
 | |
|   DIE_UNLESS(length1 == 5);
 | |
| 
 | |
|   length= 99;
 | |
|   rc= mysql_stmt_fetch(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   if (!opt_silent && is_null[0])
 | |
|     fprintf(stdout, "\n row 3: NULL, %s(%lu)", szData, length1);
 | |
|   DIE_UNLESS(is_null[0]);
 | |
|   DIE_UNLESS(strcmp(szData, "monty") == 0);
 | |
|   DIE_UNLESS(length1 == 5);
 | |
| 
 | |
|   rc= mysql_stmt_fetch(stmt);
 | |
|   DIE_UNLESS(rc == MYSQL_NO_DATA);
 | |
| 
 | |
|   mysql_stmt_close(stmt);
 | |
| }
 | |
| 
 | |
| 
 | |
| /* Test simple bind store result */
 | |
| 
 | |
| static void test_store_result1()
 | |
| {
 | |
|   MYSQL_STMT *stmt;
 | |
|   int        rc;
 | |
| 
 | |
|   myheader("test_store_result1");
 | |
| 
 | |
|   rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_store_result");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "CREATE TABLE test_store_result(col1 int , col2 varchar(50))");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "INSERT INTO test_store_result VALUES(10, 'venu'), (20, 'mysql')");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "INSERT INTO test_store_result(col2) VALUES('monty')");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_commit(mysql);
 | |
|   myquery(rc);
 | |
| 
 | |
|   stmt= mysql_simple_prepare(mysql, "SELECT * FROM test_store_result");
 | |
|   check_stmt(stmt);
 | |
| 
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= mysql_stmt_store_result(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= 0;
 | |
|   while (mysql_stmt_fetch(stmt) != MYSQL_NO_DATA)
 | |
|     rc++;
 | |
|   if (!opt_silent)
 | |
|     fprintf(stdout, "\n total rows: %d", rc);
 | |
|   DIE_UNLESS(rc == 3);
 | |
| 
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= mysql_stmt_store_result(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= 0;
 | |
|   while (mysql_stmt_fetch(stmt) != MYSQL_NO_DATA)
 | |
|     rc++;
 | |
|   if (!opt_silent)
 | |
|     fprintf(stdout, "\n total rows: %d", rc);
 | |
|   DIE_UNLESS(rc == 3);
 | |
| 
 | |
|   mysql_stmt_close(stmt);
 | |
| }
 | |
| 
 | |
| 
 | |
| /* Another test for bind and store result */
 | |
| 
 | |
| static void test_store_result2()
 | |
| {
 | |
|   MYSQL_STMT *stmt;
 | |
|   int        rc;
 | |
|   int        nData;
 | |
|   ulong      length;
 | |
|   MYSQL_BIND my_bind[1];
 | |
|   char query[MAX_TEST_QUERY_LENGTH];
 | |
| 
 | |
|   myheader("test_store_result2");
 | |
| 
 | |
|   rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_store_result");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "CREATE TABLE test_store_result(col1 int , col2 varchar(50))");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "INSERT INTO test_store_result VALUES(10, 'venu'), (20, 'mysql')");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "INSERT INTO test_store_result(col2) VALUES('monty')");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_commit(mysql);
 | |
|   myquery(rc);
 | |
| 
 | |
|   /*
 | |
|     We need to bzero bind structure because mysql_stmt_bind_param checks all
 | |
|     its members.
 | |
|   */
 | |
|   bzero((char*) my_bind, sizeof(my_bind));
 | |
| 
 | |
|   my_bind[0].buffer_type= MYSQL_TYPE_LONG;
 | |
|   my_bind[0].buffer= (void *) &nData;      /* integer data */
 | |
|   my_bind[0].length= &length;
 | |
|   my_bind[0].is_null= 0;
 | |
| 
 | |
|   strmov((char *)query , "SELECT col1 FROM test_store_result where col1= ?");
 | |
|   stmt= mysql_simple_prepare(mysql, query);
 | |
|   check_stmt(stmt);
 | |
| 
 | |
|   rc= mysql_stmt_bind_param(stmt, my_bind);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= mysql_stmt_bind_result(stmt, my_bind);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   nData= 10; length= 0;
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   nData= 0;
 | |
|   rc= mysql_stmt_store_result(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= mysql_stmt_fetch(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   if (!opt_silent)
 | |
|     fprintf(stdout, "\n row 1: %d", nData);
 | |
|   DIE_UNLESS(nData == 10);
 | |
| 
 | |
|   rc= mysql_stmt_fetch(stmt);
 | |
|   DIE_UNLESS(rc == MYSQL_NO_DATA);
 | |
| 
 | |
|   nData= 20;
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   nData= 0;
 | |
|   rc= mysql_stmt_store_result(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= mysql_stmt_fetch(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   if (!opt_silent)
 | |
|     fprintf(stdout, "\n row 1: %d", nData);
 | |
|   DIE_UNLESS(nData == 20);
 | |
| 
 | |
|   rc= mysql_stmt_fetch(stmt);
 | |
|   DIE_UNLESS(rc == MYSQL_NO_DATA);
 | |
|   mysql_stmt_close(stmt);
 | |
| }
 | |
| 
 | |
| 
 | |
| /* Test simple subselect prepare */
 | |
| 
 | |
| static void test_subselect()
 | |
| {
 | |
| 
 | |
|   MYSQL_STMT *stmt;
 | |
|   int        rc, id;
 | |
|   MYSQL_BIND my_bind[1];
 | |
|   DBUG_ENTER("test_subselect");
 | |
| 
 | |
|   myheader("test_subselect");
 | |
| 
 | |
|   rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_sub1");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_sub2");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "CREATE TABLE test_sub1(id int)");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "CREATE TABLE test_sub2(id int, id1 int)");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "INSERT INTO test_sub1 values(2)");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "INSERT INTO test_sub2 VALUES(1, 7), (2, 7)");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_commit(mysql);
 | |
|   myquery(rc);
 | |
| 
 | |
|   /* fetch */
 | |
|   /*
 | |
|     We need to bzero bind structure because mysql_stmt_bind_param checks all
 | |
|     its members.
 | |
|   */
 | |
|   bzero((char*) my_bind, sizeof(my_bind));
 | |
| 
 | |
|   my_bind[0].buffer_type= MYSQL_TYPE_LONG;
 | |
|   my_bind[0].buffer= (void *) &id;
 | |
|   my_bind[0].length= 0;
 | |
|   my_bind[0].is_null= 0;
 | |
| 
 | |
|   stmt= mysql_simple_prepare(mysql, "INSERT INTO test_sub2(id) SELECT * FROM test_sub1 WHERE id= ?");
 | |
|   check_stmt(stmt);
 | |
| 
 | |
|   rc= mysql_stmt_bind_param(stmt, my_bind);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   id= 2;
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   verify_st_affected_rows(stmt, 1);
 | |
| 
 | |
|   id= 9;
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   verify_st_affected_rows(stmt, 0);
 | |
| 
 | |
|   mysql_stmt_close(stmt);
 | |
| 
 | |
|   rc= my_stmt_result("SELECT * FROM test_sub2");
 | |
|   DIE_UNLESS(rc == 3);
 | |
| 
 | |
|   rc= my_stmt_result("SELECT ROW(1, 7) IN (select id, id1 "
 | |
|                      "from test_sub2 WHERE id1= 8)");
 | |
|   DIE_UNLESS(rc == 1);
 | |
|   rc= my_stmt_result("SELECT ROW(1, 7) IN (select id, id1 "
 | |
|                      "from test_sub2 WHERE id1= 7)");
 | |
|   DIE_UNLESS(rc == 1);
 | |
| 
 | |
|   stmt= mysql_simple_prepare(mysql, ("SELECT ROW(1, 7) IN (select id, id1 "
 | |
|                                      "from test_sub2 WHERE id1= ?)"));
 | |
|   check_stmt(stmt);
 | |
| 
 | |
|   rc= mysql_stmt_bind_param(stmt, my_bind);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= mysql_stmt_bind_result(stmt, my_bind);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   id= 7;
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= mysql_stmt_fetch(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   if (!opt_silent)
 | |
|     fprintf(stdout, "\n row 1: %d", id);
 | |
|   DIE_UNLESS(id == 1);
 | |
| 
 | |
|   rc= mysql_stmt_fetch(stmt);
 | |
|   DIE_UNLESS(rc == MYSQL_NO_DATA);
 | |
| 
 | |
|   id= 8;
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= mysql_stmt_fetch(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   if (!opt_silent)
 | |
|     fprintf(stdout, "\n row 1: %d", id);
 | |
|   DIE_UNLESS(id == 0);
 | |
| 
 | |
|   rc= mysql_stmt_fetch(stmt);
 | |
|   DIE_UNLESS(rc == MYSQL_NO_DATA);
 | |
| 
 | |
|   mysql_stmt_close(stmt);
 | |
|   DBUG_VOID_RETURN;
 | |
| }
 | |
| 
 | |
| 
 | |
| /*
 | |
|   Generalized conversion routine to handle DATE, TIME and DATETIME
 | |
|   conversion using MYSQL_TIME structure
 | |
| */
 | |
| 
 | |
| static void test_bind_date_conv(uint row_count)
 | |
| {
 | |
|   MYSQL_STMT   *stmt= 0;
 | |
|   uint         rc, i, count= row_count;
 | |
|   ulong        length[4];
 | |
|   MYSQL_BIND   my_bind[4];
 | |
|   my_bool      is_null[4]= {0};
 | |
|   MYSQL_TIME   tm[4];
 | |
|   ulong        second_part;
 | |
|   uint         year, month, day, hour, minute, sec;
 | |
|   uint         now_year= 1990, now_month= 3, now_day= 13;
 | |
| 
 | |
|   rc= mysql_query(mysql, "SET timestamp=UNIX_TIMESTAMP('1990-03-13')");
 | |
|   myquery(rc);
 | |
| 
 | |
|   stmt= mysql_simple_prepare(mysql, "INSERT INTO test_date VALUES(?, ?, ?, ?)");
 | |
|   check_stmt(stmt);
 | |
| 
 | |
|   verify_param_count(stmt, 4);
 | |
| 
 | |
|   /*
 | |
|     We need to bzero bind structure because mysql_stmt_bind_param checks all
 | |
|     its members.
 | |
|   */
 | |
|   bzero((char*) my_bind, sizeof(my_bind));
 | |
| 
 | |
|   my_bind[0].buffer_type= MYSQL_TYPE_TIMESTAMP;
 | |
|   my_bind[1].buffer_type= MYSQL_TYPE_TIME;
 | |
|   my_bind[2].buffer_type= MYSQL_TYPE_DATETIME;
 | |
|   my_bind[3].buffer_type= MYSQL_TYPE_DATE;
 | |
| 
 | |
|   for (i= 0; i < (int) array_elements(my_bind); i++)
 | |
|   {
 | |
|     my_bind[i].buffer= (void *) &tm[i];
 | |
|     my_bind[i].is_null= &is_null[i];
 | |
|     my_bind[i].length= &length[i];
 | |
|     my_bind[i].buffer_length= 30;
 | |
|     length[i]= 20;
 | |
|   }
 | |
| 
 | |
|   second_part= 0;
 | |
| 
 | |
|   year= 2000;
 | |
|   month= 01;
 | |
|   day= 10;
 | |
| 
 | |
|   hour= 11;
 | |
|   minute= 16;
 | |
|   sec= 20;
 | |
| 
 | |
|   rc= mysql_stmt_bind_param(stmt, my_bind);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   for (count= 0; count < row_count; count++)
 | |
|   {
 | |
|     for (i= 0; i < (int) array_elements(my_bind); i++)
 | |
|     {
 | |
|       tm[i].neg= 0;
 | |
|       tm[i].second_part= second_part+count;
 | |
|       if (my_bind[i].buffer_type != MYSQL_TYPE_TIME)
 | |
|       {
 | |
|         tm[i].year= year+count;
 | |
|         tm[i].month= month+count;
 | |
|         tm[i].day= day+count;
 | |
|       }
 | |
|       else
 | |
|         tm[i].year= tm[i].month= tm[i].day= 0;
 | |
|       if (my_bind[i].buffer_type != MYSQL_TYPE_DATE)
 | |
|       {
 | |
|         tm[i].hour= hour+count;
 | |
|         tm[i].minute= minute+count;
 | |
|         tm[i].second= sec+count;
 | |
|       }
 | |
|       else
 | |
|         tm[i].hour= tm[i].minute= tm[i].second= 0;
 | |
|     }
 | |
|     rc= mysql_stmt_execute(stmt);
 | |
|     check_execute(stmt, rc);
 | |
|   }
 | |
| 
 | |
|   rc= mysql_commit(mysql);
 | |
|   myquery(rc);
 | |
| 
 | |
|   mysql_stmt_close(stmt);
 | |
| 
 | |
|   rc= my_stmt_result("SELECT * FROM test_date");
 | |
|   DIE_UNLESS(row_count == rc);
 | |
| 
 | |
|   stmt= mysql_simple_prepare(mysql, "SELECT * FROM test_date");
 | |
|   check_stmt(stmt);
 | |
| 
 | |
|   rc= mysql_stmt_bind_result(stmt, my_bind);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= mysql_stmt_store_result(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   for (count= 0; count < row_count; count++)
 | |
|   {
 | |
|     rc= mysql_stmt_fetch(stmt);
 | |
|     DIE_UNLESS(rc == 0 || rc == MYSQL_DATA_TRUNCATED);
 | |
| 
 | |
|     if (!opt_silent)
 | |
|       fprintf(stdout, "\n");
 | |
|     for (i= 0; i < array_elements(my_bind); i++)
 | |
|     {
 | |
|       if (!opt_silent)
 | |
|         fprintf(stdout, "\ntime[%d]: %02d-%02d-%02d %02d:%02d:%02d.%02lu",
 | |
|                 i, tm[i].year, tm[i].month, tm[i].day,
 | |
|                 tm[i].hour, tm[i].minute, tm[i].second,
 | |
|                 tm[i].second_part);
 | |
|       DIE_UNLESS(tm[i].year == 0 || tm[i].year == year + count ||
 | |
|                  (tm[i].year == now_year &&
 | |
|                   my_bind[i].buffer_type == MYSQL_TYPE_TIME));
 | |
|       DIE_UNLESS(tm[i].month == 0 || tm[i].month == month + count ||
 | |
|                  (tm[i].month == now_month &&
 | |
|                   my_bind[i].buffer_type == MYSQL_TYPE_TIME));
 | |
|       DIE_UNLESS(tm[i].day == 0 || tm[i].day == day + count ||
 | |
|                  (tm[i].day == now_day &&
 | |
|                   my_bind[i].buffer_type == MYSQL_TYPE_TIME));
 | |
| 
 | |
|       DIE_UNLESS(tm[i].hour == 0 || tm[i].hour == hour+count);
 | |
|       DIE_UNLESS(tm[i].minute == 0 || tm[i].minute == minute+count);
 | |
|       DIE_UNLESS(tm[i].second == 0 || tm[i].second == sec+count);
 | |
|       DIE_UNLESS(tm[i].second_part == 0 ||
 | |
|                  tm[i].second_part == second_part+count);
 | |
|     }
 | |
|   }
 | |
|   rc= mysql_stmt_fetch(stmt);
 | |
|   DIE_UNLESS(rc == MYSQL_NO_DATA);
 | |
| 
 | |
|   mysql_stmt_close(stmt);
 | |
| }
 | |
| 
 | |
| 
 | |
| /* Test DATE, TIME, DATETIME and TS with MYSQL_TIME conversion */
 | |
| 
 | |
| static void test_date()
 | |
| {
 | |
|   int        rc;
 | |
| 
 | |
|   myheader("test_date");
 | |
| 
 | |
|   rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_date");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "CREATE TABLE test_date(c1 TIMESTAMP, \
 | |
|                                                  c2 TIME, \
 | |
|                                                  c3 DATETIME, \
 | |
|                                                  c4 DATE)");
 | |
| 
 | |
|   myquery(rc);
 | |
| 
 | |
|   test_bind_date_conv(5);
 | |
| }
 | |
| 
 | |
| 
 | |
| /* Test all time types to DATE and DATE to all types */
 | |
| 
 | |
| static void test_date_date()
 | |
| {
 | |
|   int        rc;
 | |
| 
 | |
|   myheader("test_date_date");
 | |
| 
 | |
|   rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_date");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "CREATE TABLE test_date(c1 DATE, \
 | |
|                                                  c2 DATE, \
 | |
|                                                  c3 DATE, \
 | |
|                                                  c4 DATE)");
 | |
| 
 | |
|   myquery(rc);
 | |
| 
 | |
|   test_bind_date_conv(3);
 | |
| }
 | |
| 
 | |
| 
 | |
| /* Test all time types to TIME and TIME to all types */
 | |
| 
 | |
| static void test_date_time()
 | |
| {
 | |
|   int        rc;
 | |
| 
 | |
|   myheader("test_date_time");
 | |
| 
 | |
|   rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_date");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "CREATE TABLE test_date(c1 TIME, \
 | |
|                                                  c2 TIME, \
 | |
|                                                  c3 TIME, \
 | |
|                                                  c4 TIME)");
 | |
| 
 | |
|   myquery(rc);
 | |
| 
 | |
|   test_bind_date_conv(3);
 | |
| }
 | |
| 
 | |
| 
 | |
| /* Test all time types to TIMESTAMP and TIMESTAMP to all types */
 | |
| 
 | |
| static void test_date_ts()
 | |
| {
 | |
|   int        rc;
 | |
| 
 | |
|   myheader("test_date_ts");
 | |
| 
 | |
|   rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_date");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "CREATE TABLE test_date(c1 TIMESTAMP, \
 | |
|                                                  c2 TIMESTAMP, \
 | |
|                                                  c3 TIMESTAMP, \
 | |
|                                                  c4 TIMESTAMP)");
 | |
| 
 | |
|   myquery(rc);
 | |
| 
 | |
|   test_bind_date_conv(2);
 | |
| }
 | |
| 
 | |
| 
 | |
| /* Test all time types to DATETIME and DATETIME to all types */
 | |
| 
 | |
| static void test_date_dt()
 | |
| {
 | |
|   int rc;
 | |
| 
 | |
|   myheader("test_date_dt");
 | |
| 
 | |
|   rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_date");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "CREATE TABLE test_date(c1 datetime, "
 | |
|                          " c2 datetime, c3 datetime, c4 date)");
 | |
|   myquery(rc);
 | |
| 
 | |
|   test_bind_date_conv(2);
 | |
| }
 | |
| 
 | |
| static void test_simple_temporal() {
 | |
| 
 | |
|   MYSQL_STMT *stmt = NULL;
 | |
|   uint rc;
 | |
|   ulong length = 0;
 | |
|   MYSQL_BIND my_bind[4], my_bind2;
 | |
|   my_bool is_null = FALSE;
 | |
|   MYSQL_TIME tm;
 | |
|   char string[100];
 | |
|   MYSQL_RES *rs;
 | |
|   MYSQL_FIELD *field;
 | |
| 
 | |
|   myheader("test_simple_temporal");
 | |
| 
 | |
|   /* Initialize param/fetch buffers for data, null flags, lengths */
 | |
|   memset(&my_bind, 0, sizeof(my_bind));
 | |
|   memset(&my_bind2, 0, sizeof(my_bind2));
 | |
| 
 | |
|   /* Initialize the first input parameter */
 | |
|   my_bind[0].buffer_type = MYSQL_TYPE_DATETIME;
 | |
|   my_bind[0].buffer = &tm;
 | |
|   my_bind[0].is_null = &is_null;
 | |
|   my_bind[0].length = &length;
 | |
|   my_bind[0].buffer_length = sizeof(tm);
 | |
| 
 | |
|   /* Clone the other input parameters */
 | |
|   my_bind[3] = my_bind[2] = my_bind[1] = my_bind[0];
 | |
| 
 | |
|   my_bind[1].buffer_type = MYSQL_TYPE_TIMESTAMP;
 | |
|   my_bind[2].buffer_type = MYSQL_TYPE_DATE;
 | |
|   my_bind[3].buffer_type = MYSQL_TYPE_TIME;
 | |
| 
 | |
|   /* Initialize fetch parameter */
 | |
|   my_bind2.buffer_type = MYSQL_TYPE_STRING;
 | |
|   my_bind2.length = &length;
 | |
|   my_bind2.is_null = &is_null;
 | |
|   my_bind2.buffer_length = sizeof(string);
 | |
|   my_bind2.buffer = string;
 | |
| 
 | |
|   /* Prepare and bind simple SELECT with DATETIME parameter */
 | |
|   stmt = mysql_simple_prepare(mysql, "SELECT ?");
 | |
|   check_stmt(stmt);
 | |
|   verify_param_count(stmt, 1);
 | |
| 
 | |
|   rc = mysql_stmt_bind_param(stmt, &my_bind[0]);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc = mysql_stmt_bind_result(stmt, &my_bind2);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   /* Initialize DATETIME value */
 | |
|   tm.neg = FALSE;
 | |
|   tm.time_type = MYSQL_TIMESTAMP_DATETIME;
 | |
|   tm.year = 2001;
 | |
|   tm.month = 10;
 | |
|   tm.day = 20;
 | |
|   tm.hour = 10;
 | |
|   tm.minute = 10;
 | |
|   tm.second = 59;
 | |
|   tm.second_part = 500000;
 | |
| 
 | |
|   /* Execute and fetch */
 | |
|   rc = mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rs = mysql_stmt_result_metadata(stmt);
 | |
|   field = mysql_fetch_fields(rs);
 | |
| 
 | |
|   rc = mysql_stmt_store_result(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc = mysql_stmt_fetch(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   DIE_UNLESS(field->type == MYSQL_TYPE_DATETIME);
 | |
|   DIE_UNLESS(strcmp(string, "2001-10-20 10:10:59.500000") == 0);
 | |
| 
 | |
|   mysql_free_result(rs);
 | |
| 
 | |
|   mysql_stmt_close(stmt);
 | |
| 
 | |
|   /* Same test with explicit CAST */
 | |
|   stmt = mysql_simple_prepare(mysql, "SELECT CAST(? AS DATETIME(6))");
 | |
|   check_stmt(stmt);
 | |
|   verify_param_count(stmt, 1);
 | |
| 
 | |
|   rc = mysql_stmt_bind_param(stmt, &my_bind[0]);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc = mysql_stmt_bind_result(stmt, &my_bind2);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   /* Execute and fetch */
 | |
|   rc = mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rs = mysql_stmt_result_metadata(stmt);
 | |
|   field = mysql_fetch_fields(rs);
 | |
| 
 | |
|   rc = mysql_stmt_store_result(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc = mysql_stmt_fetch(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   DIE_UNLESS(field->type == MYSQL_TYPE_DATETIME);
 | |
|   DIE_UNLESS(strcmp(string, "2001-10-20 10:10:59.500000") == 0);
 | |
| 
 | |
|   mysql_free_result(rs);
 | |
| 
 | |
|   mysql_stmt_close(stmt);
 | |
| 
 | |
|   /* Prepare and bind simple SELECT with TIMESTAMP parameter */
 | |
|   stmt = mysql_simple_prepare(mysql, "SELECT ?");
 | |
|   check_stmt(stmt);
 | |
|   verify_param_count(stmt, 1);
 | |
| 
 | |
|   rc = mysql_stmt_bind_param(stmt, &my_bind[1]);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc = mysql_stmt_bind_result(stmt, &my_bind2);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   /* Initialize TIMESTAMP value */
 | |
|   tm.neg = FALSE;
 | |
|   tm.time_type = MYSQL_TIMESTAMP_DATETIME;
 | |
|   tm.year = 2001;
 | |
|   tm.month = 10;
 | |
|   tm.day = 20;
 | |
|   tm.hour = 10;
 | |
|   tm.minute = 10;
 | |
|   tm.second = 59;
 | |
|   tm.second_part = 500000;
 | |
| 
 | |
|   /* Execute and fetch */
 | |
|   rc = mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rs = mysql_stmt_result_metadata(stmt);
 | |
|   field = mysql_fetch_fields(rs);
 | |
| 
 | |
|   rc = mysql_stmt_store_result(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc = mysql_stmt_fetch(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   DIE_UNLESS(field->type == MYSQL_TYPE_TIMESTAMP);
 | |
|   DIE_UNLESS(strcmp(string, "2001-10-20 10:10:59.500000") == 0);
 | |
| 
 | |
|   mysql_free_result(rs);
 | |
| 
 | |
|   mysql_stmt_close(stmt);
 | |
| 
 | |
|   /* Prepare and bind simple SELECT with DATE parameter */
 | |
|   stmt = mysql_simple_prepare(mysql, "SELECT ?");
 | |
|   check_stmt(stmt);
 | |
|   verify_param_count(stmt, 1);
 | |
| 
 | |
|   rc = mysql_stmt_bind_param(stmt, &my_bind[2]);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc = mysql_stmt_bind_result(stmt, &my_bind2);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   /* Initialize DATE value */
 | |
|   tm.neg = FALSE;
 | |
|   tm.time_type = MYSQL_TIMESTAMP_DATE;
 | |
|   tm.year = 2001;
 | |
|   tm.month = 10;
 | |
|   tm.day = 20;
 | |
|   tm.hour = 0;
 | |
|   tm.minute = 0;
 | |
|   tm.second = 0;
 | |
|   tm.second_part = 0;
 | |
| 
 | |
|   /* Execute and fetch */
 | |
|   rc = mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rs = mysql_stmt_result_metadata(stmt);
 | |
|   field = mysql_fetch_fields(rs);
 | |
| 
 | |
|   rc = mysql_stmt_store_result(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc = mysql_stmt_fetch(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   DIE_UNLESS(field->type == MYSQL_TYPE_DATE);
 | |
|   DIE_UNLESS(strcmp(string, "2001-10-20") == 0);
 | |
| 
 | |
|   mysql_free_result(rs);
 | |
| 
 | |
|   mysql_stmt_close(stmt);
 | |
| 
 | |
|   /* Same test with explicit CAST */
 | |
|   stmt = mysql_simple_prepare(mysql, "SELECT CAST(? AS DATE)");
 | |
|   check_stmt(stmt);
 | |
|   verify_param_count(stmt, 1);
 | |
| 
 | |
|   rc = mysql_stmt_bind_param(stmt, &my_bind[2]);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc = mysql_stmt_bind_result(stmt, &my_bind2);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   /* Execute and fetch */
 | |
|   rc = mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rs = mysql_stmt_result_metadata(stmt);
 | |
|   field = mysql_fetch_fields(rs);
 | |
| 
 | |
|   rc = mysql_stmt_store_result(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc = mysql_stmt_fetch(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   DIE_UNLESS(field->type == MYSQL_TYPE_DATE);
 | |
|   DIE_UNLESS(strcmp(string, "2001-10-20") == 0);
 | |
| 
 | |
|   mysql_free_result(rs);
 | |
| 
 | |
|   mysql_stmt_close(stmt);
 | |
| 
 | |
|   /* Prepare and bind simple SELECT with TIME parameter */
 | |
|   stmt = mysql_simple_prepare(mysql, "SELECT ?");
 | |
|   check_stmt(stmt);
 | |
|   verify_param_count(stmt, 1);
 | |
| 
 | |
|   rc = mysql_stmt_bind_param(stmt, &my_bind[3]);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc = mysql_stmt_bind_result(stmt, &my_bind2);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   /* Initialize TIME value */
 | |
|   tm.neg = FALSE;
 | |
|   tm.time_type = MYSQL_TIMESTAMP_TIME;
 | |
|   tm.year = 0;
 | |
|   tm.month = 0;
 | |
|   tm.day = 0;
 | |
|   tm.hour = 10;
 | |
|   tm.minute = 10;
 | |
|   tm.second = 59;
 | |
|   tm.second_part = 500000;
 | |
| 
 | |
|   /* Execute and fetch */
 | |
|   rc = mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rs = mysql_stmt_result_metadata(stmt);
 | |
|   field = mysql_fetch_fields(rs);
 | |
| 
 | |
|   rc = mysql_stmt_store_result(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc = mysql_stmt_fetch(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   DIE_UNLESS(field->type == MYSQL_TYPE_TIME);
 | |
|   DIE_UNLESS(strcmp(string, "10:10:59.500000") == 0);
 | |
| 
 | |
|   mysql_free_result(rs);
 | |
| 
 | |
|   mysql_stmt_close(stmt);
 | |
| 
 | |
|   /* Same test with explicit CAST */
 | |
|   stmt = mysql_simple_prepare(mysql, "SELECT CAST(? AS TIME(6))");
 | |
|   check_stmt(stmt);
 | |
|   verify_param_count(stmt, 1);
 | |
| 
 | |
|   rc = mysql_stmt_bind_param(stmt, &my_bind[3]);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc = mysql_stmt_bind_result(stmt, &my_bind2);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   /* Initialize TIME value */
 | |
|   tm.neg = FALSE;
 | |
|   tm.time_type = MYSQL_TIMESTAMP_TIME;
 | |
|   tm.year = 0;
 | |
|   tm.month = 0;
 | |
|   tm.day = 0;
 | |
|   tm.hour = 10;
 | |
|   tm.minute = 10;
 | |
|   tm.second = 59;
 | |
|   tm.second_part = 500000;
 | |
| 
 | |
|   /* Execute and fetch */
 | |
|   rc = mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rs = mysql_stmt_result_metadata(stmt);
 | |
|   field = mysql_fetch_fields(rs);
 | |
| 
 | |
|   rc = mysql_stmt_store_result(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc = mysql_stmt_fetch(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   DIE_UNLESS(field->type == MYSQL_TYPE_TIME);
 | |
|   DIE_UNLESS(strcmp(string, "10:10:59.500000") == 0);
 | |
| 
 | |
|   mysql_free_result(rs);
 | |
| 
 | |
|   mysql_stmt_close(stmt);
 | |
| }
 | |
| 
 | |
| 
 | |
| /* Misc tests to keep pure coverage happy */
 | |
| 
 | |
| static void test_pure_coverage()
 | |
| {
 | |
|   MYSQL_STMT *stmt;
 | |
|   MYSQL_BIND my_bind[2];
 | |
|   int        rc;
 | |
|   ulong      length;
 | |
| 
 | |
|   myheader("test_pure_coverage");
 | |
| 
 | |
|   rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_pure");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "CREATE TABLE test_pure(c1 int, c2 varchar(20))");
 | |
|   myquery(rc);
 | |
| 
 | |
|   stmt= mysql_simple_prepare(mysql, "insert into test_pure(c67788) values(10)");
 | |
|   check_stmt_r(stmt);
 | |
| 
 | |
|   /* Query without params and result should allow to bind 0 arrays */
 | |
|   stmt= mysql_simple_prepare(mysql, "insert into test_pure(c2) values(10)");
 | |
|   check_stmt(stmt);
 | |
| 
 | |
|   rc= mysql_stmt_bind_param(stmt, (MYSQL_BIND*)0);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= mysql_stmt_bind_result(stmt, (MYSQL_BIND*)0);
 | |
|   DIE_UNLESS(rc == 1);
 | |
| 
 | |
|   mysql_stmt_close(stmt);
 | |
| 
 | |
|   stmt= mysql_simple_prepare(mysql, "insert into test_pure(c2) values(?)");
 | |
|   check_stmt(stmt);
 | |
| 
 | |
|   /*
 | |
|     We need to bzero bind structure because mysql_stmt_bind_param checks all
 | |
|     its members.
 | |
|   */
 | |
|   bzero((char*) my_bind, sizeof(my_bind));
 | |
| 
 | |
|   my_bind[0].length= &length;
 | |
|   my_bind[0].is_null= 0;
 | |
|   my_bind[0].buffer_length= 0;
 | |
| 
 | |
|   my_bind[0].buffer_type= MYSQL_TYPE_GEOMETRY;
 | |
|   rc= mysql_stmt_bind_param(stmt, my_bind);
 | |
|   check_execute_r(stmt, rc); /* unsupported buffer type */
 | |
| 
 | |
|   my_bind[0].buffer_type= MYSQL_TYPE_STRING;
 | |
|   rc= mysql_stmt_bind_param(stmt, my_bind);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= mysql_stmt_store_result(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   mysql_stmt_close(stmt);
 | |
| 
 | |
|   stmt= mysql_simple_prepare(mysql, "select * from test_pure");
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   my_bind[0].buffer_type= MYSQL_TYPE_GEOMETRY;
 | |
|   rc= mysql_stmt_bind_result(stmt, my_bind);
 | |
|   check_execute(stmt, rc); /* MariaDB C/C converts geometry to string */
 | |
| 
 | |
|   rc= mysql_stmt_store_result(stmt);
 | |
|   DIE_IF(rc);
 | |
| 
 | |
|   rc= mysql_stmt_store_result(stmt);
 | |
|   DIE_UNLESS(rc); /* Old error must be reset first */
 | |
| 
 | |
|   mysql_stmt_close(stmt);
 | |
| 
 | |
|   mysql_query(mysql, "DROP TABLE test_pure");
 | |
| }
 | |
| 
 | |
| 
 | |
| /* Test for string buffer fetch */
 | |
| 
 | |
| static void test_buffers()
 | |
| {
 | |
|   MYSQL_STMT *stmt;
 | |
|   MYSQL_BIND my_bind[1];
 | |
|   int        rc;
 | |
|   ulong      length;
 | |
|   my_bool    is_null;
 | |
|   char       buffer[20];
 | |
| 
 | |
|   myheader("test_buffers");
 | |
| 
 | |
|   rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_buffer");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "CREATE TABLE test_buffer(str varchar(20))");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "insert into test_buffer values('MySQL')\
 | |
|                           , ('Database'), ('Open-Source'), ('Popular')");
 | |
|   myquery(rc);
 | |
| 
 | |
|   stmt= mysql_simple_prepare(mysql, "select str from test_buffer");
 | |
|   check_stmt(stmt);
 | |
| 
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   bzero(buffer, sizeof(buffer));              /* Avoid overruns in printf() */
 | |
| 
 | |
|   bzero((char*) my_bind, sizeof(my_bind));
 | |
|   my_bind[0].length= &length;
 | |
|   my_bind[0].is_null= &is_null;
 | |
|   my_bind[0].buffer_length= 1;
 | |
|   my_bind[0].buffer_type= MYSQL_TYPE_STRING;
 | |
|   my_bind[0].buffer= (void *)buffer;
 | |
|   my_bind[0].error= &my_bind[0].error_value;
 | |
| 
 | |
|   rc= mysql_stmt_bind_result(stmt, my_bind);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= mysql_stmt_store_result(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   buffer[1]= 'X';
 | |
|   rc= mysql_stmt_fetch(stmt);
 | |
|   DIE_UNLESS(rc == MYSQL_DATA_TRUNCATED);
 | |
|   DIE_UNLESS(my_bind[0].error_value);
 | |
|   if (!opt_silent)
 | |
|     fprintf(stdout, "\n data: %s (%lu)", buffer, length);
 | |
|   DIE_UNLESS(buffer[0] == 'M');
 | |
|   DIE_UNLESS(buffer[1] == 'X');
 | |
|   DIE_UNLESS(length == 5);
 | |
| 
 | |
|   my_bind[0].buffer_length= 8;
 | |
|   rc= mysql_stmt_bind_result(stmt, my_bind);/* re-bind */
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= mysql_stmt_fetch(stmt);
 | |
|   check_execute(stmt, rc);
 | |
|   if (!opt_silent)
 | |
|     fprintf(stdout, "\n data: %s (%lu)", buffer, length);
 | |
|   DIE_UNLESS(strncmp(buffer, "Database", 8) == 0);
 | |
|   DIE_UNLESS(length == 8);
 | |
| 
 | |
|   my_bind[0].buffer_length= 12;
 | |
|   rc= mysql_stmt_bind_result(stmt, my_bind);/* re-bind */
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= mysql_stmt_fetch(stmt);
 | |
|   check_execute(stmt, rc);
 | |
|   if (!opt_silent)
 | |
|     fprintf(stdout, "\n data: %s (%lu)", buffer, length);
 | |
|   DIE_UNLESS(strcmp(buffer, "Open-Source") == 0);
 | |
|   DIE_UNLESS(length == 11);
 | |
| 
 | |
|   my_bind[0].buffer_length= 6;
 | |
|   rc= mysql_stmt_bind_result(stmt, my_bind);/* re-bind */
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= mysql_stmt_fetch(stmt);
 | |
|   DIE_UNLESS(rc == MYSQL_DATA_TRUNCATED);
 | |
|   DIE_UNLESS(my_bind[0].error_value);
 | |
|   if (!opt_silent)
 | |
|     fprintf(stdout, "\n data: %s (%lu)", buffer, length);
 | |
|   DIE_UNLESS(strncmp(buffer, "Popula", 6) == 0);
 | |
|   DIE_UNLESS(length == 7);
 | |
| 
 | |
|   mysql_stmt_close(stmt);
 | |
| }
 | |
| 
 | |
| 
 | |
| /* Test the direct query execution in the middle of open stmts */
 | |
| 
 | |
| static void test_open_direct()
 | |
| {
 | |
|   MYSQL_STMT  *stmt;
 | |
|   MYSQL_RES   *result;
 | |
|   int         rc;
 | |
| 
 | |
|   myheader("test_open_direct");
 | |
| 
 | |
|   rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_open_direct");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "CREATE TABLE test_open_direct(id int, name char(6))");
 | |
|   myquery(rc);
 | |
| 
 | |
|   stmt= mysql_simple_prepare(mysql, "INSERT INTO test_open_direct values(10, 'mysql')");
 | |
|   check_stmt(stmt);
 | |
| 
 | |
|   rc= mysql_query(mysql, "SELECT * FROM test_open_direct");
 | |
|   myquery(rc);
 | |
| 
 | |
|   result= mysql_store_result(mysql);
 | |
|   mytest(result);
 | |
| 
 | |
|   rc= my_process_result_set(result);
 | |
|   DIE_UNLESS(rc == 0);
 | |
|   mysql_free_result(result);
 | |
| 
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   verify_st_affected_rows(stmt, 1);
 | |
| 
 | |
|   rc= mysql_query(mysql, "SELECT * FROM test_open_direct");
 | |
|   myquery(rc);
 | |
| 
 | |
|   result= mysql_store_result(mysql);
 | |
|   mytest(result);
 | |
| 
 | |
|   rc= my_process_result_set(result);
 | |
|   DIE_UNLESS(rc == 1);
 | |
|   mysql_free_result(result);
 | |
| 
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   verify_st_affected_rows(stmt, 1);
 | |
| 
 | |
|   rc= mysql_query(mysql, "SELECT * FROM test_open_direct");
 | |
|   myquery(rc);
 | |
| 
 | |
|   result= mysql_store_result(mysql);
 | |
|   mytest(result);
 | |
| 
 | |
|   rc= my_process_result_set(result);
 | |
|   DIE_UNLESS(rc == 2);
 | |
|   mysql_free_result(result);
 | |
| 
 | |
|   mysql_stmt_close(stmt);
 | |
| 
 | |
|   /* run a direct query in the middle of a fetch */
 | |
|   stmt= mysql_simple_prepare(mysql, "SELECT * FROM test_open_direct");
 | |
|   check_stmt(stmt);
 | |
| 
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= mysql_stmt_fetch(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "INSERT INTO test_open_direct(id) VALUES(20)");
 | |
|   myquery_r(rc);
 | |
| 
 | |
|   rc= mysql_stmt_close(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "INSERT INTO test_open_direct(id) VALUES(20)");
 | |
|   myquery(rc);
 | |
| 
 | |
|   /* run a direct query with store result */
 | |
|   stmt= mysql_simple_prepare(mysql, "SELECT * FROM test_open_direct");
 | |
|   check_stmt(stmt);
 | |
| 
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= mysql_stmt_store_result(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= mysql_stmt_fetch(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "drop table test_open_direct");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_stmt_close(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| }
 | |
| 
 | |
| 
 | |
| /* Test fetch without prior bound buffers */
 | |
| 
 | |
| static void test_fetch_nobuffs()
 | |
| {
 | |
|   MYSQL_STMT *stmt;
 | |
|   MYSQL_BIND my_bind[4];
 | |
|   char       str[4][50];
 | |
|   int        rc;
 | |
| 
 | |
|   myheader("test_fetch_nobuffs");
 | |
| 
 | |
|   stmt= mysql_simple_prepare(mysql, "SELECT DATABASE(), CURRENT_USER(), \
 | |
|                               CURRENT_DATE(), CURRENT_TIME()");
 | |
|   check_stmt(stmt);
 | |
| 
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= 0;
 | |
|   while (mysql_stmt_fetch(stmt) != MYSQL_NO_DATA)
 | |
|     rc++;
 | |
| 
 | |
|   if (!opt_silent)
 | |
|     fprintf(stdout, "\n total rows        : %d", rc);
 | |
|   DIE_UNLESS(rc == 1);
 | |
| 
 | |
|   bzero((char*) my_bind, sizeof(MYSQL_BIND));
 | |
|   my_bind[0].buffer_type= MYSQL_TYPE_STRING;
 | |
|   my_bind[0].buffer= (void *)str[0];
 | |
|   my_bind[0].buffer_length= sizeof(str[0]);
 | |
|   my_bind[1]= my_bind[2]= my_bind[3]= my_bind[0];
 | |
|   my_bind[1].buffer= (void *)str[1];
 | |
|   my_bind[2].buffer= (void *)str[2];
 | |
|   my_bind[3].buffer= (void *)str[3];
 | |
| 
 | |
|   rc= mysql_stmt_bind_result(stmt, my_bind);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= 0;
 | |
|   while (mysql_stmt_fetch(stmt) != MYSQL_NO_DATA)
 | |
|   {
 | |
|     rc++;
 | |
|     if (!opt_silent)
 | |
|     {
 | |
|       fprintf(stdout, "\n CURRENT_DATABASE(): %s", str[0]);
 | |
|       fprintf(stdout, "\n CURRENT_USER()    : %s", str[1]);
 | |
|       fprintf(stdout, "\n CURRENT_DATE()    : %s", str[2]);
 | |
|       fprintf(stdout, "\n CURRENT_TIME()    : %s", str[3]);
 | |
|     }
 | |
|   }
 | |
|   if (!opt_silent)
 | |
|     fprintf(stdout, "\n total rows        : %d", rc);
 | |
|   DIE_UNLESS(rc == 1);
 | |
| 
 | |
|   mysql_stmt_close(stmt);
 | |
| }
 | |
| 
 | |
| 
 | |
| /* Test a misc bug */
 | |
| 
 | |
| static void test_ushort_bug()
 | |
| {
 | |
|   MYSQL_STMT *stmt;
 | |
|   MYSQL_BIND my_bind[4];
 | |
|   ushort     short_value;
 | |
|   uint32     long_value;
 | |
|   ulong      s_length, l_length, ll_length, t_length;
 | |
|   ulonglong  longlong_value;
 | |
|   int        rc;
 | |
|   uchar      tiny_value;
 | |
|   char       llbuf[22];
 | |
|   myheader("test_ushort_bug");
 | |
| 
 | |
|   rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_ushort");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "CREATE TABLE test_ushort(a smallint unsigned, \
 | |
|                                                   b smallint unsigned, \
 | |
|                                                   c smallint unsigned, \
 | |
|                                                   d smallint unsigned)");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql,
 | |
|                   "INSERT INTO test_ushort VALUES(35999, 35999, 35999, 200)");
 | |
|   myquery(rc);
 | |
| 
 | |
| 
 | |
|   stmt= mysql_simple_prepare(mysql, "SELECT * FROM test_ushort");
 | |
|   check_stmt(stmt);
 | |
| 
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   bzero((char*) my_bind, sizeof(my_bind));
 | |
|   my_bind[0].buffer_type= MYSQL_TYPE_SHORT;
 | |
|   my_bind[0].buffer= (void *)&short_value;
 | |
|   my_bind[0].is_unsigned= TRUE;
 | |
|   my_bind[0].length= &s_length;
 | |
| 
 | |
|   my_bind[1].buffer_type= MYSQL_TYPE_LONG;
 | |
|   my_bind[1].buffer= (void *)&long_value;
 | |
|   my_bind[1].length= &l_length;
 | |
| 
 | |
|   my_bind[2].buffer_type= MYSQL_TYPE_LONGLONG;
 | |
|   my_bind[2].buffer= (void *)&longlong_value;
 | |
|   my_bind[2].length= &ll_length;
 | |
| 
 | |
|   my_bind[3].buffer_type= MYSQL_TYPE_TINY;
 | |
|   my_bind[3].buffer= (void *)&tiny_value;
 | |
|   my_bind[3].is_unsigned= TRUE;
 | |
|   my_bind[3].length= &t_length;
 | |
| 
 | |
|   rc= mysql_stmt_bind_result(stmt, my_bind);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= mysql_stmt_fetch(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   if (!opt_silent)
 | |
|   {
 | |
|     fprintf(stdout, "\n ushort   : %d (%ld)", short_value, s_length);
 | |
|     fprintf(stdout, "\n ulong    : %lu (%ld)", (ulong) long_value, l_length);
 | |
|     fprintf(stdout, "\n longlong : %s (%ld)", llstr(longlong_value, llbuf),
 | |
|             ll_length);
 | |
|     fprintf(stdout, "\n tinyint  : %d   (%ld)", tiny_value, t_length);
 | |
|   }
 | |
| 
 | |
|   DIE_UNLESS(short_value == 35999);
 | |
|   DIE_UNLESS(s_length == 2);
 | |
| 
 | |
|   DIE_UNLESS(long_value == 35999);
 | |
|   DIE_UNLESS(l_length == 4);
 | |
| 
 | |
|   DIE_UNLESS(longlong_value == 35999);
 | |
|   DIE_UNLESS(ll_length == 8);
 | |
| 
 | |
|   DIE_UNLESS(tiny_value == 200);
 | |
|   DIE_UNLESS(t_length == 1);
 | |
| 
 | |
|   rc= mysql_stmt_fetch(stmt);
 | |
|   DIE_UNLESS(rc == MYSQL_NO_DATA);
 | |
| 
 | |
|   mysql_stmt_close(stmt);
 | |
| }
 | |
| 
 | |
| 
 | |
| /* Test a misc smallint-signed conversion bug */
 | |
| 
 | |
| static void test_sshort_bug()
 | |
| {
 | |
|   MYSQL_STMT *stmt;
 | |
|   MYSQL_BIND my_bind[4];
 | |
|   short      short_value;
 | |
|   int32      long_value;
 | |
|   ulong      s_length, l_length, ll_length, t_length;
 | |
|   ulonglong  longlong_value;
 | |
|   int        rc;
 | |
|   uchar      tiny_value;
 | |
|   char       llbuf[22];
 | |
| 
 | |
|   myheader("test_sshort_bug");
 | |
| 
 | |
|   rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_sshort");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "CREATE TABLE test_sshort(a smallint signed, \
 | |
|                                                   b smallint signed, \
 | |
|                                                   c smallint unsigned, \
 | |
|                                                   d smallint unsigned)");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "INSERT INTO test_sshort VALUES(-5999, -5999, 35999, 200)");
 | |
|   myquery(rc);
 | |
| 
 | |
| 
 | |
|   stmt= mysql_simple_prepare(mysql, "SELECT * FROM test_sshort");
 | |
|   check_stmt(stmt);
 | |
| 
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   bzero((char*) my_bind, sizeof(my_bind));
 | |
|   my_bind[0].buffer_type= MYSQL_TYPE_SHORT;
 | |
|   my_bind[0].buffer= (void *)&short_value;
 | |
|   my_bind[0].length= &s_length;
 | |
| 
 | |
|   my_bind[1].buffer_type= MYSQL_TYPE_LONG;
 | |
|   my_bind[1].buffer= (void *)&long_value;
 | |
|   my_bind[1].length= &l_length;
 | |
| 
 | |
|   my_bind[2].buffer_type= MYSQL_TYPE_LONGLONG;
 | |
|   my_bind[2].buffer= (void *)&longlong_value;
 | |
|   my_bind[2].length= &ll_length;
 | |
| 
 | |
|   my_bind[3].buffer_type= MYSQL_TYPE_TINY;
 | |
|   my_bind[3].buffer= (void *)&tiny_value;
 | |
|   my_bind[3].is_unsigned= TRUE;
 | |
|   my_bind[3].length= &t_length;
 | |
| 
 | |
|   rc= mysql_stmt_bind_result(stmt, my_bind);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= mysql_stmt_fetch(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   if (!opt_silent)
 | |
|   {
 | |
|     fprintf(stdout, "\n sshort   : %d (%ld)", short_value, s_length);
 | |
|     fprintf(stdout, "\n slong    : %ld (%ld)", (long) long_value, l_length);
 | |
|     fprintf(stdout, "\n longlong : %s (%ld)", llstr(longlong_value, llbuf),
 | |
|             ll_length);
 | |
|     fprintf(stdout, "\n tinyint  : %d   (%ld)", tiny_value, t_length);
 | |
|   }
 | |
| 
 | |
|   DIE_UNLESS(short_value == -5999);
 | |
|   DIE_UNLESS(s_length == 2);
 | |
| 
 | |
|   DIE_UNLESS(long_value == -5999);
 | |
|   DIE_UNLESS(l_length == 4);
 | |
| 
 | |
|   DIE_UNLESS(longlong_value == 35999);
 | |
|   DIE_UNLESS(ll_length == 8);
 | |
| 
 | |
|   DIE_UNLESS(tiny_value == 200);
 | |
|   DIE_UNLESS(t_length == 1);
 | |
| 
 | |
|   rc= mysql_stmt_fetch(stmt);
 | |
|   DIE_UNLESS(rc == MYSQL_NO_DATA);
 | |
| 
 | |
|   mysql_stmt_close(stmt);
 | |
| }
 | |
| 
 | |
| 
 | |
| /* Test a misc tinyint-signed conversion bug */
 | |
| 
 | |
| static void test_stiny_bug()
 | |
| {
 | |
|   MYSQL_STMT *stmt;
 | |
|   MYSQL_BIND my_bind[4];
 | |
|   short      short_value;
 | |
|   int32      long_value;
 | |
|   ulong      s_length, l_length, ll_length, t_length;
 | |
|   ulonglong  longlong_value;
 | |
|   int        rc;
 | |
|   uchar      tiny_value;
 | |
|   char       llbuf[22];
 | |
| 
 | |
|   myheader("test_stiny_bug");
 | |
| 
 | |
|   rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_stiny");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "CREATE TABLE test_stiny(a tinyint signed, \
 | |
|                                                   b tinyint signed, \
 | |
|                                                   c tinyint unsigned, \
 | |
|                                                   d tinyint unsigned)");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "INSERT INTO test_stiny VALUES(-128, -127, 255, 0)");
 | |
|   myquery(rc);
 | |
| 
 | |
| 
 | |
|   stmt= mysql_simple_prepare(mysql, "SELECT * FROM test_stiny");
 | |
|   check_stmt(stmt);
 | |
| 
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   bzero((char*) my_bind, sizeof(my_bind));
 | |
|   my_bind[0].buffer_type= MYSQL_TYPE_SHORT;
 | |
|   my_bind[0].buffer= (void *)&short_value;
 | |
|   my_bind[0].length= &s_length;
 | |
| 
 | |
|   my_bind[1].buffer_type= MYSQL_TYPE_LONG;
 | |
|   my_bind[1].buffer= (void *)&long_value;
 | |
|   my_bind[1].length= &l_length;
 | |
| 
 | |
|   my_bind[2].buffer_type= MYSQL_TYPE_LONGLONG;
 | |
|   my_bind[2].buffer= (void *)&longlong_value;
 | |
|   my_bind[2].length= &ll_length;
 | |
| 
 | |
|   my_bind[3].buffer_type= MYSQL_TYPE_TINY;
 | |
|   my_bind[3].buffer= (void *)&tiny_value;
 | |
|   my_bind[3].length= &t_length;
 | |
| 
 | |
|   rc= mysql_stmt_bind_result(stmt, my_bind);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= mysql_stmt_fetch(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   if (!opt_silent)
 | |
|   {
 | |
|     fprintf(stdout, "\n sshort   : %d (%ld)", short_value, s_length);
 | |
|     fprintf(stdout, "\n slong    : %ld (%ld)", (long) long_value, l_length);
 | |
|     fprintf(stdout, "\n longlong : %s  (%ld)", llstr(longlong_value, llbuf),
 | |
|             ll_length);
 | |
|     fprintf(stdout, "\n tinyint  : %d    (%ld)", tiny_value, t_length);
 | |
|   }
 | |
| 
 | |
|   DIE_UNLESS(short_value == -128);
 | |
|   DIE_UNLESS(s_length == 2);
 | |
| 
 | |
|   DIE_UNLESS(long_value == -127);
 | |
|   DIE_UNLESS(l_length == 4);
 | |
| 
 | |
|   DIE_UNLESS(longlong_value == 255);
 | |
|   DIE_UNLESS(ll_length == 8);
 | |
| 
 | |
|   DIE_UNLESS(tiny_value == 0);
 | |
|   DIE_UNLESS(t_length == 1);
 | |
| 
 | |
|   rc= mysql_stmt_fetch(stmt);
 | |
|   DIE_UNLESS(rc == MYSQL_NO_DATA);
 | |
| 
 | |
|   mysql_stmt_close(stmt);
 | |
| }
 | |
| 
 | |
| 
 | |
| /* Test misc field information, bug: #74 */
 | |
| 
 | |
| static void test_field_misc()
 | |
| {
 | |
|   MYSQL_STMT  *stmt;
 | |
|   MYSQL_RES   *result;
 | |
|   int         rc;
 | |
| 
 | |
|   myheader("test_field_misc");
 | |
| 
 | |
|   rc= mysql_query(mysql, "SELECT @@autocommit");
 | |
|   myquery(rc);
 | |
| 
 | |
|   result= mysql_store_result(mysql);
 | |
|   mytest(result);
 | |
| 
 | |
|   rc= my_process_result_set(result);
 | |
|   DIE_UNLESS(rc == 1);
 | |
| 
 | |
|   verify_prepare_field(result, 0,
 | |
|                        "@@autocommit", "",  /* field and its org name */
 | |
|                        MYSQL_TYPE_LONGLONG, /* field type */
 | |
|                        "", "",              /* table and its org name */
 | |
|                        "", 1, 0);           /* db name, length(its bool flag)*/
 | |
| 
 | |
|   mysql_free_result(result);
 | |
| 
 | |
|   stmt= mysql_simple_prepare(mysql, "SELECT @@autocommit");
 | |
|   check_stmt(stmt);
 | |
| 
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   result= mysql_stmt_result_metadata(stmt);
 | |
|   mytest(result);
 | |
| 
 | |
|   rc= my_process_stmt_result(stmt);
 | |
|   DIE_UNLESS(rc == 1);
 | |
| 
 | |
|   verify_prepare_field(result, 0,
 | |
|                        "@@autocommit", "",  /* field and its org name */
 | |
|                        MYSQL_TYPE_LONGLONG, /* field type */
 | |
|                        "", "",              /* table and its org name */
 | |
|                        "", 1, 0);           /* db name, length(its bool flag)*/
 | |
| 
 | |
|   mysql_free_result(result);
 | |
|   mysql_stmt_close(stmt);
 | |
| 
 | |
|   stmt= mysql_simple_prepare(mysql, "SELECT @@max_error_count");
 | |
|   check_stmt(stmt);
 | |
| 
 | |
|   result= mysql_stmt_result_metadata(stmt);
 | |
|   mytest(result);
 | |
| 
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= my_process_stmt_result(stmt);
 | |
|   DIE_UNLESS(rc == 1);
 | |
| 
 | |
|   verify_prepare_field(result, 0,
 | |
|                        "@@max_error_count", "",   /* field and its org name */
 | |
|                        MYSQL_TYPE_LONGLONG, /* field type */
 | |
|                        "", "",              /* table and its org name */
 | |
|                        /* db name, length */
 | |
|                        "", MY_INT64_NUM_DECIMAL_DIGITS , 0);
 | |
| 
 | |
|   mysql_free_result(result);
 | |
|   mysql_stmt_close(stmt);
 | |
| 
 | |
|   stmt= mysql_simple_prepare(mysql, "SELECT @@max_allowed_packet");
 | |
|   check_stmt(stmt);
 | |
| 
 | |
|   result= mysql_stmt_result_metadata(stmt);
 | |
|   mytest(result);
 | |
| 
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   DIE_UNLESS(1 == my_process_stmt_result(stmt));
 | |
| 
 | |
|   verify_prepare_field(result, 0,
 | |
|                        "@@max_allowed_packet", "", /* field and its org name */
 | |
|                        MYSQL_TYPE_LONGLONG, /* field type */
 | |
|                        "", "",              /* table and its org name */
 | |
|                        /* db name, length */
 | |
|                        "", MY_INT64_NUM_DECIMAL_DIGITS, 0);
 | |
| 
 | |
|   mysql_free_result(result);
 | |
|   mysql_stmt_close(stmt);
 | |
| 
 | |
|   stmt= mysql_simple_prepare(mysql, "SELECT @@sql_warnings");
 | |
|   check_stmt(stmt);
 | |
| 
 | |
|   result= mysql_stmt_result_metadata(stmt);
 | |
|   mytest(result);
 | |
| 
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= my_process_stmt_result(stmt);
 | |
|   DIE_UNLESS(rc == 1);
 | |
| 
 | |
|   verify_prepare_field(result, 0,
 | |
|                        "@@sql_warnings", "",  /* field and its org name */
 | |
|                        MYSQL_TYPE_LONGLONG,   /* field type */
 | |
|                        "", "",                /* table and its org name */
 | |
|                        "", 1, 0);             /* db name, length */
 | |
| 
 | |
|   mysql_free_result(result);
 | |
|   mysql_stmt_close(stmt);
 | |
| }
 | |
| 
 | |
| 
 | |
| /*
 | |
|   Test SET OPTION feature with prepare stmts
 | |
|   bug #85 (reported by mark@mysql.com)
 | |
| */
 | |
| 
 | |
| static void test_set_option()
 | |
| {
 | |
|   MYSQL_STMT *stmt;
 | |
|   MYSQL_RES  *result;
 | |
|   int        rc;
 | |
| 
 | |
|   myheader("test_set_option");
 | |
| 
 | |
|   mysql_autocommit(mysql, TRUE);
 | |
| 
 | |
|   /* LIMIT the rows count to 2 */
 | |
|   rc= mysql_query(mysql, "SET SQL_SELECT_LIMIT= 2");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_limit");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "CREATE TABLE test_limit(a tinyint)");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "INSERT INTO test_limit VALUES(10), (20), (30), (40)");
 | |
|   myquery(rc);
 | |
| 
 | |
|   if (!opt_silent)
 | |
|     fprintf(stdout, "\n with SQL_SELECT_LIMIT= 2 (direct)");
 | |
|   rc= mysql_query(mysql, "SELECT * FROM test_limit");
 | |
|   myquery(rc);
 | |
| 
 | |
|   result= mysql_store_result(mysql);
 | |
|   mytest(result);
 | |
| 
 | |
|   rc= my_process_result_set(result);
 | |
|   DIE_UNLESS(rc == 2);
 | |
| 
 | |
|   mysql_free_result(result);
 | |
| 
 | |
|   if (!opt_silent)
 | |
|     fprintf(stdout, "\n with SQL_SELECT_LIMIT=2 (prepare)");
 | |
|   stmt= mysql_simple_prepare(mysql, "SELECT * FROM test_limit");
 | |
|   check_stmt(stmt);
 | |
| 
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= my_process_stmt_result(stmt);
 | |
|   DIE_UNLESS(rc == 2);
 | |
| 
 | |
|   mysql_stmt_close(stmt);
 | |
| 
 | |
|   /* RESET the LIMIT the rows count to 0 */
 | |
|   if (!opt_silent)
 | |
|     fprintf(stdout, "\n with SQL_SELECT_LIMIT=DEFAULT (prepare)");
 | |
|   rc= mysql_query(mysql, "SET SQL_SELECT_LIMIT=DEFAULT");
 | |
|   myquery(rc);
 | |
| 
 | |
|   stmt= mysql_simple_prepare(mysql, "SELECT * FROM test_limit");
 | |
|   check_stmt(stmt);
 | |
| 
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= my_process_stmt_result(stmt);
 | |
|   DIE_UNLESS(rc == 4);
 | |
| 
 | |
|   mysql_stmt_close(stmt);
 | |
| }
 | |
| 
 | |
| #ifdef EMBEDDED_LIBRARY
 | |
| static void test_embedded_start_stop()
 | |
| {
 | |
|   MYSQL *mysql_emb=NULL;
 | |
|   int i, j;
 | |
|   int argc= original_argc;                    // Start with the original args
 | |
|   char **argv, **my_argv;
 | |
|   char test_name[]= "test_embedded_start_stop";
 | |
| #define EMBEDDED_RESTARTS 64
 | |
| 
 | |
|   myheader("test_embedded_start_stop");
 | |
| 
 | |
|   /* Must stop the main embedded server, since we use the same config. */
 | |
|   client_disconnect(mysql);    /* disconnect from server */
 | |
|   free_defaults(defaults_argv);
 | |
|   mysql_server_end();
 | |
|   /* Free everything allocated by my_once_alloc */
 | |
|   my_end(0);
 | |
| 
 | |
|   /*
 | |
|     Use a copy of the original arguments.
 | |
|     The arguments will be altered when reading the configs and parsing
 | |
|     options.
 | |
|   */
 | |
|   my_argv= malloc((argc + 1) * sizeof(char*));
 | |
|   if (!my_argv)
 | |
|     exit(1);
 | |
| 
 | |
|   /* Test restarting the embedded library many times. */
 | |
|   for (i= 1; i <= EMBEDDED_RESTARTS; i++)
 | |
|   {
 | |
|     argv= my_argv;
 | |
|     argv[0]= test_name;
 | |
|     for (j= 1; j < argc; j++)
 | |
|       argv[j]= original_argv[j];
 | |
| 
 | |
|     /* Initialize everything again. */
 | |
|     MY_INIT(argv[0]);
 | |
| 
 | |
|     /* Load the client defaults from the .cnf file[s]. */
 | |
|     load_defaults_or_exit("my", client_test_load_default_groups, &argc, &argv);
 | |
| 
 | |
|     /* Parse the options (including the ones given from defaults files). */
 | |
|     get_options(&argc, &argv);
 | |
| 
 | |
|     /* mysql_library_init is the same as mysql_server_init. */
 | |
|     if (mysql_library_init(embedded_server_arg_count,
 | |
|                            embedded_server_args,
 | |
|                            (char**) embedded_server_groups))
 | |
|     {
 | |
|       myerror("mysql_library_init failed"); 
 | |
|       exit(1);
 | |
|     }
 | |
| 
 | |
|     /* Create a client connection. */
 | |
|     if (!(mysql_emb= mysql_client_init(NULL)))
 | |
|     {
 | |
|       myerror("mysql_client_init failed");
 | |
|       exit(1);
 | |
|     }
 | |
| 
 | |
|     /* Connect it and see if we can use the database. */
 | |
|     if (!(mysql_real_connect(mysql_emb, opt_host, opt_user,
 | |
|                              opt_password, current_db, 0,
 | |
|                              NULL, 0)))
 | |
|     {
 | |
|       myerror("mysql_real_connect failed");
 | |
|     }
 | |
| 
 | |
|     /* Close the client connection */
 | |
|     mysql_close(mysql_emb);
 | |
|     mysql_emb = NULL;
 | |
|     /* Free arguments allocated for defaults files. */
 | |
|     free_defaults(defaults_argv);
 | |
|     /* mysql_library_end is a define for mysql_server_end. */
 | |
|     mysql_library_end();
 | |
|     /* Free everything allocated by my_once_alloc */
 | |
|     my_end(0);
 | |
|   }
 | |
| 
 | |
|   argc= original_argc;
 | |
|   argv= my_argv;
 | |
|   argv[0]= test_name;
 | |
|   for (j= 1; j < argc; j++)
 | |
|     argv[j]= original_argv[j];
 | |
| 
 | |
|   MY_INIT(argv[0]);
 | |
| 
 | |
|   load_defaults_or_exit("my", client_test_load_default_groups, &argc, &argv);
 | |
|   get_options(&argc, &argv);
 | |
| 
 | |
|   /* Must start the main embedded server again after the test. */
 | |
|   if (mysql_server_init(embedded_server_arg_count,
 | |
|                         embedded_server_args,
 | |
|                         (char**) embedded_server_groups))
 | |
|     DIE("Can't initialize MariaDB server");
 | |
| 
 | |
|   /* connect to server with no flags, default protocol, auto reconnect true */
 | |
|   mysql= client_connect(0, MYSQL_PROTOCOL_DEFAULT, 1);
 | |
|   free(my_argv);
 | |
| }
 | |
| #endif /* EMBEDDED_LIBRARY */
 | |
| 
 | |
| 
 | |
| /*
 | |
|   Test a misc GRANT option
 | |
|   bug #89 (reported by mark@mysql.com)
 | |
| */
 | |
| 
 | |
| #ifndef EMBEDDED_LIBRARY
 | |
| static void test_prepare_grant()
 | |
| {
 | |
|   int rc;
 | |
|   char query[MAX_TEST_QUERY_LENGTH];
 | |
| 
 | |
|   myheader("test_prepare_grant");
 | |
| 
 | |
|   mysql_autocommit(mysql, TRUE);
 | |
| 
 | |
|   rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_grant");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "CREATE TABLE test_grant(a tinyint primary key auto_increment)");
 | |
|   myquery(rc);
 | |
| 
 | |
|   strxmov(query, "GRANT INSERT, UPDATE, SELECT ON ", current_db,
 | |
|                 ".test_grant TO 'test_grant'@",
 | |
|                 opt_host ? opt_host : "'localhost'", NullS);
 | |
| 
 | |
|   if (mysql_query(mysql, query))
 | |
|   {
 | |
|     myerror("GRANT failed");
 | |
| 
 | |
|     /*
 | |
|        If server started with --skip-grant-tables, skip this test, else
 | |
|        exit to indicate an error
 | |
| 
 | |
|        ER_UNKNOWN_COM_ERROR= 1047
 | |
|      */
 | |
|     if (mysql_errno(mysql) != 1047)
 | |
|       exit(1);
 | |
|   }
 | |
|   else
 | |
|   {
 | |
|     MYSQL *org_mysql= mysql, *lmysql;
 | |
|     MYSQL_STMT *stmt;
 | |
| 
 | |
|     if (!opt_silent)
 | |
|       fprintf(stdout, "\n Establishing a test connection ...");
 | |
|     if (!(lmysql= mysql_client_init(NULL)))
 | |
|     {
 | |
|       myerror("mysql_client_init() failed");
 | |
|       exit(1);
 | |
|     }
 | |
|     if (!(mysql_real_connect(lmysql, opt_host, "test_grant",
 | |
|                              "", current_db, opt_port,
 | |
|                              opt_unix_socket, 0)))
 | |
|     {
 | |
|       myerror("connection failed");
 | |
|       mysql_close(lmysql);
 | |
|       exit(1);
 | |
|     }
 | |
|     mysql_options(lmysql, MYSQL_OPT_RECONNECT, &my_true);
 | |
|     if (!opt_silent)
 | |
|       fprintf(stdout, "OK");
 | |
| 
 | |
|     mysql= lmysql;
 | |
|     rc= mysql_query(mysql, "INSERT INTO test_grant VALUES(NULL)");
 | |
|     myquery(rc);
 | |
| 
 | |
|     rc= mysql_query(mysql, "INSERT INTO test_grant(a) VALUES(NULL)");
 | |
|     myquery(rc);
 | |
| 
 | |
|     execute_prepare_query("INSERT INTO test_grant(a) VALUES(NULL)", 1);
 | |
|     execute_prepare_query("INSERT INTO test_grant VALUES(NULL)", 1);
 | |
|     execute_prepare_query("UPDATE test_grant SET a=9 WHERE a=1", 1);
 | |
|     rc= my_stmt_result("SELECT a FROM test_grant");
 | |
|     DIE_UNLESS(rc == 4);
 | |
| 
 | |
|     /* Both DELETE expected to fail as user does not have DELETE privs */
 | |
| 
 | |
|     rc= mysql_query(mysql, "DELETE FROM test_grant");
 | |
|     myquery_r(rc);
 | |
| 
 | |
|     stmt= mysql_simple_prepare(mysql, "DELETE FROM test_grant");
 | |
|     check_stmt_r(stmt);
 | |
| 
 | |
|     rc= my_stmt_result("SELECT * FROM test_grant");
 | |
|     DIE_UNLESS(rc == 4);
 | |
| 
 | |
|     mysql_close(lmysql);
 | |
|     mysql= org_mysql;
 | |
| 
 | |
|     rc= mysql_query(mysql, "delete from mysql.user where User='test_grant'");
 | |
|     myquery(rc);
 | |
|     DIE_UNLESS(1 == mysql_affected_rows(mysql));
 | |
| 
 | |
|     rc= mysql_query(mysql, "delete from mysql.tables_priv where User='test_grant'");
 | |
|     myquery(rc);
 | |
|     DIE_UNLESS(1 == mysql_affected_rows(mysql));
 | |
| 
 | |
|   }
 | |
| }
 | |
| #endif /* EMBEDDED_LIBRARY */
 | |
| 
 | |
| /*
 | |
|   Test a crash when invalid/corrupted .frm is used in the
 | |
|   SHOW TABLE STATUS
 | |
|   bug #93 (reported by serg@mysql.com).
 | |
| */
 | |
| 
 | |
| static void test_frm_bug()
 | |
| {
 | |
|   MYSQL_STMT *stmt;
 | |
|   MYSQL_BIND my_bind[2];
 | |
|   MYSQL_RES  *result;
 | |
|   MYSQL_ROW  row;
 | |
|   FILE       *test_file;
 | |
|   char       data_dir[FN_REFLEN];
 | |
|   char       test_frm[FN_REFLEN];
 | |
|   int        rc;
 | |
| 
 | |
|   myheader("test_frm_bug");
 | |
| 
 | |
|   mysql_autocommit(mysql, TRUE);
 | |
| 
 | |
|   rc= mysql_query(mysql, "drop table if exists test_frm_bug");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "flush tables");
 | |
|   myquery(rc);
 | |
| 
 | |
|   stmt= mysql_simple_prepare(mysql, "show variables like 'datadir'");
 | |
|   check_stmt(stmt);
 | |
| 
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   bzero((char*) my_bind, sizeof(my_bind));
 | |
|   my_bind[0].buffer_type= MYSQL_TYPE_STRING;
 | |
|   my_bind[0].buffer= data_dir;
 | |
|   my_bind[0].buffer_length= FN_REFLEN;
 | |
|   my_bind[1]= my_bind[0];
 | |
| 
 | |
|   rc= mysql_stmt_bind_result(stmt, my_bind);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= mysql_stmt_fetch(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   if (!opt_silent)
 | |
|     fprintf(stdout, "\n data directory: %s", data_dir);
 | |
| 
 | |
|   rc= mysql_stmt_fetch(stmt);
 | |
|   DIE_UNLESS(rc == MYSQL_NO_DATA);
 | |
| 
 | |
|   strxmov(test_frm, data_dir, "/", current_db, "/", "test_frm_bug.frm", NullS);
 | |
| 
 | |
|   if (!opt_silent)
 | |
|     fprintf(stdout, "\n test_frm: %s", test_frm);
 | |
| 
 | |
|   if (!(test_file= my_fopen(test_frm, (int) (O_RDWR | O_CREAT), MYF(MY_WME))))
 | |
|   {
 | |
|     fprintf(stdout, "\n ERROR: my_fopen failed for '%s'", test_frm);
 | |
|     fprintf(stdout, "\n test cancelled");
 | |
|     exit(1);
 | |
|   }
 | |
|   if (!opt_silent)
 | |
|     fprintf(test_file, "this is a junk file for test");
 | |
| 
 | |
|   rc= mysql_query(mysql, "SHOW TABLE STATUS like 'test_frm_bug'");
 | |
|   myquery(rc);
 | |
| 
 | |
|   result= mysql_store_result(mysql);
 | |
|   mytest(result);/* It can't be NULL */
 | |
| 
 | |
|   rc= my_process_result_set(result);
 | |
|   DIE_UNLESS(rc == 1);
 | |
| 
 | |
|   mysql_data_seek(result, 0);
 | |
| 
 | |
|   row= mysql_fetch_row(result);
 | |
|   mytest(row);
 | |
| 
 | |
|   if (!opt_silent)
 | |
|     fprintf(stdout, "\n Comment: %s", row[17]);
 | |
|   DIE_UNLESS(row[17] != 0);
 | |
| 
 | |
|   mysql_free_result(result);
 | |
|   mysql_stmt_close(stmt);
 | |
| 
 | |
|   my_fclose(test_file, MYF(0));
 | |
|   mysql_query(mysql, "drop table if exists test_frm_bug");
 | |
| }
 | |
| 
 | |
| 
 | |
| /* Test DECIMAL conversion */
 | |
| 
 | |
| static void test_decimal_bug()
 | |
| {
 | |
|   MYSQL_STMT *stmt;
 | |
|   MYSQL_BIND my_bind[1];
 | |
|   char       data[30];
 | |
|   int        rc;
 | |
|   my_bool    is_null;
 | |
| 
 | |
|   myheader("test_decimal_bug");
 | |
| 
 | |
|   mysql_autocommit(mysql, TRUE);
 | |
| 
 | |
|   rc= mysql_query(mysql, "drop table if exists test_decimal_bug");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "create table test_decimal_bug(c1 decimal(10, 2))");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "insert into test_decimal_bug value(8), (10.22), (5.61)");
 | |
|   myquery(rc);
 | |
| 
 | |
|   stmt= mysql_simple_prepare(mysql, "select c1 from test_decimal_bug where c1= ?");
 | |
|   check_stmt(stmt);
 | |
| 
 | |
|   /*
 | |
|     We need to bzero bind structure because mysql_stmt_bind_param checks all
 | |
|     its members.
 | |
|   */
 | |
|   bzero((char*) my_bind, sizeof(my_bind));
 | |
| 
 | |
|   my_bind[0].buffer_type= MYSQL_TYPE_NEWDECIMAL;
 | |
|   my_bind[0].buffer= (void *)data;
 | |
|   my_bind[0].buffer_length= 25;
 | |
|   my_bind[0].is_null= &is_null;
 | |
| 
 | |
|   is_null= 0;
 | |
|   rc= mysql_stmt_bind_param(stmt, my_bind);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   memset(data, 0, sizeof data);
 | |
|   strmov(data, "8.0");
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   data[0]= 0;
 | |
|   rc= mysql_stmt_bind_result(stmt, my_bind);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= mysql_stmt_fetch(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   if (!opt_silent)
 | |
|     fprintf(stdout, "\n data: %s", data);
 | |
|   DIE_UNLESS(strcmp(data, "8.00") == 0);
 | |
| 
 | |
|   rc= mysql_stmt_fetch(stmt);
 | |
|   DIE_UNLESS(rc == MYSQL_NO_DATA);
 | |
| 
 | |
|   strmov(data, "5.61");
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   data[0]= 0;
 | |
|   rc= mysql_stmt_bind_result(stmt, my_bind);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= mysql_stmt_fetch(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   if (!opt_silent)
 | |
|     fprintf(stdout, "\n data: %s", data);
 | |
|   DIE_UNLESS(strcmp(data, "5.61") == 0);
 | |
| 
 | |
|   rc= mysql_stmt_fetch(stmt);
 | |
|   DIE_UNLESS(rc == MYSQL_NO_DATA);
 | |
| 
 | |
|   is_null= 1;
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= mysql_stmt_fetch(stmt);
 | |
|   DIE_UNLESS(rc == MYSQL_NO_DATA);
 | |
| 
 | |
|   strmov(data, "10.22"); is_null= 0;
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   data[0]= 0;
 | |
|   rc= mysql_stmt_bind_result(stmt, my_bind);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= mysql_stmt_fetch(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   if (!opt_silent)
 | |
|     fprintf(stdout, "\n data: %s", data);
 | |
|   DIE_UNLESS(strcmp(data, "10.22") == 0);
 | |
| 
 | |
|   rc= mysql_stmt_fetch(stmt);
 | |
|   DIE_UNLESS(rc == MYSQL_NO_DATA);
 | |
| 
 | |
|   mysql_stmt_close(stmt);
 | |
| }
 | |
| 
 | |
| 
 | |
| /* Test EXPLAIN bug (#115, reported by mark@mysql.com & georg@php.net). */
 | |
| 
 | |
| static void test_explain_bug()
 | |
| {
 | |
|   MYSQL_STMT *stmt;
 | |
|   MYSQL_RES  *result;
 | |
|   int        rc;
 | |
| 
 | |
|   myheader("test_explain_bug");
 | |
| 
 | |
|   mysql_autocommit(mysql, TRUE);
 | |
| 
 | |
|   rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_explain");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "CREATE TABLE test_explain(id int, name char(2))");
 | |
|   myquery(rc);
 | |
| 
 | |
|   stmt= mysql_simple_prepare(mysql, "explain test_explain");
 | |
|   check_stmt(stmt);
 | |
| 
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= my_process_stmt_result(stmt);
 | |
|   DIE_UNLESS(rc == 2);
 | |
| 
 | |
|   result= mysql_stmt_result_metadata(stmt);
 | |
|   mytest(result);
 | |
| 
 | |
|   if (!opt_silent)
 | |
|     fprintf(stdout, "\n total fields in the result: %d",
 | |
|             mysql_num_fields(result));
 | |
|   DIE_UNLESS(6 == mysql_num_fields(result));
 | |
| 
 | |
|   verify_prepare_field(result, 0, "Field", "COLUMN_NAME",
 | |
|                        mysql_get_server_version(mysql) <= 50000 ?
 | |
|                        MYSQL_TYPE_STRING : MYSQL_TYPE_VAR_STRING,
 | |
|                        0, 0, "information_schema", 64, 0);
 | |
| 
 | |
|   verify_prepare_field(result, 1, "Type", "COLUMN_TYPE", MYSQL_TYPE_BLOB,
 | |
|                        0, 0, "information_schema", 0, 0);
 | |
| 
 | |
|   verify_prepare_field(result, 2, "Null", "IS_NULLABLE",
 | |
|                        mysql_get_server_version(mysql) <= 50000 ?
 | |
|                        MYSQL_TYPE_STRING : MYSQL_TYPE_VAR_STRING,
 | |
|                        0, 0, "information_schema", 3, 0);
 | |
| 
 | |
|   verify_prepare_field(result, 3, "Key", "COLUMN_KEY",
 | |
|                        mysql_get_server_version(mysql) <= 50000 ?
 | |
|                        MYSQL_TYPE_STRING : MYSQL_TYPE_VAR_STRING,
 | |
|                        0, 0, "information_schema", 3, 0);
 | |
| 
 | |
|   if ( mysql_get_server_version(mysql) >= 50027 )
 | |
|   {
 | |
|     /*  The patch for bug#23037 changes column type of DEFAULT to blob */
 | |
|     verify_prepare_field(result, 4, "Default", "COLUMN_DEFAULT",
 | |
|                          MYSQL_TYPE_BLOB, 0, 0, "information_schema", 0, 0);
 | |
|   }
 | |
|   else
 | |
|   {
 | |
|     verify_prepare_field(result, 4, "Default", "COLUMN_DEFAULT",
 | |
|                          mysql_get_server_version(mysql) >= 50027 ?
 | |
|                          MYSQL_TYPE_BLOB :
 | |
|                          mysql_get_server_version(mysql) <= 50000 ?
 | |
|                          MYSQL_TYPE_STRING : MYSQL_TYPE_VAR_STRING,
 | |
|                          0, 0, "information_schema",
 | |
|                          mysql_get_server_version(mysql) >= 50027 ? 0 :64, 0);
 | |
|   }
 | |
| 
 | |
|   verify_prepare_field(result, 5, "Extra", "EXTRA",
 | |
|                        mysql_get_server_version(mysql) <= 50000 ?
 | |
|                        MYSQL_TYPE_STRING : MYSQL_TYPE_VAR_STRING,
 | |
|                        0, 0, "information_schema", 80, 0);
 | |
| 
 | |
|   mysql_free_result(result);
 | |
|   mysql_stmt_close(stmt);
 | |
| 
 | |
|   stmt= mysql_simple_prepare(mysql, "explain select id, name FROM test_explain");
 | |
|   check_stmt(stmt);
 | |
| 
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= my_process_stmt_result(stmt);
 | |
|   DIE_UNLESS(rc == 1);
 | |
| 
 | |
|   result= mysql_stmt_result_metadata(stmt);
 | |
|   mytest(result);
 | |
| 
 | |
|   if (!opt_silent)
 | |
|     fprintf(stdout, "\n total fields in the result: %d",
 | |
|             mysql_num_fields(result));
 | |
|   DIE_UNLESS(10 == mysql_num_fields(result));
 | |
| 
 | |
|   verify_prepare_field(result, 0, "id", "", MYSQL_TYPE_LONGLONG,
 | |
|                        "", "", "", 3, 0);
 | |
| 
 | |
|   verify_prepare_field(result, 1, "select_type", "", MYSQL_TYPE_VAR_STRING,
 | |
|                        "", "", "", 19, 0);
 | |
| 
 | |
|   verify_prepare_field(result, 2, "table", "", MYSQL_TYPE_VAR_STRING,
 | |
|                        "", "", "", NAME_CHAR_LEN, 0);
 | |
| 
 | |
|   verify_prepare_field(result, 3, "type", "", MYSQL_TYPE_VAR_STRING,
 | |
|                        "", "", "", 10, 0);
 | |
| 
 | |
|   verify_prepare_field(result, 4, "possible_keys", "", MYSQL_TYPE_VAR_STRING,
 | |
|                        "", "", "", NAME_CHAR_LEN*MAX_KEY, 0);
 | |
| 
 | |
|   verify_prepare_field(result, 5, "key", "", MYSQL_TYPE_VAR_STRING,
 | |
|                        "", "", "", NAME_CHAR_LEN, 0);
 | |
| 
 | |
|   if (mysql_get_server_version(mysql) <= 50000)
 | |
|   {
 | |
|     verify_prepare_field(result, 6, "key_len", "", MYSQL_TYPE_LONGLONG, "",
 | |
|                          "", "", 3, 0);
 | |
|   }
 | |
|   else
 | |
|   {
 | |
|     verify_prepare_field(result, 6, "key_len", "", MYSQL_TYPE_VAR_STRING, "", 
 | |
|                          "", "", NAME_CHAR_LEN*MAX_KEY, 0);
 | |
|   }
 | |
| 
 | |
|   /* The length of this may verify between MariaDB versions (1024 / 2048) */
 | |
|   verify_prepare_field(result, 7, "ref", "", MYSQL_TYPE_VAR_STRING,
 | |
|                        "", "", "", NAME_CHAR_LEN * HA_MAX_KEY_SEG, 0);
 | |
| 
 | |
|   verify_prepare_field(result, 8, "rows", "", MYSQL_TYPE_VAR_STRING,
 | |
|                        "", "", "", NAME_CHAR_LEN, 0);
 | |
| 
 | |
|   verify_prepare_field(result, 9, "Extra", "", MYSQL_TYPE_VAR_STRING,
 | |
|                        "", "", "", 255, 0);
 | |
| 
 | |
|   mysql_free_result(result);
 | |
|   mysql_stmt_close(stmt);
 | |
| }
 | |
| 
 | |
| #ifdef NOT_YET_WORKING
 | |
| 
 | |
| /*
 | |
|   Test math functions.
 | |
|   Bug #148 (reported by salle@mysql.com).
 | |
| */
 | |
| 
 | |
| #define myerrno(n) check_errcode(n)
 | |
| 
 | |
| static void check_errcode(const unsigned int err)
 | |
| {
 | |
|   if (!opt_silent || mysql_errno(mysql) != err)
 | |
|   {
 | |
|     if (mysql->server_version)
 | |
|       fprintf(stdout, "\n [MySQL-%s]", mysql->server_version);
 | |
|     else
 | |
|       fprintf(stdout, "\n [MySQL]");
 | |
|     fprintf(stdout, "[%d] %s\n", mysql_errno(mysql), mysql_error(mysql));
 | |
|   }
 | |
|   DIE_UNLESS(mysql_errno(mysql) == err);
 | |
| }
 | |
| 
 | |
| 
 | |
| static void test_drop_temp()
 | |
| {
 | |
|   int rc;
 | |
| 
 | |
|   myheader("test_drop_temp");
 | |
| 
 | |
|   rc= mysql_query(mysql, "DROP DATABASE IF EXISTS test_drop_temp_db");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "CREATE DATABASE test_drop_temp_db");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "CREATE TABLE test_drop_temp_db.t1(c1 int, c2 char(1))");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "delete from mysql.db where Db='test_drop_temp_db'");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "delete from mysql.db where Db='test_drop_temp_db'");
 | |
|   myquery(rc);
 | |
| 
 | |
|   strxmov(query, "GRANT SELECT, USAGE, DROP ON test_drop_temp_db.* TO test_temp@",
 | |
|                 opt_host ? opt_host : "localhost", NullS);
 | |
| 
 | |
|   if (mysql_query(mysql, query))
 | |
|   {
 | |
|     myerror("GRANT failed");
 | |
| 
 | |
|     /*
 | |
|        If server started with --skip-grant-tables, skip this test, else
 | |
|        exit to indicate an error
 | |
| 
 | |
|        ER_UNKNOWN_COM_ERROR= 1047
 | |
|      */
 | |
|     if (mysql_errno(mysql) != 1047)
 | |
|       exit(1);
 | |
|   }
 | |
|   else
 | |
|   {
 | |
|     MYSQL *org_mysql= mysql, *lmysql;
 | |
| 
 | |
|     if (!opt_silent)
 | |
|       fprintf(stdout, "\n Establishing a test connection ...");
 | |
|     if (!(lmysql= mysql_client_init(NULL)))
 | |
|     {
 | |
|       myerror("mysql_client_init() failed");
 | |
|       exit(1);
 | |
|     }
 | |
| 
 | |
|     rc= mysql_query(mysql, "flush privileges");
 | |
|     myquery(rc);
 | |
| 
 | |
|     if (!(mysql_real_connect(lmysql, opt_host ? opt_host : "localhost", "test_temp",
 | |
|                              "", "test_drop_temp_db", opt_port,
 | |
|                              opt_unix_socket, 0)))
 | |
|     {
 | |
|       mysql= lmysql;
 | |
|       myerror("connection failed");
 | |
|       mysql_close(lmysql);
 | |
|       exit(1);
 | |
|     }
 | |
|     mysql_options(lmysql, MYSQL_OPT_RECONNECT, &my_true);
 | |
|     if (!opt_silent)
 | |
|       fprintf(stdout, "OK");
 | |
| 
 | |
|     mysql= lmysql;
 | |
|     rc= mysql_query(mysql, "INSERT INTO t1 VALUES(10, 'C')");
 | |
|     myerrno((uint)1142);
 | |
| 
 | |
|     rc= mysql_query(mysql, "DROP TABLE t1");
 | |
|     myerrno((uint)1142);
 | |
| 
 | |
|     mysql= org_mysql;
 | |
|     rc= mysql_query(mysql, "CREATE TEMPORARY TABLE test_drop_temp_db.t1(c1 int)");
 | |
|     myquery(rc);
 | |
| 
 | |
|     rc= mysql_query(mysql, "CREATE TEMPORARY TABLE test_drop_temp_db.t2 LIKE test_drop_temp_db.t1");
 | |
|     myquery(rc);
 | |
| 
 | |
|     mysql= lmysql;
 | |
| 
 | |
|     rc= mysql_query(mysql, "DROP TABLE t1, t2");
 | |
|     myquery_r(rc);
 | |
| 
 | |
|     rc= mysql_query(mysql, "DROP TEMPORARY TABLE t1");
 | |
|     myquery_r(rc);
 | |
| 
 | |
|     rc= mysql_query(mysql, "DROP TEMPORARY TABLE t2");
 | |
|     myquery_r(rc);
 | |
| 
 | |
|     mysql_close(lmysql);
 | |
|     mysql= org_mysql;
 | |
| 
 | |
|     rc= mysql_query(mysql, "drop database test_drop_temp_db");
 | |
|     myquery(rc);
 | |
|     DIE_UNLESS(1 == mysql_affected_rows(mysql));
 | |
| 
 | |
|     rc= mysql_query(mysql, "delete from mysql.user where User='test_temp'");
 | |
|     myquery(rc);
 | |
|     DIE_UNLESS(1 == mysql_affected_rows(mysql));
 | |
| 
 | |
| 
 | |
|     rc= mysql_query(mysql, "delete from mysql.tables_priv where User='test_temp'");
 | |
|     myquery(rc);
 | |
|     DIE_UNLESS(1 == mysql_affected_rows(mysql));
 | |
|   }
 | |
| }
 | |
| #endif
 | |
| 
 | |
| 
 | |
| /* Test warnings for cuted rows */
 | |
| 
 | |
| static void test_cuted_rows()
 | |
| {
 | |
|   int        rc, count;
 | |
|   MYSQL_RES  *result;
 | |
| 
 | |
|   myheader("test_cuted_rows");
 | |
| 
 | |
|   mysql_query(mysql, "DROP TABLE if exists t1");
 | |
|   mysql_query(mysql, "DROP TABLE if exists t2");
 | |
| 
 | |
|   rc= mysql_query(mysql, "CREATE TABLE t1(c1 tinyint)");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "CREATE TABLE t2(c1 int not null)");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "INSERT INTO t1 values(10), (NULL), (NULL)");
 | |
|   myquery(rc);
 | |
| 
 | |
|   count= mysql_warning_count(mysql);
 | |
|   if (!opt_silent)
 | |
|     fprintf(stdout, "\n total warnings: %d", count);
 | |
|   DIE_UNLESS(count == 0);
 | |
| 
 | |
|   rc= mysql_query(mysql, "INSERT INTO t2 SELECT * FROM t1");
 | |
|   myquery(rc);
 | |
| 
 | |
|   count= mysql_warning_count(mysql);
 | |
|   if (!opt_silent)
 | |
|     fprintf(stdout, "\n total warnings: %d", count);
 | |
|   DIE_UNLESS(count == 2);
 | |
| 
 | |
|   rc= mysql_query(mysql, "SHOW WARNINGS");
 | |
|   myquery(rc);
 | |
| 
 | |
|   result= mysql_store_result(mysql);
 | |
|   mytest(result);
 | |
| 
 | |
|   rc= my_process_result_set(result);
 | |
|   DIE_UNLESS(rc == 2);
 | |
|   mysql_free_result(result);
 | |
| 
 | |
|   rc= mysql_query(mysql, "INSERT INTO t1 VALUES('junk'), (876789)");
 | |
|   myquery(rc);
 | |
| 
 | |
|   count= mysql_warning_count(mysql);
 | |
|   if (!opt_silent)
 | |
|     fprintf(stdout, "\n total warnings: %d", count);
 | |
|   DIE_UNLESS(count == 2);
 | |
| 
 | |
|   rc= mysql_query(mysql, "SHOW WARNINGS");
 | |
|   myquery(rc);
 | |
| 
 | |
|   result= mysql_store_result(mysql);
 | |
|   mytest(result);
 | |
| 
 | |
|   rc= my_process_result_set(result);
 | |
|   DIE_UNLESS(rc == 2);
 | |
|   mysql_free_result(result);
 | |
| }
 | |
| 
 | |
| 
 | |
| /* Test update/binary logs */
 | |
| 
 | |
| static void test_logs()
 | |
| {
 | |
|   MYSQL_STMT *stmt;
 | |
|   MYSQL_BIND my_bind[2];
 | |
|   char       data[255];
 | |
|   ulong      length;
 | |
|   int        rc;
 | |
|   short      id;
 | |
| 
 | |
|   myheader("test_logs");
 | |
| 
 | |
| 
 | |
|   rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_logs");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "CREATE TABLE test_logs(id smallint, name varchar(20))");
 | |
|   myquery(rc);
 | |
| 
 | |
|   strmov((char *)data, "INSERT INTO test_logs VALUES(?, ?)");
 | |
|   stmt= mysql_simple_prepare(mysql, data);
 | |
|   check_stmt(stmt);
 | |
| 
 | |
|   /*
 | |
|     We need to bzero bind structure because mysql_stmt_bind_param checks all
 | |
|     its members.
 | |
|   */
 | |
|   bzero((char*) my_bind, sizeof(my_bind));
 | |
| 
 | |
|   my_bind[0].buffer_type= MYSQL_TYPE_SHORT;
 | |
|   my_bind[0].buffer= (void *)&id;
 | |
| 
 | |
|   my_bind[1].buffer_type= MYSQL_TYPE_STRING;
 | |
|   my_bind[1].buffer= (void *)&data;
 | |
|   my_bind[1].buffer_length= 255;
 | |
|   my_bind[1].length= &length;
 | |
| 
 | |
|   id= 9876;
 | |
|   length= (ulong)(strmov((char *)data, "MySQL - Open Source Database")- data);
 | |
| 
 | |
|   rc= mysql_stmt_bind_param(stmt, my_bind);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   strmov((char *)data, "'");
 | |
|   length= 1;
 | |
| 
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   strmov((char *)data, "\"");
 | |
|   length= 1;
 | |
| 
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   length= (ulong)(strmov((char *)data, "my\'sql\'")-data);
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   length= (ulong)(strmov((char *)data, "my\"sql\"")-data);
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   mysql_stmt_close(stmt);
 | |
| 
 | |
|   strmov((char *)data, "INSERT INTO test_logs VALUES(20, 'mysql')");
 | |
|   stmt= mysql_simple_prepare(mysql, data);
 | |
|   check_stmt(stmt);
 | |
| 
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   mysql_stmt_close(stmt);
 | |
| 
 | |
|   strmov((char *)data, "SELECT * FROM test_logs WHERE id=?");
 | |
|   stmt= mysql_simple_prepare(mysql, data);
 | |
|   check_stmt(stmt);
 | |
| 
 | |
|   rc= mysql_stmt_bind_param(stmt, my_bind);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   my_bind[1].buffer_length= 255;
 | |
|   rc= mysql_stmt_bind_result(stmt, my_bind);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= mysql_stmt_fetch(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   if (!opt_silent)
 | |
|   {
 | |
|     fprintf(stdout, "id    : %d\n", id);
 | |
|     fprintf(stdout, "name  : %s(%ld)\n", data, length);
 | |
|   }
 | |
| 
 | |
|   DIE_UNLESS(id == 9876);
 | |
|   DIE_UNLESS(length == 19 || length == 20); /* Due to VARCHAR(20) */
 | |
|   DIE_UNLESS(is_prefix(data, "MySQL - Open Source") == 1);
 | |
| 
 | |
|   rc= mysql_stmt_fetch(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   if (!opt_silent)
 | |
|     fprintf(stdout, "\n name  : %s(%ld)", data, length);
 | |
| 
 | |
|   DIE_UNLESS(length == 1);
 | |
|   DIE_UNLESS(strcmp(data, "'") == 0);
 | |
| 
 | |
|   rc= mysql_stmt_fetch(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   if (!opt_silent)
 | |
|     fprintf(stdout, "\n name  : %s(%ld)", data, length);
 | |
| 
 | |
|   DIE_UNLESS(length == 1);
 | |
|   DIE_UNLESS(strcmp(data, "\"") == 0);
 | |
| 
 | |
|   rc= mysql_stmt_fetch(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   if (!opt_silent)
 | |
|     fprintf(stdout, "\n name  : %s(%ld)", data, length);
 | |
| 
 | |
|   DIE_UNLESS(length == 7);
 | |
|   DIE_UNLESS(strcmp(data, "my\'sql\'") == 0);
 | |
| 
 | |
|   rc= mysql_stmt_fetch(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   if (!opt_silent)
 | |
|     fprintf(stdout, "\n name  : %s(%ld)", data, length);
 | |
| 
 | |
|   DIE_UNLESS(length == 7);
 | |
|   /*DIE_UNLESS(strcmp(data, "my\"sql\"") == 0); */
 | |
| 
 | |
|   rc= mysql_stmt_fetch(stmt);
 | |
|   DIE_UNLESS(rc == MYSQL_NO_DATA);
 | |
| 
 | |
|   mysql_stmt_close(stmt);
 | |
| 
 | |
|   rc= mysql_query(mysql, "DROP TABLE test_logs");
 | |
|   myquery(rc);
 | |
| }
 | |
| 
 | |
| 
 | |
| /* Test 'n' statements create and close */
 | |
| 
 | |
| static void test_nstmts()
 | |
| {
 | |
|   MYSQL_STMT  *stmt;
 | |
|   char        query[255];
 | |
|   int         rc;
 | |
|   static uint i, total_stmts= 2000;
 | |
|   MYSQL_BIND  my_bind[1];
 | |
| 
 | |
|   myheader("test_nstmts");
 | |
| 
 | |
|   mysql_autocommit(mysql, TRUE);
 | |
| 
 | |
|   rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_nstmts");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "CREATE TABLE test_nstmts(id int)");
 | |
|   myquery(rc);
 | |
| 
 | |
|   /*
 | |
|     We need to bzero bind structure because mysql_stmt_bind_param checks all
 | |
|     its members.
 | |
|   */
 | |
|   bzero((char*) my_bind, sizeof(my_bind));
 | |
| 
 | |
|   my_bind[0].buffer= (void *)&i;
 | |
|   my_bind[0].buffer_type= MYSQL_TYPE_LONG;
 | |
| 
 | |
|   for (i= 0; i < total_stmts; i++)
 | |
|   {
 | |
|     if (!opt_silent)
 | |
|       fprintf(stdout, "\r stmt: %d", i);
 | |
| 
 | |
|     strmov(query, "insert into test_nstmts values(?)");
 | |
|     stmt= mysql_simple_prepare(mysql, query);
 | |
|     check_stmt(stmt);
 | |
| 
 | |
|     rc= mysql_stmt_bind_param(stmt, my_bind);
 | |
|     check_execute(stmt, rc);
 | |
| 
 | |
|     rc= mysql_stmt_execute(stmt);
 | |
|     check_execute(stmt, rc);
 | |
| 
 | |
|     mysql_stmt_close(stmt);
 | |
|   }
 | |
| 
 | |
|   stmt= mysql_simple_prepare(mysql, " select count(*) from test_nstmts");
 | |
|   check_stmt(stmt);
 | |
| 
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   i= 0;
 | |
|   rc= mysql_stmt_bind_result(stmt, my_bind);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= mysql_stmt_fetch(stmt);
 | |
|   check_execute(stmt, rc);
 | |
|   if (!opt_silent)
 | |
|     fprintf(stdout, "\n total rows: %d", i);
 | |
|   DIE_UNLESS( i == total_stmts);
 | |
| 
 | |
|   rc= mysql_stmt_fetch(stmt);
 | |
|   DIE_UNLESS(rc == MYSQL_NO_DATA);
 | |
| 
 | |
|   mysql_stmt_close(stmt);
 | |
| 
 | |
|   rc= mysql_query(mysql, "DROP TABLE test_nstmts");
 | |
|   myquery(rc);
 | |
| }
 | |
| 
 | |
| 
 | |
| /* Test stmt seek() functions */
 | |
| 
 | |
| static void test_fetch_seek()
 | |
| {
 | |
|   MYSQL_STMT *stmt;
 | |
|   MYSQL_BIND my_bind[3];
 | |
|   MYSQL_ROW_OFFSET row;
 | |
|   int        rc;
 | |
|   int32      c1;
 | |
|   char       c2[11], c3[20];
 | |
| 
 | |
|   myheader("test_fetch_seek");
 | |
|   rc= mysql_query(mysql, "drop table if exists t1");
 | |
| 
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "create table t1(c1 int primary key auto_increment, c2 char(10), c3 timestamp)");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "insert into t1(c2) values('venu'), ('mysql'), ('open'), ('source')");
 | |
|   myquery(rc);
 | |
| 
 | |
|   stmt= mysql_simple_prepare(mysql, "select * from t1");
 | |
|   check_stmt(stmt);
 | |
| 
 | |
|   bzero((char*) my_bind, sizeof(my_bind));
 | |
|   my_bind[0].buffer_type= MYSQL_TYPE_LONG;
 | |
|   my_bind[0].buffer= (void *)&c1;
 | |
| 
 | |
|   my_bind[1].buffer_type= MYSQL_TYPE_STRING;
 | |
|   my_bind[1].buffer= (void *)c2;
 | |
|   my_bind[1].buffer_length= sizeof(c2);
 | |
| 
 | |
|   my_bind[2]= my_bind[1];
 | |
|   my_bind[2].buffer= (void *)c3;
 | |
|   my_bind[2].buffer_length= sizeof(c3);
 | |
| 
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= mysql_stmt_bind_result(stmt, my_bind);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= mysql_stmt_store_result(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= mysql_stmt_fetch(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   if (!opt_silent)
 | |
|     fprintf(stdout, "\n row 0: %ld, %s, %s", (long) c1, c2, c3);
 | |
| 
 | |
|   row= mysql_stmt_row_tell(stmt);
 | |
| 
 | |
|   row= mysql_stmt_row_seek(stmt, row);
 | |
| 
 | |
|   rc= mysql_stmt_fetch(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   if (!opt_silent)
 | |
|     fprintf(stdout, "\n row 2: %ld, %s, %s", (long) c1, c2, c3);
 | |
| 
 | |
|   row= mysql_stmt_row_seek(stmt, row);
 | |
| 
 | |
|   rc= mysql_stmt_fetch(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   if (!opt_silent)
 | |
|     fprintf(stdout, "\n row 2: %ld, %s, %s", (long) c1, c2, c3);
 | |
| 
 | |
|   mysql_stmt_data_seek(stmt, 0);
 | |
| 
 | |
|   rc= mysql_stmt_fetch(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   if (!opt_silent)
 | |
|     fprintf(stdout, "\n row 0: %ld, %s, %s", (long) c1, c2, c3);
 | |
| 
 | |
|   rc= mysql_stmt_fetch(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= mysql_stmt_fetch(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= mysql_stmt_fetch(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= mysql_stmt_fetch(stmt);
 | |
|   DIE_UNLESS(rc == MYSQL_NO_DATA);
 | |
| 
 | |
|   mysql_stmt_close(stmt);
 | |
|   myquery(mysql_query(mysql, "drop table t1"));
 | |
| }
 | |
| 
 | |
| 
 | |
| /* Test mysql_stmt_fetch_column() with offset */
 | |
| 
 | |
| static void test_fetch_offset()
 | |
| {
 | |
|   MYSQL_STMT *stmt;
 | |
|   MYSQL_BIND my_bind[1];
 | |
|   char       data[11];
 | |
|   ulong      length;
 | |
|   int        rc;
 | |
|   my_bool    is_null;
 | |
| 
 | |
| 
 | |
|   myheader("test_fetch_offset");
 | |
| 
 | |
|   rc= mysql_query(mysql, "drop table if exists t1");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "create table t1(a char(10))");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "insert into t1 values('abcdefghij'), (null)");
 | |
|   myquery(rc);
 | |
| 
 | |
|   stmt= mysql_simple_prepare(mysql, "select * from t1");
 | |
|   check_stmt(stmt);
 | |
| 
 | |
|   bzero((char*) my_bind, sizeof(my_bind));
 | |
|   my_bind[0].buffer_type= MYSQL_TYPE_STRING;
 | |
|   my_bind[0].buffer= (void *)data;
 | |
|   my_bind[0].buffer_length= 11;
 | |
|   my_bind[0].is_null= &is_null;
 | |
|   my_bind[0].length= &length;
 | |
| 
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= mysql_stmt_fetch_column(stmt, my_bind, 0, 0);
 | |
|   check_execute_r(stmt, rc);
 | |
| 
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= mysql_stmt_bind_result(stmt, my_bind);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= mysql_stmt_store_result(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= mysql_stmt_fetch(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   data[0]= '\0';
 | |
|   rc= mysql_stmt_fetch_column(stmt, my_bind, 0, 0);
 | |
|   check_execute(stmt, rc);
 | |
|   if (!opt_silent)
 | |
|     fprintf(stdout, "\n col 1: %s (%ld)", data, length);
 | |
|   DIE_UNLESS(strncmp(data, "abcd", 4) == 0 && length == 10);
 | |
| 
 | |
|   rc= mysql_stmt_fetch_column(stmt, my_bind, 0, 5);
 | |
|   check_execute(stmt, rc);
 | |
|   if (!opt_silent)
 | |
|     fprintf(stdout, "\n col 1: %s (%ld)", data, length);
 | |
|   DIE_UNLESS(strncmp(data, "fg", 2) == 0 && length == 10);
 | |
| 
 | |
|   rc= mysql_stmt_fetch_column(stmt, my_bind, 0, 9);
 | |
|   check_execute(stmt, rc);
 | |
|   if (!opt_silent)
 | |
|     fprintf(stdout, "\n col 0: %s (%ld)", data, length);
 | |
|   DIE_UNLESS(strncmp(data, "j", 1) == 0 && length == 10);
 | |
| 
 | |
|   rc= mysql_stmt_fetch(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   is_null= 0;
 | |
| 
 | |
|   rc= mysql_stmt_fetch_column(stmt, my_bind, 0, 0);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   DIE_UNLESS(is_null == 1);
 | |
| 
 | |
|   rc= mysql_stmt_fetch(stmt);
 | |
|   DIE_UNLESS(rc == MYSQL_NO_DATA);
 | |
| 
 | |
|   rc= mysql_stmt_fetch_column(stmt, my_bind, 1, 0);
 | |
|   check_execute_r(stmt, rc);
 | |
| 
 | |
|   mysql_stmt_close(stmt);
 | |
| 
 | |
|   myquery(mysql_query(mysql, "drop table t1"));
 | |
| }
 | |
| 
 | |
| 
 | |
| /* Test mysql_stmt_fetch_column() */
 | |
| 
 | |
| static void test_fetch_column()
 | |
| {
 | |
|   MYSQL_STMT *stmt;
 | |
|   MYSQL_BIND my_bind[2];
 | |
|   char       c2[20], bc2[20];
 | |
|   ulong      l1, l2, bl1, bl2;
 | |
|   int        rc, c1, bc1;
 | |
| 
 | |
|   myheader("test_fetch_column");
 | |
| 
 | |
|   rc= mysql_query(mysql, "drop table if exists t1");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "create table t1(c1 int primary key auto_increment, c2 char(10))");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "insert into t1(c2) values('venu'), ('mysql')");
 | |
|   myquery(rc);
 | |
| 
 | |
|   stmt= mysql_simple_prepare(mysql, "select * from t1 order by c2 desc");
 | |
|   check_stmt(stmt);
 | |
| 
 | |
|   bzero((char*) my_bind, sizeof(my_bind));
 | |
|   my_bind[0].buffer_type= MYSQL_TYPE_LONG;
 | |
|   my_bind[0].buffer= (void *)&bc1;
 | |
|   my_bind[0].buffer_length= 0;
 | |
|   my_bind[0].is_null= 0;
 | |
|   my_bind[0].length= &bl1;
 | |
|   my_bind[1].buffer_type= MYSQL_TYPE_STRING;
 | |
|   my_bind[1].buffer= (void *)bc2;
 | |
|   my_bind[1].buffer_length= 7;
 | |
|   my_bind[1].is_null= 0;
 | |
|   my_bind[1].length= &bl2;
 | |
| 
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= mysql_stmt_bind_result(stmt, my_bind);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= mysql_stmt_store_result(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= mysql_stmt_fetch_column(stmt, my_bind, 1, 0); /* No-op at this point */
 | |
|   check_execute_r(stmt, rc);
 | |
| 
 | |
|   rc= mysql_stmt_fetch(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   if (!opt_silent)
 | |
|     fprintf(stdout, "\n row 0: %d, %s", bc1, bc2);
 | |
| 
 | |
|   c2[0]= '\0'; l2= 0;
 | |
|   my_bind[0].buffer_type= MYSQL_TYPE_STRING;
 | |
|   my_bind[0].buffer= (void *)c2;
 | |
|   my_bind[0].buffer_length= 7;
 | |
|   my_bind[0].is_null= 0;
 | |
|   my_bind[0].length= &l2;
 | |
| 
 | |
|   rc= mysql_stmt_fetch_column(stmt, my_bind, 1, 0);
 | |
|   check_execute(stmt, rc);
 | |
|   if (!opt_silent)
 | |
|     fprintf(stdout, "\n col 1: %s(%ld)", c2, l2);
 | |
|   DIE_UNLESS(strncmp(c2, "venu", 4) == 0 && l2 == 4);
 | |
| 
 | |
|   c2[0]= '\0'; l2= 0;
 | |
|   rc= mysql_stmt_fetch_column(stmt, my_bind, 1, 0);
 | |
|   check_execute(stmt, rc);
 | |
|   if (!opt_silent)
 | |
|     fprintf(stdout, "\n col 1: %s(%ld)", c2, l2);
 | |
|   DIE_UNLESS(strcmp(c2, "venu") == 0 && l2 == 4);
 | |
| 
 | |
|   c1= 0;
 | |
|   my_bind[0].buffer_type= MYSQL_TYPE_LONG;
 | |
|   my_bind[0].buffer= (void *)&c1;
 | |
|   my_bind[0].buffer_length= 0;
 | |
|   my_bind[0].is_null= 0;
 | |
|   my_bind[0].length= &l1;
 | |
| 
 | |
|   rc= mysql_stmt_fetch_column(stmt, my_bind, 0, 0);
 | |
|   check_execute(stmt, rc);
 | |
|   if (!opt_silent)
 | |
|     fprintf(stdout, "\n col 0: %d(%ld)", c1, l1);
 | |
|   DIE_UNLESS(c1 == 1 && l1 == 4);
 | |
| 
 | |
|   rc= mysql_stmt_fetch(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   if (!opt_silent)
 | |
|     fprintf(stdout, "\n row 1: %d, %s", bc1, bc2);
 | |
| 
 | |
|   c2[0]= '\0'; l2= 0;
 | |
|   my_bind[0].buffer_type= MYSQL_TYPE_STRING;
 | |
|   my_bind[0].buffer= (void *)c2;
 | |
|   my_bind[0].buffer_length= 7;
 | |
|   my_bind[0].is_null= 0;
 | |
|   my_bind[0].length= &l2;
 | |
| 
 | |
|   rc= mysql_stmt_fetch_column(stmt, my_bind, 1, 0);
 | |
|   check_execute(stmt, rc);
 | |
|   if (!opt_silent)
 | |
|     fprintf(stdout, "\n col 1: %s(%ld)", c2, l2);
 | |
|   DIE_UNLESS(strncmp(c2, "mysq", 4) == 0 && l2 == 5);
 | |
| 
 | |
|   c2[0]= '\0'; l2= 0;
 | |
|   rc= mysql_stmt_fetch_column(stmt, my_bind, 1, 0);
 | |
|   check_execute(stmt, rc);
 | |
|   if (!opt_silent)
 | |
|     fprintf(stdout, "\n col 1: %si(%ld)", c2, l2);
 | |
|   DIE_UNLESS(strcmp(c2, "mysql") == 0 && l2 == 5);
 | |
| 
 | |
|   c1= 0;
 | |
|   my_bind[0].buffer_type= MYSQL_TYPE_LONG;
 | |
|   my_bind[0].buffer= (void *)&c1;
 | |
|   my_bind[0].buffer_length= 0;
 | |
|   my_bind[0].is_null= 0;
 | |
|   my_bind[0].length= &l1;
 | |
| 
 | |
|   rc= mysql_stmt_fetch_column(stmt, my_bind, 0, 0);
 | |
|   check_execute(stmt, rc);
 | |
|   if (!opt_silent)
 | |
|     fprintf(stdout, "\n col 0: %d(%ld)", c1, l1);
 | |
|   DIE_UNLESS(c1 == 2 && l1 == 4);
 | |
| 
 | |
|   rc= mysql_stmt_fetch(stmt);
 | |
|   DIE_UNLESS(rc == MYSQL_NO_DATA);
 | |
| 
 | |
|   rc= mysql_stmt_fetch_column(stmt, my_bind, 1, 0);
 | |
|   check_execute_r(stmt, rc);
 | |
| 
 | |
|   mysql_stmt_close(stmt);
 | |
|   myquery(mysql_query(mysql, "drop table t1"));
 | |
| }
 | |
| 
 | |
| 
 | |
| /* Test mysql_list_fields() */
 | |
| 
 | |
| static void test_list_fields()
 | |
| {
 | |
|   MYSQL_RES *result;
 | |
|   int rc;
 | |
|   myheader("test_list_fields");
 | |
| 
 | |
|   rc= mysql_query(mysql, "drop table if exists t1");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "create table t1(c1 int primary key auto_increment, c2 char(10) default 'mysql')");
 | |
|   myquery(rc);
 | |
| 
 | |
|   result= mysql_list_fields(mysql, "t1", NULL);
 | |
|   mytest(result);
 | |
| 
 | |
|   rc= my_process_result_set(result);
 | |
|   DIE_UNLESS(rc == 0);
 | |
| 
 | |
|   verify_prepare_field(result, 0, "c1", "c1", MYSQL_TYPE_LONG,
 | |
|                        "t1", "t1",
 | |
|                        current_db, 11, "0");
 | |
| 
 | |
|   verify_prepare_field(result, 1, "c2", "c2", MYSQL_TYPE_STRING,
 | |
|                        "t1", "t1",
 | |
|                        current_db, 10, "mysql");
 | |
| 
 | |
|   mysql_free_result(result);
 | |
|   myquery(mysql_query(mysql, "drop table t1"));
 | |
| }
 | |
| 
 | |
| 
 | |
| /* Test mysql_list_fields() with information_schema */
 | |
| 
 | |
| static void test_list_information_schema_fields()
 | |
| {
 | |
|   MYSQL_RES *result;
 | |
|   int rc;
 | |
|   myheader("test_list_information_schema_fields");
 | |
| 
 | |
|   rc= mysql_select_db(mysql, "information_schema");
 | |
|   myquery(rc);
 | |
|   result= mysql_list_fields(mysql, "all_plugins", NULL);
 | |
|   mytest(result);
 | |
|   rc= my_process_result_set(result);
 | |
|   DIE_UNLESS(rc == 0);
 | |
|   mysql_free_result(result);
 | |
|   rc= mysql_select_db(mysql, current_db);
 | |
|   myquery(rc);
 | |
| }
 | |
| 
 | |
| 
 | |
| static void test_list_fields_blob()
 | |
| {
 | |
|   MYSQL_RES *result;
 | |
|   int rc;
 | |
|   myheader("test_list_fields_blob");
 | |
| 
 | |
|   rc= mysql_query(mysql, "drop table if exists t1");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "create table t1(c1 tinyblob, c2 blob, c3 mediumblob, c4 longblob)");
 | |
|   myquery(rc);
 | |
| 
 | |
|   result= mysql_list_fields(mysql, "t1", NULL);
 | |
|   mytest(result);
 | |
| 
 | |
|   rc= my_process_result_set(result);
 | |
|   DIE_UNLESS(rc == 0);
 | |
| 
 | |
|   /*
 | |
|     All BLOB variant Fields are displayed as MYSQL_TYPE_BLOB in
 | |
|     the result set metadata. Note, some Items display the exact
 | |
|     BLOB type. This inconsistency should be fixed eventually.
 | |
|   */
 | |
|   verify_prepare_field(result, 0, "c1", "c1", MYSQL_TYPE_BLOB,
 | |
|                        "t1", "t1",
 | |
|                        current_db, 255, NULL);
 | |
| 
 | |
|   verify_prepare_field(result, 1, "c2", "c2", MYSQL_TYPE_BLOB,
 | |
|                        "t1", "t1",
 | |
|                        current_db, 65535, NULL);
 | |
| 
 | |
|   verify_prepare_field(result, 2, "c3", "c3", MYSQL_TYPE_BLOB,
 | |
|                        "t1", "t1",
 | |
|                        current_db, 16777215, NULL);
 | |
| 
 | |
|   verify_prepare_field(result, 3, "c4", "c4", MYSQL_TYPE_BLOB,
 | |
|                        "t1", "t1",
 | |
|                        current_db, 4294967295ULL, NULL);
 | |
| 
 | |
|   mysql_free_result(result);
 | |
|   myquery(mysql_query(mysql, "drop table t1"));
 | |
| }
 | |
| 
 | |
| 
 | |
| static void test_list_fields_default()
 | |
| {
 | |
|   int rc, i;
 | |
|   myheader("test_list_fields_default");
 | |
| 
 | |
|   rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql,
 | |
|                   "CREATE TABLE t1 ("
 | |
|                   " i1 INT NOT NULL DEFAULT 0,"
 | |
|                   " i3 BIGINT UNSIGNED NOT NULL DEFAULT 0xFFFFFFFFFFFFFFFF,"
 | |
|                   " s1 VARCHAR(10) CHARACTER SET latin1 NOT NULL DEFAULT 's1def',"
 | |
|                   " d1 DECIMAL(31,1) NOT NULL DEFAULT 111111111122222222223333333333.9,"
 | |
|                   " t1 DATETIME(6) NOT NULL DEFAULT '2001-01-01 10:20:30.123456',"
 | |
|                   " e1 ENUM('a','b') NOT NULL DEFAULT 'a'"
 | |
|                   ")");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "DROP VIEW IF EXISTS v1");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "CREATE VIEW v1 AS SELECT * FROM t1");
 | |
|   myquery(rc);
 | |
| 
 | |
|   /*
 | |
|     Checking that mysql_list_fields() returns the same result
 | |
|     for a TABLE and a VIEW on the same table.
 | |
|   */
 | |
|   for (i= 0; i < 2; i++)
 | |
|   {
 | |
|     const char *table_name= i == 0 ? "t1" : "v1";
 | |
|     MYSQL_RES *result= mysql_list_fields(mysql, table_name, NULL);
 | |
|     mytest(result);
 | |
| 
 | |
|     rc= my_process_result_set(result);
 | |
|     DIE_UNLESS(rc == 0);
 | |
| 
 | |
|     verify_prepare_field(result, 0, "i1", "i1", MYSQL_TYPE_LONG,
 | |
|                          table_name, table_name, current_db,
 | |
|                          11, "0");
 | |
| 
 | |
|     verify_prepare_field(result, 1, "i3", "i3", MYSQL_TYPE_LONGLONG,
 | |
|                          table_name, table_name, current_db,
 | |
|                          20, "18446744073709551615");
 | |
| 
 | |
|     verify_prepare_field(result, 2, "s1", "s1", MYSQL_TYPE_VAR_STRING,
 | |
|                          table_name, table_name, current_db,
 | |
|                          10, "s1def");
 | |
| 
 | |
|     verify_prepare_field(result, 3, "d1", "d1", MYSQL_TYPE_NEWDECIMAL,
 | |
|                          table_name, table_name, current_db,
 | |
|                          33, "111111111122222222223333333333.9");
 | |
| 
 | |
|     verify_prepare_field(result, 4, "t1", "t1", MYSQL_TYPE_DATETIME,
 | |
|                          table_name, table_name, current_db,
 | |
|                          26, "2001-01-01 10:20:30.123456");
 | |
| 
 | |
|     verify_prepare_field(result, 5, "e1", "e1", MYSQL_TYPE_STRING,
 | |
|                          table_name, table_name, current_db,
 | |
|                          1, "a");
 | |
| 
 | |
|     mysql_free_result(result);
 | |
|   }
 | |
| 
 | |
|   myquery(mysql_query(mysql, "DROP VIEW v1"));
 | |
|   myquery(mysql_query(mysql, "DROP TABLE t1"));
 | |
| }
 | |
| 
 | |
| 
 | |
| /**
 | |
|   Note, this test covers MDEV-18408 and MDEV-18685
 | |
| */
 | |
| 
 | |
| static void test_mdev18408()
 | |
| {
 | |
|   MYSQL_RES *result;
 | |
|   int rc;
 | |
|   myheader("test_mdev18408s");
 | |
| 
 | |
|   rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "DROP VIEW IF EXISTS v1");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "CREATE TABLE t1 (c1 TIMESTAMP NULL DEFAULT NULL)");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "CREATE VIEW v1 AS SELECT c1 FROM t1");
 | |
|   myquery(rc);
 | |
| 
 | |
|   result= mysql_list_fields(mysql, "v1", NULL);
 | |
|   mytest(result);
 | |
| 
 | |
|   rc= my_process_result_set(result);
 | |
|   DIE_UNLESS(rc == 0);
 | |
| 
 | |
|   verify_prepare_field(result, 0, "c1", "c1", MYSQL_TYPE_TIMESTAMP,
 | |
|                        "v1", "v1",  current_db, 19, 0);
 | |
| 
 | |
|   mysql_free_result(result);
 | |
|   myquery(mysql_query(mysql, "DROP VIEW v1"));
 | |
|   myquery(mysql_query(mysql, "DROP TABLE t1"));
 | |
| }
 | |
| 
 | |
| 
 | |
| static void test_bug19671()
 | |
| {
 | |
|   MYSQL_RES *result;
 | |
|   int rc;
 | |
|   myheader("test_bug19671");
 | |
| 
 | |
|   mysql_query(mysql, "set sql_mode=''");
 | |
|   rc= mysql_query(mysql, "drop table if exists t1");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "drop view if exists v1");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "create table t1(f1 int)");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "create view v1 as select va.* from t1 va");
 | |
|   myquery(rc);
 | |
| 
 | |
|   result= mysql_list_fields(mysql, "v1", NULL);
 | |
|   mytest(result);
 | |
| 
 | |
|   rc= my_process_result_set(result);
 | |
|   DIE_UNLESS(rc == 0);
 | |
| 
 | |
|   verify_prepare_field(result, 0, "f1", "f1", MYSQL_TYPE_LONG,
 | |
|                        "v1", "v1", current_db, 11, NULL);
 | |
| 
 | |
|   mysql_free_result(result);
 | |
|   myquery(mysql_query(mysql, "drop view v1"));
 | |
|   myquery(mysql_query(mysql, "drop table t1"));
 | |
| }
 | |
| 
 | |
| 
 | |
| /* Test a memory ovverun bug */
 | |
| 
 | |
| static void test_mem_overun()
 | |
| {
 | |
|   char       buffer[10000], field[10];
 | |
|   MYSQL_STMT *stmt;
 | |
|   MYSQL_RES  *field_res;
 | |
|   int        rc, length;
 | |
|   unsigned   i;
 | |
| 
 | |
|   myheader("test_mem_overun");
 | |
| 
 | |
|   /*
 | |
|     Test a memory ovverun bug when a table had 1000 fields with
 | |
|     a row of data
 | |
|   */
 | |
|   rc= mysql_query(mysql, "drop table if exists t_mem_overun");
 | |
|   myquery(rc);
 | |
| 
 | |
|   strxmov(buffer, "create table t_mem_overun(", NullS);
 | |
|   for (i= 0; i < 1000; i++)
 | |
|   {
 | |
|     sprintf(field, "c%u int", i);
 | |
|     strxmov(buffer, buffer, field, ", ", NullS);
 | |
|   }
 | |
|   length= strlen(buffer);
 | |
|   buffer[length-2]= ')';
 | |
|   buffer[--length]= '\0';
 | |
| 
 | |
|   rc= mysql_real_query(mysql, buffer, length);
 | |
|   myquery(rc);
 | |
| 
 | |
|   strxmov(buffer, "insert into t_mem_overun values(", NullS);
 | |
|   for (i= 0; i < 1000; i++)
 | |
|   {
 | |
|     strxmov(buffer, buffer, "1, ", NullS);
 | |
|   }
 | |
|   length= strlen(buffer);
 | |
|   buffer[length-2]= ')';
 | |
|   buffer[--length]= '\0';
 | |
| 
 | |
|   rc= mysql_real_query(mysql, buffer, length);
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "select * from t_mem_overun");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= my_process_result(mysql);
 | |
|   DIE_UNLESS(rc == 1);
 | |
| 
 | |
|   stmt= mysql_simple_prepare(mysql, "select * from t_mem_overun");
 | |
|   check_stmt(stmt);
 | |
| 
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   field_res= mysql_stmt_result_metadata(stmt);
 | |
|   mytest(field_res);
 | |
| 
 | |
|   if (!opt_silent)
 | |
|     fprintf(stdout, "\n total fields : %d", mysql_num_fields(field_res));
 | |
|   DIE_UNLESS( 1000 == mysql_num_fields(field_res));
 | |
| 
 | |
|   rc= mysql_stmt_store_result(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= mysql_stmt_fetch(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= mysql_stmt_fetch(stmt);
 | |
|   DIE_UNLESS(rc == MYSQL_NO_DATA);
 | |
| 
 | |
|   mysql_free_result(field_res);
 | |
| 
 | |
|   mysql_stmt_close(stmt);
 | |
| }
 | |
| 
 | |
| 
 | |
| /* Test mysql_stmt_free_result() */
 | |
| 
 | |
| static void test_free_result()
 | |
| {
 | |
|   MYSQL_STMT *stmt;
 | |
|   MYSQL_BIND my_bind[1];
 | |
|   char       c2[5];
 | |
|   ulong      bl1, l2;
 | |
|   int        rc, c1, bc1;
 | |
| 
 | |
|   myheader("test_free_result");
 | |
| 
 | |
|   rc= mysql_query(mysql, "drop table if exists test_free_result");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "create table test_free_result("
 | |
|                          "c1 int primary key auto_increment)");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "insert into test_free_result values(), (), ()");
 | |
|   myquery(rc);
 | |
| 
 | |
|   stmt= mysql_simple_prepare(mysql, "select * from test_free_result");
 | |
|   check_stmt(stmt);
 | |
| 
 | |
|   bzero((char*) my_bind, sizeof(my_bind));
 | |
|   my_bind[0].buffer_type= MYSQL_TYPE_LONG;
 | |
|   my_bind[0].buffer= (void *)&bc1;
 | |
|   my_bind[0].length= &bl1;
 | |
| 
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= mysql_stmt_bind_result(stmt, my_bind);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= mysql_stmt_fetch(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   c2[0]= '\0'; l2= 0;
 | |
|   my_bind[0].buffer_type= MYSQL_TYPE_STRING;
 | |
|   my_bind[0].buffer= (void *)c2;
 | |
|   my_bind[0].buffer_length= 7;
 | |
|   my_bind[0].is_null= 0;
 | |
|   my_bind[0].length= &l2;
 | |
| 
 | |
|   rc= mysql_stmt_fetch_column(stmt, my_bind, 0, 0);
 | |
|   check_execute(stmt, rc);
 | |
|   if (!opt_silent)
 | |
|     fprintf(stdout, "\n col 0: %s(%ld)", c2, l2);
 | |
|   DIE_UNLESS(strncmp(c2, "1", 1) == 0 && l2 == 1);
 | |
| 
 | |
|   rc= mysql_stmt_fetch(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   c1= 0, l2= 0;
 | |
|   my_bind[0].buffer_type= MYSQL_TYPE_LONG;
 | |
|   my_bind[0].buffer= (void *)&c1;
 | |
|   my_bind[0].buffer_length= 0;
 | |
|   my_bind[0].is_null= 0;
 | |
|   my_bind[0].length= &l2;
 | |
| 
 | |
|   rc= mysql_stmt_fetch_column(stmt, my_bind, 0, 0);
 | |
|   check_execute(stmt, rc);
 | |
|   if (!opt_silent)
 | |
|     fprintf(stdout, "\n col 0: %d(%ld)", c1, l2);
 | |
|   DIE_UNLESS(c1 == 2 && l2 == 4);
 | |
| 
 | |
|   rc= mysql_query(mysql, "drop table test_free_result");
 | |
|   myquery_r(rc); /* error should be, COMMANDS OUT OF SYNC */
 | |
| 
 | |
|   rc= mysql_stmt_free_result(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "drop table test_free_result");
 | |
|   myquery(rc);  /* should be successful */
 | |
| 
 | |
|   mysql_stmt_close(stmt);
 | |
| }
 | |
| 
 | |
| 
 | |
| /* Test mysql_stmt_store_result() */
 | |
| 
 | |
| static void test_free_store_result()
 | |
| {
 | |
|   MYSQL_STMT *stmt;
 | |
|   MYSQL_BIND my_bind[1];
 | |
|   char       c2[5];
 | |
|   ulong      bl1, l2;
 | |
|   int        rc, c1, bc1;
 | |
| 
 | |
|   myheader("test_free_store_result");
 | |
| 
 | |
|   rc= mysql_query(mysql, "drop table if exists test_free_result");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "create table test_free_result(c1 int primary key auto_increment)");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "insert into test_free_result values(), (), ()");
 | |
|   myquery(rc);
 | |
| 
 | |
|   stmt= mysql_simple_prepare(mysql, "select * from test_free_result");
 | |
|   check_stmt(stmt);
 | |
| 
 | |
|   bzero((char*) my_bind, sizeof(my_bind));
 | |
|   my_bind[0].buffer_type= MYSQL_TYPE_LONG;
 | |
|   my_bind[0].buffer= (void *)&bc1;
 | |
|   my_bind[0].buffer_length= 0;
 | |
|   my_bind[0].is_null= 0;
 | |
|   my_bind[0].length= &bl1;
 | |
| 
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= mysql_stmt_bind_result(stmt, my_bind);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= mysql_stmt_store_result(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= mysql_stmt_fetch(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   c2[0]= '\0'; l2= 0;
 | |
|   my_bind[0].buffer_type= MYSQL_TYPE_STRING;
 | |
|   my_bind[0].buffer= (void *)c2;
 | |
|   my_bind[0].buffer_length= 7;
 | |
|   my_bind[0].is_null= 0;
 | |
|   my_bind[0].length= &l2;
 | |
| 
 | |
|   rc= mysql_stmt_fetch_column(stmt, my_bind, 0, 0);
 | |
|   check_execute(stmt, rc);
 | |
|   if (!opt_silent)
 | |
|     fprintf(stdout, "\n col 1: %s(%ld)", c2, l2);
 | |
|   DIE_UNLESS(strncmp(c2, "1", 1) == 0 && l2 == 1);
 | |
| 
 | |
|   rc= mysql_stmt_fetch(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   c1= 0, l2= 0;
 | |
|   my_bind[0].buffer_type= MYSQL_TYPE_LONG;
 | |
|   my_bind[0].buffer= (void *)&c1;
 | |
|   my_bind[0].buffer_length= 0;
 | |
|   my_bind[0].is_null= 0;
 | |
|   my_bind[0].length= &l2;
 | |
| 
 | |
|   rc= mysql_stmt_fetch_column(stmt, my_bind, 0, 0);
 | |
|   check_execute(stmt, rc);
 | |
|   if (!opt_silent)
 | |
|     fprintf(stdout, "\n col 0: %d(%ld)", c1, l2);
 | |
|   DIE_UNLESS(c1 == 2 && l2 == 4);
 | |
| 
 | |
|   rc= mysql_stmt_free_result(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "drop table test_free_result");
 | |
|   myquery(rc);
 | |
| 
 | |
|   mysql_stmt_close(stmt);
 | |
| }
 | |
| 
 | |
| 
 | |
| /* Test SQLmode */
 | |
| 
 | |
| static void test_sqlmode()
 | |
| {
 | |
|   MYSQL_STMT *stmt;
 | |
|   MYSQL_BIND my_bind[2];
 | |
|   char       c1[5], c2[5];
 | |
|   int        rc;
 | |
|   char query[MAX_TEST_QUERY_LENGTH];
 | |
| 
 | |
|   myheader("test_sqlmode");
 | |
| 
 | |
|   rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_piping");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "CREATE TABLE test_piping(name varchar(10))");
 | |
|   myquery(rc);
 | |
| 
 | |
|   /* PIPES_AS_CONCAT */
 | |
|   strmov(query, "SET SQL_MODE= \"PIPES_AS_CONCAT\"");
 | |
|   if (!opt_silent)
 | |
|     fprintf(stdout, "\n With %s", query);
 | |
|   rc= mysql_query(mysql, query);
 | |
|   myquery(rc);
 | |
| 
 | |
|   strmov(query, "INSERT INTO test_piping VALUES(?||?)");
 | |
|   if (!opt_silent)
 | |
|     fprintf(stdout, "\n  query: %s", query);
 | |
|   stmt= mysql_simple_prepare(mysql, query);
 | |
|   check_stmt(stmt);
 | |
| 
 | |
|   if (!opt_silent)
 | |
|     fprintf(stdout, "\n  total parameters: %ld", mysql_stmt_param_count(stmt));
 | |
| 
 | |
|   /*
 | |
|     We need to bzero bind structure because mysql_stmt_bind_param checks all
 | |
|     its members.
 | |
|   */
 | |
|   bzero((char*) my_bind, sizeof(my_bind));
 | |
| 
 | |
|   my_bind[0].buffer_type= MYSQL_TYPE_STRING;
 | |
|   my_bind[0].buffer= (void *)c1;
 | |
|   my_bind[0].buffer_length= 2;
 | |
| 
 | |
|   my_bind[1].buffer_type= MYSQL_TYPE_STRING;
 | |
|   my_bind[1].buffer= (void *)c2;
 | |
|   my_bind[1].buffer_length= 3;
 | |
| 
 | |
|   rc= mysql_stmt_bind_param(stmt, my_bind);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   strmov(c1, "My"); strmov(c2, "SQL");
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
|   mysql_stmt_close(stmt);
 | |
| 
 | |
|   verify_col_data("test_piping", "name", "MySQL");
 | |
| 
 | |
|   rc= mysql_query(mysql, "DELETE FROM test_piping");
 | |
|   myquery(rc);
 | |
| 
 | |
|   strmov(query, "SELECT connection_id    ()");
 | |
|   if (!opt_silent)
 | |
|     fprintf(stdout, "\n  query: %s", query);
 | |
|   stmt= mysql_simple_prepare(mysql, query);
 | |
|   check_stmt(stmt);
 | |
|   mysql_stmt_close(stmt);
 | |
| 
 | |
|   /* ANSI */
 | |
|   strmov(query, "SET SQL_MODE= \"ANSI\"");
 | |
|   if (!opt_silent)
 | |
|     fprintf(stdout, "\n With %s", query);
 | |
|   rc= mysql_query(mysql, query);
 | |
|   myquery(rc);
 | |
| 
 | |
|   strmov(query, "INSERT INTO test_piping VALUES(?||?)");
 | |
|   if (!opt_silent)
 | |
|     fprintf(stdout, "\n  query: %s", query);
 | |
|   stmt= mysql_simple_prepare(mysql, query);
 | |
|   check_stmt(stmt);
 | |
|   if (!opt_silent)
 | |
|     fprintf(stdout, "\n  total parameters: %ld", mysql_stmt_param_count(stmt));
 | |
| 
 | |
|   rc= mysql_stmt_bind_param(stmt, my_bind);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   strmov(c1, "My"); strmov(c2, "SQL");
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   mysql_stmt_close(stmt);
 | |
|   verify_col_data("test_piping", "name", "MySQL");
 | |
| 
 | |
|   /* ANSI mode spaces ... */
 | |
|   strmov(query, "SELECT connection_id    ()");
 | |
|   if (!opt_silent)
 | |
|     fprintf(stdout, "\n  query: %s", query);
 | |
|   stmt= mysql_simple_prepare(mysql, query);
 | |
|   check_stmt(stmt);
 | |
| 
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= mysql_stmt_fetch(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= mysql_stmt_fetch(stmt);
 | |
|   DIE_UNLESS(rc == MYSQL_NO_DATA);
 | |
|   if (!opt_silent)
 | |
|     fprintf(stdout, "\n  returned 1 row\n");
 | |
| 
 | |
|   mysql_stmt_close(stmt);
 | |
| 
 | |
|   /* IGNORE SPACE MODE */
 | |
|   strmov(query, "SET SQL_MODE= \"IGNORE_SPACE\"");
 | |
|   if (!opt_silent)
 | |
|     fprintf(stdout, "\n With %s", query);
 | |
|   rc= mysql_query(mysql, query);
 | |
|   myquery(rc);
 | |
| 
 | |
|   strmov(query, "SELECT connection_id    ()");
 | |
|   if (!opt_silent)
 | |
|     fprintf(stdout, "\n  query: %s", query);
 | |
|   stmt= mysql_simple_prepare(mysql, query);
 | |
|   check_stmt(stmt);
 | |
| 
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= mysql_stmt_fetch(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= mysql_stmt_fetch(stmt);
 | |
|   DIE_UNLESS(rc == MYSQL_NO_DATA);
 | |
|   if (!opt_silent)
 | |
|     fprintf(stdout, "\n  returned 1 row");
 | |
| 
 | |
|   mysql_stmt_close(stmt);
 | |
| }
 | |
| 
 | |
| 
 | |
| /* Test for timestamp handling */
 | |
| 
 | |
| static void test_ts()
 | |
| {
 | |
|   MYSQL_STMT *stmt;
 | |
|   MYSQL_BIND my_bind[6];
 | |
|   MYSQL_TIME ts;
 | |
|   MYSQL_RES  *prep_res;
 | |
|   char       strts[30];
 | |
|   ulong      length;
 | |
|   int        rc, field_count;
 | |
|   char       name;
 | |
|   char query[MAX_TEST_QUERY_LENGTH];
 | |
|   const char *queries [3]= {"SELECT a, b, c FROM test_ts WHERE %c=?",
 | |
|                             "SELECT a, b, c FROM test_ts WHERE %c=CAST(? AS TIME)",
 | |
|                             "SELECT a, b, c FROM test_ts WHERE %c=CAST(? AS DATE)"};
 | |
|   myheader("test_ts");
 | |
| 
 | |
|   rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_ts");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "CREATE TABLE test_ts(a DATE, b TIME, c TIMESTAMP)");
 | |
|   myquery(rc);
 | |
| 
 | |
|   stmt= mysql_simple_prepare(mysql, "INSERT INTO test_ts VALUES(?, ?, ?), (?, ?, ?)");
 | |
|   check_stmt(stmt);
 | |
| 
 | |
|   ts.year= 2003;
 | |
|   ts.month= 07;
 | |
|   ts.day= 12;
 | |
|   ts.hour= 21;
 | |
|   ts.minute= 07;
 | |
|   ts.second= 46;
 | |
|   ts.second_part= 0;
 | |
|   length= (long)(strmov(strts, "2003-07-12 21:07:46") - strts);
 | |
| 
 | |
|   /*
 | |
|     We need to bzero bind structure because mysql_stmt_bind_param checks all
 | |
|     its members.
 | |
|   */
 | |
|   bzero((char*) my_bind, sizeof(my_bind));
 | |
| 
 | |
|   my_bind[0].buffer_type= MYSQL_TYPE_TIMESTAMP;
 | |
|   my_bind[0].buffer= (void *)&ts;
 | |
|   my_bind[0].buffer_length= sizeof(ts);
 | |
| 
 | |
|   my_bind[2]= my_bind[1]= my_bind[0];
 | |
| 
 | |
|   my_bind[3].buffer_type= MYSQL_TYPE_STRING;
 | |
|   my_bind[3].buffer= (void *)strts;
 | |
|   my_bind[3].buffer_length= sizeof(strts);
 | |
|   my_bind[3].length= &length;
 | |
| 
 | |
|   my_bind[5]= my_bind[4]= my_bind[3];
 | |
| 
 | |
|   rc= mysql_stmt_bind_param(stmt, my_bind);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   mysql_stmt_close(stmt);
 | |
| 
 | |
|   verify_col_data("test_ts", "a", "2003-07-12");
 | |
|   verify_col_data("test_ts", "b", "21:07:46");
 | |
|   verify_col_data("test_ts", "c", "2003-07-12 21:07:46");
 | |
| 
 | |
|   stmt= mysql_simple_prepare(mysql, "SELECT * FROM test_ts");
 | |
|   check_stmt(stmt);
 | |
| 
 | |
|   prep_res= mysql_stmt_result_metadata(stmt);
 | |
|   mytest(prep_res);
 | |
| 
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= my_process_stmt_result(stmt);
 | |
|   DIE_UNLESS(rc == 2);
 | |
|   field_count= mysql_num_fields(prep_res);
 | |
| 
 | |
|   mysql_free_result(prep_res);
 | |
|   mysql_stmt_close(stmt);
 | |
| 
 | |
|   for (name= 'a'; field_count--; name++)
 | |
|   {
 | |
|     int row_count= 0;
 | |
| 
 | |
|     sprintf(query, queries[field_count], name);
 | |
| 
 | |
|     if (!opt_silent)
 | |
|       fprintf(stdout, "\n  %s", query);
 | |
|     stmt= mysql_simple_prepare(mysql, query);
 | |
|     check_stmt(stmt);
 | |
| 
 | |
|     rc= mysql_stmt_bind_param(stmt, my_bind);
 | |
|     check_execute(stmt, rc);
 | |
| 
 | |
|     rc= mysql_stmt_execute(stmt);
 | |
|     check_execute(stmt, rc);
 | |
| 
 | |
|     while (mysql_stmt_fetch(stmt) == 0)
 | |
|       row_count++;
 | |
| 
 | |
|     if (!opt_silent)
 | |
|       fprintf(stdout, "\n   returned '%d' rows", row_count);
 | |
|     DIE_UNLESS(row_count == 2);
 | |
|     mysql_stmt_close(stmt);
 | |
|   }
 | |
| }
 | |
| 
 | |
| 
 | |
| /* Test for bug #1500. */
 | |
| 
 | |
| static void test_bug1500()
 | |
| {
 | |
|   MYSQL_STMT *stmt;
 | |
|   MYSQL_BIND my_bind[3];
 | |
|   int        rc;
 | |
|   int32 int_data[3]= {2, 3, 4};
 | |
|   const char *data;
 | |
| 
 | |
|   myheader("test_bug1500");
 | |
| 
 | |
|   rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_bg1500");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "CREATE TABLE test_bg1500 (i INT)");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "INSERT INTO test_bg1500 VALUES (1), (2)");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_commit(mysql);
 | |
|   myquery(rc);
 | |
| 
 | |
|   stmt= mysql_simple_prepare(mysql, "SELECT i FROM test_bg1500 WHERE i IN (?, ?, ?)");
 | |
|   check_stmt(stmt);
 | |
|   verify_param_count(stmt, 3);
 | |
| 
 | |
|   /*
 | |
|     We need to bzero bind structure because mysql_stmt_bind_param checks all
 | |
|     its members.
 | |
|   */
 | |
|   bzero((char*) my_bind, sizeof(my_bind));
 | |
| 
 | |
|   my_bind[0].buffer= (void *)int_data;
 | |
|   my_bind[0].buffer_type= MYSQL_TYPE_LONG;
 | |
|   my_bind[2]= my_bind[1]= my_bind[0];
 | |
|   my_bind[1].buffer= (void *)(int_data + 1);
 | |
|   my_bind[2].buffer= (void *)(int_data + 2);
 | |
| 
 | |
|   rc= mysql_stmt_bind_param(stmt, my_bind);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= my_process_stmt_result(stmt);
 | |
|   DIE_UNLESS(rc == 1);
 | |
| 
 | |
|   mysql_stmt_close(stmt);
 | |
| 
 | |
|   rc= mysql_query(mysql, "DROP TABLE test_bg1500");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "CREATE TABLE test_bg1500 (s VARCHAR(25), FULLTEXT(s)) engine=MyISAM");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql,
 | |
|         "INSERT INTO test_bg1500 VALUES ('Gravedigger'), ('Greed'), ('Hollow Dogs')");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_commit(mysql);
 | |
|   myquery(rc);
 | |
| 
 | |
|   stmt= mysql_simple_prepare(mysql,
 | |
|           "SELECT s FROM test_bg1500 WHERE MATCH (s) AGAINST (?)");
 | |
|   check_stmt(stmt);
 | |
| 
 | |
|   verify_param_count(stmt, 1);
 | |
| 
 | |
|   data= "Dogs";
 | |
|   my_bind[0].buffer_type= MYSQL_TYPE_STRING;
 | |
|   my_bind[0].buffer= (void *) data;
 | |
|   my_bind[0].buffer_length= strlen(data);
 | |
|   my_bind[0].is_null= 0;
 | |
|   my_bind[0].length= 0;
 | |
| 
 | |
|   rc= mysql_stmt_bind_param(stmt, my_bind);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= my_process_stmt_result(stmt);
 | |
|   DIE_UNLESS(rc == 1);
 | |
| 
 | |
|   mysql_stmt_close(stmt);
 | |
| 
 | |
|   /* This should work too */
 | |
|   stmt= mysql_simple_prepare(mysql,
 | |
|           "SELECT s FROM test_bg1500 WHERE MATCH (s) AGAINST (CONCAT(?, 'digger'))");
 | |
|   check_stmt(stmt);
 | |
| 
 | |
|   verify_param_count(stmt, 1);
 | |
| 
 | |
|   data= "Grave";
 | |
|   my_bind[0].buffer_type= MYSQL_TYPE_STRING;
 | |
|   my_bind[0].buffer= (void *) data;
 | |
|   my_bind[0].buffer_length= strlen(data);
 | |
| 
 | |
|   rc= mysql_stmt_bind_param(stmt, my_bind);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= my_process_stmt_result(stmt);
 | |
|   DIE_UNLESS(rc == 1);
 | |
| 
 | |
|   mysql_stmt_close(stmt);
 | |
| }
 | |
| 
 | |
| 
 | |
| static void test_bug1946()
 | |
| {
 | |
|   MYSQL_STMT *stmt;
 | |
|   int rc;
 | |
|   const char *query= "INSERT INTO prepare_command VALUES (?)";
 | |
| 
 | |
|   myheader("test_bug1946");
 | |
| 
 | |
|   rc= mysql_query(mysql, "DROP TABLE IF EXISTS prepare_command");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "CREATE TABLE prepare_command(ID INT)");
 | |
|   myquery(rc);
 | |
| 
 | |
|   stmt= mysql_simple_prepare(mysql, query);
 | |
|   check_stmt(stmt);
 | |
|   rc= mysql_real_query(mysql, query, strlen(query));
 | |
|   DIE_UNLESS(rc != 0);
 | |
|   if (!opt_silent)
 | |
|     fprintf(stdout, "Got error (as expected):\n");
 | |
|   myerror(NULL);
 | |
| 
 | |
|   mysql_stmt_close(stmt);
 | |
|   rc= mysql_query(mysql, "DROP TABLE prepare_command");
 | |
| }
 | |
| 
 | |
| 
 | |
| static void test_parse_error_and_bad_length()
 | |
| {
 | |
|   MYSQL_STMT *stmt;
 | |
|   int rc;
 | |
| 
 | |
|   /* check that we get 4 syntax errors over the 4 calls */
 | |
|   myheader("test_parse_error_and_bad_length");
 | |
| 
 | |
|   rc= mysql_query(mysql, "SHOW DATABAAAA");
 | |
|   DIE_UNLESS(rc);
 | |
|   if (!opt_silent)
 | |
|     fprintf(stdout, "Got error (as expected): '%s'\n", mysql_error(mysql));
 | |
|   rc= mysql_real_query(mysql, STRING_WITH_LEN("SHOW DATABASES\0AAAAAAAA"));
 | |
|   DIE_UNLESS(rc);
 | |
|   if (!opt_silent)
 | |
|     fprintf(stdout, "Got error (as expected): '%s'\n", mysql_error(mysql));
 | |
| 
 | |
|   stmt= mysql_simple_prepare(mysql, "SHOW DATABAAAA");
 | |
|   DIE_UNLESS(!stmt);
 | |
|   if (!opt_silent)
 | |
|     fprintf(stdout, "Got error (as expected): '%s'\n", mysql_error(mysql));
 | |
|   stmt= mysql_stmt_init(mysql);
 | |
|   DIE_UNLESS(stmt);
 | |
|   rc= mysql_stmt_prepare(stmt, STRING_WITH_LEN("SHOW DATABASES\0AAAAAAA"));
 | |
|   DIE_UNLESS(rc != 0);
 | |
|   if (!opt_silent)
 | |
|     fprintf(stdout, "Got error (as expected): '%s'\n", mysql_stmt_error(stmt));
 | |
|   mysql_stmt_close(stmt);
 | |
| }
 | |
| 
 | |
| 
 | |
| static void test_bug2247()
 | |
| {
 | |
|   MYSQL_STMT *stmt;
 | |
|   MYSQL_RES *res;
 | |
|   int rc;
 | |
|   int i;
 | |
|   const char *create= "CREATE TABLE bug2247(id INT UNIQUE AUTO_INCREMENT)";
 | |
|   const char *insert= "INSERT INTO bug2247 VALUES (NULL)";
 | |
|   const char *SELECT= "SELECT id FROM bug2247";
 | |
|   const char *update= "UPDATE bug2247 SET id=id+10";
 | |
|   const char *drop= "DROP TABLE IF EXISTS bug2247";
 | |
|   ulonglong exp_count;
 | |
|   enum { NUM_ROWS= 5 };
 | |
| 
 | |
|   myheader("test_bug2247");
 | |
| 
 | |
|   if (!opt_silent)
 | |
|     fprintf(stdout, "\nChecking if stmt_affected_rows is not affected by\n"
 | |
|                   "mysql_query ... ");
 | |
|   /* create table and insert few rows */
 | |
|   rc= mysql_query(mysql, drop);
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, create);
 | |
|   myquery(rc);
 | |
| 
 | |
|   stmt= mysql_simple_prepare(mysql, insert);
 | |
|   check_stmt(stmt);
 | |
|   for (i= 0; i < NUM_ROWS; ++i)
 | |
|   {
 | |
|     rc= mysql_stmt_execute(stmt);
 | |
|     check_execute(stmt, rc);
 | |
|   }
 | |
|   exp_count= mysql_stmt_affected_rows(stmt);
 | |
|   DIE_UNLESS(exp_count == 1);
 | |
| 
 | |
|   rc= mysql_query(mysql, SELECT);
 | |
|   myquery(rc);
 | |
|   /*
 | |
|     mysql_store_result overwrites mysql->affected_rows. Check that
 | |
|     mysql_stmt_affected_rows() returns the same value, whereas
 | |
|     mysql_affected_rows() value is correct.
 | |
|   */
 | |
|   res= mysql_store_result(mysql);
 | |
|   mytest(res);
 | |
| 
 | |
|   DIE_UNLESS(mysql_affected_rows(mysql) == NUM_ROWS);
 | |
|   DIE_UNLESS(exp_count == mysql_stmt_affected_rows(stmt));
 | |
| 
 | |
|   rc= mysql_query(mysql, update);
 | |
|   myquery(rc);
 | |
|   DIE_UNLESS(mysql_affected_rows(mysql) == NUM_ROWS);
 | |
|   DIE_UNLESS(exp_count == mysql_stmt_affected_rows(stmt));
 | |
| 
 | |
|   mysql_free_result(res);
 | |
|   mysql_stmt_close(stmt);
 | |
| 
 | |
|   /* check that mysql_stmt_store_result modifies mysql_stmt_affected_rows */
 | |
|   stmt= mysql_simple_prepare(mysql, SELECT);
 | |
|   check_stmt(stmt);
 | |
| 
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
|   rc= mysql_stmt_store_result(stmt);
 | |
|   check_execute(stmt, rc);
 | |
|   exp_count= mysql_stmt_affected_rows(stmt);
 | |
|   DIE_UNLESS(exp_count == NUM_ROWS);
 | |
| 
 | |
|   rc= mysql_query(mysql, insert);
 | |
|   myquery(rc);
 | |
|   DIE_UNLESS(mysql_affected_rows(mysql) == 1);
 | |
|   DIE_UNLESS(mysql_stmt_affected_rows(stmt) == exp_count);
 | |
| 
 | |
|   mysql_stmt_close(stmt);
 | |
|   if (!opt_silent)
 | |
|     fprintf(stdout, "OK");
 | |
| }
 | |
| 
 | |
| 
 | |
| static void test_subqueries()
 | |
| {
 | |
|   MYSQL_STMT *stmt;
 | |
|   int rc, i;
 | |
|   const char *query= "SELECT (SELECT SUM(a+b) FROM t2 where t1.b=t2.b GROUP BY t1.a LIMIT 1) as scalar_s, exists (select 1 from t2 where t2.a/2=t1.a) as exists_s, a in (select a+3 from t2) as in_s, (a-1, b-1) in (select a, b from t2) as in_row_s FROM t1, (select a x, b y from t2) tt WHERE x=a";
 | |
| 
 | |
|   myheader("test_subqueries");
 | |
| 
 | |
|   rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1, t2");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "CREATE TABLE t1 (a int , b int);");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql,
 | |
|                   "insert into t1 values (1, 1), (2, 2), (3, 3), (4, 4), (5, 5);");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "create table t2 select * from t1;");
 | |
|   myquery(rc);
 | |
| 
 | |
|   stmt= mysql_simple_prepare(mysql, query);
 | |
|   check_stmt(stmt);
 | |
|   for (i= 0; i < 3; i++)
 | |
|   {
 | |
|     rc= mysql_stmt_execute(stmt);
 | |
|     check_execute(stmt, rc);
 | |
|     rc= my_process_stmt_result(stmt);
 | |
|     DIE_UNLESS(rc == 5);
 | |
|   }
 | |
|   mysql_stmt_close(stmt);
 | |
| 
 | |
|   rc= mysql_query(mysql, "DROP TABLE t1, t2");
 | |
|   myquery(rc);
 | |
| }
 | |
| 
 | |
| 
 | |
| static void test_bad_union()
 | |
| {
 | |
|   MYSQL_STMT *stmt;
 | |
|   const char *query= "SELECT 1, 2 union SELECT 1";
 | |
| 
 | |
|   myheader("test_bad_union");
 | |
| 
 | |
|   stmt= mysql_simple_prepare(mysql, query);
 | |
|   DIE_UNLESS(stmt == 0);
 | |
|   myerror(NULL);
 | |
| }
 | |
| 
 | |
| 
 | |
| static void test_distinct()
 | |
| {
 | |
|   MYSQL_STMT *stmt;
 | |
|   int rc, i;
 | |
|   const char *query=
 | |
|     "SELECT 2+count(distinct b), group_concat(a) FROM t1 group by a";
 | |
| 
 | |
|   myheader("test_distinct");
 | |
| 
 | |
|   rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "CREATE TABLE t1 (a int , b int);");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql,
 | |
|                   "insert into t1 values (1, 1), (2, 2), (3, 3), (4, 4), (5, 5), \
 | |
| (1, 10), (2, 20), (3, 30), (4, 40), (5, 50);");
 | |
|   myquery(rc);
 | |
| 
 | |
|   for (i= 0; i < 3; i++)
 | |
|   {
 | |
|     stmt= mysql_simple_prepare(mysql, query);
 | |
|     check_stmt(stmt);
 | |
|     rc= mysql_stmt_execute(stmt);
 | |
|     check_execute(stmt, rc);
 | |
|     rc= my_process_stmt_result(stmt);
 | |
|     DIE_UNLESS(rc == 5);
 | |
|     mysql_stmt_close(stmt);
 | |
|   }
 | |
| 
 | |
|   rc= mysql_query(mysql, "DROP TABLE t1");
 | |
|   myquery(rc);
 | |
| }
 | |
| 
 | |
| 
 | |
| /*
 | |
|   Test for bug#2248 "mysql_fetch without prior mysql_stmt_execute hangs"
 | |
| */
 | |
| 
 | |
| static void test_bug2248()
 | |
| {
 | |
|   MYSQL_STMT *stmt;
 | |
|   int rc;
 | |
|   const char *query1= "SELECT DATABASE()";
 | |
|   const char *query2= "INSERT INTO test_bug2248 VALUES (10)";
 | |
| 
 | |
|   myheader("test_bug2248");
 | |
| 
 | |
|   rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_bug2248");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "CREATE TABLE test_bug2248 (id int)");
 | |
|   myquery(rc);
 | |
| 
 | |
|   stmt= mysql_simple_prepare(mysql, query1);
 | |
|   check_stmt(stmt);
 | |
| 
 | |
|   /* This should not hang */
 | |
|   rc= mysql_stmt_fetch(stmt);
 | |
|   check_execute_r(stmt, rc);
 | |
| 
 | |
|   /* And this too */
 | |
|   rc= mysql_stmt_store_result(stmt);
 | |
|   check_execute_r(stmt, rc);
 | |
| 
 | |
|   mysql_stmt_close(stmt);
 | |
| 
 | |
|   stmt= mysql_simple_prepare(mysql, query2);
 | |
|   check_stmt(stmt);
 | |
| 
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   /* This too should not hang but should return proper error */
 | |
|   rc= mysql_stmt_fetch(stmt);
 | |
|   DIE_UNLESS(rc == 1);
 | |
| 
 | |
|   /* This too should not hang but should not bark */
 | |
|   rc= mysql_stmt_store_result(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   /* This should return proper error */
 | |
|   rc= mysql_stmt_fetch(stmt);
 | |
|   check_execute_r(stmt, rc);
 | |
|   DIE_UNLESS(rc == 1);
 | |
| 
 | |
|   mysql_stmt_close(stmt);
 | |
| 
 | |
|   rc= mysql_query(mysql, "DROP TABLE test_bug2248");
 | |
|   myquery(rc);
 | |
| }
 | |
| 
 | |
| 
 | |
| static void test_subqueries_ref()
 | |
| {
 | |
|   MYSQL_STMT *stmt;
 | |
|   int rc, i;
 | |
|   const char *query= "SELECT a as ccc from t1 outr where a+1=(SELECT 1+outr.a from t1 where outr.a+1=a+1 and a=1)";
 | |
| 
 | |
|   myheader("test_subqueries_ref");
 | |
| 
 | |
|   rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "CREATE TABLE t1 (a int);");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql,
 | |
|                   "insert into t1 values (1), (2), (3), (4), (5);");
 | |
|   myquery(rc);
 | |
| 
 | |
|   stmt= mysql_simple_prepare(mysql, query);
 | |
|   check_stmt(stmt);
 | |
|   for (i= 0; i < 3; i++)
 | |
|   {
 | |
|     rc= mysql_stmt_execute(stmt);
 | |
|     check_execute(stmt, rc);
 | |
|     rc= my_process_stmt_result(stmt);
 | |
|     DIE_UNLESS(rc == 1);
 | |
|   }
 | |
|   mysql_stmt_close(stmt);
 | |
| 
 | |
|   rc= mysql_query(mysql, "DROP TABLE t1");
 | |
|   myquery(rc);
 | |
| }
 | |
| 
 | |
| 
 | |
| static void test_union()
 | |
| {
 | |
|   MYSQL_STMT *stmt;
 | |
|   int rc;
 | |
| 
 | |
|   myheader("test_union");
 | |
| 
 | |
|   rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1, t2");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql,
 | |
|                   "CREATE TABLE t1 "
 | |
|                   "(id INTEGER NOT NULL PRIMARY KEY, "
 | |
|                   " name VARCHAR(20) NOT NULL)");
 | |
|   myquery(rc);
 | |
|   rc= mysql_query(mysql,
 | |
|                   "INSERT INTO t1 (id, name) VALUES "
 | |
|                   "(2, 'Ja'), (3, 'Ede'), "
 | |
|                   "(4, 'Haag'), (5, 'Kabul'), "
 | |
|                   "(6, 'Almere'), (7, 'Utrecht'), "
 | |
|                   "(8, 'Qandahar'), (9, 'Amsterdam'), "
 | |
|                   "(10, 'Amersfoort'), (11, 'Constantine')");
 | |
|   myquery(rc);
 | |
|   rc= mysql_query(mysql,
 | |
|                   "CREATE TABLE t2 "
 | |
|                   "(id INTEGER NOT NULL PRIMARY KEY, "
 | |
|                   " name VARCHAR(20) NOT NULL)");
 | |
|   myquery(rc);
 | |
|   rc= mysql_query(mysql,
 | |
|                   "INSERT INTO t2 (id, name) VALUES "
 | |
|                   "(4, 'Guam'), (5, 'Aruba'), "
 | |
|                   "(6, 'Angola'), (7, 'Albania'), "
 | |
|                   "(8, 'Anguilla'), (9, 'Argentina'), "
 | |
|                   "(10, 'Azerbaijan'), (11, 'Afghanistan'), "
 | |
|                   "(12, 'Burkina Faso'), (13, 'Faroe Islands')");
 | |
|   myquery(rc);
 | |
| 
 | |
|   stmt= mysql_simple_prepare(mysql,
 | |
|                              "SELECT t1.name FROM t1 UNION "
 | |
|                              "SELECT t2.name FROM t2");
 | |
|   check_stmt(stmt);
 | |
| 
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
|   rc= my_process_stmt_result(stmt);
 | |
|   DIE_UNLESS(rc == 20);
 | |
|   mysql_stmt_close(stmt);
 | |
| 
 | |
|   rc= mysql_query(mysql, "DROP TABLE t1, t2");
 | |
|   myquery(rc);
 | |
| }
 | |
| 
 | |
| 
 | |
| static void test_bug3117()
 | |
| {
 | |
|   MYSQL_STMT *stmt;
 | |
|   MYSQL_BIND buffer;
 | |
|   longlong lii;
 | |
|   ulong length;
 | |
|   my_bool is_null;
 | |
|   int rc;
 | |
| 
 | |
|   myheader("test_bug3117");
 | |
| 
 | |
|   rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "CREATE TABLE t1 (id int auto_increment primary key)");
 | |
|   myquery(rc);
 | |
| 
 | |
|   stmt= mysql_simple_prepare(mysql, "SELECT LAST_INSERT_ID()");
 | |
|   check_stmt(stmt);
 | |
| 
 | |
|   rc= mysql_query(mysql, "INSERT INTO t1 VALUES (NULL)");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   bzero((char*) &buffer, sizeof(buffer));
 | |
|   buffer.buffer_type= MYSQL_TYPE_LONGLONG;
 | |
|   buffer.buffer_length= sizeof(lii);
 | |
|   buffer.buffer= (void *)&lii;
 | |
|   buffer.length= &length;
 | |
|   buffer.is_null= &is_null;
 | |
| 
 | |
|   rc= mysql_stmt_bind_result(stmt, &buffer);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= mysql_stmt_store_result(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= mysql_stmt_fetch(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   DIE_UNLESS(is_null == 0 && lii == 1);
 | |
|   if (!opt_silent)
 | |
|     fprintf(stdout, "\n\tLAST_INSERT_ID()= 1 ok\n");
 | |
| 
 | |
|   rc= mysql_query(mysql, "INSERT INTO t1 VALUES (NULL)");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= mysql_stmt_fetch(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   DIE_UNLESS(is_null == 0 && lii == 2);
 | |
|   if (!opt_silent)
 | |
|     fprintf(stdout, "\tLAST_INSERT_ID()= 2 ok\n");
 | |
| 
 | |
|   mysql_stmt_close(stmt);
 | |
| 
 | |
|   rc= mysql_query(mysql, "DROP TABLE t1");
 | |
|   myquery(rc);
 | |
| }
 | |
| 
 | |
| 
 | |
| static void test_join()
 | |
| {
 | |
|   MYSQL_STMT *stmt;
 | |
|   int rc, i, j;
 | |
|   const char *query[]= {"SELECT * FROM t2 join t1 on (t1.a=t2.a)",
 | |
|                         "SELECT * FROM t2 natural join t1",
 | |
|                         "SELECT * FROM t2 join t1 using(a)",
 | |
|                         "SELECT * FROM t2 left join t1 on(t1.a=t2.a)",
 | |
|                         "SELECT * FROM t2 natural left join t1",
 | |
|                         "SELECT * FROM t2 left join t1 using(a)",
 | |
|                         "SELECT * FROM t2 right join t1 on(t1.a=t2.a)",
 | |
|                         "SELECT * FROM t2 natural right join t1",
 | |
|                         "SELECT * FROM t2 right join t1 using(a)"};
 | |
| 
 | |
|   myheader("test_join");
 | |
| 
 | |
|   rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1, t2");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "CREATE TABLE t1 (a int , b int);");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql,
 | |
|                   "insert into t1 values (1, 1), (2, 2), (3, 3), (4, 4), (5, 5);");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "CREATE TABLE t2 (a int , c int);");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql,
 | |
|                   "insert into t2 values (1, 1), (2, 2), (3, 3), (4, 4), (5, 5);");
 | |
|   myquery(rc);
 | |
| 
 | |
|   for (j= 0; j < 9; j++)
 | |
|   {
 | |
|     stmt= mysql_simple_prepare(mysql, query[j]);
 | |
|     check_stmt(stmt);
 | |
|     for (i= 0; i < 3; i++)
 | |
|     {
 | |
|       rc= mysql_stmt_execute(stmt);
 | |
|       check_execute(stmt, rc);
 | |
|       rc= my_process_stmt_result(stmt);
 | |
|       DIE_UNLESS(rc == 5);
 | |
|     }
 | |
|     mysql_stmt_close(stmt);
 | |
|   }
 | |
| 
 | |
|   rc= mysql_query(mysql, "DROP TABLE t1, t2");
 | |
|   myquery(rc);
 | |
| }
 | |
| 
 | |
| 
 | |
| static void test_selecttmp()
 | |
| {
 | |
|   MYSQL_STMT *stmt;
 | |
|   int rc, i;
 | |
|   const char *query= "select a, (select count(distinct t1.b) as sum from t1, t2 where t1.a=t2.a and t2.b > 0 and t1.a <= t3.b group by t1.a order by sum limit 1) from t3";
 | |
| 
 | |
|   myheader("test_select_tmp");
 | |
| 
 | |
|   rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1, t2, t3");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "CREATE TABLE t1 (a int , b int);");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "create table t2 (a int, b int);");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "create table t3 (a int, b int);");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql,
 | |
|                   "insert into t1 values (0, 100), (1, 2), (1, 3), (2, 2), (2, 7), \
 | |
| (2, -1), (3, 10);");
 | |
|   myquery(rc);
 | |
|   rc= mysql_query(mysql,
 | |
|                   "insert into t2 values (0, 0), (1, 1), (2, 1), (3, 1), (4, 1);");
 | |
|   myquery(rc);
 | |
|   rc= mysql_query(mysql,
 | |
|                   "insert into t3 values (3, 3), (2, 2), (1, 1);");
 | |
|   myquery(rc);
 | |
| 
 | |
|   stmt= mysql_simple_prepare(mysql, query);
 | |
|   check_stmt(stmt);
 | |
|   for (i= 0; i < 3; i++)
 | |
|   {
 | |
|     rc= mysql_stmt_execute(stmt);
 | |
|     check_execute(stmt, rc);
 | |
|     rc= my_process_stmt_result(stmt);
 | |
|     DIE_UNLESS(rc == 3);
 | |
|   }
 | |
|   mysql_stmt_close(stmt);
 | |
| 
 | |
|   rc= mysql_query(mysql, "DROP TABLE t1, t2, t3");
 | |
|   myquery(rc);
 | |
| }
 | |
| 
 | |
| 
 | |
| static void test_create_drop()
 | |
| {
 | |
|   MYSQL_STMT *stmt_create, *stmt_drop, *stmt_select, *stmt_create_select;
 | |
|   char *query;
 | |
|   int rc, i;
 | |
|   myheader("test_table_manipulation");
 | |
| 
 | |
|   rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1, t2");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "create table t2 (a int);");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "create table t1 (a int);");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "insert into t2 values (3), (2), (1);");
 | |
|   myquery(rc);
 | |
| 
 | |
|   query= (char*)"create table t1 (a int)";
 | |
|   stmt_create= mysql_simple_prepare(mysql, query);
 | |
|   check_stmt(stmt_create);
 | |
| 
 | |
|   query= (char*)"drop table t1";
 | |
|   stmt_drop= mysql_simple_prepare(mysql, query);
 | |
|   check_stmt(stmt_drop);
 | |
| 
 | |
|   query= (char*)"select a in (select a from t2) from t1";
 | |
|   stmt_select= mysql_simple_prepare(mysql, query);
 | |
|   check_stmt(stmt_select);
 | |
| 
 | |
|   rc= mysql_query(mysql, "DROP TABLE t1");
 | |
|   myquery(rc);
 | |
| 
 | |
|   query= (char*)"create table t1 select a from t2";
 | |
|   stmt_create_select= mysql_simple_prepare(mysql, query);
 | |
|   check_stmt(stmt_create_select);
 | |
| 
 | |
|   for (i= 0; i < 3; i++)
 | |
|   {
 | |
|     rc= mysql_stmt_execute(stmt_create);
 | |
|     check_execute(stmt_create, rc);
 | |
|     if (!opt_silent)
 | |
|       fprintf(stdout, "created %i\n", i);
 | |
| 
 | |
|     rc= mysql_stmt_execute(stmt_select);
 | |
|     check_execute(stmt_select, rc);
 | |
|     rc= my_process_stmt_result(stmt_select);
 | |
|     DIE_UNLESS(rc == 0);
 | |
| 
 | |
|     rc= mysql_stmt_execute(stmt_drop);
 | |
|     check_execute(stmt_drop, rc);
 | |
|     if (!opt_silent)
 | |
|       fprintf(stdout, "dropped %i\n", i);
 | |
| 
 | |
|     rc= mysql_stmt_execute(stmt_create_select);
 | |
|     check_execute(stmt_create, rc);
 | |
|     if (!opt_silent)
 | |
|       fprintf(stdout, "created select %i\n", i);
 | |
| 
 | |
|     rc= mysql_stmt_execute(stmt_select);
 | |
|     check_execute(stmt_select, rc);
 | |
|     rc= my_process_stmt_result(stmt_select);
 | |
|     DIE_UNLESS(rc == 3);
 | |
| 
 | |
|     rc= mysql_stmt_execute(stmt_drop);
 | |
|     check_execute(stmt_drop, rc);
 | |
|     if (!opt_silent)
 | |
|       fprintf(stdout, "dropped %i\n", i);
 | |
|   }
 | |
| 
 | |
|   mysql_stmt_close(stmt_create);
 | |
|   mysql_stmt_close(stmt_drop);
 | |
|   mysql_stmt_close(stmt_select);
 | |
|   mysql_stmt_close(stmt_create_select);
 | |
| 
 | |
|   rc= mysql_query(mysql, "DROP TABLE t2");
 | |
|   myquery(rc);
 | |
| }
 | |
| 
 | |
| 
 | |
| static void test_rename()
 | |
| {
 | |
|   MYSQL_STMT *stmt;
 | |
|   const char *query= "rename table t1 to t2, t3 to t4";
 | |
|   int rc;
 | |
|   myheader("test_table_rename");
 | |
| 
 | |
|   rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1, t2, t3, t4");
 | |
|   myquery(rc);
 | |
| 
 | |
|   stmt= mysql_simple_prepare(mysql, query);
 | |
|   check_stmt(stmt);
 | |
| 
 | |
|   rc= mysql_query(mysql, "create table t1 (a int)");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute_r(stmt, rc);
 | |
|   if (!opt_silent)
 | |
|     fprintf(stdout, "rename without t3\n");
 | |
| 
 | |
|   rc= mysql_query(mysql, "create table t3 (a int)");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
|   if (!opt_silent)
 | |
|     fprintf(stdout, "rename with t3\n");
 | |
| 
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute_r(stmt, rc);
 | |
|   if (!opt_silent)
 | |
|     fprintf(stdout, "rename renamed\n");
 | |
| 
 | |
|   rc= mysql_query(mysql, "rename table t2 to t1, t4 to t3");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
|   if (!opt_silent)
 | |
|     fprintf(stdout, "rename reverted\n");
 | |
| 
 | |
|   mysql_stmt_close(stmt);
 | |
| 
 | |
|   rc= mysql_query(mysql, "DROP TABLE t2, t4");
 | |
|   myquery(rc);
 | |
| }
 | |
| 
 | |
| 
 | |
| static void test_do_set()
 | |
| {
 | |
|   MYSQL_STMT *stmt_do, *stmt_set;
 | |
|   char *query;
 | |
|   int rc, i;
 | |
|   myheader("test_do_set");
 | |
| 
 | |
|   rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "create table t1 (a int)");
 | |
|   myquery(rc);
 | |
| 
 | |
|   query= (char*)"do @var:=(1 in (select * from t1))";
 | |
|   stmt_do= mysql_simple_prepare(mysql, query);
 | |
|   check_stmt(stmt_do);
 | |
| 
 | |
|   query= (char*)"set @var=(1 in (select * from t1))";
 | |
|   stmt_set= mysql_simple_prepare(mysql, query);
 | |
|   check_stmt(stmt_set);
 | |
| 
 | |
|   for (i= 0; i < 3; i++)
 | |
|   {
 | |
|     rc= mysql_stmt_execute(stmt_do);
 | |
|     check_execute(stmt_do, rc);
 | |
|     if (!opt_silent)
 | |
|       fprintf(stdout, "do %i\n", i);
 | |
|     rc= mysql_stmt_execute(stmt_set);
 | |
|     check_execute(stmt_set, rc);
 | |
|     if (!opt_silent)
 | |
|       fprintf(stdout, "set %i\n", i);
 | |
|   }
 | |
| 
 | |
|   mysql_stmt_close(stmt_do);
 | |
|   mysql_stmt_close(stmt_set);
 | |
| }
 | |
| 
 | |
| 
 | |
| static void test_multi()
 | |
| {
 | |
|   MYSQL_STMT *stmt_delete, *stmt_update, *stmt_select1, *stmt_select2;
 | |
|   char *query;
 | |
|   MYSQL_BIND my_bind[1];
 | |
|   int rc, i;
 | |
|   int32 param= 1;
 | |
|   ulong length= 1;
 | |
|   myheader("test_multi");
 | |
| 
 | |
|   /*
 | |
|     We need to bzero bind structure because mysql_stmt_bind_param checks all
 | |
|     its members.
 | |
|   */
 | |
|   bzero((char*) my_bind, sizeof(my_bind));
 | |
| 
 | |
|   my_bind[0].buffer_type= MYSQL_TYPE_LONG;
 | |
|   my_bind[0].buffer= (void *)¶m;
 | |
|   my_bind[0].length= &length;
 | |
| 
 | |
|   rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1, t2");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "create table t1 (a int, b int)");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "create table t2 (a int, b int)");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "insert into t1 values (3, 3), (2, 2), (1, 1)");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "insert into t2 values (3, 3), (2, 2), (1, 1)");
 | |
|   myquery(rc);
 | |
| 
 | |
|   query= (char*)"delete t1, t2 from t1, t2 where t1.a=t2.a and t1.b=10";
 | |
|   stmt_delete= mysql_simple_prepare(mysql, query);
 | |
|   check_stmt(stmt_delete);
 | |
| 
 | |
|   query= (char*)"update t1, t2 set t1.b=10, t2.b=10 where t1.a=t2.a and t1.b=?";
 | |
|   stmt_update= mysql_simple_prepare(mysql, query);
 | |
|   check_stmt(stmt_update);
 | |
| 
 | |
|   query= (char*)"select * from t1";
 | |
|   stmt_select1= mysql_simple_prepare(mysql, query);
 | |
|   check_stmt(stmt_select1);
 | |
| 
 | |
|   query= (char*)"select * from t2";
 | |
|   stmt_select2= mysql_simple_prepare(mysql, query);
 | |
|   check_stmt(stmt_select2);
 | |
| 
 | |
|   for(i= 0; i < 3; i++)
 | |
|   {
 | |
|     rc= mysql_stmt_bind_param(stmt_update, my_bind);
 | |
|     check_execute(stmt_update, rc);
 | |
| 
 | |
|     rc= mysql_stmt_execute(stmt_update);
 | |
|     check_execute(stmt_update, rc);
 | |
|     if (!opt_silent)
 | |
|       fprintf(stdout, "update %ld\n", (long) param);
 | |
| 
 | |
|     rc= mysql_stmt_execute(stmt_delete);
 | |
|     check_execute(stmt_delete, rc);
 | |
|     if (!opt_silent)
 | |
|       fprintf(stdout, "delete %ld\n", (long) param);
 | |
| 
 | |
|     rc= mysql_stmt_execute(stmt_select1);
 | |
|     check_execute(stmt_select1, rc);
 | |
|     rc= my_process_stmt_result(stmt_select1);
 | |
|     DIE_UNLESS(rc == 3-param);
 | |
| 
 | |
|     rc= mysql_stmt_execute(stmt_select2);
 | |
|     check_execute(stmt_select2, rc);
 | |
|     rc= my_process_stmt_result(stmt_select2);
 | |
|     DIE_UNLESS(rc == 3-param);
 | |
| 
 | |
|     param++;
 | |
|   }
 | |
| 
 | |
|   mysql_stmt_close(stmt_delete);
 | |
|   mysql_stmt_close(stmt_update);
 | |
|   mysql_stmt_close(stmt_select1);
 | |
|   mysql_stmt_close(stmt_select2);
 | |
|   rc= mysql_query(mysql, "drop table t1, t2");
 | |
|   myquery(rc);
 | |
| }
 | |
| 
 | |
| 
 | |
| static void test_insert_select()
 | |
| {
 | |
|   MYSQL_STMT *stmt_insert, *stmt_select;
 | |
|   char *query;
 | |
|   int rc;
 | |
|   uint i;
 | |
|   myheader("test_insert_select");
 | |
| 
 | |
|   rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1, t2");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "create table t1 (a int)");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "create table t2 (a int)");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "insert into t2 values (1)");
 | |
|   myquery(rc);
 | |
| 
 | |
|   query= (char*)"insert into t1 select a from t2";
 | |
|   stmt_insert= mysql_simple_prepare(mysql, query);
 | |
|   check_stmt(stmt_insert);
 | |
| 
 | |
|   query= (char*)"select * from t1";
 | |
|   stmt_select= mysql_simple_prepare(mysql, query);
 | |
|   check_stmt(stmt_select);
 | |
| 
 | |
|   for(i= 0; i < 3; i++)
 | |
|   {
 | |
|     rc= mysql_stmt_execute(stmt_insert);
 | |
|     check_execute(stmt_insert, rc);
 | |
|     if (!opt_silent)
 | |
|       fprintf(stdout, "insert %u\n", i);
 | |
| 
 | |
|     rc= mysql_stmt_execute(stmt_select);
 | |
|     check_execute(stmt_select, rc);
 | |
|     rc= my_process_stmt_result(stmt_select);
 | |
|     DIE_UNLESS(rc == (int)(i+1));
 | |
|   }
 | |
| 
 | |
|   mysql_stmt_close(stmt_insert);
 | |
|   mysql_stmt_close(stmt_select);
 | |
|   rc= mysql_query(mysql, "drop table t1, t2");
 | |
|   myquery(rc);
 | |
| }
 | |
| 
 | |
| 
 | |
| static void test_bind_nagative()
 | |
| {
 | |
|   MYSQL_STMT *stmt_insert;
 | |
|   char *query;
 | |
|   int rc;
 | |
|   MYSQL_BIND      my_bind[1];
 | |
|   int32           my_val= 0;
 | |
|   ulong           my_length= 0L;
 | |
|   my_bool         my_null= FALSE;
 | |
|   myheader("test_insert_select");
 | |
| 
 | |
|   rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "create temporary table t1 (c1 int unsigned)");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "INSERT INTO t1 VALUES (1), (-1)");
 | |
|   myquery(rc);
 | |
| 
 | |
|   query= (char*)"INSERT INTO t1 VALUES (?)";
 | |
|   stmt_insert= mysql_simple_prepare(mysql, query);
 | |
|   check_stmt(stmt_insert);
 | |
| 
 | |
|   /* bind parameters */
 | |
|   bzero((char*) my_bind, sizeof(my_bind));
 | |
| 
 | |
|   my_bind[0].buffer_type= MYSQL_TYPE_LONG;
 | |
|   my_bind[0].buffer= (void *)&my_val;
 | |
|   my_bind[0].length= &my_length;
 | |
|   my_bind[0].is_null= (char*)&my_null;
 | |
| 
 | |
|   rc= mysql_stmt_bind_param(stmt_insert, my_bind);
 | |
|   check_execute(stmt_insert, rc);
 | |
| 
 | |
|   my_val= -1;
 | |
|   rc= mysql_stmt_execute(stmt_insert);
 | |
|   check_execute(stmt_insert, rc);
 | |
| 
 | |
|   mysql_stmt_close(stmt_insert);
 | |
|   rc= mysql_query(mysql, "drop table t1");
 | |
|   myquery(rc);
 | |
| }
 | |
| 
 | |
| 
 | |
| static void test_derived()
 | |
| {
 | |
|   MYSQL_STMT *stmt;
 | |
|   int rc, i;
 | |
|   MYSQL_BIND      my_bind[1];
 | |
|   int32           my_val= 0;
 | |
|   ulong           my_length= 0L;
 | |
|   my_bool         my_null= FALSE;
 | |
|   const char *query=
 | |
|     "select count(1) from (select f.id from t1 f where f.id=?) as x";
 | |
| 
 | |
|   myheader("test_derived");
 | |
| 
 | |
|   rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "create table t1 (id  int(8), primary key (id)) \
 | |
| ENGINE=InnoDB DEFAULT CHARSET=utf8");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "insert into t1 values (1)");
 | |
|   myquery(rc);
 | |
| 
 | |
|   stmt= mysql_simple_prepare(mysql, query);
 | |
|   check_stmt(stmt);
 | |
|   /*
 | |
|     We need to bzero bind structure because mysql_stmt_bind_param checks all
 | |
|     its members.
 | |
|   */
 | |
|   bzero((char*) my_bind, sizeof(my_bind));
 | |
| 
 | |
|   my_bind[0].buffer_type= MYSQL_TYPE_LONG;
 | |
|   my_bind[0].buffer= (void *)&my_val;
 | |
|   my_bind[0].length= &my_length;
 | |
|   my_bind[0].is_null= (char*)&my_null;
 | |
|   my_val= 1;
 | |
|   rc= mysql_stmt_bind_param(stmt, my_bind);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   for (i= 0; i < 3; i++)
 | |
|   {
 | |
|     rc= mysql_stmt_execute(stmt);
 | |
|     check_execute(stmt, rc);
 | |
|     rc= my_process_stmt_result(stmt);
 | |
|     DIE_UNLESS(rc == 1);
 | |
|   }
 | |
|   mysql_stmt_close(stmt);
 | |
| 
 | |
|   rc= mysql_query(mysql, "DROP TABLE t1");
 | |
|   myquery(rc);
 | |
| }
 | |
| 
 | |
| 
 | |
| static void test_xjoin()
 | |
| {
 | |
|   MYSQL_STMT *stmt;
 | |
|   int rc, i;
 | |
|   const char *query=
 | |
|     "select t.id, p1.value, n1.value, p2.value, n2.value from t3 t LEFT JOIN t1 p1 ON (p1.id=t.param1_id) LEFT JOIN t2 p2 ON (p2.id=t.param2_id) LEFT JOIN t4 n1 ON (n1.id=p1.name_id) LEFT JOIN t4 n2 ON (n2.id=p2.name_id) where t.id=1";
 | |
| 
 | |
|   myheader("test_xjoin");
 | |
| 
 | |
|   rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1, t2, t3, t4");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "create table t3 (id int(8), param1_id int(8), param2_id int(8)) ENGINE=InnoDB DEFAULT CHARSET=utf8");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "create table t1 ( id int(8), name_id int(8), value varchar(10)) ENGINE=InnoDB DEFAULT CHARSET=utf8");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "create table t2 (id int(8), name_id int(8), value varchar(10)) ENGINE=InnoDB DEFAULT CHARSET=utf8;");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "create table t4(id int(8), value varchar(10)) ENGINE=InnoDB DEFAULT CHARSET=utf8");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "insert into t3 values (1, 1, 1), (2, 2, null)");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "insert into t1 values (1, 1, 'aaa'), (2, null, 'bbb')");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "insert into t2 values (1, 2, 'ccc')");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "insert into t4 values (1, 'Name1'), (2, null)");
 | |
|   myquery(rc);
 | |
| 
 | |
|   stmt= mysql_simple_prepare(mysql, query);
 | |
|   check_stmt(stmt);
 | |
| 
 | |
|   for (i= 0; i < 3; i++)
 | |
|   {
 | |
|     rc= mysql_stmt_execute(stmt);
 | |
|     check_execute(stmt, rc);
 | |
|     rc= my_process_stmt_result(stmt);
 | |
|     DIE_UNLESS(rc == 1);
 | |
|   }
 | |
|   mysql_stmt_close(stmt);
 | |
| 
 | |
|   rc= mysql_query(mysql, "DROP TABLE t1, t2, t3, t4");
 | |
|   myquery(rc);
 | |
| }
 | |
| 
 | |
| 
 | |
| static void test_bug3035()
 | |
| {
 | |
|   MYSQL_STMT *stmt;
 | |
|   int rc;
 | |
|   MYSQL_BIND bind_array[12], *my_bind= bind_array, *bind_end= my_bind + 12;
 | |
|   int8 int8_val;
 | |
|   uint8 uint8_val;
 | |
|   int16 int16_val;
 | |
|   uint16 uint16_val;
 | |
|   int32 int32_val;
 | |
|   uint32 uint32_val;
 | |
|   longlong int64_val;
 | |
|   ulonglong uint64_val;
 | |
|   double double_val, udouble_val, double_tmp;
 | |
|   char longlong_as_string[22], ulonglong_as_string[22];
 | |
| 
 | |
|   /* mins and maxes */
 | |
|   const int8 int8_min= -128;
 | |
|   const int8 int8_max= 127;
 | |
|   const uint8 uint8_min= 0;
 | |
|   const uint8 uint8_max= 255;
 | |
| 
 | |
|   const int16 int16_min= -32768;
 | |
|   const int16 int16_max= 32767;
 | |
|   const uint16 uint16_min= 0;
 | |
|   const uint16 uint16_max= 65535;
 | |
| 
 | |
|   const int32 int32_max= 2147483647L;
 | |
|   const int32 int32_min= -int32_max - 1;
 | |
|   const uint32 uint32_min= 0;
 | |
|   const uint32 uint32_max= 4294967295U;
 | |
| 
 | |
|   /* it might not work okay everyplace */
 | |
|   const longlong int64_max= 9223372036854775807LL;
 | |
|   const longlong int64_min= -int64_max - 1;
 | |
| 
 | |
|   const ulonglong uint64_min= 0U;
 | |
|   const ulonglong uint64_max= 18446744073709551615ULL;
 | |
| 
 | |
|   const char *stmt_text;
 | |
| 
 | |
|   myheader("test_bug3035");
 | |
| 
 | |
|   stmt_text= "DROP TABLE IF EXISTS t1";
 | |
|   rc= mysql_real_query(mysql, stmt_text, strlen(stmt_text));
 | |
|   myquery(rc);
 | |
| 
 | |
|   stmt_text= "CREATE TABLE t1 (i8 TINYINT, ui8 TINYINT UNSIGNED, "
 | |
|                               "i16 SMALLINT, ui16 SMALLINT UNSIGNED, "
 | |
|                               "i32 INT, ui32 INT UNSIGNED, "
 | |
|                               "i64 BIGINT, ui64 BIGINT UNSIGNED, "
 | |
|                               "id INTEGER NOT NULL PRIMARY KEY AUTO_INCREMENT)";
 | |
|   rc= mysql_real_query(mysql, stmt_text, strlen(stmt_text));
 | |
|   myquery(rc);
 | |
| 
 | |
|   bzero((char*) bind_array, sizeof(bind_array));
 | |
| 
 | |
|   for (my_bind= bind_array; my_bind < bind_end; my_bind++)
 | |
|     my_bind->error= &my_bind->error_value;
 | |
| 
 | |
|   bind_array[0].buffer_type= MYSQL_TYPE_TINY;
 | |
|   bind_array[0].buffer= (void *) &int8_val;
 | |
| 
 | |
|   bind_array[1].buffer_type= MYSQL_TYPE_TINY;
 | |
|   bind_array[1].buffer= (void *) &uint8_val;
 | |
|   bind_array[1].is_unsigned= 1;
 | |
| 
 | |
|   bind_array[2].buffer_type= MYSQL_TYPE_SHORT;
 | |
|   bind_array[2].buffer= (void *) &int16_val;
 | |
| 
 | |
|   bind_array[3].buffer_type= MYSQL_TYPE_SHORT;
 | |
|   bind_array[3].buffer= (void *) &uint16_val;
 | |
|   bind_array[3].is_unsigned= 1;
 | |
| 
 | |
|   bind_array[4].buffer_type= MYSQL_TYPE_LONG;
 | |
|   bind_array[4].buffer= (void *) &int32_val;
 | |
| 
 | |
|   bind_array[5].buffer_type= MYSQL_TYPE_LONG;
 | |
|   bind_array[5].buffer= (void *) &uint32_val;
 | |
|   bind_array[5].is_unsigned= 1;
 | |
| 
 | |
|   bind_array[6].buffer_type= MYSQL_TYPE_LONGLONG;
 | |
|   bind_array[6].buffer= (void *) &int64_val;
 | |
| 
 | |
|   bind_array[7].buffer_type= MYSQL_TYPE_LONGLONG;
 | |
|   bind_array[7].buffer= (void *) &uint64_val;
 | |
|   bind_array[7].is_unsigned= 1;
 | |
| 
 | |
|   stmt= mysql_stmt_init(mysql);
 | |
|   check_stmt(stmt);
 | |
| 
 | |
|   stmt_text= "INSERT INTO t1 (i8, ui8, i16, ui16, i32, ui32, i64, ui64) "
 | |
|                      "VALUES (?, ?, ?, ?, ?, ?, ?, ?)";
 | |
|   rc= mysql_stmt_prepare(stmt, stmt_text, strlen(stmt_text));
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   mysql_stmt_bind_param(stmt, bind_array);
 | |
| 
 | |
|   int8_val= int8_min;
 | |
|   uint8_val= uint8_min;
 | |
|   int16_val= int16_min;
 | |
|   uint16_val= uint16_min;
 | |
|   int32_val= int32_min;
 | |
|   uint32_val= uint32_min;
 | |
|   int64_val= int64_min;
 | |
|   uint64_val= uint64_min;
 | |
| 
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   int8_val= int8_max;
 | |
|   uint8_val= uint8_max;
 | |
|   int16_val= int16_max;
 | |
|   uint16_val= uint16_max;
 | |
|   int32_val= int32_max;
 | |
|   uint32_val= uint32_max;
 | |
|   int64_val= int64_max;
 | |
|   uint64_val= uint64_max;
 | |
| 
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   stmt_text= "SELECT i8, ui8, i16, ui16, i32, ui32, i64, ui64, ui64, "
 | |
|              "cast(ui64 as signed), ui64, cast(ui64 as signed)"
 | |
|              "FROM t1 ORDER BY id ASC";
 | |
| 
 | |
|   rc= mysql_stmt_prepare(stmt, stmt_text, strlen(stmt_text));
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   bind_array[8].buffer_type= MYSQL_TYPE_DOUBLE;
 | |
|   bind_array[8].buffer= (void *) &udouble_val;
 | |
| 
 | |
|   bind_array[9].buffer_type= MYSQL_TYPE_DOUBLE;
 | |
|   bind_array[9].buffer= (void *) &double_val;
 | |
| 
 | |
|   bind_array[10].buffer_type= MYSQL_TYPE_STRING;
 | |
|   bind_array[10].buffer= (void *) &ulonglong_as_string;
 | |
|   bind_array[10].buffer_length= sizeof(ulonglong_as_string);
 | |
| 
 | |
|   bind_array[11].buffer_type= MYSQL_TYPE_STRING;
 | |
|   bind_array[11].buffer= (void *) &longlong_as_string;
 | |
|   bind_array[11].buffer_length= sizeof(longlong_as_string);
 | |
| 
 | |
|   mysql_stmt_bind_result(stmt, bind_array);
 | |
| 
 | |
|   rc= mysql_stmt_fetch(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   DIE_UNLESS(int8_val == int8_min);
 | |
|   DIE_UNLESS(uint8_val == uint8_min);
 | |
|   DIE_UNLESS(int16_val == int16_min);
 | |
|   DIE_UNLESS(uint16_val == uint16_min);
 | |
|   DIE_UNLESS(int32_val == int32_min);
 | |
|   DIE_UNLESS(uint32_val == uint32_min);
 | |
|   DIE_UNLESS(int64_val == int64_min);
 | |
|   DIE_UNLESS(uint64_val == uint64_min);
 | |
|   DIE_UNLESS(double_val == (longlong) uint64_min);
 | |
|   double_tmp= ulonglong2double(uint64_val);
 | |
|   DIE_UNLESS(cmp_double(&udouble_val, &double_tmp));
 | |
|   DIE_UNLESS(!strcmp(longlong_as_string, "0"));
 | |
|   DIE_UNLESS(!strcmp(ulonglong_as_string, "0"));
 | |
| 
 | |
|   rc= mysql_stmt_fetch(stmt);
 | |
| 
 | |
|   if (!opt_silent)
 | |
|   {
 | |
|     printf("Truncation mask: ");
 | |
|     for (my_bind= bind_array; my_bind < bind_end; my_bind++)
 | |
|       printf("%d", (int) my_bind->error_value);
 | |
|     printf("\n");
 | |
|   }
 | |
|   DIE_UNLESS(rc == MYSQL_DATA_TRUNCATED || rc == 0);
 | |
| 
 | |
|   DIE_UNLESS(int8_val == int8_max);
 | |
|   DIE_UNLESS(uint8_val == uint8_max);
 | |
|   DIE_UNLESS(int16_val == int16_max);
 | |
|   DIE_UNLESS(uint16_val == uint16_max);
 | |
|   DIE_UNLESS(int32_val == int32_max);
 | |
|   DIE_UNLESS(uint32_val == uint32_max);
 | |
|   DIE_UNLESS(int64_val == int64_max);
 | |
|   DIE_UNLESS(uint64_val == uint64_max);
 | |
|   DIE_UNLESS(double_val == (longlong) uint64_val);
 | |
|   double_tmp= ulonglong2double(uint64_val);
 | |
|   DIE_UNLESS(cmp_double(&udouble_val, &double_tmp));
 | |
|   DIE_UNLESS(!strcmp(longlong_as_string, "-1"));
 | |
|   DIE_UNLESS(!strcmp(ulonglong_as_string, "18446744073709551615"));
 | |
| 
 | |
|   rc= mysql_stmt_fetch(stmt);
 | |
|   DIE_UNLESS(rc == MYSQL_NO_DATA);
 | |
| 
 | |
|   mysql_stmt_close(stmt);
 | |
| 
 | |
|   stmt_text= "DROP TABLE t1";
 | |
|   mysql_real_query(mysql, stmt_text, strlen(stmt_text));
 | |
| }
 | |
| 
 | |
| 
 | |
| static void test_union2()
 | |
| {
 | |
|   MYSQL_STMT *stmt;
 | |
|   int rc, i;
 | |
| 
 | |
|   myheader("test_union2");
 | |
| 
 | |
|   rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "CREATE TABLE t1(col1 INT, \
 | |
|                                          col2 VARCHAR(40),      \
 | |
|                                          col3 SMALLINT, \
 | |
|                                          col4 TIMESTAMP)");
 | |
|   myquery(rc);
 | |
| 
 | |
|   stmt= mysql_simple_prepare(mysql,
 | |
|                              "select col1 FROM t1 where col1=1 union distinct "
 | |
|                              "select col1 FROM t1 where col1=2");
 | |
|   check_stmt(stmt);
 | |
| 
 | |
|   for (i= 0; i < 3; i++)
 | |
|   {
 | |
|     rc= mysql_stmt_execute(stmt);
 | |
|     check_execute(stmt, rc);
 | |
|     rc= my_process_stmt_result(stmt);
 | |
|     DIE_UNLESS(rc == 0);
 | |
|   }
 | |
| 
 | |
|   mysql_stmt_close(stmt);
 | |
| 
 | |
|   rc= mysql_query(mysql, "DROP TABLE t1");
 | |
|   myquery(rc);
 | |
| }
 | |
| 
 | |
| 
 | |
| /*
 | |
|   This tests for various mysql_stmt_send_long_data bugs described in #1664
 | |
| */
 | |
| 
 | |
| static void test_bug1664()
 | |
| {
 | |
|     MYSQL_STMT *stmt;
 | |
|     int        rc, int_data;
 | |
|     const char *data;
 | |
|     const char *str_data= "Simple string";
 | |
|     MYSQL_BIND my_bind[2];
 | |
|     const char *query= "INSERT INTO test_long_data(col2, col1) VALUES(?, ?)";
 | |
| 
 | |
|     myheader("test_bug1664");
 | |
| 
 | |
|     rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_long_data");
 | |
|     myquery(rc);
 | |
| 
 | |
|     rc= mysql_query(mysql, "CREATE TABLE test_long_data(col1 int, col2 long varchar)");
 | |
|     myquery(rc);
 | |
| 
 | |
|     stmt= mysql_stmt_init(mysql);
 | |
|     check_stmt(stmt);
 | |
|     rc= mysql_stmt_prepare(stmt, query, strlen(query));
 | |
|     check_execute(stmt, rc);
 | |
| 
 | |
|     verify_param_count(stmt, 2);
 | |
| 
 | |
|     bzero((char*) my_bind, sizeof(my_bind));
 | |
| 
 | |
|     my_bind[0].buffer_type= MYSQL_TYPE_STRING;
 | |
|     my_bind[0].buffer= (void *)str_data;
 | |
|     my_bind[0].buffer_length= strlen(str_data);
 | |
| 
 | |
|     my_bind[1].buffer= (void *)&int_data;
 | |
|     my_bind[1].buffer_type= MYSQL_TYPE_LONG;
 | |
| 
 | |
|     rc= mysql_stmt_bind_param(stmt, my_bind);
 | |
|     check_execute(stmt, rc);
 | |
| 
 | |
|     int_data= 1;
 | |
| 
 | |
|     /*
 | |
|       Let us supply empty long_data. This should work and should
 | |
|       not break following execution.
 | |
|     */
 | |
|     data= "";
 | |
|     rc= mysql_stmt_send_long_data(stmt, 0, data, strlen(data));
 | |
|     check_execute(stmt, rc);
 | |
| 
 | |
|     rc= mysql_stmt_execute(stmt);
 | |
|     check_execute(stmt, rc);
 | |
| 
 | |
|     verify_col_data("test_long_data", "col1", "1");
 | |
|     verify_col_data("test_long_data", "col2", "");
 | |
| 
 | |
|     rc= mysql_query(mysql, "DELETE FROM test_long_data");
 | |
|     myquery(rc);
 | |
| 
 | |
|     /* This should pass OK */
 | |
|     data= (char *)"Data";
 | |
|     rc= mysql_stmt_send_long_data(stmt, 0, data, strlen(data));
 | |
|     check_execute(stmt, rc);
 | |
| 
 | |
|     rc= mysql_stmt_execute(stmt);
 | |
|     check_execute(stmt, rc);
 | |
| 
 | |
|     verify_col_data("test_long_data", "col1", "1");
 | |
|     verify_col_data("test_long_data", "col2", "Data");
 | |
| 
 | |
|     /* clean up */
 | |
|     rc= mysql_query(mysql, "DELETE FROM test_long_data");
 | |
|     myquery(rc);
 | |
| 
 | |
|     /*
 | |
|       Now we are changing int parameter and don't do anything
 | |
|       with first parameter. Second mysql_stmt_execute() should run
 | |
|       OK treating this first parameter as string parameter.
 | |
|     */
 | |
| 
 | |
|     int_data= 2;
 | |
|     /* execute */
 | |
|     rc= mysql_stmt_execute(stmt);
 | |
|     check_execute(stmt, rc);
 | |
| 
 | |
|     verify_col_data("test_long_data", "col1", "2");
 | |
|     verify_col_data("test_long_data", "col2", str_data);
 | |
| 
 | |
|     /* clean up */
 | |
|     rc= mysql_query(mysql, "DELETE FROM test_long_data");
 | |
|     myquery(rc);
 | |
| 
 | |
|     /*
 | |
|       Now we are sending other long data. It should not be
 | |
|       concatened to previous.
 | |
|     */
 | |
| 
 | |
|     data= (char *)"SomeOtherData";
 | |
|     rc= mysql_stmt_send_long_data(stmt, 0, data, strlen(data));
 | |
|     check_execute(stmt, rc);
 | |
| 
 | |
|     rc= mysql_stmt_execute(stmt);
 | |
|     check_execute(stmt, rc);
 | |
| 
 | |
|     verify_col_data("test_long_data", "col1", "2");
 | |
|     verify_col_data("test_long_data", "col2", "SomeOtherData");
 | |
| 
 | |
|     mysql_stmt_close(stmt);
 | |
| 
 | |
|     /* clean up */
 | |
|     rc= mysql_query(mysql, "DELETE FROM test_long_data");
 | |
|     myquery(rc);
 | |
| 
 | |
|     /* Now let us test how mysql_stmt_reset works. */
 | |
|     stmt= mysql_stmt_init(mysql);
 | |
|     check_stmt(stmt);
 | |
|     rc= mysql_stmt_prepare(stmt, query, strlen(query));
 | |
|     check_execute(stmt, rc);
 | |
|     rc= mysql_stmt_bind_param(stmt, my_bind);
 | |
|     check_execute(stmt, rc);
 | |
| 
 | |
|     data= (char *)"SomeData";
 | |
|     rc= mysql_stmt_send_long_data(stmt, 0, data, strlen(data));
 | |
|     check_execute(stmt, rc);
 | |
| 
 | |
|     rc= mysql_stmt_reset(stmt);
 | |
|     check_execute(stmt, rc);
 | |
| 
 | |
|     rc= mysql_stmt_execute(stmt);
 | |
|     check_execute(stmt, rc);
 | |
| 
 | |
|     verify_col_data("test_long_data", "col1", "2");
 | |
|     verify_col_data("test_long_data", "col2", str_data);
 | |
| 
 | |
|     mysql_stmt_close(stmt);
 | |
| 
 | |
|     /* Final clean up */
 | |
|     rc= mysql_query(mysql, "DROP TABLE test_long_data");
 | |
|     myquery(rc);
 | |
| }
 | |
| 
 | |
| 
 | |
| static void test_order_param()
 | |
| {
 | |
|   MYSQL_STMT *stmt;
 | |
|   int rc;
 | |
| 
 | |
|   myheader("test_order_param");
 | |
| 
 | |
|   rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "CREATE TABLE t1(a INT, b char(10))");
 | |
|   myquery(rc);
 | |
| 
 | |
|   stmt= mysql_simple_prepare(mysql,
 | |
|                              "select sum(a) + 200, 1 from t1 "
 | |
|                              " union distinct "
 | |
|                              "select sum(a) + 200, 1 from t1 group by b ");
 | |
|   check_stmt(stmt);
 | |
|   mysql_stmt_close(stmt);
 | |
| 
 | |
|   stmt= mysql_simple_prepare(mysql,
 | |
|                              "select sum(a) + 200, ? from t1 group by b "
 | |
|                              " union distinct "
 | |
|                              "select sum(a) + 200, 1 from t1 group by b ");
 | |
|   check_stmt(stmt);
 | |
|   mysql_stmt_close(stmt);
 | |
| 
 | |
|   stmt= mysql_simple_prepare(mysql,
 | |
|                              "select sum(a) + 200, ? from t1 "
 | |
|                              " union distinct "
 | |
|                              "select sum(a) + 200, 1 from t1 group by b ");
 | |
|   check_stmt(stmt);
 | |
|   mysql_stmt_close(stmt);
 | |
| 
 | |
|   rc= mysql_query(mysql, "DROP TABLE t1");
 | |
|   myquery(rc);
 | |
| }
 | |
| 
 | |
| 
 | |
| static void test_union_param()
 | |
| {
 | |
|   MYSQL_STMT *stmt;
 | |
|   char *query;
 | |
|   int rc, i;
 | |
|   MYSQL_BIND      my_bind[2];
 | |
|   char            my_val[4];
 | |
|   ulong           my_length= 3L;
 | |
|   my_bool         my_null= FALSE;
 | |
|   myheader("test_union_param");
 | |
| 
 | |
|   strmov(my_val, "abc");
 | |
| 
 | |
|   query= (char*)"select ? as my_col union distinct select ?";
 | |
|   stmt= mysql_simple_prepare(mysql, query);
 | |
|   check_stmt(stmt);
 | |
| 
 | |
|   /*
 | |
|     We need to bzero bind structure because mysql_stmt_bind_param checks all
 | |
|     its members.
 | |
|   */
 | |
|   bzero((char*) my_bind, sizeof(my_bind));
 | |
| 
 | |
|   /* bind parameters */
 | |
|   my_bind[0].buffer_type=    MYSQL_TYPE_STRING;
 | |
|   my_bind[0].buffer=         (char*) &my_val;
 | |
|   my_bind[0].buffer_length=  4;
 | |
|   my_bind[0].length=         &my_length;
 | |
|   my_bind[0].is_null=        (char*)&my_null;
 | |
|   my_bind[1].buffer_type=    MYSQL_TYPE_STRING;
 | |
|   my_bind[1].buffer=         (char*) &my_val;
 | |
|   my_bind[1].buffer_length=  4;
 | |
|   my_bind[1].length=         &my_length;
 | |
|   my_bind[1].is_null=        (char*)&my_null;
 | |
| 
 | |
|   rc= mysql_stmt_bind_param(stmt, my_bind);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   for (i= 0; i < 3; i++)
 | |
|   {
 | |
|     rc= mysql_stmt_execute(stmt);
 | |
|     check_execute(stmt, rc);
 | |
|     rc= my_process_stmt_result(stmt);
 | |
|     DIE_UNLESS(rc == 1);
 | |
|   }
 | |
| 
 | |
|   mysql_stmt_close(stmt);
 | |
| }
 | |
| 
 | |
| 
 | |
| static void test_ps_i18n()
 | |
| {
 | |
|   MYSQL_STMT *stmt;
 | |
|   int rc;
 | |
|   const char *stmt_text;
 | |
|   MYSQL_BIND bind_array[2];
 | |
| 
 | |
|   /* Represented as numbers to keep UTF8 tools from clobbering them. */
 | |
|   const char *koi8= "\xee\xd5\x2c\x20\xda\xc1\x20\xd2\xd9\xc2\xc1\xcc\xcb\xd5";
 | |
|   const char *cp1251= "\xcd\xf3\x2c\x20\xe7\xe0\x20\xf0\xfb\xe1\xe0\xeb\xea\xf3";
 | |
|   char buf1[16], buf2[16];
 | |
|   ulong buf1_len, buf2_len;
 | |
| 
 | |
| 
 | |
|   myheader("test_ps_i18n");
 | |
| 
 | |
|   stmt_text= "DROP TABLE IF EXISTS t1";
 | |
|   rc= mysql_real_query(mysql, stmt_text, strlen(stmt_text));
 | |
|   myquery(rc);
 | |
| 
 | |
|   /*
 | |
|     Create table with binary columns, set session character set to cp1251,
 | |
|     client character set to koi8, and make sure that there is conversion
 | |
|     on insert and no conversion on select
 | |
|   */
 | |
| 
 | |
|   stmt_text= "CREATE TABLE t1 (c1 VARBINARY(255), c2 VARBINARY(255))";
 | |
| 
 | |
|   rc= mysql_real_query(mysql, stmt_text, strlen(stmt_text));
 | |
|   myquery(rc);
 | |
| 
 | |
|   stmt_text= "SET CHARACTER_SET_CLIENT=koi8r, "
 | |
|                  "CHARACTER_SET_CONNECTION=cp1251, "
 | |
|                  "CHARACTER_SET_RESULTS=koi8r";
 | |
| 
 | |
|   rc= mysql_real_query(mysql, stmt_text, strlen(stmt_text));
 | |
|   myquery(rc);
 | |
| 
 | |
|   bzero((char*) bind_array, sizeof(bind_array));
 | |
| 
 | |
|   bind_array[0].buffer_type= MYSQL_TYPE_STRING;
 | |
|   bind_array[0].buffer= (void *) koi8;
 | |
|   bind_array[0].buffer_length= strlen(koi8);
 | |
| 
 | |
|   bind_array[1].buffer_type= MYSQL_TYPE_STRING;
 | |
|   bind_array[1].buffer= (void *) koi8;
 | |
|   bind_array[1].buffer_length= strlen(koi8);
 | |
| 
 | |
|   stmt= mysql_stmt_init(mysql);
 | |
|   check_stmt(stmt);
 | |
| 
 | |
|   stmt_text= "INSERT INTO t1 (c1, c2) VALUES (?, ?)";
 | |
| 
 | |
|   rc= mysql_stmt_prepare(stmt, stmt_text, strlen(stmt_text));
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   mysql_stmt_bind_param(stmt, bind_array);
 | |
| 
 | |
|   mysql_stmt_send_long_data(stmt, 0, koi8, strlen(koi8));
 | |
| 
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   stmt_text= "SELECT c1, c2 FROM t1";
 | |
| 
 | |
|   /* c1 and c2 are binary so no conversion will be done on select */
 | |
|   rc= mysql_stmt_prepare(stmt, stmt_text, strlen(stmt_text));
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   bind_array[0].buffer= buf1;
 | |
|   bind_array[0].buffer_length= sizeof(buf1);
 | |
|   bind_array[0].length= &buf1_len;
 | |
| 
 | |
|   bind_array[1].buffer= buf2;
 | |
|   bind_array[1].buffer_length= sizeof(buf2);
 | |
|   bind_array[1].length= &buf2_len;
 | |
| 
 | |
|   mysql_stmt_bind_result(stmt, bind_array);
 | |
| 
 | |
|   rc= mysql_stmt_fetch(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   DIE_UNLESS(buf1_len == strlen(cp1251));
 | |
|   DIE_UNLESS(buf2_len == strlen(cp1251));
 | |
|   DIE_UNLESS(!memcmp(buf1, cp1251, buf1_len));
 | |
|   DIE_UNLESS(!memcmp(buf2, cp1251, buf1_len));
 | |
| 
 | |
|   rc= mysql_stmt_fetch(stmt);
 | |
|   DIE_UNLESS(rc == MYSQL_NO_DATA);
 | |
| 
 | |
|   stmt_text= "DROP TABLE IF EXISTS t1";
 | |
|   rc= mysql_real_query(mysql, stmt_text, strlen(stmt_text));
 | |
|   myquery(rc);
 | |
| 
 | |
|   /*
 | |
|     Now create table with two cp1251 columns, set client character
 | |
|     set to koi8 and supply columns of one row as string and another as
 | |
|     binary data. Binary data must not be converted on insert, and both
 | |
|     columns must be converted to client character set on select.
 | |
|   */
 | |
| 
 | |
|   stmt_text= "CREATE TABLE t1 (c1 VARCHAR(255) CHARACTER SET cp1251, "
 | |
|                               "c2 VARCHAR(255) CHARACTER SET cp1251)";
 | |
| 
 | |
|   rc= mysql_real_query(mysql, stmt_text, strlen(stmt_text));
 | |
|   myquery(rc);
 | |
| 
 | |
|   stmt_text= "INSERT INTO t1 (c1, c2) VALUES (?, ?)";
 | |
| 
 | |
|   rc= mysql_stmt_prepare(stmt, stmt_text, strlen(stmt_text));
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   /* this data must be converted */
 | |
|   bind_array[0].buffer_type= MYSQL_TYPE_STRING;
 | |
|   bind_array[0].buffer= (void *) koi8;
 | |
|   bind_array[0].buffer_length= strlen(koi8);
 | |
| 
 | |
|   bind_array[1].buffer_type= MYSQL_TYPE_STRING;
 | |
|   bind_array[1].buffer= (void *) koi8;
 | |
|   bind_array[1].buffer_length= strlen(koi8);
 | |
| 
 | |
|   mysql_stmt_bind_param(stmt, bind_array);
 | |
| 
 | |
|   mysql_stmt_send_long_data(stmt, 0, koi8, strlen(koi8));
 | |
| 
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   /* this data must not be converted */
 | |
|   bind_array[0].buffer_type= MYSQL_TYPE_BLOB;
 | |
|   bind_array[0].buffer= (void *) cp1251;
 | |
|   bind_array[0].buffer_length= strlen(cp1251);
 | |
| 
 | |
|   bind_array[1].buffer_type= MYSQL_TYPE_BLOB;
 | |
|   bind_array[1].buffer= (void *) cp1251;
 | |
|   bind_array[1].buffer_length= strlen(cp1251);
 | |
| 
 | |
|   mysql_stmt_bind_param(stmt, bind_array);
 | |
| 
 | |
|   mysql_stmt_send_long_data(stmt, 0, cp1251, strlen(cp1251));
 | |
| 
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   /* Fetch data and verify that rows are in koi8 */
 | |
| 
 | |
|   stmt_text= "SELECT c1, c2 FROM t1";
 | |
| 
 | |
|   /* c1 and c2 are binary so no conversion will be done on select */
 | |
|   rc= mysql_stmt_prepare(stmt, stmt_text, strlen(stmt_text));
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   bind_array[0].buffer= buf1;
 | |
|   bind_array[0].buffer_length= sizeof(buf1);
 | |
|   bind_array[0].length= &buf1_len;
 | |
| 
 | |
|   bind_array[1].buffer= buf2;
 | |
|   bind_array[1].buffer_length= sizeof(buf2);
 | |
|   bind_array[1].length= &buf2_len;
 | |
| 
 | |
|   mysql_stmt_bind_result(stmt, bind_array);
 | |
| 
 | |
|   while ((rc= mysql_stmt_fetch(stmt)) == 0)
 | |
|   {
 | |
|     DIE_UNLESS(buf1_len == strlen(koi8));
 | |
|     DIE_UNLESS(buf2_len == strlen(koi8));
 | |
|     DIE_UNLESS(!memcmp(buf1, koi8, buf1_len));
 | |
|     DIE_UNLESS(!memcmp(buf2, koi8, buf1_len));
 | |
|   }
 | |
|   DIE_UNLESS(rc == MYSQL_NO_DATA);
 | |
|   mysql_stmt_close(stmt);
 | |
| 
 | |
|   stmt_text= "DROP TABLE t1";
 | |
|   rc= mysql_real_query(mysql, stmt_text, strlen(stmt_text));
 | |
|   myquery(rc);
 | |
|   stmt_text= "SET NAMES DEFAULT";
 | |
|   rc= mysql_real_query(mysql, stmt_text, strlen(stmt_text));
 | |
|   myquery(rc);
 | |
| }
 | |
| 
 | |
| 
 | |
| static void test_bug3796()
 | |
| {
 | |
|   MYSQL_STMT *stmt;
 | |
|   MYSQL_BIND my_bind[1];
 | |
|   const char *concat_arg0= "concat_with_";
 | |
|   enum { OUT_BUFF_SIZE= 30 };
 | |
|   char out_buff[OUT_BUFF_SIZE];
 | |
|   char canonical_buff[OUT_BUFF_SIZE];
 | |
|   ulong out_length;
 | |
|   const char *stmt_text;
 | |
|   int rc;
 | |
| 
 | |
|   myheader("test_bug3796");
 | |
| 
 | |
|   /* Create and fill test table */
 | |
|   stmt_text= "DROP TABLE IF EXISTS t1";
 | |
|   rc= mysql_real_query(mysql, stmt_text, strlen(stmt_text));
 | |
|   myquery(rc);
 | |
| 
 | |
|   stmt_text= "CREATE TABLE t1 (a INT, b VARCHAR(30))";
 | |
|   rc= mysql_real_query(mysql, stmt_text, strlen(stmt_text));
 | |
|   myquery(rc);
 | |
| 
 | |
|   stmt_text= "INSERT INTO t1 VALUES(1, 'ONE'), (2, 'TWO')";
 | |
|   rc= mysql_real_query(mysql, stmt_text, strlen(stmt_text));
 | |
|   myquery(rc);
 | |
| 
 | |
|   /* Create statement handle and prepare it with select */
 | |
|   stmt= mysql_stmt_init(mysql);
 | |
|   stmt_text= "SELECT concat(?, b) FROM t1";
 | |
| 
 | |
|   rc= mysql_stmt_prepare(stmt, stmt_text, strlen(stmt_text));
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   /* Bind input buffers */
 | |
|   bzero((char*) my_bind, sizeof(my_bind));
 | |
| 
 | |
|   my_bind[0].buffer_type= MYSQL_TYPE_STRING;
 | |
|   my_bind[0].buffer= (void *) concat_arg0;
 | |
|   my_bind[0].buffer_length= strlen(concat_arg0);
 | |
| 
 | |
|   mysql_stmt_bind_param(stmt, my_bind);
 | |
| 
 | |
|   /* Execute the select statement */
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   my_bind[0].buffer= (void *) out_buff;
 | |
|   my_bind[0].buffer_length= OUT_BUFF_SIZE;
 | |
|   my_bind[0].length= &out_length;
 | |
| 
 | |
|   mysql_stmt_bind_result(stmt, my_bind);
 | |
| 
 | |
|   rc= mysql_stmt_fetch(stmt);
 | |
|   if (!opt_silent)
 | |
|     printf("Concat result: '%s'\n", out_buff);
 | |
|   check_execute(stmt, rc);
 | |
|   strmov(canonical_buff, concat_arg0);
 | |
|   strcat(canonical_buff, "ONE");
 | |
|   DIE_UNLESS(strlen(canonical_buff) == out_length &&
 | |
|          strncmp(out_buff, canonical_buff, out_length) == 0);
 | |
| 
 | |
|   rc= mysql_stmt_fetch(stmt);
 | |
|   check_execute(stmt, rc);
 | |
|   strmov(canonical_buff + strlen(concat_arg0), "TWO");
 | |
|   DIE_UNLESS(strlen(canonical_buff) == out_length &&
 | |
|          strncmp(out_buff, canonical_buff, out_length) == 0);
 | |
|   if (!opt_silent)
 | |
|     printf("Concat result: '%s'\n", out_buff);
 | |
| 
 | |
|   rc= mysql_stmt_fetch(stmt);
 | |
|   DIE_UNLESS(rc == MYSQL_NO_DATA);
 | |
| 
 | |
|   mysql_stmt_close(stmt);
 | |
| 
 | |
|   stmt_text= "DROP TABLE IF EXISTS t1";
 | |
|   rc= mysql_real_query(mysql, stmt_text, strlen(stmt_text));
 | |
|   myquery(rc);
 | |
| }
 | |
| 
 | |
| 
 | |
| static void test_bug4026()
 | |
| {
 | |
|   MYSQL_STMT *stmt;
 | |
|   MYSQL_BIND my_bind[2];
 | |
|   MYSQL_TIME time_in, time_out;
 | |
|   MYSQL_TIME datetime_in, datetime_out;
 | |
|   const char *stmt_text;
 | |
|   int rc;
 | |
| 
 | |
|   myheader("test_bug4026");
 | |
| 
 | |
|   /* Check that microseconds are inserted and selected successfully */
 | |
| 
 | |
|   /* Create a statement handle and prepare it with select */
 | |
|   stmt= mysql_stmt_init(mysql);
 | |
|   stmt_text= "SELECT ?, ?";
 | |
| 
 | |
|   rc= mysql_stmt_prepare(stmt, stmt_text, strlen(stmt_text));
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   /* Bind input buffers */
 | |
|   bzero((char*) my_bind, sizeof(my_bind));
 | |
|   bzero((char*) &time_in, sizeof(time_in));
 | |
|   bzero((char*) &time_out, sizeof(time_out));
 | |
|   bzero((char*) &datetime_in, sizeof(datetime_in));
 | |
|   bzero((char*) &datetime_out, sizeof(datetime_out));
 | |
| 
 | |
|   my_bind[0].buffer_type= MYSQL_TYPE_TIME;
 | |
|   my_bind[0].buffer= (void *) &time_in;
 | |
|   my_bind[1].buffer_type= MYSQL_TYPE_DATETIME;
 | |
|   my_bind[1].buffer= (void *) &datetime_in;
 | |
| 
 | |
|   time_in.hour= 23;
 | |
|   time_in.minute= 59;
 | |
|   time_in.second= 59;
 | |
|   time_in.second_part= 123456;
 | |
|   /*
 | |
|     This is not necessary, just to make DIE_UNLESS below work: this field
 | |
|     is filled in when time is received from server
 | |
|   */
 | |
|   time_in.time_type= MYSQL_TIMESTAMP_TIME;
 | |
| 
 | |
|   datetime_in= time_in;
 | |
|   datetime_in.year= 2003;
 | |
|   datetime_in.month= 12;
 | |
|   datetime_in.day= 31;
 | |
|   datetime_in.time_type= MYSQL_TIMESTAMP_DATETIME;
 | |
| 
 | |
|   mysql_stmt_bind_param(stmt, my_bind);
 | |
| 
 | |
|   /* Execute the select statement */
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   my_bind[0].buffer= (void *) &time_out;
 | |
|   my_bind[1].buffer= (void *) &datetime_out;
 | |
| 
 | |
|   mysql_stmt_bind_result(stmt, my_bind);
 | |
| 
 | |
|   rc= mysql_stmt_fetch(stmt);
 | |
|   DIE_UNLESS(rc == 0);
 | |
|   if (!opt_silent)
 | |
|   {
 | |
|     printf("%d:%d:%d.%lu\n", time_out.hour, time_out.minute, time_out.second,
 | |
|            time_out.second_part);
 | |
|     printf("%d-%d-%d %d:%d:%d.%lu\n", datetime_out.year, datetime_out.month,
 | |
|            datetime_out.day, datetime_out.hour,
 | |
|            datetime_out.minute, datetime_out.second,
 | |
|            datetime_out.second_part);
 | |
|   }
 | |
|   DIE_UNLESS(memcmp(&time_in, &time_out, sizeof(time_in)) == 0);
 | |
|   DIE_UNLESS(memcmp(&datetime_in, &datetime_out, sizeof(datetime_in)) == 0);
 | |
|   mysql_stmt_close(stmt);
 | |
| }
 | |
| 
 | |
| 
 | |
| static void test_bug4079()
 | |
| {
 | |
|   MYSQL_STMT *stmt;
 | |
|   MYSQL_BIND my_bind[1];
 | |
|   const char *stmt_text;
 | |
|   uint32 res;
 | |
|   int rc;
 | |
| 
 | |
|   myheader("test_bug4079");
 | |
| 
 | |
|   /* Create and fill table */
 | |
|   mysql_query(mysql, "DROP TABLE IF EXISTS t1");
 | |
|   mysql_query(mysql, "CREATE TABLE t1 (a int)");
 | |
|   mysql_query(mysql, "INSERT INTO t1 VALUES (1), (2)");
 | |
| 
 | |
|   /* Prepare erroneous statement */
 | |
|   stmt= mysql_stmt_init(mysql);
 | |
|   stmt_text= "SELECT 1 < (SELECT a FROM t1)";
 | |
| 
 | |
|   rc= mysql_stmt_prepare(stmt, stmt_text, strlen(stmt_text));
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   /* Execute the select statement */
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   /* Bind input buffers */
 | |
|   bzero((char*) my_bind, sizeof(my_bind));
 | |
| 
 | |
|   my_bind[0].buffer_type= MYSQL_TYPE_LONG;
 | |
|   my_bind[0].buffer= (void *) &res;
 | |
| 
 | |
|   mysql_stmt_bind_result(stmt, my_bind);
 | |
| 
 | |
|   rc= mysql_stmt_fetch(stmt);
 | |
|   DIE_UNLESS(rc != 0 && rc != MYSQL_NO_DATA);
 | |
|   if (!opt_silent)
 | |
|     printf("Got error from mysql_stmt_fetch (as expected):\n%s\n",
 | |
|            mysql_stmt_error(stmt));
 | |
|   /* buggy version of libmysql hanged up here */
 | |
|   mysql_stmt_close(stmt);
 | |
| }
 | |
| 
 | |
| 
 | |
| static void test_bug4236()
 | |
| {
 | |
|   MYSQL_STMT *stmt;
 | |
|   const char *stmt_text;
 | |
|   int rc;
 | |
|   MYSQL_STMT backup;
 | |
| 
 | |
|   myheader("test_bug4236");
 | |
| 
 | |
|   stmt= mysql_stmt_init(mysql);
 | |
| 
 | |
|   /* mysql_stmt_execute() of statement with statement id= 0 crashed server */
 | |
|   stmt_text= "SELECT 1";
 | |
|   /* We need to prepare statement to pass by possible check in libmysql */
 | |
|   rc= mysql_stmt_prepare(stmt, stmt_text, strlen(stmt_text));
 | |
|   check_execute(stmt, rc);
 | |
|   /* Hack to check that server works OK if statement wasn't found */
 | |
|   backup.stmt_id= stmt->stmt_id;
 | |
|   stmt->stmt_id= 0;
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   DIE_UNLESS(rc);
 | |
|   /* Restore original statement id to be able to reprepare it */
 | |
|   stmt->stmt_id= backup.stmt_id;
 | |
| 
 | |
|   mysql_stmt_close(stmt);
 | |
| }
 | |
| 
 | |
| 
 | |
| static void test_bug4030()
 | |
| {
 | |
|   MYSQL_STMT *stmt;
 | |
|   MYSQL_BIND my_bind[3];
 | |
|   MYSQL_TIME time_canonical, time_out;
 | |
|   MYSQL_TIME date_canonical, date_out;
 | |
|   MYSQL_TIME datetime_canonical, datetime_out;
 | |
|   const char *stmt_text;
 | |
|   int rc;
 | |
| 
 | |
|   myheader("test_bug4030");
 | |
| 
 | |
|   /* Check that microseconds are inserted and selected successfully */
 | |
| 
 | |
|   /* Execute a query with time values in prepared mode */
 | |
|   stmt= mysql_stmt_init(mysql);
 | |
|   stmt_text= "SELECT '23:59:59.123456', '2003-12-31', "
 | |
|              "'2003-12-31 23:59:59.123456'";
 | |
|   rc= mysql_stmt_prepare(stmt, stmt_text, strlen(stmt_text));
 | |
|   check_execute(stmt, rc);
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   /* Bind output buffers */
 | |
|   bzero((char*) my_bind, sizeof(my_bind));
 | |
|   bzero((char*) &time_canonical, sizeof(time_canonical));
 | |
|   bzero((char*) &time_out, sizeof(time_out));
 | |
|   bzero((char*) &date_canonical, sizeof(date_canonical));
 | |
|   bzero((char*) &date_out, sizeof(date_out));
 | |
|   bzero((char*) &datetime_canonical, sizeof(datetime_canonical));
 | |
|   bzero((char*) &datetime_out, sizeof(datetime_out));
 | |
| 
 | |
|   my_bind[0].buffer_type= MYSQL_TYPE_TIME;
 | |
|   my_bind[0].buffer= (void *) &time_out;
 | |
|   my_bind[1].buffer_type= MYSQL_TYPE_DATE;
 | |
|   my_bind[1].buffer= (void *) &date_out;
 | |
|   my_bind[2].buffer_type= MYSQL_TYPE_DATETIME;
 | |
|   my_bind[2].buffer= (void *) &datetime_out;
 | |
| 
 | |
|   time_canonical.hour= 23;
 | |
|   time_canonical.minute= 59;
 | |
|   time_canonical.second= 59;
 | |
|   time_canonical.second_part= 123456;
 | |
|   time_canonical.time_type= MYSQL_TIMESTAMP_TIME;
 | |
| 
 | |
|   date_canonical.year= 2003;
 | |
|   date_canonical.month= 12;
 | |
|   date_canonical.day= 31;
 | |
|   date_canonical.time_type= MYSQL_TIMESTAMP_DATE;
 | |
| 
 | |
|   datetime_canonical= time_canonical;
 | |
|   datetime_canonical.year= 2003;
 | |
|   datetime_canonical.month= 12;
 | |
|   datetime_canonical.day= 31;
 | |
|   datetime_canonical.time_type= MYSQL_TIMESTAMP_DATETIME;
 | |
| 
 | |
|   mysql_stmt_bind_result(stmt, my_bind);
 | |
| 
 | |
|   rc= mysql_stmt_fetch(stmt);
 | |
|   DIE_UNLESS(rc == 0);
 | |
|   if (!opt_silent)
 | |
|   {
 | |
|     printf("%d:%d:%d.%lu\n", time_out.hour, time_out.minute, time_out.second,
 | |
|            time_out.second_part);
 | |
|     printf("%d-%d-%d\n", date_out.year, date_out.month, date_out.day);
 | |
|     printf("%d-%d-%d %d:%d:%d.%lu\n", datetime_out.year, datetime_out.month,
 | |
|            datetime_out.day, datetime_out.hour,
 | |
|            datetime_out.minute, datetime_out.second,
 | |
|            datetime_out.second_part);
 | |
|   }
 | |
|   DIE_UNLESS(memcmp(&time_canonical, &time_out, sizeof(time_out)) == 0);
 | |
|   DIE_UNLESS(memcmp(&date_canonical, &date_out, sizeof(date_out)) == 0);
 | |
|   DIE_UNLESS(memcmp(&datetime_canonical, &datetime_out, sizeof(datetime_out)) == 0);
 | |
|   mysql_stmt_close(stmt);
 | |
| }
 | |
| 
 | |
| static void test_view()
 | |
| {
 | |
|   MYSQL_STMT *stmt;
 | |
|   int rc, i;
 | |
|   MYSQL_BIND      my_bind[1];
 | |
|   char            str_data[50];
 | |
|   ulong           length = 0L;
 | |
|   long            is_null = 0L;
 | |
|   const char *query=
 | |
|     "SELECT COUNT(*) FROM v1 WHERE SERVERNAME=?";
 | |
| 
 | |
|   myheader("test_view");
 | |
| 
 | |
|   rc = mysql_query(mysql, "DROP TABLE IF EXISTS t1,t2,t3,v1");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc = mysql_query(mysql, "DROP VIEW IF EXISTS v1,t1,t2,t3");
 | |
|   myquery(rc);
 | |
|   rc= mysql_query(mysql,"CREATE TABLE t1 ("
 | |
|                         " SERVERGRP varchar(20) NOT NULL default '', "
 | |
|                         " DBINSTANCE varchar(20) NOT NULL default '', "
 | |
|                         " PRIMARY KEY  (SERVERGRP)) "
 | |
|                         " CHARSET=latin1 collate=latin1_bin");
 | |
|   myquery(rc);
 | |
|   rc= mysql_query(mysql,"CREATE TABLE t2 ("
 | |
|                         " SERVERNAME varchar(20) NOT NULL, "
 | |
|                         " SERVERGRP varchar(20) NOT NULL, "
 | |
|                         " PRIMARY KEY (SERVERNAME)) "
 | |
|                         " CHARSET=latin1 COLLATE latin1_bin");
 | |
|   myquery(rc);
 | |
|   rc= mysql_query(mysql,
 | |
|                   "CREATE TABLE t3 ("
 | |
|                   " SERVERGRP varchar(20) BINARY NOT NULL, "
 | |
|                   " TABNAME varchar(30) NOT NULL, MAPSTATE char(1) NOT NULL, "
 | |
|                   " ACTSTATE char(1) NOT NULL , "
 | |
|                   " LOCAL_NAME varchar(30) NOT NULL, "
 | |
|                   " CHG_DATE varchar(8) NOT NULL default '00000000', "
 | |
|                   " CHG_TIME varchar(6) NOT NULL default '000000', "
 | |
|                   " MXUSER varchar(12) NOT NULL default '', "
 | |
|                   " PRIMARY KEY (SERVERGRP, TABNAME, MAPSTATE, ACTSTATE, "
 | |
|                   " LOCAL_NAME)) CHARSET=latin1 COLLATE latin1_bin");
 | |
|   myquery(rc);
 | |
|   rc= mysql_query(mysql,"CREATE VIEW v1 AS select sql_no_cache"
 | |
|                   " T0001.SERVERNAME AS SERVERNAME, T0003.TABNAME AS"
 | |
|                   " TABNAME,T0003.LOCAL_NAME AS LOCAL_NAME,T0002.DBINSTANCE AS"
 | |
|                   " DBINSTANCE from t2 T0001 join t1 T0002 join t3 T0003 where"
 | |
|                   " ((T0002.SERVERGRP = T0001.SERVERGRP) and"
 | |
|                   " (T0002.SERVERGRP = T0003.SERVERGRP)"
 | |
|                   " and (T0003.MAPSTATE = _latin1'A') and"
 | |
|                   " (T0003.ACTSTATE = _latin1' '))");
 | |
|   myquery(rc);
 | |
| 
 | |
|   stmt= mysql_stmt_init(mysql);
 | |
|   rc= mysql_stmt_prepare(stmt, query, strlen(query));
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   strmov(str_data, "TEST");
 | |
|   bzero((char*) my_bind, sizeof(my_bind));
 | |
|   my_bind[0].buffer_type= MYSQL_TYPE_STRING;
 | |
|   my_bind[0].buffer= (char *)&str_data;
 | |
|   my_bind[0].buffer_length= 50;
 | |
|   my_bind[0].length= &length;
 | |
|   length= 4;
 | |
|   my_bind[0].is_null= (char*)&is_null;
 | |
|   rc= mysql_stmt_bind_param(stmt, my_bind);
 | |
|   check_execute(stmt,rc);
 | |
| 
 | |
|   for (i= 0; i < 3; i++)
 | |
|   {
 | |
|     rc= mysql_stmt_execute(stmt);
 | |
|     check_execute(stmt, rc);
 | |
|     rc= my_process_stmt_result(stmt);
 | |
|     DIE_UNLESS(1 == rc);
 | |
|   }
 | |
|   mysql_stmt_close(stmt);
 | |
| 
 | |
|   rc= mysql_query(mysql, "DROP TABLE t1,t2,t3");
 | |
|   myquery(rc);
 | |
|   rc= mysql_query(mysql, "DROP VIEW v1");
 | |
|   myquery(rc);
 | |
| }
 | |
| 
 | |
| 
 | |
| static void test_view_where()
 | |
| {
 | |
|   MYSQL_STMT *stmt;
 | |
|   int rc, i;
 | |
|   const char *query=
 | |
|     "select v1.c,v2.c from v1, v2";
 | |
| 
 | |
|   myheader("test_view_where");
 | |
| 
 | |
|   rc = mysql_query(mysql, "DROP TABLE IF EXISTS t1,v1,v2");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc = mysql_query(mysql, "DROP VIEW IF EXISTS v1,v2,t1");
 | |
|   myquery(rc);
 | |
|   rc= mysql_query(mysql,"CREATE TABLE t1 (a int, b int)");
 | |
|   myquery(rc);
 | |
|   rc= mysql_query(mysql,"insert into t1 values (1,2), (1,3), (2,4), (2,5), (3,10)");
 | |
|   myquery(rc);
 | |
|   rc= mysql_query(mysql,"create view v1 (c) as select b from t1 where a<3");
 | |
|   myquery(rc);
 | |
|   rc= mysql_query(mysql,"create view v2 (c) as select b from t1 where a>=3");
 | |
|   myquery(rc);
 | |
| 
 | |
|   stmt= mysql_stmt_init(mysql);
 | |
|   rc= mysql_stmt_prepare(stmt, query, strlen(query));
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   for (i= 0; i < 3; i++)
 | |
|   {
 | |
|     rc= mysql_stmt_execute(stmt);
 | |
|     check_execute(stmt, rc);
 | |
|     rc= my_process_stmt_result(stmt);
 | |
|     DIE_UNLESS(4 == rc);
 | |
|   }
 | |
|   mysql_stmt_close(stmt);
 | |
| 
 | |
|   rc= mysql_query(mysql, "DROP TABLE t1");
 | |
|   myquery(rc);
 | |
|   rc= mysql_query(mysql, "DROP VIEW v1, v2");
 | |
|   myquery(rc);
 | |
| }
 | |
| 
 | |
| 
 | |
| static void test_view_2where()
 | |
| {
 | |
|   MYSQL_STMT *stmt;
 | |
|   int rc, i;
 | |
|   MYSQL_BIND      my_bind[8];
 | |
|   char            parms[8][100];
 | |
|   ulong           length[8];
 | |
|   const char *query=
 | |
|     "select relid, report, handle, log_group, username, variant, type, "
 | |
|     "version, erfdat, erftime, erfname, aedat, aetime, aename, dependvars, "
 | |
|     "inactive from V_LTDX where mandt = ? and relid = ? and report = ? and "
 | |
|     "handle = ? and log_group = ? and username in ( ? , ? ) and type = ?";
 | |
| 
 | |
|   myheader("test_view_2where");
 | |
| 
 | |
|   rc= mysql_query(mysql, "DROP TABLE IF EXISTS LTDX");
 | |
|   myquery(rc);
 | |
|   rc= mysql_query(mysql, "DROP VIEW IF EXISTS V_LTDX");
 | |
|   myquery(rc);
 | |
|   rc= mysql_query(mysql,
 | |
|                   "CREATE TABLE LTDX (MANDT char(3) NOT NULL default '000', "
 | |
|                   " RELID char(2) NOT NULL, REPORT varchar(40) NOT NULL,"
 | |
|                   " HANDLE varchar(4) NOT NULL, LOG_GROUP varchar(4) NOT NULL,"
 | |
|                   " USERNAME varchar(12) NOT NULL,"
 | |
|                   " VARIANT varchar(12) NOT NULL,"
 | |
|                   " TYPE char(1) NOT NULL, SRTF2 int(11) NOT NULL,"
 | |
|                   " VERSION varchar(6) NOT NULL default '000000',"
 | |
|                   " ERFDAT varchar(8) NOT NULL default '00000000',"
 | |
|                   " ERFTIME varchar(6) NOT NULL default '000000',"
 | |
|                   " ERFNAME varchar(12) NOT NULL,"
 | |
|                   " AEDAT varchar(8) NOT NULL default '00000000',"
 | |
|                   " AETIME varchar(6) NOT NULL default '000000',"
 | |
|                   " AENAME varchar(12) NOT NULL,"
 | |
|                   " DEPENDVARS varchar(10) NOT NULL,"
 | |
|                   " INACTIVE char(1) NOT NULL, CLUSTR smallint(6) NOT NULL,"
 | |
|                   " CLUSTD blob,"
 | |
|                   " PRIMARY KEY (MANDT, RELID, REPORT, HANDLE, LOG_GROUP, "
 | |
|                                 "USERNAME, VARIANT, TYPE, SRTF2))"
 | |
|                  " CHARSET=latin1 COLLATE latin1_bin");
 | |
|   myquery(rc);
 | |
|   rc= mysql_query(mysql,
 | |
|                   "CREATE VIEW V_LTDX AS select T0001.MANDT AS "
 | |
|                   " MANDT,T0001.RELID AS RELID,T0001.REPORT AS "
 | |
|                   " REPORT,T0001.HANDLE AS HANDLE,T0001.LOG_GROUP AS "
 | |
|                   " LOG_GROUP,T0001.USERNAME AS USERNAME,T0001.VARIANT AS "
 | |
|                   " VARIANT,T0001.TYPE AS TYPE,T0001.VERSION AS "
 | |
|                   " VERSION,T0001.ERFDAT AS ERFDAT,T0001.ERFTIME AS "
 | |
|                   " ERFTIME,T0001.ERFNAME AS ERFNAME,T0001.AEDAT AS "
 | |
|                   " AEDAT,T0001.AETIME AS AETIME,T0001.AENAME AS "
 | |
|                   " AENAME,T0001.DEPENDVARS AS DEPENDVARS,T0001.INACTIVE AS "
 | |
|                   " INACTIVE from LTDX T0001 where (T0001.SRTF2 = 0)");
 | |
|   myquery(rc);
 | |
|   bzero((char*) my_bind, sizeof(my_bind));
 | |
|   for (i=0; i < 8; i++) {
 | |
|     strmov(parms[i], "1");
 | |
|     my_bind[i].buffer_type = MYSQL_TYPE_VAR_STRING;
 | |
|     my_bind[i].buffer = (char *)&parms[i];
 | |
|     my_bind[i].buffer_length = 100;
 | |
|     my_bind[i].is_null = 0;
 | |
|     my_bind[i].length = &length[i];
 | |
|     length[i] = 1;
 | |
|   }
 | |
|   stmt= mysql_stmt_init(mysql);
 | |
|   rc= mysql_stmt_prepare(stmt, query, strlen(query));
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= mysql_stmt_bind_param(stmt, my_bind);
 | |
|   check_execute(stmt,rc);
 | |
| 
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
|   rc= my_process_stmt_result(stmt);
 | |
|   DIE_UNLESS(0 == rc);
 | |
| 
 | |
|   mysql_stmt_close(stmt);
 | |
| 
 | |
|   rc= mysql_query(mysql, "DROP VIEW V_LTDX");
 | |
|   myquery(rc);
 | |
|   rc= mysql_query(mysql, "DROP TABLE LTDX");
 | |
|   myquery(rc);
 | |
| }
 | |
| 
 | |
| 
 | |
| static void test_view_star()
 | |
| {
 | |
|   MYSQL_STMT *stmt;
 | |
|   int rc, i;
 | |
|   MYSQL_BIND      my_bind[8];
 | |
|   char            parms[8][100];
 | |
|   ulong           length[8];
 | |
|   const char *query= "SELECT * FROM vt1 WHERE a IN (?,?)";
 | |
| 
 | |
|   myheader("test_view_star");
 | |
| 
 | |
|   rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1, vt1");
 | |
|   myquery(rc);
 | |
|   rc= mysql_query(mysql, "DROP VIEW IF EXISTS t1, vt1");
 | |
|   myquery(rc);
 | |
|   rc= mysql_query(mysql, "CREATE TABLE t1 (a int)");
 | |
|   myquery(rc);
 | |
|   rc= mysql_query(mysql, "CREATE VIEW vt1 AS SELECT a FROM t1");
 | |
|   myquery(rc);
 | |
|   bzero((char*) my_bind, sizeof(my_bind));
 | |
|   for (i= 0; i < 2; i++) {
 | |
|     sprintf((char *)&parms[i], "%d", i);
 | |
|     my_bind[i].buffer_type = MYSQL_TYPE_VAR_STRING;
 | |
|     my_bind[i].buffer = (char *)&parms[i];
 | |
|     my_bind[i].buffer_length = 100;
 | |
|     my_bind[i].is_null = 0;
 | |
|     my_bind[i].length = &length[i];
 | |
|     length[i] = 1;
 | |
|   }
 | |
| 
 | |
|   stmt= mysql_stmt_init(mysql);
 | |
|   rc= mysql_stmt_prepare(stmt, query, strlen(query));
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= mysql_stmt_bind_param(stmt, my_bind);
 | |
|   check_execute(stmt,rc);
 | |
| 
 | |
|   for (i= 0; i < 3; i++)
 | |
|   {
 | |
|     rc= mysql_stmt_execute(stmt);
 | |
|     check_execute(stmt, rc);
 | |
|     rc= my_process_stmt_result(stmt);
 | |
|     DIE_UNLESS(0 == rc);
 | |
|   }
 | |
| 
 | |
|   mysql_stmt_close(stmt);
 | |
| 
 | |
|   rc= mysql_query(mysql, "DROP TABLE t1");
 | |
|   myquery(rc);
 | |
|   rc= mysql_query(mysql, "DROP VIEW vt1");
 | |
|   myquery(rc);
 | |
| }
 | |
| 
 | |
| 
 | |
| static void test_view_insert()
 | |
| {
 | |
|   MYSQL_STMT *insert_stmt, *select_stmt;
 | |
|   int rc, i;
 | |
|   MYSQL_BIND      my_bind[1];
 | |
|   int             my_val = 0;
 | |
|   ulong           my_length = 0L;
 | |
|   long            my_null = 0L;
 | |
|   const char *query=
 | |
|     "insert into v1 values (?)";
 | |
| 
 | |
|   myheader("test_view_insert");
 | |
| 
 | |
|   rc = mysql_query(mysql, "DROP TABLE IF EXISTS t1,v1");
 | |
|   myquery(rc);
 | |
|   rc = mysql_query(mysql, "DROP VIEW IF EXISTS t1,v1");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql,"create table t1 (a int, primary key (a))");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "create view v1 as select a from t1 where a>=1");
 | |
|   myquery(rc);
 | |
| 
 | |
|   insert_stmt= mysql_stmt_init(mysql);
 | |
|   rc= mysql_stmt_prepare(insert_stmt, query, strlen(query));
 | |
|   check_execute(insert_stmt, rc);
 | |
|   query= "select * from t1";
 | |
|   select_stmt= mysql_stmt_init(mysql);
 | |
|   rc= mysql_stmt_prepare(select_stmt, query, strlen(query));
 | |
|   check_execute(select_stmt, rc);
 | |
| 
 | |
|   bzero((char*) my_bind, sizeof(my_bind));
 | |
|   my_bind[0].buffer_type = MYSQL_TYPE_LONG;
 | |
|   my_bind[0].buffer = (char *)&my_val;
 | |
|   my_bind[0].length = &my_length;
 | |
|   my_bind[0].is_null = (char*)&my_null;
 | |
|   rc= mysql_stmt_bind_param(insert_stmt, my_bind);
 | |
|   check_execute(insert_stmt, rc);
 | |
| 
 | |
|   for (i= 0; i < 3; i++)
 | |
|   {
 | |
|     int rowcount= 0;
 | |
|     my_val= i;
 | |
| 
 | |
|     rc= mysql_stmt_execute(insert_stmt);
 | |
|     check_execute(insert_stmt, rc);
 | |
| 
 | |
|     rc= mysql_stmt_execute(select_stmt);
 | |
|     check_execute(select_stmt, rc);
 | |
|     rowcount= (int)my_process_stmt_result(select_stmt);
 | |
|     DIE_UNLESS((i+1) == rowcount);
 | |
|   }
 | |
|   mysql_stmt_close(insert_stmt);
 | |
|   mysql_stmt_close(select_stmt);
 | |
| 
 | |
|   rc= mysql_query(mysql, "DROP VIEW v1");
 | |
|   myquery(rc);
 | |
|   rc= mysql_query(mysql, "DROP TABLE t1");
 | |
|   myquery(rc);
 | |
| }
 | |
| 
 | |
| 
 | |
| static void test_left_join_view()
 | |
| {
 | |
|   MYSQL_STMT *stmt;
 | |
|   int rc, i;
 | |
|   const char *query=
 | |
|     "select t1.a, v1.x from t1 left join v1 on (t1.a= v1.x);";
 | |
| 
 | |
|   myheader("test_left_join_view");
 | |
| 
 | |
|   rc = mysql_query(mysql, "DROP TABLE IF EXISTS t1,v1");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc = mysql_query(mysql, "DROP VIEW IF EXISTS v1,t1");
 | |
|   myquery(rc);
 | |
|   rc= mysql_query(mysql,"CREATE TABLE t1 (a int)");
 | |
|   myquery(rc);
 | |
|   rc= mysql_query(mysql,"insert into t1 values (1), (2), (3)");
 | |
|   myquery(rc);
 | |
|   rc= mysql_query(mysql,"create view v1 (x) as select a from t1 where a > 1");
 | |
|   myquery(rc);
 | |
|   stmt= mysql_stmt_init(mysql);
 | |
|   rc= mysql_stmt_prepare(stmt, query, strlen(query));
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   for (i= 0; i < 3; i++)
 | |
|   {
 | |
|     rc= mysql_stmt_execute(stmt);
 | |
|     check_execute(stmt, rc);
 | |
|     rc= my_process_stmt_result(stmt);
 | |
|     DIE_UNLESS(3 == rc);
 | |
|   }
 | |
|   mysql_stmt_close(stmt);
 | |
| 
 | |
|   rc= mysql_query(mysql, "DROP VIEW v1");
 | |
|   myquery(rc);
 | |
|   rc= mysql_query(mysql, "DROP TABLE t1");
 | |
|   myquery(rc);
 | |
| }
 | |
| 
 | |
| 
 | |
| static void test_view_insert_fields()
 | |
| {
 | |
|   MYSQL_STMT	*stmt;
 | |
|   char		parm[11][1000];
 | |
|   ulong         l[11];
 | |
|   int		rc, i;
 | |
|   MYSQL_BIND	my_bind[11];
 | |
|   const char    *query= "INSERT INTO `v1` ( `K1C4` ,`K2C4` ,`K3C4` ,`K4N4` ,`F1C4` ,`F2I4` ,`F3N5` ,`F7F8` ,`F6N4` ,`F5C8` ,`F9D8` ) VALUES( ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? )";
 | |
| 
 | |
|   myheader("test_view_insert_fields");
 | |
| 
 | |
|   rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1, v1");
 | |
|   myquery(rc);
 | |
|   rc= mysql_query(mysql, "DROP VIEW IF EXISTS t1, v1");
 | |
|   myquery(rc);
 | |
|   rc= mysql_query(mysql,
 | |
|                   "CREATE TABLE t1 (K1C4 varchar(4) NOT NULL,"
 | |
|                   "K2C4 varchar(4) NOT NULL, K3C4 varchar(4) NOT NULL,"
 | |
|                   "K4N4 varchar(4) NOT NULL default '0000',"
 | |
|                   "F1C4 varchar(4) NOT NULL, F2I4 int(11) NOT NULL,"
 | |
|                   "F3N5 varchar(5) NOT NULL default '00000',"
 | |
|                   "F4I4 int(11) NOT NULL default '0', F5C8 varchar(8) NOT NULL,"
 | |
|                   "F6N4 varchar(4) NOT NULL default '0000',"
 | |
|                   "F7F8 double NOT NULL default '0',"
 | |
|                   "F8F8 double NOT NULL default '0',"
 | |
|                   "F9D8 decimal(8,2) NOT NULL default '0.00',"
 | |
|                   "PRIMARY KEY (K1C4,K2C4,K3C4,K4N4)) "
 | |
|                   "CHARSET=latin1 COLLATE latin1_bin");
 | |
|   myquery(rc);
 | |
|   rc= mysql_query(mysql,
 | |
|                   "CREATE VIEW v1 AS select sql_no_cache "
 | |
|                   " K1C4 AS K1C4, K2C4 AS K2C4, K3C4 AS K3C4, K4N4 AS K4N4, "
 | |
|                   " F1C4 AS F1C4, F2I4 AS F2I4, F3N5 AS F3N5,"
 | |
|                   " F7F8 AS F7F8, F6N4 AS F6N4, F5C8 AS F5C8, F9D8 AS F9D8"
 | |
|                   " from t1 T0001");
 | |
| 
 | |
|   bzero((char*) my_bind, sizeof(my_bind));
 | |
|   for (i= 0; i < 11; i++)
 | |
|   {
 | |
|     l[i]= 20;
 | |
|     my_bind[i].buffer_type= MYSQL_TYPE_STRING;
 | |
|     my_bind[i].is_null= 0;
 | |
|     my_bind[i].buffer= (char *)&parm[i];
 | |
| 
 | |
|     memset(parm[i], 0, sizeof parm[i]);
 | |
|     strmov(parm[i], "1");
 | |
|     my_bind[i].buffer_length= 2;
 | |
|     my_bind[i].length= &l[i];
 | |
|   }
 | |
|   stmt= mysql_stmt_init(mysql);
 | |
|   rc= mysql_stmt_prepare(stmt, query, strlen(query));
 | |
|   check_execute(stmt, rc);
 | |
|   rc= mysql_stmt_bind_param(stmt, my_bind);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
|   mysql_stmt_close(stmt);
 | |
| 
 | |
|   query= "select * from t1";
 | |
|   stmt= mysql_stmt_init(mysql);
 | |
|   rc= mysql_stmt_prepare(stmt, query, strlen(query));
 | |
|   check_execute(stmt, rc);
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
|   rc= my_process_stmt_result(stmt);
 | |
|   DIE_UNLESS(1 == rc);
 | |
| 
 | |
|   mysql_stmt_close(stmt);
 | |
|   rc= mysql_query(mysql, "DROP VIEW v1");
 | |
|   myquery(rc);
 | |
|   rc= mysql_query(mysql, "DROP TABLE t1");
 | |
|   myquery(rc);
 | |
| 
 | |
| }
 | |
| 
 | |
| static void test_bug5126()
 | |
| {
 | |
|   MYSQL_STMT *stmt;
 | |
|   MYSQL_BIND my_bind[2];
 | |
|   int32 c1, c2;
 | |
|   const char *stmt_text;
 | |
|   int rc;
 | |
| 
 | |
|   myheader("test_bug5126");
 | |
| 
 | |
|   stmt_text= "DROP TABLE IF EXISTS t1";
 | |
|   rc= mysql_real_query(mysql, stmt_text, strlen(stmt_text));
 | |
|   myquery(rc);
 | |
| 
 | |
|   stmt_text= "CREATE TABLE t1 (a mediumint, b int)";
 | |
|   rc= mysql_real_query(mysql, stmt_text, strlen(stmt_text));
 | |
|   myquery(rc);
 | |
| 
 | |
|   stmt_text= "INSERT INTO t1 VALUES (8386608, 1)";
 | |
|   rc= mysql_real_query(mysql, stmt_text, strlen(stmt_text));
 | |
|   myquery(rc);
 | |
| 
 | |
|   stmt= mysql_stmt_init(mysql);
 | |
|   stmt_text= "SELECT a, b FROM t1";
 | |
|   rc= mysql_stmt_prepare(stmt, stmt_text, strlen(stmt_text));
 | |
|   check_execute(stmt, rc);
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   /* Bind output buffers */
 | |
|   bzero((char*) my_bind, sizeof(my_bind));
 | |
| 
 | |
|   my_bind[0].buffer_type= MYSQL_TYPE_LONG;
 | |
|   my_bind[0].buffer= &c1;
 | |
|   my_bind[1].buffer_type= MYSQL_TYPE_LONG;
 | |
|   my_bind[1].buffer= &c2;
 | |
| 
 | |
|   mysql_stmt_bind_result(stmt, my_bind);
 | |
| 
 | |
|   rc= mysql_stmt_fetch(stmt);
 | |
|   DIE_UNLESS(rc == 0);
 | |
|   DIE_UNLESS(c1 == 8386608 && c2 == 1);
 | |
|   if (!opt_silent)
 | |
|     printf("%ld, %ld\n", (long) c1, (long) c2);
 | |
|   mysql_stmt_close(stmt);
 | |
| }
 | |
| 
 | |
| 
 | |
| static void test_bug4231()
 | |
| {
 | |
|   MYSQL_STMT *stmt;
 | |
|   MYSQL_BIND my_bind[2];
 | |
|   MYSQL_TIME tm[2];
 | |
|   const char *stmt_text;
 | |
|   int rc;
 | |
| 
 | |
|   myheader("test_bug4231");
 | |
| 
 | |
|   stmt_text= "DROP TABLE IF EXISTS t1";
 | |
|   rc= mysql_real_query(mysql, stmt_text, strlen(stmt_text));
 | |
|   myquery(rc);
 | |
| 
 | |
|   stmt_text= "CREATE TABLE t1 (a int)";
 | |
|   rc= mysql_real_query(mysql, stmt_text, strlen(stmt_text));
 | |
|   myquery(rc);
 | |
| 
 | |
|   stmt_text= "INSERT INTO t1 VALUES (1)";
 | |
|   rc= mysql_real_query(mysql, stmt_text, strlen(stmt_text));
 | |
|   myquery(rc);
 | |
| 
 | |
|   stmt= mysql_stmt_init(mysql);
 | |
|   stmt_text= "SELECT a FROM t1 WHERE ? = ?";
 | |
|   rc= mysql_stmt_prepare(stmt, stmt_text, strlen(stmt_text));
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   /* Bind input buffers */
 | |
|   bzero((char*) my_bind, sizeof(my_bind));
 | |
|   bzero((char*) tm, sizeof(tm));
 | |
| 
 | |
|   my_bind[0].buffer_type= MYSQL_TYPE_DATE;
 | |
|   my_bind[0].buffer= &tm[0];
 | |
|   my_bind[1].buffer_type= MYSQL_TYPE_DATE;
 | |
|   my_bind[1].buffer= &tm[1];
 | |
| 
 | |
|   mysql_stmt_bind_param(stmt, my_bind);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   /*
 | |
|     First set server-side params to some non-zero non-equal values:
 | |
|     then we will check that they are not used when client sends
 | |
|     new (zero) times.
 | |
|   */
 | |
|   tm[0].time_type = MYSQL_TIMESTAMP_DATE;
 | |
|   tm[0].year = 2000;
 | |
|   tm[0].month = 1;
 | |
|   tm[0].day = 1;
 | |
|   tm[1]= tm[0];
 | |
|   --tm[1].year;                                 /* tm[0] != tm[1] */
 | |
| 
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= mysql_stmt_fetch(stmt);
 | |
| 
 | |
|   /* binds are unequal, no rows should be returned */
 | |
|   DIE_UNLESS(rc == MYSQL_NO_DATA);
 | |
| 
 | |
|   /* Set one of the dates to zero */
 | |
|   tm[0].year= tm[0].month= tm[0].day= 0;
 | |
|   tm[1]= tm[0];
 | |
|   mysql_stmt_execute(stmt);
 | |
|   rc= mysql_stmt_fetch(stmt);
 | |
|   DIE_UNLESS(rc == 0);
 | |
| 
 | |
|   mysql_stmt_close(stmt);
 | |
|   stmt_text= "DROP TABLE t1";
 | |
|   rc= mysql_real_query(mysql, stmt_text, strlen(stmt_text));
 | |
|   myquery(rc);
 | |
| }
 | |
| 
 | |
| 
 | |
| static void test_bug5399()
 | |
| {
 | |
|   /*
 | |
|     Ascii 97 is 'a', which gets mapped to Ascii 65 'A' unless internal
 | |
|     statement id hash in the server uses binary collation.
 | |
|   */
 | |
| #define NUM_OF_USED_STMT 97 
 | |
|   MYSQL_STMT *stmt_list[NUM_OF_USED_STMT];
 | |
|   MYSQL_STMT **stmt;
 | |
|   MYSQL_BIND my_bind[1];
 | |
|   char buff[600];
 | |
|   int rc;
 | |
|   int32 no;
 | |
| 
 | |
|   myheader("test_bug5399");
 | |
| 
 | |
|   bzero((char*) my_bind, sizeof(my_bind));
 | |
|   my_bind[0].buffer_type= MYSQL_TYPE_LONG;
 | |
|   my_bind[0].buffer= &no;
 | |
| 
 | |
|   for (stmt= stmt_list; stmt != stmt_list + NUM_OF_USED_STMT; ++stmt)
 | |
|   {
 | |
|     sprintf(buff, "select %d", (int) (stmt - stmt_list));
 | |
|     *stmt= mysql_stmt_init(mysql);
 | |
|     rc= mysql_stmt_prepare(*stmt, buff, strlen(buff));
 | |
|     check_execute(*stmt, rc);
 | |
|     mysql_stmt_bind_result(*stmt, my_bind);
 | |
|   }
 | |
|   if (!opt_silent)
 | |
|     printf("%d statements prepared.\n", NUM_OF_USED_STMT);
 | |
| 
 | |
|   for (stmt= stmt_list; stmt != stmt_list + NUM_OF_USED_STMT; ++stmt)
 | |
|   {
 | |
|     rc= mysql_stmt_execute(*stmt);
 | |
|     check_execute(*stmt, rc);
 | |
|     rc= mysql_stmt_store_result(*stmt);
 | |
|     check_execute(*stmt, rc);
 | |
|     rc= mysql_stmt_fetch(*stmt);
 | |
|     DIE_UNLESS(rc == 0);
 | |
|     DIE_UNLESS((int32) (stmt - stmt_list) == no);
 | |
|   }
 | |
| 
 | |
|   for (stmt= stmt_list; stmt != stmt_list + NUM_OF_USED_STMT; ++stmt)
 | |
|     mysql_stmt_close(*stmt);
 | |
| #undef NUM_OF_USED_STMT
 | |
| }
 | |
| 
 | |
| 
 | |
| static void test_bug5194()
 | |
| {
 | |
|   MYSQL_STMT *stmt;
 | |
|   MYSQL_BIND *my_bind;
 | |
|   char *query;
 | |
|   char *param_str;
 | |
|   int param_str_length;
 | |
|   const char *stmt_text;
 | |
|   int rc;
 | |
|   float float_array[250] =
 | |
|   {
 | |
|     0.5,  0.5,  0.5,  0.5,  0.5,  0.5,  0.5,  0.5,  0.5,  0.5,
 | |
|     0.5,  0.5,  0.5,  0.5,  0.5,  0.5,  0.5,  0.5,  0.5,  0.5,
 | |
|     0.5,  0.5,  0.5,  0.5,  0.5,  0.5,  0.5,  0.5,  0.5,  0.5,
 | |
|     0.5,  0.5,  0.5,  0.5,  0.5,  0.5,  0.5,  0.5,  0.5,  0.5,
 | |
|     0.5,  0.5,  0.5,  0.5,  0.5,  0.5,  0.5,  0.5,  0.5,  0.5,
 | |
|     0.5,  0.5,  0.5,  0.5,  0.5,  0.5,  0.5,  0.5,  0.5,  0.5,
 | |
|     0.5,  0.5,  0.5,  0.5,  0.5,  0.5,  0.5,  0.5,  0.5,  0.5,
 | |
|     0.5,  0.5,  0.5,  0.5,  0.5,  0.5,  0.5,  0.5,  0.5,  0.5,
 | |
|     0.5,  0.5,  0.5,  0.5,  0.5,  0.5,  0.5,  0.5,  0.5,  0.5,
 | |
|     0.5,  0.5,  0.5,  0.5,  0.5,  0.5,  0.5,  0.5,  0.5,  0.5,
 | |
|     0.5,  0.5,  0.5,  0.5,  0.5,  0.5,  0.5,  0.5,  0.5,  0.5,
 | |
|     0.5,  0.5,  0.5,  0.5,  0.5,  0.5,  0.5,  0.5,  0.5,  0.5,
 | |
|     0.5,  0.5,  0.5,  0.5,  0.5,  0.5,  0.5,  0.5,  0.5,  0.5,
 | |
|     0.25,  0.25,  0.25,  0.25,  0.25,  0.25,  0.25,  0.25,  0.25,  0.25,
 | |
|     0.25,  0.25,  0.25,  0.25,  0.25,  0.25,  0.25,  0.25,  0.25,  0.25,
 | |
|     0.25,  0.25,  0.25,  0.25,  0.25,  0.25,  0.25,  0.25,  0.25,  0.25,
 | |
|     0.25,  0.25,  0.25,  0.25,  0.25,  0.25,  0.25,  0.25,  0.25,  0.25,
 | |
|     0.25,  0.25,  0.25,  0.25,  0.25,  0.25,  0.25,  0.25,  0.25,  0.25,
 | |
|     0.25,  0.25,  0.25,  0.25,  0.25,  0.25,  0.25,  0.25,  0.25,  0.25,
 | |
|     0.25,  0.25,  0.25,  0.25,  0.25,  0.25,  0.25,  0.25,  0.25,  0.25,
 | |
|     0.25,  0.25,  0.25,  0.25,  0.25,  0.25,  0.25,  0.25,  0.25,  0.25,
 | |
|     0.25,  0.25,  0.25,  0.25,  0.25,  0.25,  0.25,  0.25,  0.25,  0.25,
 | |
|     0.25,  0.25,  0.25,  0.25,  0.25,  0.25,  0.25,  0.25,  0.25,  0.25,
 | |
|     0.25,  0.25,  0.25,  0.25,  0.25,  0.25,  0.25,  0.25,  0.25,  0.25,
 | |
|     0.25,  0.25,  0.25,  0.25,  0.25,  0.25,  0.25,  0.25,  0.25,  0.25
 | |
|   };
 | |
|   float *fa_ptr= float_array;
 | |
|   /* Number of columns per row */
 | |
|   const int COLUMN_COUNT= sizeof(float_array)/sizeof(*float_array);
 | |
|   /* Number of rows per bulk insert to start with */
 | |
|   const int MIN_ROWS_PER_INSERT= 262;
 | |
|   /* Max number of rows per bulk insert to end with */
 | |
|   const int MAX_ROWS_PER_INSERT= 300;
 | |
|   const int MAX_PARAM_COUNT= COLUMN_COUNT*MAX_ROWS_PER_INSERT;
 | |
|   const char *query_template= "insert into t1 values %s";
 | |
|   const int CHARS_PER_PARAM= 5; /* space needed to place ", ?" in the query */
 | |
|   const int uint16_max= 65535;
 | |
|   int nrows, i;
 | |
| 
 | |
|   myheader("test_bug5194");
 | |
| 
 | |
|   stmt_text= "drop table if exists t1";
 | |
|   rc= mysql_real_query(mysql, stmt_text, strlen(stmt_text));
 | |
| 
 | |
|   stmt_text= "create table if not exists t1"
 | |
|    "(c1 float, c2 float, c3 float, c4 float, c5 float, c6 float, "
 | |
|    "c7 float, c8 float, c9 float, c10 float, c11 float, c12 float, "
 | |
|    "c13 float, c14 float, c15 float, c16 float, c17 float, c18 float, "
 | |
|    "c19 float, c20 float, c21 float, c22 float, c23 float, c24 float, "
 | |
|    "c25 float, c26 float, c27 float, c28 float, c29 float, c30 float, "
 | |
|    "c31 float, c32 float, c33 float, c34 float, c35 float, c36 float, "
 | |
|    "c37 float, c38 float, c39 float, c40 float, c41 float, c42 float, "
 | |
|    "c43 float, c44 float, c45 float, c46 float, c47 float, c48 float, "
 | |
|    "c49 float, c50 float, c51 float, c52 float, c53 float, c54 float, "
 | |
|    "c55 float, c56 float, c57 float, c58 float, c59 float, c60 float, "
 | |
|    "c61 float, c62 float, c63 float, c64 float, c65 float, c66 float, "
 | |
|    "c67 float, c68 float, c69 float, c70 float, c71 float, c72 float, "
 | |
|    "c73 float, c74 float, c75 float, c76 float, c77 float, c78 float, "
 | |
|    "c79 float, c80 float, c81 float, c82 float, c83 float, c84 float, "
 | |
|    "c85 float, c86 float, c87 float, c88 float, c89 float, c90 float, "
 | |
|    "c91 float, c92 float, c93 float, c94 float, c95 float, c96 float, "
 | |
|    "c97 float, c98 float, c99 float, c100 float, c101 float, c102 float, "
 | |
|    "c103 float, c104 float, c105 float, c106 float, c107 float, c108 float, "
 | |
|    "c109 float, c110 float, c111 float, c112 float, c113 float, c114 float, "
 | |
|    "c115 float, c116 float, c117 float, c118 float, c119 float, c120 float, "
 | |
|    "c121 float, c122 float, c123 float, c124 float, c125 float, c126 float, "
 | |
|    "c127 float, c128 float, c129 float, c130 float, c131 float, c132 float, "
 | |
|    "c133 float, c134 float, c135 float, c136 float, c137 float, c138 float, "
 | |
|    "c139 float, c140 float, c141 float, c142 float, c143 float, c144 float, "
 | |
|    "c145 float, c146 float, c147 float, c148 float, c149 float, c150 float, "
 | |
|    "c151 float, c152 float, c153 float, c154 float, c155 float, c156 float, "
 | |
|    "c157 float, c158 float, c159 float, c160 float, c161 float, c162 float, "
 | |
|    "c163 float, c164 float, c165 float, c166 float, c167 float, c168 float, "
 | |
|    "c169 float, c170 float, c171 float, c172 float, c173 float, c174 float, "
 | |
|    "c175 float, c176 float, c177 float, c178 float, c179 float, c180 float, "
 | |
|    "c181 float, c182 float, c183 float, c184 float, c185 float, c186 float, "
 | |
|    "c187 float, c188 float, c189 float, c190 float, c191 float, c192 float, "
 | |
|    "c193 float, c194 float, c195 float, c196 float, c197 float, c198 float, "
 | |
|    "c199 float, c200 float, c201 float, c202 float, c203 float, c204 float, "
 | |
|    "c205 float, c206 float, c207 float, c208 float, c209 float, c210 float, "
 | |
|    "c211 float, c212 float, c213 float, c214 float, c215 float, c216 float, "
 | |
|    "c217 float, c218 float, c219 float, c220 float, c221 float, c222 float, "
 | |
|    "c223 float, c224 float, c225 float, c226 float, c227 float, c228 float, "
 | |
|    "c229 float, c230 float, c231 float, c232 float, c233 float, c234 float, "
 | |
|    "c235 float, c236 float, c237 float, c238 float, c239 float, c240 float, "
 | |
|    "c241 float, c242 float, c243 float, c244 float, c245 float, c246 float, "
 | |
|    "c247 float, c248 float, c249 float, c250 float)";
 | |
|   rc= mysql_real_query(mysql, stmt_text, strlen(stmt_text));
 | |
|   myquery(rc);
 | |
| 
 | |
|   my_bind= (MYSQL_BIND*) malloc(MAX_PARAM_COUNT * sizeof(MYSQL_BIND));
 | |
|   query= (char*) malloc(strlen(query_template) +
 | |
|                         MAX_PARAM_COUNT * CHARS_PER_PARAM + 1);
 | |
|   param_str= (char*) malloc(COLUMN_COUNT * CHARS_PER_PARAM);
 | |
| 
 | |
|   if (my_bind == 0 || query == 0 || param_str == 0)
 | |
|   {
 | |
|     fprintf(stderr, "Can't allocate enough memory for query structs\n");
 | |
|     if (my_bind)
 | |
|       free(my_bind);
 | |
|     if (query)
 | |
|       free(query);
 | |
|     if (param_str)
 | |
|       free(param_str);
 | |
|     return;
 | |
|   }
 | |
| 
 | |
|   stmt= mysql_stmt_init(mysql);
 | |
| 
 | |
|   /* setup a template for one row of parameters */
 | |
|   sprintf(param_str, "(");
 | |
|   for (i= 1; i < COLUMN_COUNT; ++i)
 | |
|     strcat(param_str, "?, ");
 | |
|   strcat(param_str, "?)");
 | |
|   param_str_length= strlen(param_str);
 | |
| 
 | |
|   /* setup bind array */
 | |
|   bzero((char*) my_bind, MAX_PARAM_COUNT * sizeof(MYSQL_BIND));
 | |
|   for (i= 0; i < MAX_PARAM_COUNT; ++i)
 | |
|   {
 | |
|     my_bind[i].buffer_type= MYSQL_TYPE_FLOAT;
 | |
|     my_bind[i].buffer= fa_ptr;
 | |
|     if (++fa_ptr == float_array + COLUMN_COUNT)
 | |
|       fa_ptr= float_array;
 | |
|   }
 | |
| 
 | |
|   /*
 | |
|     Test each number of rows per bulk insert, so that we can see where
 | |
|     MySQL fails.
 | |
|   */
 | |
|   for (nrows= MIN_ROWS_PER_INSERT; nrows <= MAX_ROWS_PER_INSERT; ++nrows)
 | |
|   {
 | |
|     char *query_ptr;
 | |
|     /* Create statement text for current number of rows */
 | |
|     sprintf(query, query_template, param_str);
 | |
|     query_ptr= query + strlen(query);
 | |
|     for (i= 1; i < nrows; ++i)
 | |
|     {
 | |
|       memcpy(query_ptr, ", ", 2);
 | |
|       query_ptr+= 2;
 | |
|       memcpy(query_ptr, param_str, param_str_length);
 | |
|       query_ptr+= param_str_length;
 | |
|     }
 | |
|     *query_ptr= '\0';
 | |
| 
 | |
|     rc= mysql_stmt_prepare(stmt, query, (ulong)(query_ptr - query));
 | |
|     if (rc && nrows * COLUMN_COUNT > uint16_max)
 | |
|     {
 | |
|       if (!opt_silent)
 | |
|         printf("Failed to prepare a statement with %d placeholders "
 | |
|                "(as expected).\n", nrows * COLUMN_COUNT);
 | |
|       break;
 | |
|     }
 | |
|     else
 | |
|       check_execute(stmt, rc);
 | |
| 
 | |
|     if (!opt_silent)
 | |
|       printf("Insert: query length= %d, row count= %d, param count= %lu\n",
 | |
|              (int) strlen(query), nrows, mysql_stmt_param_count(stmt));
 | |
| 
 | |
|     /* bind the parameter array and execute the query */
 | |
|     rc= mysql_stmt_bind_param(stmt, my_bind);
 | |
|     check_execute(stmt, rc);
 | |
| 
 | |
|     rc= mysql_stmt_execute(stmt);
 | |
|     check_execute(stmt, rc);
 | |
|     mysql_stmt_reset(stmt);
 | |
|   }
 | |
| 
 | |
|   mysql_stmt_close(stmt);
 | |
|   free(my_bind);
 | |
|   free(query);
 | |
|   free(param_str);
 | |
|   stmt_text= "drop table t1";
 | |
|   rc= mysql_real_query(mysql, stmt_text, strlen(stmt_text));
 | |
|   myquery(rc);
 | |
| }
 | |
| 
 | |
| 
 | |
| static void test_bug5315()
 | |
| {
 | |
|   MYSQL_STMT *stmt;
 | |
|   const char *stmt_text;
 | |
|   int rc;
 | |
| 
 | |
|   myheader("test_bug5315");
 | |
| 
 | |
|   stmt_text= "SELECT 1";
 | |
|   stmt= mysql_stmt_init(mysql);
 | |
|   rc= mysql_stmt_prepare(stmt, stmt_text, strlen(stmt_text));
 | |
|   DIE_UNLESS(rc == 0);
 | |
|   if (!opt_silent)
 | |
|     printf("Executing mysql_change_user\n");
 | |
|   mysql_change_user(mysql, opt_user, opt_password, current_db);
 | |
|   if (!opt_silent)
 | |
|     printf("Executing mysql_stmt_execute\n");
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   DIE_UNLESS(rc != 0);
 | |
|   if (rc)
 | |
|   {
 | |
|     if (!opt_silent)
 | |
|       printf("Got error (as expected): '%s'\n", mysql_stmt_error(stmt));
 | |
|   }
 | |
|   /* check that connection is OK */
 | |
|   if (!opt_silent)
 | |
|     printf("Executing mysql_stmt_close\n");
 | |
|   mysql_stmt_close(stmt);
 | |
|   if (!opt_silent)
 | |
|     printf("Executing mysql_stmt_init\n");
 | |
|   stmt= mysql_stmt_init(mysql);
 | |
|   rc= mysql_stmt_prepare(stmt, stmt_text, strlen(stmt_text));
 | |
|   DIE_UNLESS(rc == 0);
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   DIE_UNLESS(rc == 0);
 | |
|   mysql_stmt_close(stmt);
 | |
| }
 | |
| 
 | |
| 
 | |
| static void test_bug6049()
 | |
| {
 | |
|   MYSQL_STMT *stmt;
 | |
|   MYSQL_BIND my_bind[1];
 | |
|   MYSQL_RES *res;
 | |
|   MYSQL_ROW row;
 | |
|   const char *stmt_text;
 | |
|   char buffer[30];
 | |
|   ulong length;
 | |
|   int rc;
 | |
| 
 | |
|   myheader("test_bug6049");
 | |
| 
 | |
|   stmt_text= "SELECT MAKETIME(-25, 12, 12)";
 | |
| 
 | |
|   rc= mysql_real_query(mysql, stmt_text, strlen(stmt_text));
 | |
|   myquery(rc);
 | |
|   res= mysql_store_result(mysql);
 | |
|   row= mysql_fetch_row(res);
 | |
| 
 | |
|   stmt= mysql_stmt_init(mysql);
 | |
|   rc= mysql_stmt_prepare(stmt, stmt_text, strlen(stmt_text));
 | |
|   check_execute(stmt, rc);
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   bzero((char*) my_bind, sizeof(my_bind));
 | |
|   my_bind[0].buffer_type    = MYSQL_TYPE_STRING;
 | |
|   my_bind[0].buffer         = &buffer;
 | |
|   my_bind[0].buffer_length  = sizeof(buffer);
 | |
|   my_bind[0].length         = &length;
 | |
| 
 | |
|   mysql_stmt_bind_result(stmt, my_bind);
 | |
|   rc= mysql_stmt_fetch(stmt);
 | |
|   DIE_UNLESS(rc == 0);
 | |
| 
 | |
|   if (!opt_silent)
 | |
|   {
 | |
|     printf("Result from query: %s\n", row[0]);
 | |
|     printf("Result from prepared statement: %s\n", (char*) buffer);
 | |
|   }
 | |
| 
 | |
|   DIE_UNLESS(strcmp(row[0], (char*) buffer) == 0);
 | |
| 
 | |
|   mysql_free_result(res);
 | |
|   mysql_stmt_close(stmt);
 | |
| }
 | |
| 
 | |
| 
 | |
| static void test_bug6058()
 | |
| {
 | |
|   MYSQL_STMT *stmt;
 | |
|   MYSQL_BIND my_bind[1];
 | |
|   MYSQL_RES *res;
 | |
|   MYSQL_ROW row;
 | |
|   const char *stmt_text;
 | |
|   char buffer[30];
 | |
|   ulong length;
 | |
|   int rc;
 | |
| 
 | |
|   myheader("test_bug6058");
 | |
| 
 | |
|   rc= mysql_query(mysql, "SET SQL_MODE=''");
 | |
|   myquery(rc);
 | |
| 
 | |
|   stmt_text= "SELECT CAST('0000-00-00' AS DATE)";
 | |
| 
 | |
|   rc= mysql_real_query(mysql, stmt_text, strlen(stmt_text));
 | |
|   myquery(rc);
 | |
|   res= mysql_store_result(mysql);
 | |
|   row= mysql_fetch_row(res);
 | |
| 
 | |
|   stmt= mysql_stmt_init(mysql);
 | |
|   rc= mysql_stmt_prepare(stmt, stmt_text, strlen(stmt_text));
 | |
|   check_execute(stmt, rc);
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   bzero((char*) my_bind, sizeof(my_bind));
 | |
|   my_bind[0].buffer_type    = MYSQL_TYPE_STRING;
 | |
|   my_bind[0].buffer         = &buffer;
 | |
|   my_bind[0].buffer_length  = sizeof(buffer);
 | |
|   my_bind[0].length         = &length;
 | |
| 
 | |
|   mysql_stmt_bind_result(stmt, my_bind);
 | |
|   rc= mysql_stmt_fetch(stmt);
 | |
|   DIE_UNLESS(rc == 0);
 | |
| 
 | |
|   if (!opt_silent)
 | |
|   {
 | |
|     printf("Result from query: %s\n", row[0]);
 | |
|     printf("Result from prepared statement: %s\n", buffer);
 | |
|   }
 | |
| 
 | |
|   DIE_UNLESS(strcmp(row[0], buffer) == 0);
 | |
| 
 | |
|   mysql_free_result(res);
 | |
|   mysql_stmt_close(stmt);
 | |
| }
 | |
| 
 | |
| 
 | |
| static void test_bug6059()
 | |
| {
 | |
|   MYSQL_STMT *stmt;
 | |
|   const char *stmt_text;
 | |
| 
 | |
|   myheader("test_bug6059");
 | |
| 
 | |
|   stmt_text= "SELECT 'foo' INTO OUTFILE 'x.3'";
 | |
| 
 | |
|   stmt= mysql_stmt_init(mysql);
 | |
|   (void) mysql_stmt_prepare(stmt, stmt_text, strlen(stmt_text));
 | |
|   DIE_UNLESS(mysql_stmt_field_count(stmt) == 0);
 | |
|   mysql_stmt_close(stmt);
 | |
| }
 | |
| 
 | |
| 
 | |
| static void test_bug6046()
 | |
| {
 | |
|   MYSQL_STMT *stmt;
 | |
|   const char *stmt_text;
 | |
|   int rc;
 | |
|   short b= 1;
 | |
|   MYSQL_BIND my_bind[1];
 | |
| 
 | |
|   myheader("test_bug6046");
 | |
| 
 | |
|   stmt_text= "DROP TABLE IF EXISTS t1";
 | |
|   rc= mysql_real_query(mysql, stmt_text, strlen(stmt_text));
 | |
|   myquery(rc);
 | |
|   stmt_text= "CREATE TABLE t1 (a int, b int)";
 | |
|   rc= mysql_real_query(mysql, stmt_text, strlen(stmt_text));
 | |
|   myquery(rc);
 | |
|   stmt_text= "INSERT INTO t1 VALUES (1,1),(2,2),(3,1),(4,2)";
 | |
|   rc= mysql_real_query(mysql, stmt_text, strlen(stmt_text));
 | |
|   myquery(rc);
 | |
| 
 | |
|   stmt= mysql_stmt_init(mysql);
 | |
| 
 | |
|   stmt_text= "SELECT t1.a FROM t1 NATURAL JOIN t1 as X1 "
 | |
|              "WHERE t1.b > ? ORDER BY t1.a";
 | |
| 
 | |
|   rc= mysql_stmt_prepare(stmt, stmt_text, strlen(stmt_text));
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   b= 1;
 | |
|   bzero((char*) my_bind, sizeof(my_bind));
 | |
|   my_bind[0].buffer= &b;
 | |
|   my_bind[0].buffer_type= MYSQL_TYPE_SHORT;
 | |
| 
 | |
|   mysql_stmt_bind_param(stmt, my_bind);
 | |
| 
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
|   mysql_stmt_store_result(stmt);
 | |
| 
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   mysql_stmt_close(stmt);
 | |
| }
 | |
| 
 | |
| 
 | |
| 
 | |
| static void test_basic_cursors()
 | |
| {
 | |
|   const char *basic_tables[]=
 | |
|   {
 | |
|     "DROP TABLE IF EXISTS t1, t2",
 | |
| 
 | |
|     "CREATE TABLE t1 "
 | |
|     "(id INTEGER NOT NULL PRIMARY KEY, "
 | |
|     " name VARCHAR(20) NOT NULL)",
 | |
| 
 | |
|     "INSERT INTO t1 (id, name) VALUES "
 | |
|     "  (2, 'Ja'), (3, 'Ede'), "
 | |
|     "  (4, 'Haag'), (5, 'Kabul'), "
 | |
|     "  (6, 'Almere'), (7, 'Utrecht'), "
 | |
|     "  (8, 'Qandahar'), (9, 'Amsterdam'), "
 | |
|     "  (10, 'Amersfoort'), (11, 'Constantine')",
 | |
| 
 | |
|     "CREATE TABLE t2 "
 | |
|     "(id INTEGER NOT NULL PRIMARY KEY, "
 | |
|     " name VARCHAR(20) NOT NULL)",
 | |
| 
 | |
|     "INSERT INTO t2 (id, name) VALUES "
 | |
|     "  (4, 'Guam'), (5, 'Aruba'), "
 | |
|     "  (6, 'Angola'), (7, 'Albania'), "
 | |
|     "  (8, 'Anguilla'), (9, 'Argentina'), "
 | |
|     "  (10, 'Azerbaijan'), (11, 'Afghanistan'), "
 | |
|     "  (12, 'Burkina Faso'), (13, 'Faroe Islands')"
 | |
|   };
 | |
|   const char *queries[]=
 | |
|   {
 | |
|     "SELECT * FROM t1",
 | |
|     "SELECT * FROM t2"
 | |
|   };
 | |
| 
 | |
|   DBUG_ENTER("test_basic_cursors");
 | |
|   myheader("test_basic_cursors");
 | |
| 
 | |
|   fill_tables(basic_tables, sizeof(basic_tables)/sizeof(*basic_tables));
 | |
| 
 | |
|   fetch_n(queries, sizeof(queries)/sizeof(*queries), USE_ROW_BY_ROW_FETCH);
 | |
|   fetch_n(queries, sizeof(queries)/sizeof(*queries), USE_STORE_RESULT);
 | |
|   DBUG_VOID_RETURN;
 | |
| }
 | |
| 
 | |
| 
 | |
| static void test_cursors_with_union()
 | |
| {
 | |
|   const char *queries[]=
 | |
|   {
 | |
|     "SELECT t1.name FROM t1 UNION SELECT t2.name FROM t2",
 | |
|     "SELECT t1.id FROM t1 WHERE t1.id < 5"
 | |
|   };
 | |
|   myheader("test_cursors_with_union");
 | |
|   fetch_n(queries, sizeof(queries)/sizeof(*queries), USE_ROW_BY_ROW_FETCH);
 | |
|   fetch_n(queries, sizeof(queries)/sizeof(*queries), USE_STORE_RESULT);
 | |
| }
 | |
| 
 | |
| 
 | |
| static void test_cursors_with_procedure()
 | |
| {
 | |
|   const char *queries[]=
 | |
|   {
 | |
|     "SELECT * FROM t1 procedure analyse()"
 | |
|   };
 | |
|   myheader("test_cursors_with_procedure");
 | |
|   fetch_n(queries, sizeof(queries)/sizeof(*queries), USE_ROW_BY_ROW_FETCH);
 | |
|   fetch_n(queries, sizeof(queries)/sizeof(*queries), USE_STORE_RESULT);
 | |
| }
 | |
| 
 | |
| 
 | |
| /*
 | |
|   Altough mysql_create_db(), mysql_rm_db() are deprecated since 4.0 they
 | |
|   should not crash server and should not hang in case of errors.
 | |
| 
 | |
|   Since those functions can't be seen in modern API (unless client library
 | |
|   was compiled with USE_OLD_FUNCTIONS define) we use simple_command() macro.
 | |
| */
 | |
| static void test_bug6081()
 | |
| {
 | |
|   int rc;
 | |
|   myheader("test_bug6081");
 | |
| 
 | |
|   rc= simple_command(mysql, COM_DROP_DB, (uchar*) current_db,
 | |
|                      (ulong)strlen(current_db), 0);
 | |
|   if (rc == 0 && mysql_errno(mysql) != ER_UNKNOWN_COM_ERROR)
 | |
|   {
 | |
|     myerror(NULL);                                   /* purecov: inspected */
 | |
|     die(__FILE__, __LINE__, "COM_DROP_DB failed");   /* purecov: inspected */
 | |
|   }
 | |
|   rc= simple_command(mysql, COM_DROP_DB, (uchar*) current_db,
 | |
|                      (ulong)strlen(current_db), 0);
 | |
|   myquery_r(rc);
 | |
|   rc= simple_command(mysql, COM_CREATE_DB, (uchar*) current_db,
 | |
|                      (ulong)strlen(current_db), 0);
 | |
|   if (rc == 0 && mysql_errno(mysql) != ER_UNKNOWN_COM_ERROR)
 | |
|   {
 | |
|     myerror(NULL);                                   /* purecov: inspected */
 | |
|     die(__FILE__, __LINE__, "COM_CREATE_DB failed"); /* purecov: inspected */
 | |
|   }
 | |
|   rc= simple_command(mysql, COM_CREATE_DB, (uchar*) current_db,
 | |
|                      (ulong)strlen(current_db), 0);
 | |
|   myquery_r(rc);
 | |
|   rc= mysql_select_db(mysql, current_db);
 | |
|   myquery(rc);
 | |
| }
 | |
| 
 | |
| 
 | |
| static void test_bug6096()
 | |
| {
 | |
|   MYSQL_STMT *stmt;
 | |
|   MYSQL_RES *query_result, *stmt_metadata;
 | |
|   const char *stmt_text;
 | |
|   MYSQL_BIND my_bind[12];
 | |
|   MYSQL_FIELD *query_field_list, *stmt_field_list;
 | |
|   ulong query_field_count, stmt_field_count;
 | |
|   int rc;
 | |
|   my_bool update_max_length= TRUE;
 | |
|   uint i;
 | |
| 
 | |
|   myheader("test_bug6096");
 | |
| 
 | |
|   stmt_text= "drop table if exists t1";
 | |
|   rc= mysql_real_query(mysql, stmt_text, strlen(stmt_text));
 | |
|   myquery(rc);
 | |
| 
 | |
|   mysql_query(mysql, "set sql_mode=''");
 | |
|   stmt_text= "create table t1 (c_tinyint tinyint, c_smallint smallint, "
 | |
|                              " c_mediumint mediumint, c_int int, "
 | |
|                              " c_bigint bigint, c_float float, "
 | |
|                              " c_double double, c_varchar varchar(20), "
 | |
|                              " c_char char(20), c_time time, c_date date, "
 | |
|                              " c_datetime datetime)";
 | |
|   rc= mysql_real_query(mysql, stmt_text, strlen(stmt_text));
 | |
|   myquery(rc);
 | |
|   stmt_text= "insert into t1  values (-100, -20000, 30000000, 4, 8, 1.0, "
 | |
|                                      "2.0, 'abc', 'def', now(), now(), now())";
 | |
|   rc= mysql_real_query(mysql, stmt_text, strlen(stmt_text));
 | |
|   myquery(rc);
 | |
| 
 | |
|   stmt_text= "select * from t1";
 | |
| 
 | |
|   /* Run select in prepared and non-prepared mode and compare metadata */
 | |
|   rc= mysql_real_query(mysql, stmt_text, strlen(stmt_text));
 | |
|   myquery(rc);
 | |
|   query_result= mysql_store_result(mysql);
 | |
|   query_field_list= mysql_fetch_fields(query_result);
 | |
|   query_field_count= mysql_num_fields(query_result);
 | |
| 
 | |
|   stmt= mysql_stmt_init(mysql);
 | |
|   rc= mysql_stmt_prepare(stmt, stmt_text, strlen(stmt_text));
 | |
|   check_execute(stmt, rc);
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
|   mysql_stmt_attr_set(stmt, STMT_ATTR_UPDATE_MAX_LENGTH,
 | |
|                       (void*) &update_max_length);
 | |
|   mysql_stmt_store_result(stmt);
 | |
|   stmt_metadata= mysql_stmt_result_metadata(stmt);
 | |
|   stmt_field_list= mysql_fetch_fields(stmt_metadata);
 | |
|   stmt_field_count= mysql_num_fields(stmt_metadata);
 | |
|   DIE_UNLESS(stmt_field_count == query_field_count);
 | |
| 
 | |
|   /* Print out and check the metadata */
 | |
| 
 | |
|   if (!opt_silent)
 | |
|   {
 | |
|     printf(" ------------------------------------------------------------\n");
 | |
|     printf("             |                     Metadata \n");
 | |
|     printf(" ------------------------------------------------------------\n");
 | |
|     printf("             |         Query          |   Prepared statement \n");
 | |
|     printf(" ------------------------------------------------------------\n");
 | |
|     printf(" field name  |  length   | max_length |  length   |  max_length\n");
 | |
|     printf(" ------------------------------------------------------------\n");
 | |
| 
 | |
|     for (i= 0; i < query_field_count; ++i)
 | |
|     {
 | |
|       MYSQL_FIELD *f1= &query_field_list[i], *f2= &stmt_field_list[i];
 | |
|       printf(" %-11s | %9lu | %10lu | %9lu | %10lu \n",
 | |
|              f1->name, f1->length, f1->max_length, f2->length, f2->max_length);
 | |
|       DIE_UNLESS(f1->length == f2->length);
 | |
|     }
 | |
|     printf(" ---------------------------------------------------------------\n");
 | |
|   }
 | |
| 
 | |
|   /* Bind and fetch the data */
 | |
| 
 | |
|   bzero((char*) my_bind, sizeof(my_bind));
 | |
|   for (i= 0; i < stmt_field_count; ++i)
 | |
|   {
 | |
|     my_bind[i].buffer_type= MYSQL_TYPE_STRING;
 | |
|     my_bind[i].buffer_length= stmt_field_list[i].max_length + 1;
 | |
|     my_bind[i].buffer= malloc(my_bind[i].buffer_length);
 | |
|   }
 | |
|   mysql_stmt_bind_result(stmt, my_bind);
 | |
|   rc= mysql_stmt_fetch(stmt);
 | |
|   check_execute(stmt, rc);
 | |
|   rc= mysql_stmt_fetch(stmt);
 | |
|   DIE_UNLESS(rc == MYSQL_NO_DATA);
 | |
| 
 | |
|   /* Clean up */
 | |
| 
 | |
|   for (i= 0; i < stmt_field_count; ++i)
 | |
|     free(my_bind[i].buffer);
 | |
|   mysql_stmt_close(stmt);
 | |
|   mysql_free_result(query_result);
 | |
|   mysql_free_result(stmt_metadata);
 | |
|   stmt_text= "drop table t1";
 | |
|   rc= mysql_real_query(mysql, stmt_text, strlen(stmt_text));
 | |
|   myquery(rc);
 | |
| }
 | |
| 
 | |
| 
 | |
| /*
 | |
|   Test of basic checks that are performed in server for components
 | |
|   of MYSQL_TIME parameters.
 | |
| */
 | |
| 
 | |
| static void test_datetime_ranges()
 | |
| {
 | |
|   const char *stmt_text;
 | |
|   int rc, i;
 | |
|   MYSQL_STMT *stmt;
 | |
|   MYSQL_BIND my_bind[6];
 | |
|   MYSQL_TIME tm[6];
 | |
| 
 | |
|   myheader("test_datetime_ranges");
 | |
| 
 | |
|   stmt_text= "drop table if exists t1";
 | |
|   rc= mysql_real_query(mysql, stmt_text, strlen(stmt_text));
 | |
|   myquery(rc);
 | |
| 
 | |
|   stmt_text= "create table t1 (year datetime, month datetime, day datetime, "
 | |
|                               "hour datetime, min datetime, sec datetime)";
 | |
|   rc= mysql_real_query(mysql, stmt_text, strlen(stmt_text));
 | |
|   myquery(rc);
 | |
| 
 | |
|   stmt= mysql_simple_prepare(mysql,
 | |
|                              "INSERT INTO t1 VALUES (?, ?, ?, ?, ?, ?)");
 | |
|   check_stmt(stmt);
 | |
|   verify_param_count(stmt, 6);
 | |
| 
 | |
|   bzero((char*) my_bind, sizeof(my_bind));
 | |
|   for (i= 0; i < 6; i++)
 | |
|   {
 | |
|     my_bind[i].buffer_type= MYSQL_TYPE_DATETIME;
 | |
|     my_bind[i].buffer= &tm[i];
 | |
|   }
 | |
|   rc= mysql_stmt_bind_param(stmt, my_bind);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   tm[0].year= 2004; tm[0].month= 11; tm[0].day= 10;
 | |
|   tm[0].hour= 12; tm[0].minute= 30; tm[0].second= 30;
 | |
|   tm[0].second_part= 0; tm[0].neg= 0;
 | |
| 
 | |
|   tm[5]= tm[4]= tm[3]= tm[2]= tm[1]= tm[0];
 | |
|   tm[0].year= 10000;  tm[1].month= 13; tm[2].day= 32;
 | |
|   tm[3].hour= 24; tm[4].minute= 60; tm[5].second= 60;
 | |
| 
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
|   my_process_warnings(mysql, 6);
 | |
| 
 | |
|   verify_col_data("t1", "year", "0000-00-00 00:00:00");
 | |
|   verify_col_data("t1", "month", "0000-00-00 00:00:00");
 | |
|   verify_col_data("t1", "day", "0000-00-00 00:00:00");
 | |
|   verify_col_data("t1", "hour", "0000-00-00 00:00:00");
 | |
|   verify_col_data("t1", "min", "0000-00-00 00:00:00");
 | |
|   verify_col_data("t1", "sec", "0000-00-00 00:00:00");
 | |
| 
 | |
|   mysql_stmt_close(stmt);
 | |
| 
 | |
|   stmt_text= "delete from t1";
 | |
|   rc= mysql_real_query(mysql, stmt_text, strlen(stmt_text));
 | |
|   myquery(rc);
 | |
| 
 | |
|   stmt= mysql_simple_prepare(mysql, "INSERT INTO t1 (year, month, day) "
 | |
|                                     "VALUES (?, ?, ?)");
 | |
|   check_stmt(stmt);
 | |
|   verify_param_count(stmt, 3);
 | |
| 
 | |
|   /*
 | |
|     We reuse contents of bind and tm arrays left from previous part of test.
 | |
|   */
 | |
|   for (i= 0; i < 3; i++)
 | |
|     my_bind[i].buffer_type= MYSQL_TYPE_DATE;
 | |
| 
 | |
|   rc= mysql_stmt_bind_param(stmt, my_bind);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
|   my_process_warnings(mysql, 3);
 | |
| 
 | |
|   verify_col_data("t1", "year", "0000-00-00 00:00:00");
 | |
|   verify_col_data("t1", "month", "0000-00-00 00:00:00");
 | |
|   verify_col_data("t1", "day", "0000-00-00 00:00:00");
 | |
| 
 | |
|   mysql_stmt_close(stmt);
 | |
| 
 | |
|   stmt_text= "drop table t1";
 | |
|   rc= mysql_real_query(mysql, stmt_text, strlen(stmt_text));
 | |
|   myquery(rc);
 | |
| 
 | |
|   stmt_text= "create table t1 (day_ovfl time, day time, hour time, min time, sec time)";
 | |
|   rc= mysql_real_query(mysql, stmt_text, strlen(stmt_text));
 | |
|   myquery(rc);
 | |
| 
 | |
|   stmt= mysql_simple_prepare(mysql,
 | |
|                              "INSERT INTO t1 VALUES (?, ?, ?, ?, ?)");
 | |
|   check_stmt(stmt);
 | |
|   verify_param_count(stmt, 5);
 | |
| 
 | |
|   /*
 | |
|     Again we reuse what we can from previous part of test.
 | |
|   */
 | |
|   for (i= 0; i < 5; i++)
 | |
|     my_bind[i].buffer_type= MYSQL_TYPE_TIME;
 | |
| 
 | |
|   rc= mysql_stmt_bind_param(stmt, my_bind);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   tm[0].year= 0; tm[0].month= 0; tm[0].day= 10;
 | |
|   tm[0].hour= 12; tm[0].minute= 30; tm[0].second= 30;
 | |
|   tm[0].second_part= 0; tm[0].neg= 0;
 | |
| 
 | |
|   tm[4]= tm[3]= tm[2]= tm[1]= tm[0];
 | |
|   tm[0].day= 35; tm[1].day= 34; tm[2].hour= 30; tm[3].minute= 60; tm[4].second= 60;
 | |
| 
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
|   my_process_warnings(mysql, 2);
 | |
| 
 | |
|   verify_col_data("t1", "day_ovfl", "838:59:59");
 | |
|   verify_col_data("t1", "day", "828:30:30");
 | |
|   verify_col_data("t1", "hour", "270:30:30");
 | |
|   verify_col_data("t1", "min", "00:00:00");
 | |
|   verify_col_data("t1", "sec", "00:00:00");
 | |
| 
 | |
|   mysql_stmt_close(stmt);
 | |
| 
 | |
|   stmt_text= "drop table t1";
 | |
|   rc= mysql_real_query(mysql, stmt_text, strlen(stmt_text));
 | |
|   myquery(rc);
 | |
| }
 | |
| 
 | |
| 
 | |
| /*
 | |
|   This test is used in:
 | |
|   mysql-test/suite/binlog/binlog_stm_datetime_ranges_mdev15289.test
 | |
| */
 | |
| static void test_datetime_ranges_mdev15289()
 | |
| {
 | |
|   const char *stmt_text;
 | |
|   int rc, i;
 | |
|   MYSQL_STMT *stmt;
 | |
|   MYSQL_BIND my_bind[4];
 | |
|   MYSQL_TIME tm[4];
 | |
| 
 | |
|   myheader("test_datetime_ranges_mdev15289");
 | |
| 
 | |
|   stmt_text= "SET sql_mode=''";
 | |
|   rc= mysql_real_query(mysql, stmt_text, strlen(stmt_text));
 | |
|   myquery(rc);
 | |
| 
 | |
|   stmt_text= "create or replace table t1 "
 | |
|              "(t time, d date, dt datetime,ts timestamp)";
 | |
|   rc= mysql_real_query(mysql, stmt_text, strlen(stmt_text));
 | |
|   myquery(rc);
 | |
| 
 | |
|   stmt= mysql_simple_prepare(mysql, "INSERT INTO t1 VALUES (?, ?, ?, ?)");
 | |
|   check_stmt(stmt);
 | |
|   verify_param_count(stmt, 4);
 | |
| 
 | |
|   /*** Testing DATETIME ***/
 | |
|   bzero((char*) my_bind, sizeof(my_bind));
 | |
|   for (i= 0; i < 4; i++)
 | |
|   {
 | |
|     my_bind[i].buffer_type= MYSQL_TYPE_DATETIME;
 | |
|     my_bind[i].buffer= &tm[i];
 | |
|   }
 | |
|   rc= mysql_stmt_bind_param(stmt, my_bind);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   /* Notice bad year */
 | |
|   tm[0].year= 20010; tm[0].month= 1; tm[0].day= 2;
 | |
|   tm[0].hour= 03; tm[0].minute= 04; tm[0].second= 05;
 | |
|   tm[0].second_part= 0; tm[0].neg= 0;
 | |
|   tm[0].time_type= MYSQL_TIMESTAMP_DATETIME;
 | |
|   tm[3]= tm[2]= tm[1]= tm[0];
 | |
| 
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
|   my_process_warnings(mysql, 4);
 | |
| 
 | |
|   verify_col_data("t1", "t", "00:00:00");
 | |
|   verify_col_data("t1", "d", "0000-00-00");
 | |
|   verify_col_data("t1", "dt", "0000-00-00 00:00:00");
 | |
|   verify_col_data("t1", "ts", "0000-00-00 00:00:00");
 | |
| 
 | |
|   /*** Testing DATE ***/
 | |
|   bzero((char*) my_bind, sizeof(my_bind));
 | |
|   for (i= 0; i < 4; i++)
 | |
|   {
 | |
|     my_bind[i].buffer_type= MYSQL_TYPE_DATE;
 | |
|     my_bind[i].buffer= &tm[i];
 | |
|   }
 | |
|   rc= mysql_stmt_bind_param(stmt, my_bind);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   /* Notice bad year */
 | |
|   tm[0].year= 20010; tm[0].month= 1; tm[0].day= 2;
 | |
|   tm[0].hour= 00; tm[0].minute= 00; tm[0].second= 00;
 | |
|   tm[0].second_part= 0; tm[0].neg= 0;
 | |
|   tm[0].time_type= MYSQL_TIMESTAMP_DATE;
 | |
|   tm[3]= tm[2]= tm[1]= tm[0];
 | |
| 
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
|   my_process_warnings(mysql, 4);
 | |
| 
 | |
|   verify_col_data("t1", "t", "00:00:00");
 | |
|   verify_col_data("t1", "d", "0000-00-00");
 | |
|   verify_col_data("t1", "dt", "0000-00-00 00:00:00");
 | |
|   verify_col_data("t1", "ts", "0000-00-00 00:00:00");
 | |
| 
 | |
|   /*** Testing TIME ***/
 | |
|   bzero((char*) my_bind, sizeof(my_bind));
 | |
|   for (i= 0; i < 4; i++)
 | |
|   {
 | |
|     my_bind[i].buffer_type= MYSQL_TYPE_TIME;
 | |
|     my_bind[i].buffer= &tm[i];
 | |
|   }
 | |
|   rc= mysql_stmt_bind_param(stmt, my_bind);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   /* Notice bad hour */
 | |
|   tm[0].year= 0; tm[0].month= 0; tm[0].day= 0;
 | |
|   tm[0].hour= 100; tm[0].minute= 64; tm[0].second= 05;
 | |
|   tm[0].second_part= 0; tm[0].neg= 0;
 | |
|   tm[0].time_type= MYSQL_TIMESTAMP_TIME;
 | |
|   tm[3]= tm[2]= tm[1]= tm[0];
 | |
| 
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
|   my_process_warnings(mysql, 4);
 | |
| 
 | |
|   verify_col_data("t1", "t", "00:00:00");
 | |
|   verify_col_data("t1", "d", "0000-00-00");
 | |
|   verify_col_data("t1", "dt", "0000-00-00 00:00:00");
 | |
|   verify_col_data("t1", "ts", "0000-00-00 00:00:00");
 | |
| 
 | |
|   mysql_stmt_close(stmt);
 | |
| 
 | |
|   stmt_text= "drop table t1";
 | |
|   rc= mysql_real_query(mysql, stmt_text, strlen(stmt_text));
 | |
|   myquery(rc);
 | |
| }
 | |
| 
 | |
| 
 | |
| static void test_bug4172()
 | |
| {
 | |
|   MYSQL_STMT *stmt;
 | |
|   MYSQL_BIND my_bind[3];
 | |
|   const char *stmt_text;
 | |
|   MYSQL_RES *res;
 | |
|   MYSQL_ROW row;
 | |
|   int rc;
 | |
|   char f[100], d[100], e[100];
 | |
|   ulong f_len, d_len, e_len;
 | |
| 
 | |
|   myheader("test_bug4172");
 | |
| 
 | |
|   mysql_query(mysql, "DROP TABLE IF EXISTS t1");
 | |
|   mysql_query(mysql, "CREATE TABLE t1 (f float, d double, e decimal(10,4))");
 | |
|   mysql_query(mysql, "INSERT INTO t1 VALUES (12345.1234, 123456.123456, "
 | |
|                                             "123456.1234)");
 | |
| 
 | |
|   stmt= mysql_stmt_init(mysql);
 | |
|   stmt_text= "SELECT f, d, e FROM t1";
 | |
| 
 | |
|   rc= mysql_stmt_prepare(stmt, stmt_text, strlen(stmt_text));
 | |
|   check_execute(stmt, rc);
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   bzero((char*) my_bind, sizeof(my_bind));
 | |
|   my_bind[0].buffer_type= MYSQL_TYPE_STRING;
 | |
|   my_bind[0].buffer= f;
 | |
|   my_bind[0].buffer_length= sizeof(f);
 | |
|   my_bind[0].length= &f_len;
 | |
|   my_bind[1].buffer_type= MYSQL_TYPE_STRING;
 | |
|   my_bind[1].buffer= d;
 | |
|   my_bind[1].buffer_length= sizeof(d);
 | |
|   my_bind[1].length= &d_len;
 | |
|   my_bind[2].buffer_type= MYSQL_TYPE_STRING;
 | |
|   my_bind[2].buffer= e;
 | |
|   my_bind[2].buffer_length= sizeof(e);
 | |
|   my_bind[2].length= &e_len;
 | |
| 
 | |
|   mysql_stmt_bind_result(stmt, my_bind);
 | |
| 
 | |
|   mysql_stmt_store_result(stmt);
 | |
|   rc= mysql_stmt_fetch(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= mysql_real_query(mysql, stmt_text, strlen(stmt_text));
 | |
|   myquery(rc);
 | |
|   res= mysql_store_result(mysql);
 | |
|   row= mysql_fetch_row(res);
 | |
| 
 | |
|   if (!opt_silent)
 | |
|   {
 | |
|     printf("Binary protocol: float=%s, double=%s, decimal(10,4)=%s\n",
 | |
|            f, d, e);
 | |
|     printf("Text protocol:   float=%s, double=%s, decimal(10,4)=%s\n",
 | |
|            row[0], row[1], row[2]);
 | |
|   }
 | |
|   DIE_UNLESS(!strcmp(f, row[0]) && !strcmp(d, row[1]) && !strcmp(e, row[2]));
 | |
| 
 | |
|   mysql_free_result(res);
 | |
|   mysql_stmt_close(stmt);
 | |
| }
 | |
| 
 | |
| 
 | |
| static void test_conversion()
 | |
| {
 | |
|   MYSQL_STMT *stmt;
 | |
|   const char *stmt_text;
 | |
|   int rc;
 | |
|   MYSQL_BIND my_bind[1];
 | |
|   uchar buff[4];
 | |
|   ulong length;
 | |
| 
 | |
|   myheader("test_conversion");
 | |
| 
 | |
|   stmt_text= "DROP TABLE IF EXISTS t1";
 | |
|   rc= mysql_real_query(mysql, stmt_text, strlen(stmt_text));
 | |
|   myquery(rc);
 | |
|   stmt_text= "CREATE TABLE t1 (a TEXT) DEFAULT CHARSET latin1";
 | |
|   rc= mysql_real_query(mysql, stmt_text, strlen(stmt_text));
 | |
|   myquery(rc);
 | |
|   stmt_text= "SET character_set_connection=utf8, character_set_client=utf8, "
 | |
|              " character_set_results=latin1";
 | |
|   rc= mysql_real_query(mysql, stmt_text, strlen(stmt_text));
 | |
|   myquery(rc);
 | |
| 
 | |
|   stmt= mysql_stmt_init(mysql);
 | |
| 
 | |
|   stmt_text= "INSERT INTO t1 (a) VALUES (?)";
 | |
|   rc= mysql_stmt_prepare(stmt, stmt_text, strlen(stmt_text));
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   bzero((char*) my_bind, sizeof(my_bind));
 | |
|   my_bind[0].buffer= (char*) buff;
 | |
|   my_bind[0].length= &length;
 | |
|   my_bind[0].buffer_type= MYSQL_TYPE_STRING;
 | |
| 
 | |
|   mysql_stmt_bind_param(stmt, my_bind);
 | |
| 
 | |
|   buff[0]= (uchar) 0xC3;
 | |
|   buff[1]= (uchar) 0xA0;
 | |
|   length= 2;
 | |
| 
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   stmt_text= "SELECT a FROM t1";
 | |
|   rc= mysql_stmt_prepare(stmt, stmt_text, strlen(stmt_text));
 | |
|   check_execute(stmt, rc);
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   my_bind[0].buffer_length= sizeof(buff);
 | |
|   mysql_stmt_bind_result(stmt, my_bind);
 | |
| 
 | |
|   rc= mysql_stmt_fetch(stmt);
 | |
|   DIE_UNLESS(rc == 0);
 | |
|   DIE_UNLESS(length == 1);
 | |
|   DIE_UNLESS(buff[0] == 0xE0);
 | |
|   rc= mysql_stmt_fetch(stmt);
 | |
|   DIE_UNLESS(rc == MYSQL_NO_DATA);
 | |
| 
 | |
|   mysql_stmt_close(stmt);
 | |
|   stmt_text= "DROP TABLE t1";
 | |
|   rc= mysql_real_query(mysql, stmt_text, strlen(stmt_text));
 | |
|   myquery(rc);
 | |
|   stmt_text= "SET NAMES DEFAULT";
 | |
|   rc= mysql_real_query(mysql, stmt_text, strlen(stmt_text));
 | |
|   myquery(rc);
 | |
| }
 | |
| 
 | |
| static void test_rewind(void)
 | |
| {
 | |
|   MYSQL_STMT *stmt;
 | |
|   MYSQL_BIND my_bind;
 | |
|   int rc = 0;
 | |
|   const char *stmt_text;
 | |
|   long unsigned int length=4, Data=0;
 | |
|   my_bool isnull=0;
 | |
| 
 | |
|   myheader("test_rewind");
 | |
| 
 | |
|   stmt_text= "CREATE TABLE t1 (a int)";
 | |
|   rc= mysql_real_query(mysql, stmt_text, strlen(stmt_text));
 | |
|   myquery(rc);
 | |
|   stmt_text= "INSERT INTO t1 VALUES(2),(3),(4)";
 | |
|   rc= mysql_real_query(mysql, stmt_text, strlen(stmt_text));
 | |
|   myquery(rc);
 | |
| 
 | |
|   stmt= mysql_stmt_init(mysql);
 | |
| 
 | |
|   stmt_text= "SELECT * FROM t1";
 | |
|   rc= mysql_stmt_prepare(stmt, stmt_text, strlen(stmt_text));
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   bzero((char*) &my_bind, sizeof(MYSQL_BIND));
 | |
|   my_bind.buffer_type= MYSQL_TYPE_LONG;
 | |
|   my_bind.buffer= (void *)&Data; /* this buffer won't be altered */
 | |
|   my_bind.length= &length;
 | |
|   my_bind.is_null= &isnull;
 | |
| 
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= mysql_stmt_store_result(stmt);
 | |
|   DIE_UNLESS(rc == 0);
 | |
| 
 | |
|   rc= mysql_stmt_bind_result(stmt, &my_bind);
 | |
|   DIE_UNLESS(rc == 0);
 | |
| 
 | |
|   /* retreive all result sets till we are at the end */
 | |
|   while(!mysql_stmt_fetch(stmt))
 | |
|     if (!opt_silent)
 | |
|       printf("fetched result:%ld\n", Data);
 | |
| 
 | |
|   DIE_UNLESS(rc != MYSQL_NO_DATA);
 | |
| 
 | |
|   /* seek to the first row */
 | |
|   mysql_stmt_data_seek(stmt, 0);
 | |
| 
 | |
|   /* now we should be able to fetch the results again */
 | |
|   /* but mysql_stmt_fetch returns MYSQL_NO_DATA */
 | |
|   while(!(rc= mysql_stmt_fetch(stmt)))
 | |
|     if (!opt_silent)
 | |
|       printf("fetched result after seek:%ld\n", Data);
 | |
|   
 | |
|   DIE_UNLESS(rc == MYSQL_NO_DATA);
 | |
| 
 | |
|   stmt_text= "DROP TABLE t1";
 | |
|   rc= mysql_real_query(mysql, stmt_text, strlen(stmt_text));
 | |
|   myquery(rc);
 | |
|   rc= mysql_stmt_free_result(stmt);
 | |
|   rc= mysql_stmt_close(stmt);
 | |
| }
 | |
| 
 | |
| 
 | |
| static void test_truncation()
 | |
| {
 | |
|   MYSQL_STMT *stmt;
 | |
|   const char *stmt_text;
 | |
|   int rc;
 | |
|   uint bind_count;
 | |
|   MYSQL_BIND *bind_array, *my_bind;
 | |
| 
 | |
|   myheader("test_truncation");
 | |
| 
 | |
|   /* Prepare the test table */
 | |
|   rc= mysql_query(mysql, "drop table if exists t1");
 | |
|   myquery(rc);
 | |
| 
 | |
|   stmt_text= "create table t1 ("
 | |
|              "i8 tinyint, ui8 tinyint unsigned, "
 | |
|              "i16 smallint, i16_1 smallint, "
 | |
|              "ui16 smallint unsigned, i32 int, i32_1 int, "
 | |
|              "d double, d_1 double, ch char(30), ch_1 char(30), "
 | |
|              "tx text, tx_1 text, ch_2 char(30) "
 | |
|              ")";
 | |
|   rc= mysql_real_query(mysql, stmt_text, strlen(stmt_text));
 | |
|   myquery(rc);
 | |
| 
 | |
|   {
 | |
|     const char insert_text[]= 
 | |
|              "insert into t1 VALUES ("
 | |
|              "-10, "                            /* i8 */
 | |
|              "200, "                            /* ui8 */
 | |
|              "32000, "                          /* i16 */
 | |
|              "-32767, "                         /* i16_1 */
 | |
|              "64000, "                          /* ui16 */
 | |
|              "1073741824, "                     /* i32 */
 | |
|              "1073741825, "                     /* i32_1 */
 | |
|              "123.456, "                        /* d */
 | |
|              "-12345678910, "                   /* d_1 */
 | |
|              "'111111111111111111111111111111',"/* ch */
 | |
|              "'abcdef', "                       /* ch_1 */
 | |
|              "'12345 	      ', "              /* tx */
 | |
|              "'12345.67 	      ', "      /* tx_1 */
 | |
|              "'12345.67abc'"                    /* ch_2 */
 | |
|              ")";
 | |
|     rc= mysql_real_query(mysql, insert_text, strlen(insert_text));
 | |
|     myquery(rc);
 | |
|   }
 | |
| 
 | |
|   stmt_text= "select i8 c1, i8 c2, ui8 c3, i16_1 c4, ui16 c5, "
 | |
|              "       i16 c6, ui16 c7, i32 c8, i32_1 c9, i32_1 c10, "
 | |
|              "       d c11, d_1 c12, d_1 c13, ch c14, ch_1 c15, tx c16, "
 | |
|              "       tx_1 c17, ch_2 c18 "
 | |
|              "from t1";
 | |
| 
 | |
|   stmt= mysql_stmt_init(mysql);
 | |
|   rc= mysql_stmt_prepare(stmt, stmt_text, strlen(stmt_text));
 | |
|   check_execute(stmt, rc);
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
|   bind_count= (uint) mysql_stmt_field_count(stmt);
 | |
| 
 | |
|   /*************** Fill in the bind structure and bind it **************/
 | |
|   bind_array= malloc(sizeof(MYSQL_BIND) * bind_count);
 | |
|   bzero((char*) bind_array, sizeof(MYSQL_BIND) * bind_count);
 | |
|   for (my_bind= bind_array; my_bind < bind_array + bind_count; my_bind++)
 | |
|     my_bind->error= &my_bind->error_value;
 | |
|   my_bind= bind_array;
 | |
| 
 | |
|   my_bind->buffer= malloc(sizeof(uint8));
 | |
|   my_bind->buffer_type= MYSQL_TYPE_TINY;
 | |
|   my_bind->is_unsigned= TRUE;
 | |
| 
 | |
|   DIE_UNLESS(my_bind++ < bind_array + bind_count);
 | |
|   my_bind->buffer= malloc(sizeof(uint32));
 | |
|   my_bind->buffer_type= MYSQL_TYPE_LONG;
 | |
|   my_bind->is_unsigned= TRUE;
 | |
| 
 | |
|   DIE_UNLESS(my_bind++ < bind_array + bind_count);
 | |
|   my_bind->buffer= malloc(sizeof(int8));
 | |
|   my_bind->buffer_type= MYSQL_TYPE_TINY;
 | |
| 
 | |
|   DIE_UNLESS(my_bind++ < bind_array + bind_count);
 | |
|   my_bind->buffer= malloc(sizeof(uint16));
 | |
|   my_bind->buffer_type= MYSQL_TYPE_SHORT;
 | |
|   my_bind->is_unsigned= TRUE;
 | |
| 
 | |
|   DIE_UNLESS(my_bind++ < bind_array + bind_count);
 | |
|   my_bind->buffer= malloc(sizeof(int16));
 | |
|   my_bind->buffer_type= MYSQL_TYPE_SHORT;
 | |
| 
 | |
|   DIE_UNLESS(my_bind++ < bind_array + bind_count);
 | |
|   my_bind->buffer= malloc(sizeof(uint16));
 | |
|   my_bind->buffer_type= MYSQL_TYPE_SHORT;
 | |
|   my_bind->is_unsigned= TRUE;
 | |
| 
 | |
|   DIE_UNLESS(my_bind++ < bind_array + bind_count);
 | |
|   my_bind->buffer= malloc(sizeof(int8));
 | |
|   my_bind->buffer_type= MYSQL_TYPE_TINY;
 | |
|   my_bind->is_unsigned= TRUE;
 | |
| 
 | |
|   DIE_UNLESS(my_bind++ < bind_array + bind_count);
 | |
|   my_bind->buffer= malloc(sizeof(float));
 | |
|   my_bind->buffer_type= MYSQL_TYPE_FLOAT;
 | |
| 
 | |
|   DIE_UNLESS(my_bind++ < bind_array + bind_count);
 | |
|   my_bind->buffer= malloc(sizeof(float));
 | |
|   my_bind->buffer_type= MYSQL_TYPE_FLOAT;
 | |
| 
 | |
|   DIE_UNLESS(my_bind++ < bind_array + bind_count);
 | |
|   my_bind->buffer= malloc(sizeof(double));
 | |
|   my_bind->buffer_type= MYSQL_TYPE_DOUBLE;
 | |
| 
 | |
|   DIE_UNLESS(my_bind++ < bind_array + bind_count);
 | |
|   my_bind->buffer= malloc(sizeof(longlong));
 | |
|   my_bind->buffer_type= MYSQL_TYPE_LONGLONG;
 | |
| 
 | |
|   DIE_UNLESS(my_bind++ < bind_array + bind_count);
 | |
|   my_bind->buffer= malloc(sizeof(ulonglong));
 | |
|   my_bind->buffer_type= MYSQL_TYPE_LONGLONG;
 | |
|   my_bind->is_unsigned= TRUE;
 | |
| 
 | |
|   DIE_UNLESS(my_bind++ < bind_array + bind_count);
 | |
|   my_bind->buffer= malloc(sizeof(longlong));
 | |
|   my_bind->buffer_type= MYSQL_TYPE_LONGLONG;
 | |
| 
 | |
|   DIE_UNLESS(my_bind++ < bind_array + bind_count);
 | |
|   my_bind->buffer= malloc(sizeof(longlong));
 | |
|   my_bind->buffer_type= MYSQL_TYPE_LONGLONG;
 | |
| 
 | |
|   DIE_UNLESS(my_bind++ < bind_array + bind_count);
 | |
|   my_bind->buffer= malloc(sizeof(longlong));
 | |
|   my_bind->buffer_type= MYSQL_TYPE_LONGLONG;
 | |
| 
 | |
|   DIE_UNLESS(my_bind++ < bind_array + bind_count);
 | |
|   my_bind->buffer= malloc(sizeof(longlong));
 | |
|   my_bind->buffer_type= MYSQL_TYPE_LONGLONG;
 | |
| 
 | |
|   DIE_UNLESS(my_bind++ < bind_array + bind_count);
 | |
|   my_bind->buffer= malloc(sizeof(double));
 | |
|   my_bind->buffer_type= MYSQL_TYPE_DOUBLE;
 | |
| 
 | |
|   DIE_UNLESS(my_bind++ < bind_array + bind_count);
 | |
|   my_bind->buffer= malloc(sizeof(double));
 | |
|   my_bind->buffer_type= MYSQL_TYPE_DOUBLE;
 | |
| 
 | |
|   rc= mysql_stmt_bind_result(stmt, bind_array);
 | |
|   check_execute(stmt, rc);
 | |
|   rc= mysql_stmt_fetch(stmt);
 | |
|   DIE_UNLESS(rc == MYSQL_DATA_TRUNCATED);
 | |
| 
 | |
|   /*************** Verify truncation results ***************************/
 | |
|   my_bind= bind_array;
 | |
| 
 | |
|   /* signed tiny -> tiny */
 | |
|   DIE_UNLESS(*my_bind->error && * (int8*) my_bind->buffer == -10);
 | |
| 
 | |
|   /* signed tiny -> uint32 */
 | |
|   DIE_UNLESS(my_bind++ < bind_array + bind_count);
 | |
|   DIE_UNLESS(*my_bind->error && * (int32*) my_bind->buffer == -10);
 | |
| 
 | |
|   /* unsigned tiny -> tiny */
 | |
|   DIE_UNLESS(my_bind++ < bind_array + bind_count);
 | |
|   DIE_UNLESS(*my_bind->error && * (uint8*) my_bind->buffer == 200);
 | |
| 
 | |
|   /* short -> ushort */
 | |
|   DIE_UNLESS(my_bind++ < bind_array + bind_count);
 | |
|   DIE_UNLESS(*my_bind->error && * (int16*) my_bind->buffer == -32767);
 | |
| 
 | |
|   /* ushort -> short */
 | |
|   DIE_UNLESS(my_bind++ < bind_array + bind_count);
 | |
|   DIE_UNLESS(*my_bind->error && * (uint16*) my_bind->buffer == 64000);
 | |
| 
 | |
|   /* short -> ushort (no truncation, data is in the range of target type) */
 | |
|   DIE_UNLESS(my_bind++ < bind_array + bind_count);
 | |
|   DIE_UNLESS(! *my_bind->error && * (uint16*) my_bind->buffer == 32000);
 | |
| 
 | |
|   /* ushort -> utiny */
 | |
|   DIE_UNLESS(my_bind++ < bind_array + bind_count);
 | |
|   DIE_UNLESS(*my_bind->error && * (int8*) my_bind->buffer == 0);
 | |
| 
 | |
|   /* int -> float: no truncation, the number is a power of two */
 | |
|   DIE_UNLESS(my_bind++ < bind_array + bind_count);
 | |
|   DIE_UNLESS(! *my_bind->error && * (float*) my_bind->buffer == 1073741824);
 | |
| 
 | |
|   /* int -> float: truncation, not enough bits in float */
 | |
|   DIE_UNLESS(my_bind++ < bind_array + bind_count);
 | |
|   DIE_UNLESS(*my_bind->error);
 | |
| 
 | |
|   /* int -> double: no truncation */
 | |
|   DIE_UNLESS(my_bind++ < bind_array + bind_count);
 | |
|   DIE_UNLESS(! *my_bind->error && * (double*) my_bind->buffer == 1073741825);
 | |
| 
 | |
|   /* double -> longlong: fractional part is lost */
 | |
|   DIE_UNLESS(my_bind++ < bind_array + bind_count);
 | |
| 
 | |
|   /* double -> ulonglong, negative fp number to unsigned integer */
 | |
|   DIE_UNLESS(my_bind++ < bind_array + bind_count);
 | |
|   /* Value in the buffer is not defined: don't test it */
 | |
|   DIE_UNLESS(*my_bind->error);
 | |
| 
 | |
|   /* double -> longlong, negative fp number to signed integer: no loss */
 | |
|   DIE_UNLESS(my_bind++ < bind_array + bind_count);
 | |
|   DIE_UNLESS(! *my_bind->error && * (longlong*) my_bind->buffer == -12345678910LL);
 | |
| 
 | |
|   /* big numeric string -> number */
 | |
|   DIE_UNLESS(my_bind++ < bind_array + bind_count);
 | |
|   DIE_UNLESS(*my_bind->error);
 | |
| 
 | |
|   /* junk string -> number */
 | |
|   DIE_UNLESS(my_bind++ < bind_array + bind_count);
 | |
|   DIE_UNLESS(*my_bind->error && *(longlong*) my_bind->buffer == 0);
 | |
| 
 | |
|   /* string with trailing spaces -> number */
 | |
|   DIE_UNLESS(my_bind++ < bind_array + bind_count);
 | |
|   DIE_UNLESS(! *my_bind->error && *(longlong*) my_bind->buffer == 12345);
 | |
| 
 | |
|   /* string with trailing spaces -> double */
 | |
|   DIE_UNLESS(my_bind++ < bind_array + bind_count);
 | |
|   DIE_UNLESS(! *my_bind->error && *(double*) my_bind->buffer == 12345.67);
 | |
| 
 | |
|   /* string with trailing junk -> double */
 | |
|   DIE_UNLESS(my_bind++ < bind_array + bind_count);
 | |
|   /*
 | |
|     XXX: There must be a truncation error: but it's not the way the server
 | |
|     behaves, so let's leave it for now.
 | |
|   */
 | |
|   DIE_UNLESS(*(double*) my_bind->buffer == 12345.67);
 | |
|   /*
 | |
|     TODO: string -> double,  double -> time, double -> string (truncation
 | |
|           errors are not supported here yet)
 | |
|           longlong -> time/date/datetime
 | |
|           date -> time, date -> timestamp, date -> number
 | |
|           time -> string, time -> date, time -> timestamp,
 | |
|           number -> date string -> date
 | |
|   */
 | |
|   /*************** Cleanup *********************************************/
 | |
| 
 | |
|   mysql_stmt_close(stmt);
 | |
| 
 | |
|   for (my_bind= bind_array; my_bind < bind_array + bind_count; my_bind++)
 | |
|     free(my_bind->buffer);
 | |
|   free(bind_array);
 | |
| 
 | |
|   rc= mysql_query(mysql, "drop table t1");
 | |
|   myquery(rc);
 | |
| }
 | |
| 
 | |
| static void test_truncation_option()
 | |
| {
 | |
|   MYSQL_STMT *stmt;
 | |
|   const char *stmt_text;
 | |
|   int rc;
 | |
|   uint8 buf;
 | |
|   my_bool option= 0;
 | |
|   my_bool error;
 | |
|   MYSQL_BIND my_bind;
 | |
| 
 | |
|   myheader("test_truncation_option");
 | |
| 
 | |
|   /* Prepare the test table */
 | |
|   stmt_text= "select -1";
 | |
| 
 | |
|   stmt= mysql_stmt_init(mysql);
 | |
|   rc= mysql_stmt_prepare(stmt, stmt_text, strlen(stmt_text));
 | |
|   check_execute(stmt, rc);
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   bzero((char*) &my_bind, sizeof(my_bind));
 | |
| 
 | |
|   my_bind.buffer= (void*) &buf;
 | |
|   my_bind.buffer_type= MYSQL_TYPE_TINY;
 | |
|   my_bind.is_unsigned= TRUE;
 | |
|   my_bind.error= &error;
 | |
| 
 | |
|   rc= mysql_stmt_bind_result(stmt, &my_bind);
 | |
|   check_execute(stmt, rc);
 | |
|   rc= mysql_stmt_fetch(stmt);
 | |
|   DIE_UNLESS(rc == MYSQL_DATA_TRUNCATED);
 | |
|   DIE_UNLESS(error);
 | |
|   rc= mysql_options(mysql, MYSQL_REPORT_DATA_TRUNCATION, (char*) &option);
 | |
|   myquery(rc);
 | |
|   /* need to rebind for the new setting to take effect */
 | |
|   rc= mysql_stmt_bind_result(stmt, &my_bind);
 | |
|   check_execute(stmt, rc);
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
|   rc= mysql_stmt_fetch(stmt);
 | |
|   check_execute(stmt, rc);
 | |
|   /* The only change is rc - error pointers are still filled in */
 | |
|   DIE_UNLESS(error == 1);
 | |
|   /* restore back the defaults */
 | |
|   option= 1;
 | |
|   mysql_options(mysql, MYSQL_REPORT_DATA_TRUNCATION, (char*) &option);
 | |
| 
 | |
|   mysql_stmt_close(stmt);
 | |
| }
 | |
| 
 | |
| 
 | |
| /* Bug#6761 - mysql_list_fields doesn't work */
 | |
| 
 | |
| static void test_bug6761(void)
 | |
| {
 | |
|   const char *stmt_text;
 | |
|   MYSQL_RES *res;
 | |
|   int rc;
 | |
|   myheader("test_bug6761");
 | |
| 
 | |
|   stmt_text= "CREATE TABLE t1 (a int, b char(255), c decimal)";
 | |
|   rc= mysql_real_query(mysql, stmt_text, strlen(stmt_text));
 | |
|   myquery(rc);
 | |
| 
 | |
|   res= mysql_list_fields(mysql, "t1", "%");
 | |
|   DIE_UNLESS(res && mysql_num_fields(res) == 3);
 | |
|   mysql_free_result(res);
 | |
| 
 | |
|   stmt_text= "DROP TABLE t1";
 | |
|   rc= mysql_real_query(mysql, stmt_text, strlen(stmt_text));
 | |
|   myquery(rc);
 | |
| }
 | |
| 
 | |
| 
 | |
| /* Bug#8330 - mysql_stmt_execute crashes (libmysql) */
 | |
| 
 | |
| static void test_bug8330()
 | |
| {
 | |
|   const char *stmt_text;
 | |
|   MYSQL_STMT *stmt[2];
 | |
|   int i, rc;
 | |
|   const char *query= "select a,b from t1 where a=?";
 | |
|   MYSQL_BIND my_bind[2];
 | |
|   long lval[2];
 | |
| 
 | |
|   myheader("test_bug8330");
 | |
| 
 | |
|   stmt_text= "drop table if exists t1";
 | |
|   /* in case some previos test failed */
 | |
|   rc= mysql_real_query(mysql, stmt_text, strlen(stmt_text));
 | |
|   myquery(rc);
 | |
|   stmt_text= "create table t1 (a int, b int)";
 | |
|   rc= mysql_real_query(mysql, stmt_text, strlen(stmt_text));
 | |
|   myquery(rc);
 | |
| 
 | |
|   bzero((char*) my_bind, sizeof(my_bind));
 | |
|   for (i=0; i < 2; i++)
 | |
|   {
 | |
|     stmt[i]= mysql_stmt_init(mysql);
 | |
|     rc= mysql_stmt_prepare(stmt[i], query, strlen(query));
 | |
|     check_execute(stmt[i], rc);
 | |
| 
 | |
|     my_bind[i].buffer_type= MYSQL_TYPE_LONG;
 | |
|     lval[i]= 0;
 | |
|     my_bind[i].buffer= (void*) &lval[i];
 | |
|     my_bind[i].is_null= 0;
 | |
|     mysql_stmt_bind_param(stmt[i], &my_bind[i]);
 | |
|   }
 | |
| 
 | |
|   rc= mysql_stmt_execute(stmt[0]);
 | |
|   check_execute(stmt[0], rc);
 | |
| 
 | |
|   rc= mysql_stmt_execute(stmt[1]);
 | |
|   DIE_UNLESS(rc && mysql_stmt_errno(stmt[1]) == CR_COMMANDS_OUT_OF_SYNC);
 | |
|   rc= mysql_stmt_execute(stmt[0]);
 | |
|   check_execute(stmt[0], rc);
 | |
| 
 | |
|   mysql_stmt_close(stmt[0]);
 | |
|   mysql_stmt_close(stmt[1]);
 | |
| 
 | |
|   stmt_text= "drop table t1";
 | |
|   rc= mysql_real_query(mysql, stmt_text, strlen(stmt_text));
 | |
|   myquery(rc);
 | |
| }
 | |
| 
 | |
| 
 | |
| /* Bug#7990 - mysql_stmt_close doesn't reset mysql->net.last_error */
 | |
| 
 | |
| static void test_bug7990()
 | |
| {
 | |
|   MYSQL_STMT *stmt;
 | |
|   int rc;
 | |
|   myheader("test_bug7990");
 | |
| 
 | |
|   stmt= mysql_stmt_init(mysql);
 | |
|   rc= mysql_stmt_prepare(stmt, "foo", 3);
 | |
|   /*
 | |
|     XXX: the fact that we store errno both in STMT and in
 | |
|     MYSQL is not documented and is subject to change in 5.0
 | |
|   */
 | |
|   DIE_UNLESS(rc && mysql_stmt_errno(stmt) && mysql_errno(mysql));
 | |
|   mysql_stmt_close(stmt);
 | |
|   DIE_UNLESS(!mysql_errno(mysql));
 | |
| }
 | |
| 
 | |
| /*
 | |
|   Bug #15518 - Reusing a stmt that has failed during prepare
 | |
|   does not clear error
 | |
| */
 | |
| 
 | |
| static void test_bug15518()
 | |
| {
 | |
|   MYSQL_STMT *stmt;
 | |
|   MYSQL* mysql1;
 | |
|   int rc;
 | |
|   myheader("test_bug15518");
 | |
| 
 | |
|   mysql1= mysql_client_init(NULL);
 | |
| 
 | |
|   if (!mysql_real_connect(mysql1, opt_host, opt_user, opt_password,
 | |
|                           opt_db ? opt_db : "test", opt_port, opt_unix_socket,
 | |
|                           CLIENT_MULTI_STATEMENTS))
 | |
|   {
 | |
|     fprintf(stderr, "Failed to connect to the database\n");
 | |
|     DIE_UNLESS(0);
 | |
|   }
 | |
| 
 | |
|   stmt= mysql_stmt_init(mysql1);
 | |
| 
 | |
|   /*
 | |
|     The prepare of foo should fail with errno 1064 since
 | |
|     it's not a valid query
 | |
|   */
 | |
|   rc= mysql_stmt_prepare(stmt, "foo", 3);
 | |
|   if (!opt_silent)
 | |
|     fprintf(stdout, "rc: %d, mysql_stmt_errno: %d, mysql_errno: %d\n",
 | |
|             rc, mysql_stmt_errno(stmt), mysql_errno(mysql1));
 | |
|   DIE_UNLESS(rc && mysql_stmt_errno(stmt) && mysql_errno(mysql1));
 | |
| 
 | |
|   /*
 | |
|     Use the same stmt and reprepare with another query that
 | |
|     suceeds
 | |
|   */
 | |
|   rc= mysql_stmt_prepare(stmt, "SHOW STATUS", 12);
 | |
|   if (!opt_silent)
 | |
|     fprintf(stdout, "rc: %d, mysql_stmt_errno: %d, mysql_errno: %d\n",
 | |
|             rc, mysql_stmt_errno(stmt), mysql_errno(mysql1));
 | |
|   DIE_UNLESS(!rc || mysql_stmt_errno(stmt) || mysql_errno(mysql1));
 | |
| 
 | |
|   mysql_stmt_close(stmt);
 | |
|   DIE_UNLESS(!mysql_errno(mysql1));
 | |
| 
 | |
|   /*
 | |
|     part2, when connection to server has been closed
 | |
|     after first prepare
 | |
|   */
 | |
|   stmt= mysql_stmt_init(mysql1);
 | |
|   rc= mysql_stmt_prepare(stmt, "foo", 3);
 | |
|   if (!opt_silent)
 | |
|     fprintf(stdout, "rc: %d, mysql_stmt_errno: %d, mysql_errno: %d\n",
 | |
|             rc, mysql_stmt_errno(stmt), mysql_errno(mysql1));
 | |
|   DIE_UNLESS(rc && mysql_stmt_errno(stmt) && mysql_errno(mysql1));
 | |
| 
 | |
|   /* Close connection to server */
 | |
|   mysql_close(mysql1);
 | |
| 
 | |
|   /*
 | |
|     Use the same stmt and reprepare with another query that
 | |
|     suceeds. The prepare should fail with error 2013 since
 | |
|     connection to server has been closed.
 | |
|   */
 | |
|   rc= mysql_stmt_prepare(stmt, "SHOW STATUS", 12);
 | |
|   if (!opt_silent)
 | |
|     fprintf(stdout, "rc: %d, mysql_stmt_errno: %d\n",
 | |
|             rc, mysql_stmt_errno(stmt));
 | |
|   DIE_UNLESS(rc && mysql_stmt_errno(stmt));
 | |
| 
 | |
|   mysql_stmt_close(stmt);
 | |
| }
 | |
| 
 | |
| 
 | |
| static void disable_query_logs()
 | |
| {
 | |
|   int rc;
 | |
|   rc= mysql_query(mysql, "set @@global.general_log=off");
 | |
|   myquery(rc);
 | |
|   rc= mysql_query(mysql, "set @@global.slow_query_log=off");
 | |
|   myquery(rc);
 | |
| }
 | |
| 
 | |
| 
 | |
| static void enable_query_logs(int truncate)
 | |
| {
 | |
|   int rc;
 | |
| 
 | |
|   rc= mysql_query(mysql, "set @save_global_general_log=@@global.general_log");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "set @save_global_slow_query_log=@@global.slow_query_log");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "set @@global.general_log=on");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "set @@global.slow_query_log=on");
 | |
|   myquery(rc);
 | |
| 
 | |
| 
 | |
|   if (truncate)
 | |
|   {
 | |
|     rc= mysql_query(mysql, "truncate mysql.general_log");
 | |
|     myquery(rc);
 | |
| 
 | |
|     rc= mysql_query(mysql, "truncate mysql.slow_log");
 | |
|     myquery(rc);
 | |
|   }
 | |
| }
 | |
| 
 | |
| 
 | |
| static void restore_query_logs()
 | |
| {
 | |
|   int rc;
 | |
|   rc= mysql_query(mysql, "set @@global.general_log=@save_global_general_log");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "set @@global.slow_query_log=@save_global_slow_query_log");
 | |
|   myquery(rc);
 | |
| }
 | |
| 
 | |
| 
 | |
| static void test_view_sp_list_fields()
 | |
| {
 | |
|   int		rc;
 | |
|   MYSQL_RES     *res;
 | |
| 
 | |
|   myheader("test_view_sp_list_fields");
 | |
| 
 | |
|   rc= mysql_query(mysql, "DROP FUNCTION IF EXISTS f1");
 | |
|   myquery(rc);
 | |
|   rc= mysql_query(mysql, "DROP TABLE IF EXISTS v1, t1, t2");
 | |
|   myquery(rc);
 | |
|   rc= mysql_query(mysql, "DROP VIEW IF EXISTS v1, t1, t2");
 | |
|   myquery(rc);
 | |
|   rc= mysql_query(mysql, "create function f1 () returns int return 5");
 | |
|   myquery(rc);
 | |
|   rc= mysql_query(mysql, "create table t1 (s1 char,s2 char)");
 | |
|   myquery(rc);
 | |
|   rc= mysql_query(mysql, "create table t2 (s1 int);");
 | |
|   myquery(rc);
 | |
|   rc= mysql_query(mysql, "create view v1 as select s2,sum(s1) - \
 | |
| count(s2) as vx from t1 group by s2 having sum(s1) - count(s2) < (select f1() \
 | |
| from t2);");
 | |
|   myquery(rc);
 | |
|   res= mysql_list_fields(mysql, "v1", NullS);
 | |
|   DIE_UNLESS(res != 0 && mysql_num_fields(res) != 0);
 | |
|   rc= mysql_query(mysql, "DROP FUNCTION f1");
 | |
|   myquery(rc);
 | |
|   rc= mysql_query(mysql, "DROP VIEW v1");
 | |
|   myquery(rc);
 | |
|   rc= mysql_query(mysql, "DROP TABLE t1, t2");
 | |
|   mysql_free_result(res);
 | |
|   myquery(rc);
 | |
| 
 | |
| }
 | |
| 
 | |
| 
 | |
| /*
 | |
|  Test mysql_real_escape_string() with gbk charset
 | |
| 
 | |
|  The important part is that 0x27 (') is the second-byte in a invalid
 | |
|  two-byte GBK character here. But 0xbf5c is a valid GBK character, so
 | |
|  it needs to be escaped as 0x5cbf27
 | |
| */
 | |
| #define TEST_BUG8378_IN  "\xef\xbb\xbf\x27\xbf\x10"
 | |
| #define TEST_BUG8378_OUT "\xef\xbb\x5c\xbf\x5c\x27\x5c\xbf\x10"
 | |
| 
 | |
| static void test_bug8378()
 | |
| {
 | |
| #if defined(HAVE_CHARSET_gbk) && !defined(EMBEDDED_LIBRARY)
 | |
|   MYSQL *lmysql;
 | |
|   char out[9]; /* strlen(TEST_BUG8378)*2+1 */
 | |
|   char buf[256];
 | |
|   int len, rc;
 | |
| 
 | |
|   myheader("test_bug8378");
 | |
| 
 | |
|   if (!opt_silent)
 | |
|     fprintf(stdout, "\n Establishing a test connection ...");
 | |
|   if (!(lmysql= mysql_client_init(NULL)))
 | |
|   {
 | |
|     myerror("mysql_client_init() failed");
 | |
|     exit(1);
 | |
|   }
 | |
|   if (mysql_options(lmysql, MYSQL_SET_CHARSET_NAME, "gbk"))
 | |
|   {
 | |
|     myerror("mysql_options() failed");
 | |
|     exit(1);
 | |
|   }
 | |
|   if (!(mysql_real_connect(lmysql, opt_host, opt_user,
 | |
|                            opt_password, current_db, opt_port,
 | |
|                            opt_unix_socket, 0)))
 | |
|   {
 | |
|     myerror("connection failed");
 | |
|     exit(1);
 | |
|   }
 | |
|   if (!opt_silent)
 | |
|     fprintf(stdout, "OK");
 | |
| 
 | |
|   rc= mysql_query(lmysql, "SET SQL_MODE=''");
 | |
|   myquery(rc);
 | |
| 
 | |
|   len= mysql_real_escape_string(lmysql, out, TEST_BUG8378_IN, 4);
 | |
| 
 | |
|   /* No escaping should have actually happened. */
 | |
|   DIE_UNLESS(memcmp(out, TEST_BUG8378_OUT, len) == 0);
 | |
| 
 | |
|   sprintf(buf, "SELECT '%s'", out);
 | |
|   
 | |
|   rc=mysql_real_query(lmysql, buf, strlen(buf));
 | |
|   myquery(rc);
 | |
| 
 | |
|   mysql_close(lmysql);
 | |
| #endif
 | |
| }
 | |
| 
 | |
| 
 | |
| static void test_bug8722()
 | |
| {
 | |
|   MYSQL_STMT *stmt;
 | |
|   int rc;
 | |
|   const char *stmt_text;
 | |
| 
 | |
|   myheader("test_bug8722");
 | |
|   /* Prepare test data */
 | |
|   stmt_text= "drop table if exists t1, v1";
 | |
|   rc= mysql_real_query(mysql, stmt_text, strlen(stmt_text));
 | |
|   myquery(rc);
 | |
|   stmt_text= "CREATE TABLE t1 (c1 varchar(10), c2 varchar(10), c3 varchar(10),"
 | |
|                              " c4 varchar(10), c5 varchar(10), c6 varchar(10),"
 | |
|                              " c7 varchar(10), c8 varchar(10), c9 varchar(10),"
 | |
|                              "c10 varchar(10))";
 | |
|   rc= mysql_real_query(mysql, stmt_text, strlen(stmt_text));
 | |
|   myquery(rc);
 | |
|   stmt_text= "INSERT INTO t1 VALUES (1,2,3,4,5,6,7,8,9,10)";
 | |
|   rc= mysql_real_query(mysql, stmt_text, strlen(stmt_text));
 | |
|   myquery(rc);
 | |
|   stmt_text= "CREATE VIEW v1 AS SELECT * FROM t1";
 | |
|   rc= mysql_real_query(mysql, stmt_text, strlen(stmt_text));
 | |
|   myquery(rc);
 | |
|   /* Note: if you uncomment following block everything works fine */
 | |
| /*
 | |
|   rc= mysql_query(mysql, "select * from v1");
 | |
|   myquery(rc);
 | |
|   mysql_free_result(mysql_store_result(mysql));
 | |
| */
 | |
| 
 | |
|   stmt= mysql_stmt_init(mysql);
 | |
|   stmt_text= "select * from v1";
 | |
|   rc= mysql_stmt_prepare(stmt, stmt_text, strlen(stmt_text));
 | |
|   check_execute(stmt, rc);
 | |
|   mysql_stmt_close(stmt);
 | |
|   stmt_text= "drop table if exists t1, v1";
 | |
|   rc= mysql_real_query(mysql, stmt_text, strlen(stmt_text));
 | |
|   myquery(rc);
 | |
| }
 | |
| 
 | |
| 
 | |
| MYSQL_STMT *open_cursor(const char *query)
 | |
| {
 | |
|   int rc;
 | |
|   const ulong type= (ulong)CURSOR_TYPE_READ_ONLY;
 | |
| 
 | |
|   MYSQL_STMT *stmt= mysql_stmt_init(mysql);
 | |
|   rc= mysql_stmt_prepare(stmt, query, strlen(query));
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   mysql_stmt_attr_set(stmt, STMT_ATTR_CURSOR_TYPE, (void*) &type);
 | |
|   return stmt;
 | |
| }
 | |
| 
 | |
| 
 | |
| static void test_bug8880()
 | |
| {
 | |
|   MYSQL_STMT *stmt_list[2], **stmt;
 | |
|   MYSQL_STMT **stmt_list_end= (MYSQL_STMT**) stmt_list + 2;
 | |
|   int rc;
 | |
| 
 | |
|   myheader("test_bug8880");
 | |
| 
 | |
|   mysql_query(mysql, "drop table if exists t1");
 | |
|   mysql_query(mysql, "create table t1 (a int not null primary key, b int)");
 | |
|   rc= mysql_query(mysql, "insert into t1 values (1,1)");
 | |
|   myquery(rc);                                  /* one check is enough */
 | |
|   /*
 | |
|     when inserting 2 rows everything works well
 | |
|     mysql_query(mysql, "INSERT INTO t1 VALUES (1,1),(2,2)");
 | |
|   */
 | |
|   for (stmt= stmt_list; stmt < stmt_list_end; stmt++)
 | |
|     *stmt= open_cursor("select a from t1");
 | |
|   for (stmt= stmt_list; stmt < stmt_list_end; stmt++)
 | |
|   {
 | |
|     rc= mysql_stmt_execute(*stmt);
 | |
|     check_execute(*stmt, rc);
 | |
|   }
 | |
|   for (stmt= stmt_list; stmt < stmt_list_end; stmt++)
 | |
|     mysql_stmt_close(*stmt);
 | |
| }
 | |
| 
 | |
| /*
 | |
|   Test executing a query with prepared statements while query cache is active
 | |
| */
 | |
| 
 | |
| static void test_open_cursor_prepared_statement_query_cache()
 | |
| {
 | |
|   MYSQL_STMT *stmt;
 | |
|   int rc;
 | |
|   MYSQL_RES *result;
 | |
| 
 | |
|   myheader("test_open_cursor_prepared_statement_query_cache");
 | |
|   if (! is_query_cache_available())
 | |
|   {
 | |
|     fprintf(stdout, "Skipping test_open_cursor_prepared_statement_query_cache: Query cache not available.\n");
 | |
|     return;
 | |
|   }
 | |
| 
 | |
|   rc= mysql_query(mysql,
 | |
|                   "set @save_query_cache_type="
 | |
|                   "@@global.query_cache_type,"
 | |
|                   "@save_query_cache_size="
 | |
|                   "@@global.query_cache_size");
 | |
|   myquery(rc);
 | |
|   rc= mysql_query(mysql, "set global query_cache_type=ON");
 | |
|   myquery(rc);
 | |
|   rc= mysql_query(mysql, "set local query_cache_type=ON");
 | |
|   myquery(rc);
 | |
|   rc= mysql_query(mysql, "set global query_cache_size=1000000");
 | |
|   myquery(rc);
 | |
| 
 | |
|   mysql_query(mysql, "drop table if exists t1");
 | |
|   mysql_query(mysql, "create table t1 (a int not null primary key, b int)");
 | |
|   rc= mysql_query(mysql, "insert into t1 values (1,1)");
 | |
|   myquery(rc);                                  /* one check is enough */
 | |
| 
 | |
|   /* Store query in query cache */
 | |
|   rc= mysql_query(mysql, "SELECT * FROM t1");
 | |
|   myquery(rc);
 | |
|   result= mysql_store_result(mysql);
 | |
|   mytest(result);
 | |
|   (void) my_process_result_set(result);
 | |
|   mysql_free_result(result);
 | |
| 
 | |
|   /* Test using a cursor */
 | |
|   stmt= open_cursor("select a from t1");
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
|   mysql_stmt_close(stmt);
 | |
| 
 | |
|   rc= mysql_query(mysql, "set global query_cache_type=@save_query_cache_type");
 | |
|   myquery(rc);
 | |
|   rc= mysql_query(mysql, "set global query_cache_size=@save_query_cache_size");
 | |
|   myquery(rc);
 | |
| }
 | |
| 
 | |
| 
 | |
| static void test_bug9159()
 | |
| {
 | |
|   MYSQL_STMT *stmt;
 | |
|   int rc;
 | |
|   const char *stmt_text= "select a, b from t1";
 | |
|   const unsigned long type= CURSOR_TYPE_READ_ONLY;
 | |
| 
 | |
|   myheader("test_bug9159");
 | |
| 
 | |
|   mysql_query(mysql, "drop table if exists t1");
 | |
|   mysql_query(mysql, "create table t1 (a int not null primary key, b int)");
 | |
|   rc= mysql_query(mysql, "insert into t1 values (1,1)");
 | |
|   myquery(rc);
 | |
| 
 | |
|   stmt= mysql_stmt_init(mysql);
 | |
|   mysql_stmt_prepare(stmt, stmt_text, strlen(stmt_text));
 | |
|   mysql_stmt_attr_set(stmt, STMT_ATTR_CURSOR_TYPE, (const void *)&type);
 | |
| 
 | |
|   mysql_stmt_execute(stmt);
 | |
|   mysql_stmt_close(stmt);
 | |
|   rc= mysql_query(mysql, "drop table if exists t1");
 | |
|   myquery(rc);
 | |
| }
 | |
| 
 | |
| 
 | |
| /* Crash when opening a cursor to a query with DISTINCT and no key */
 | |
| 
 | |
| static void test_bug9520()
 | |
| {
 | |
|   MYSQL_STMT *stmt;
 | |
|   MYSQL_BIND my_bind[1];
 | |
|   char a[6];
 | |
|   ulong a_len;
 | |
|   int rc, row_count= 0;
 | |
| 
 | |
|   myheader("test_bug9520");
 | |
| 
 | |
|   mysql_query(mysql, "drop table if exists t1");
 | |
|   mysql_query(mysql, "create table t1 (a char(5), b char(5), c char(5),"
 | |
|                      " primary key (a, b, c))");
 | |
|   rc= mysql_query(mysql, "insert into t1 values ('x', 'y', 'z'), "
 | |
|                   " ('a', 'b', 'c'), ('k', 'l', 'm')");
 | |
|   myquery(rc);
 | |
| 
 | |
|   stmt= open_cursor("select distinct b from t1");
 | |
| 
 | |
|   /*
 | |
|     Not crashes with:
 | |
|     stmt= open_cursor("select distinct a from t1");
 | |
|   */
 | |
| 
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   bzero((char*) my_bind, sizeof(my_bind));
 | |
|   my_bind[0].buffer_type= MYSQL_TYPE_STRING;
 | |
|   my_bind[0].buffer= (char*) a;
 | |
|   my_bind[0].buffer_length= sizeof(a);
 | |
|   my_bind[0].length= &a_len;
 | |
| 
 | |
|   mysql_stmt_bind_result(stmt, my_bind);
 | |
| 
 | |
|   while (!(rc= mysql_stmt_fetch(stmt)))
 | |
|     row_count++;
 | |
| 
 | |
|   DIE_UNLESS(rc == MYSQL_NO_DATA);
 | |
| 
 | |
|   if (!opt_silent)
 | |
|     printf("Fetched %d rows\n", row_count);
 | |
|   DBUG_ASSERT(row_count == 3);
 | |
| 
 | |
|   mysql_stmt_close(stmt);
 | |
| 
 | |
|   rc= mysql_query(mysql, "drop table t1");
 | |
|   myquery(rc);
 | |
| }
 | |
| 
 | |
| 
 | |
| /*
 | |
|   We can't have more than one cursor open for a prepared statement.
 | |
|   Test re-executions of a PS with cursor; mysql_stmt_reset must close
 | |
|   the cursor attached to the statement, if there is one.
 | |
| */
 | |
| 
 | |
| static void test_bug9478()
 | |
| {
 | |
|   MYSQL_STMT *stmt;
 | |
|   MYSQL_BIND my_bind[1];
 | |
|   char a[6];
 | |
|   ulong a_len;
 | |
|   int rc, i;
 | |
|   DBUG_ENTER("test_bug9478");
 | |
| 
 | |
|   myheader("test_bug9478");
 | |
| 
 | |
|   mysql_query(mysql, "drop table if exists t1");
 | |
|   mysql_query(mysql, "create table t1 (id integer not null primary key, "
 | |
|                      " name varchar(20) not null)");
 | |
|   rc= mysql_query(mysql, "insert into t1 (id, name) values "
 | |
|                          " (1, 'aaa'), (2, 'bbb'), (3, 'ccc')");
 | |
|   myquery(rc);
 | |
| 
 | |
|   stmt= open_cursor("select name from t1 where id=2");
 | |
| 
 | |
|   bzero((char*) my_bind, sizeof(my_bind));
 | |
|   my_bind[0].buffer_type= MYSQL_TYPE_STRING;
 | |
|   my_bind[0].buffer= (char*) a;
 | |
|   my_bind[0].buffer_length= sizeof(a);
 | |
|   my_bind[0].length= &a_len;
 | |
|   mysql_stmt_bind_result(stmt, my_bind);
 | |
| 
 | |
|   for (i= 0; i < 5; i++)
 | |
|   {
 | |
|     rc= mysql_stmt_execute(stmt);
 | |
|     check_execute(stmt, rc);
 | |
|     rc= mysql_stmt_fetch(stmt);
 | |
|     check_execute(stmt, rc);
 | |
|     if (!opt_silent && i == 0)
 | |
|       printf("Fetched row: %s\n", a);
 | |
| 
 | |
|     /*
 | |
|       The query above is a one-row result set. Therefore, there is no
 | |
|       cursor associated with it, as the server won't bother with opening
 | |
|       a cursor for a one-row result set. The first row was read from the
 | |
|       server in the fetch above. But there is eof packet pending in the
 | |
|       network. mysql_stmt_execute will flush the packet and successfully
 | |
|       execute the statement.
 | |
|     */
 | |
| 
 | |
|     rc= mysql_stmt_execute(stmt);
 | |
|     check_execute(stmt, rc);
 | |
| 
 | |
|     rc= mysql_stmt_fetch(stmt);
 | |
|     check_execute(stmt, rc);
 | |
|     if (!opt_silent && i == 0)
 | |
|       printf("Fetched row: %s\n", a);
 | |
|     rc= mysql_stmt_fetch(stmt);
 | |
|     DIE_UNLESS(rc == MYSQL_NO_DATA);
 | |
| 
 | |
|     {
 | |
|       char buff[8];
 | |
|       /* Fill in the fetch packet */
 | |
|       int4store(buff, stmt->stmt_id);
 | |
|       buff[4]= 1;                               /* prefetch rows */
 | |
|       rc= mysql_stmt_fetch(stmt);
 | |
|       DIE_UNLESS(rc);
 | |
|       if (!opt_silent && i == 0)
 | |
|         printf("Got error (as expected): %s\n", mysql_error(mysql));
 | |
|     }
 | |
| 
 | |
|     rc= mysql_stmt_execute(stmt);
 | |
|     check_execute(stmt, rc);
 | |
| 
 | |
|     rc= mysql_stmt_fetch(stmt);
 | |
|     check_execute(stmt, rc);
 | |
|     if (!opt_silent && i == 0)
 | |
|       printf("Fetched row: %s\n", a);
 | |
| 
 | |
|     rc= mysql_stmt_reset(stmt);
 | |
|     check_execute(stmt, rc);
 | |
|     rc= mysql_stmt_fetch(stmt);
 | |
|     DIE_UNLESS(rc && mysql_stmt_errno(stmt));
 | |
|     if (!opt_silent && i == 0)
 | |
|       printf("Got error (as expected): %s\n", mysql_stmt_error(stmt));
 | |
|   }
 | |
|   rc= mysql_stmt_close(stmt);
 | |
|   DIE_UNLESS(rc == 0);
 | |
| 
 | |
|   /* Test the case with a server side cursor */
 | |
|   stmt= open_cursor("select name from t1");
 | |
| 
 | |
|   mysql_stmt_bind_result(stmt, my_bind);
 | |
| 
 | |
|   for (i= 0; i < 5; i++)
 | |
|   {
 | |
|     DBUG_PRINT("loop",("i: %d", i));
 | |
|     rc= mysql_stmt_execute(stmt);
 | |
|     check_execute(stmt, rc);
 | |
|     rc= mysql_stmt_fetch(stmt);
 | |
|     check_execute(stmt, rc);
 | |
|     if (!opt_silent && i == 0)
 | |
|       printf("Fetched row: %s\n", a);
 | |
|     rc= mysql_stmt_execute(stmt);
 | |
|     check_execute(stmt, rc);
 | |
| 
 | |
|     while (! (rc= mysql_stmt_fetch(stmt)))
 | |
|     {
 | |
|       if (!opt_silent && i == 0)
 | |
|         printf("Fetched row: %s\n", a);
 | |
|     }
 | |
|     DIE_UNLESS(rc == MYSQL_NO_DATA);
 | |
| 
 | |
|     rc= mysql_stmt_execute(stmt);
 | |
|     check_execute(stmt, rc);
 | |
| 
 | |
|     rc= mysql_stmt_fetch(stmt);
 | |
|     check_execute(stmt, rc);
 | |
|     if (!opt_silent && i == 0)
 | |
|       printf("Fetched row: %s\n", a);
 | |
| 
 | |
|     rc= mysql_stmt_reset(stmt);
 | |
|     check_execute(stmt, rc);
 | |
|     rc= mysql_stmt_fetch(stmt);
 | |
|     DIE_UNLESS(rc && mysql_stmt_errno(stmt));
 | |
|     if (!opt_silent && i == 0)
 | |
|       printf("Got error (as expected): %s\n", mysql_stmt_error(stmt));
 | |
|   }
 | |
| 
 | |
|   rc= mysql_stmt_close(stmt);
 | |
|   DIE_UNLESS(rc == 0);
 | |
| 
 | |
|   rc= mysql_query(mysql, "drop table t1");
 | |
|   myquery(rc);
 | |
|   DBUG_VOID_RETURN;
 | |
| }
 | |
| 
 | |
| 
 | |
| /*
 | |
|   Error message is returned for unsupported features.
 | |
|   Test also cursors with non-default PREFETCH_ROWS
 | |
| */
 | |
| 
 | |
| static void test_bug9643()
 | |
| {
 | |
|   MYSQL_STMT *stmt;
 | |
|   MYSQL_BIND my_bind[1];
 | |
|   int32 a;
 | |
|   int rc;
 | |
|   const char *stmt_text;
 | |
|   int num_rows= 0;
 | |
|   ulong type;
 | |
|   ulong prefetch_rows= 5;
 | |
| 
 | |
|   myheader("test_bug9643");
 | |
| 
 | |
|   mysql_query(mysql, "drop table if exists t1");
 | |
|   mysql_query(mysql, "create table t1 (id integer not null primary key)");
 | |
|   rc= mysql_query(mysql, "insert into t1 (id) values "
 | |
|                          " (1), (2), (3), (4), (5), (6), (7), (8), (9)");
 | |
|   myquery(rc);
 | |
| 
 | |
|   stmt= mysql_stmt_init(mysql);
 | |
|   /* Not implemented in 5.0 */
 | |
|   type= (ulong) CURSOR_TYPE_SCROLLABLE;
 | |
|   rc= mysql_stmt_attr_set(stmt, STMT_ATTR_CURSOR_TYPE, (void*) &type);
 | |
|   DIE_UNLESS(rc);
 | |
|   if (! opt_silent)
 | |
|     printf("Got error (as expected): %s\n", mysql_stmt_error(stmt));
 | |
| 
 | |
|   type= (ulong) CURSOR_TYPE_READ_ONLY;
 | |
|   rc= mysql_stmt_attr_set(stmt, STMT_ATTR_CURSOR_TYPE, (void*) &type);
 | |
|   check_execute(stmt, rc);
 | |
|   rc= mysql_stmt_attr_set(stmt, STMT_ATTR_PREFETCH_ROWS,
 | |
|                           (void*) &prefetch_rows);
 | |
|   check_execute(stmt, rc);
 | |
|   stmt_text= "select * from t1";
 | |
|   rc= mysql_stmt_prepare(stmt, stmt_text, strlen(stmt_text));
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   bzero((char*) my_bind, sizeof(my_bind));
 | |
|   my_bind[0].buffer_type= MYSQL_TYPE_LONG;
 | |
|   my_bind[0].buffer= (void*) &a;
 | |
|   my_bind[0].buffer_length= sizeof(a);
 | |
|   mysql_stmt_bind_result(stmt, my_bind);
 | |
| 
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   while ((rc= mysql_stmt_fetch(stmt)) == 0)
 | |
|     ++num_rows;
 | |
|   DIE_UNLESS(num_rows == 9);
 | |
| 
 | |
|   rc= mysql_stmt_close(stmt);
 | |
|   DIE_UNLESS(rc == 0);
 | |
| 
 | |
|   rc= mysql_query(mysql, "drop table t1");
 | |
|   myquery(rc);
 | |
| }
 | |
| 
 | |
| /*
 | |
|   Bug#11111: fetch from view returns wrong data
 | |
| */
 | |
| 
 | |
| static void test_bug11111()
 | |
| {
 | |
|   MYSQL_STMT    *stmt;
 | |
|   MYSQL_BIND    my_bind[2];
 | |
|   char          buf[2][20];
 | |
|   ulong         len[2];
 | |
|   int i;
 | |
|   int rc;
 | |
|   const char *query= "SELECT DISTINCT f1,ff2 FROM v1";
 | |
| 
 | |
|   myheader("test_bug11111");
 | |
| 
 | |
|   rc= mysql_query(mysql, "drop table if exists t1, t2, v1");
 | |
|   myquery(rc);
 | |
|   rc= mysql_query(mysql, "drop view if exists t1, t2, v1");
 | |
|   myquery(rc);
 | |
|   rc= mysql_query(mysql, "create table t1 (f1 int, f2 int)");
 | |
|   myquery(rc);
 | |
|   rc= mysql_query(mysql, "create table t2 (ff1 int, ff2 int)");
 | |
|   myquery(rc);
 | |
|   rc= mysql_query(mysql, "create view v1 as select * from t1, t2 where f1=ff1");
 | |
|   myquery(rc);
 | |
|   rc= mysql_query(mysql, "insert into t1 values (1,1), (2,2), (3,3)");
 | |
|   myquery(rc);
 | |
|   rc= mysql_query(mysql, "insert into t2 values (1,1), (2,2), (3,3)");
 | |
|   myquery(rc);
 | |
| 
 | |
|   stmt= mysql_stmt_init(mysql);
 | |
| 
 | |
|   mysql_stmt_prepare(stmt, query, strlen(query));
 | |
|   mysql_stmt_execute(stmt);
 | |
| 
 | |
|   bzero((char*) my_bind, sizeof(my_bind));
 | |
|   for (i=0; i < 2; i++)
 | |
|   {
 | |
|     my_bind[i].buffer_type= MYSQL_TYPE_STRING;
 | |
|     my_bind[i].buffer= (uchar* *)&buf[i];
 | |
|     my_bind[i].buffer_length= 20;
 | |
|     my_bind[i].length= &len[i];
 | |
|   }
 | |
| 
 | |
|   rc= mysql_stmt_bind_result(stmt, my_bind);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= mysql_stmt_fetch(stmt);
 | |
|   check_execute(stmt, rc);
 | |
|   if (!opt_silent)
 | |
|     printf("return: %s", buf[1]);
 | |
|   DIE_UNLESS(!strcmp(buf[1],"1"));
 | |
|   mysql_stmt_close(stmt);
 | |
|   rc= mysql_query(mysql, "drop view v1");
 | |
|   myquery(rc);
 | |
|   rc= mysql_query(mysql, "drop table t1, t2");
 | |
|   myquery(rc);
 | |
| }
 | |
| 
 | |
| /*
 | |
|   Check that proper cleanups are done for prepared statement when
 | |
|   fetching through a cursor.
 | |
| */
 | |
| 
 | |
| static void test_bug10729()
 | |
| {
 | |
|   MYSQL_STMT *stmt;
 | |
|   MYSQL_BIND my_bind[1];
 | |
|   char a[21];
 | |
|   int rc;
 | |
|   const char *stmt_text;
 | |
|   int i= 0;
 | |
|   const char *name_array[3]= { "aaa", "bbb", "ccc" };
 | |
|   ulong type;
 | |
| 
 | |
|   myheader("test_bug10729");
 | |
| 
 | |
|   mysql_query(mysql, "drop table if exists t1");
 | |
|   mysql_query(mysql, "create table t1 (id integer not null primary key,"
 | |
|                                       "name VARCHAR(20) NOT NULL)");
 | |
|   rc= mysql_query(mysql, "insert into t1 (id, name) values "
 | |
|                          "(1, 'aaa'), (2, 'bbb'), (3, 'ccc')");
 | |
|   myquery(rc);
 | |
| 
 | |
|   stmt= mysql_stmt_init(mysql);
 | |
| 
 | |
|   type= (ulong) CURSOR_TYPE_READ_ONLY;
 | |
|   rc= mysql_stmt_attr_set(stmt, STMT_ATTR_CURSOR_TYPE, (void*) &type);
 | |
|   check_execute(stmt, rc);
 | |
|   stmt_text= "select name from t1";
 | |
|   rc= mysql_stmt_prepare(stmt, stmt_text, strlen(stmt_text));
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   bzero((char*) my_bind, sizeof(my_bind));
 | |
|   my_bind[0].buffer_type= MYSQL_TYPE_STRING;
 | |
|   my_bind[0].buffer= (void*) a;
 | |
|   my_bind[0].buffer_length= sizeof(a);
 | |
|   mysql_stmt_bind_result(stmt, my_bind);
 | |
| 
 | |
|   for (i= 0; i < 3; i++)
 | |
|   {
 | |
|     int row_no= 0;
 | |
|     rc= mysql_stmt_execute(stmt);
 | |
|     check_execute(stmt, rc);
 | |
|     while ((rc= mysql_stmt_fetch(stmt)) == 0)
 | |
|     {
 | |
|       DIE_UNLESS(strcmp(a, name_array[row_no]) == 0);
 | |
|       if (!opt_silent)
 | |
|         printf("%d: %s\n", row_no, a);
 | |
|       ++row_no;
 | |
|     }
 | |
|     DIE_UNLESS(rc == MYSQL_NO_DATA);
 | |
|   }
 | |
|   rc= mysql_stmt_close(stmt);
 | |
|   DIE_UNLESS(rc == 0);
 | |
| 
 | |
|   rc= mysql_query(mysql, "drop table t1");
 | |
|   myquery(rc);
 | |
| }
 | |
| 
 | |
| 
 | |
| /*
 | |
|   Check that mysql_next_result works properly in case when one of
 | |
|   the statements used in a multi-statement query is erroneous
 | |
| */
 | |
| 
 | |
| static void test_bug9992()
 | |
| {
 | |
|   MYSQL *mysql1;
 | |
|   MYSQL_RES* res ;
 | |
|   int   rc;
 | |
| 
 | |
|   myheader("test_bug9992");
 | |
| 
 | |
|   if (!opt_silent)
 | |
|     printf("Establishing a connection with option CLIENT_MULTI_STATEMENTS..\n");
 | |
| 
 | |
|   mysql1= mysql_client_init(NULL);
 | |
| 
 | |
|   if (!mysql_real_connect(mysql1, opt_host, opt_user, opt_password,
 | |
|                           opt_db ? opt_db : "test", opt_port, opt_unix_socket,
 | |
|                           CLIENT_MULTI_STATEMENTS))
 | |
|   {
 | |
|     fprintf(stderr, "Failed to connect to the database\n");
 | |
|     DIE_UNLESS(0);
 | |
|   }
 | |
| 
 | |
| 
 | |
|   /* Sic: SHOW DATABASE is incorrect syntax. */
 | |
|   rc= mysql_query(mysql1, "SHOW TABLES; SHOW DATABASE; SELECT 1;");
 | |
| 
 | |
|   if (rc)
 | |
|   {
 | |
|     fprintf(stderr, "[%d] %s\n", mysql_errno(mysql1), mysql_error(mysql1));
 | |
|     DIE_UNLESS(0);
 | |
|   }
 | |
| 
 | |
|   if (!opt_silent)
 | |
|     printf("Testing mysql_store_result/mysql_next_result..\n");
 | |
| 
 | |
|   res= mysql_store_result(mysql1);
 | |
|   DIE_UNLESS(res);
 | |
|   mysql_free_result(res);
 | |
|   rc= mysql_next_result(mysql1);
 | |
|   DIE_UNLESS(rc == 1);                         /* Got errors, as expected */
 | |
| 
 | |
|   if (!opt_silent)
 | |
|     fprintf(stdout, "Got error, as expected:\n [%d] %s\n",
 | |
|             mysql_errno(mysql1), mysql_error(mysql1));
 | |
| 
 | |
|   mysql_close(mysql1);
 | |
| }
 | |
| 
 | |
| /* Bug#10736: cursors and subqueries, memroot management */
 | |
| 
 | |
| static void test_bug10736()
 | |
| {
 | |
|   MYSQL_STMT *stmt;
 | |
|   MYSQL_BIND my_bind[1];
 | |
|   char a[21];
 | |
|   int rc;
 | |
|   const char *stmt_text;
 | |
|   int i= 0;
 | |
|   ulong type;
 | |
| 
 | |
|   myheader("test_bug10736");
 | |
| 
 | |
|   mysql_query(mysql, "drop table if exists t1");
 | |
|   mysql_query(mysql, "create table t1 (id integer not null primary key,"
 | |
|                                       "name VARCHAR(20) NOT NULL)");
 | |
|   rc= mysql_query(mysql, "insert into t1 (id, name) values "
 | |
|                          "(1, 'aaa'), (2, 'bbb'), (3, 'ccc')");
 | |
|   myquery(rc);
 | |
| 
 | |
|   stmt= mysql_stmt_init(mysql);
 | |
| 
 | |
|   type= (ulong) CURSOR_TYPE_READ_ONLY;
 | |
|   rc= mysql_stmt_attr_set(stmt, STMT_ATTR_CURSOR_TYPE, (void*) &type);
 | |
|   check_execute(stmt, rc);
 | |
|   stmt_text= "select name from t1 where name=(select name from t1 where id=2)";
 | |
|   rc= mysql_stmt_prepare(stmt, stmt_text, strlen(stmt_text));
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   bzero((char*) my_bind, sizeof(my_bind));
 | |
|   my_bind[0].buffer_type= MYSQL_TYPE_STRING;
 | |
|   my_bind[0].buffer= (void*) a;
 | |
|   my_bind[0].buffer_length= sizeof(a);
 | |
|   mysql_stmt_bind_result(stmt, my_bind);
 | |
| 
 | |
|   for (i= 0; i < 3; i++)
 | |
|   {
 | |
|     int row_no= 0;
 | |
|     rc= mysql_stmt_execute(stmt);
 | |
|     check_execute(stmt, rc);
 | |
|     while ((rc= mysql_stmt_fetch(stmt)) == 0)
 | |
|     {
 | |
|       if (!opt_silent)
 | |
|         printf("%d: %s\n", row_no, a);
 | |
|       ++row_no;
 | |
|     }
 | |
|     DIE_UNLESS(rc == MYSQL_NO_DATA);
 | |
|   }
 | |
|   rc= mysql_stmt_close(stmt);
 | |
|   DIE_UNLESS(rc == 0);
 | |
| 
 | |
|   rc= mysql_query(mysql, "drop table t1");
 | |
|   myquery(rc);
 | |
| }
 | |
| 
 | |
| /* Bug#10794: cursors, packets out of order */
 | |
| 
 | |
| static void test_bug10794()
 | |
| {
 | |
|   MYSQL_STMT *stmt, *stmt1;
 | |
|   MYSQL_BIND my_bind[2];
 | |
|   char a[21];
 | |
|   int id_val;
 | |
|   ulong a_len;
 | |
|   int rc;
 | |
|   const char *stmt_text;
 | |
|   int i= 0;
 | |
|   ulong type;
 | |
| 
 | |
|   myheader("test_bug10794");
 | |
| 
 | |
|   mysql_query(mysql, "drop table if exists t1");
 | |
|   mysql_query(mysql, "create table t1 (id integer not null primary key,"
 | |
|                                       "name varchar(20) not null)");
 | |
|   stmt= mysql_stmt_init(mysql);
 | |
|   stmt_text= "insert into t1 (id, name) values (?, ?)";
 | |
|   rc= mysql_stmt_prepare(stmt, stmt_text, strlen(stmt_text));
 | |
|   check_execute(stmt, rc);
 | |
|   bzero((char*) my_bind, sizeof(my_bind));
 | |
|   my_bind[0].buffer_type= MYSQL_TYPE_LONG;
 | |
|   my_bind[0].buffer= (void*) &id_val;
 | |
|   my_bind[1].buffer_type= MYSQL_TYPE_STRING;
 | |
|   my_bind[1].buffer= (void*) a;
 | |
|   my_bind[1].length= &a_len;
 | |
|   rc= mysql_stmt_bind_param(stmt, my_bind);
 | |
|   check_execute(stmt, rc);
 | |
|   for (i= 0; i < 42; i++)
 | |
|   {
 | |
|     id_val= (i+1)*10;
 | |
|     sprintf(a, "a%d", i);
 | |
|     a_len= strlen(a); /* safety against broken sprintf */
 | |
|     rc= mysql_stmt_execute(stmt);
 | |
|     check_execute(stmt, rc);
 | |
|   }
 | |
|   stmt_text= "select name from t1";
 | |
|   rc= mysql_stmt_prepare(stmt, stmt_text, strlen(stmt_text));
 | |
|   type= (ulong) CURSOR_TYPE_READ_ONLY;
 | |
|   mysql_stmt_attr_set(stmt, STMT_ATTR_CURSOR_TYPE, (const void*) &type);
 | |
|   stmt1= mysql_stmt_init(mysql);
 | |
|   mysql_stmt_attr_set(stmt1, STMT_ATTR_CURSOR_TYPE, (const void*) &type);
 | |
|   bzero((char*) my_bind, sizeof(my_bind));
 | |
|   my_bind[0].buffer_type= MYSQL_TYPE_STRING;
 | |
|   my_bind[0].buffer= (void*) a;
 | |
|   my_bind[0].buffer_length= sizeof(a);
 | |
|   my_bind[0].length= &a_len;
 | |
|   rc= mysql_stmt_bind_result(stmt, my_bind);
 | |
|   check_execute(stmt, rc);
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
|   rc= mysql_stmt_fetch(stmt);
 | |
|   check_execute(stmt, rc);
 | |
|   if (!opt_silent)
 | |
|     printf("Fetched row from stmt: %s\n", a);
 | |
|   /* Don't optimize: an attribute of the original test case */
 | |
|   mysql_stmt_free_result(stmt);
 | |
|   mysql_stmt_reset(stmt);
 | |
|   stmt_text= "select name from t1 where id=10";
 | |
|   rc= mysql_stmt_prepare(stmt1, stmt_text, strlen(stmt_text));
 | |
|   check_execute(stmt1, rc);
 | |
|   rc= mysql_stmt_bind_result(stmt1, my_bind);
 | |
|   check_execute(stmt1, rc);
 | |
|   rc= mysql_stmt_execute(stmt1);
 | |
|   while (1)
 | |
|   {
 | |
|     rc= mysql_stmt_fetch(stmt1);
 | |
|     if (rc == MYSQL_NO_DATA)
 | |
|     {
 | |
|       if (!opt_silent)
 | |
|         printf("End of data in stmt1\n");
 | |
|       break;
 | |
|     }
 | |
|     check_execute(stmt1, rc);
 | |
|     if (!opt_silent)
 | |
|       printf("Fetched row from stmt1: %s\n", a);
 | |
|   }
 | |
|   mysql_stmt_close(stmt);
 | |
|   mysql_stmt_close(stmt1);
 | |
| 
 | |
|   rc= mysql_query(mysql, "drop table t1");
 | |
|   myquery(rc);
 | |
| }
 | |
| 
 | |
| 
 | |
| /* Bug#11172: cursors, crash on a fetch from a datetime column */
 | |
| 
 | |
| static void test_bug11172()
 | |
| {
 | |
|   MYSQL_STMT *stmt;
 | |
|   MYSQL_BIND bind_in[1], bind_out[2];
 | |
|   MYSQL_TIME hired;
 | |
|   int rc;
 | |
|   const char *stmt_text;
 | |
|   int i= 0, id;
 | |
|   ulong type;
 | |
| 
 | |
|   myheader("test_bug11172");
 | |
| 
 | |
|   mysql_query(mysql, "drop table if exists t1");
 | |
|   mysql_query(mysql, "create table t1 (id integer not null primary key,"
 | |
|                                       "hired date not null)");
 | |
|   rc= mysql_query(mysql,
 | |
|                   "insert into t1 (id, hired) values (1, '1933-08-24'), "
 | |
|                   "(2, '1965-01-01'), (3, '1949-08-17'), (4, '1945-07-07'), "
 | |
|                   "(5, '1941-05-15'), (6, '1978-09-15'), (7, '1936-03-28')");
 | |
|   myquery(rc);
 | |
|   stmt= mysql_stmt_init(mysql);
 | |
|   stmt_text= "SELECT id, hired FROM t1 WHERE hired=?";
 | |
|   rc= mysql_stmt_prepare(stmt, stmt_text, strlen(stmt_text));
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   type= (ulong) CURSOR_TYPE_READ_ONLY;
 | |
|   mysql_stmt_attr_set(stmt, STMT_ATTR_CURSOR_TYPE, (const void*) &type);
 | |
| 
 | |
|   bzero((char*) bind_in, sizeof(bind_in));
 | |
|   bzero((char*) bind_out, sizeof(bind_out));
 | |
|   bzero((char*) &hired, sizeof(hired));
 | |
|   hired.year= 1965;
 | |
|   hired.month= 1;
 | |
|   hired.day= 1;
 | |
|   bind_in[0].buffer_type= MYSQL_TYPE_DATE;
 | |
|   bind_in[0].buffer= (void*) &hired;
 | |
|   bind_in[0].buffer_length= sizeof(hired);
 | |
|   bind_out[0].buffer_type= MYSQL_TYPE_LONG;
 | |
|   bind_out[0].buffer= (void*) &id;
 | |
|   bind_out[1]= bind_in[0];
 | |
| 
 | |
|   for (i= 0; i < 3; i++)
 | |
|   {
 | |
|     rc= mysql_stmt_bind_param(stmt, bind_in);
 | |
|     check_execute(stmt, rc);
 | |
|     rc= mysql_stmt_bind_result(stmt, bind_out);
 | |
|     check_execute(stmt, rc);
 | |
|     rc= mysql_stmt_execute(stmt);
 | |
|     check_execute(stmt, rc);
 | |
|     while ((rc= mysql_stmt_fetch(stmt)) == 0)
 | |
|     {
 | |
|       if (!opt_silent)
 | |
|         printf("fetched data %d:%d-%d-%d\n", id,
 | |
|                hired.year, hired.month, hired.day);
 | |
|     }
 | |
|     DIE_UNLESS(rc == MYSQL_NO_DATA);
 | |
|     if (!mysql_stmt_free_result(stmt))
 | |
|       mysql_stmt_reset(stmt);
 | |
|   }
 | |
|   mysql_stmt_close(stmt);
 | |
|   mysql_rollback(mysql);
 | |
|   mysql_rollback(mysql);
 | |
| 
 | |
|   rc= mysql_query(mysql, "drop table t1");
 | |
|   myquery(rc);
 | |
| }
 | |
| 
 | |
| 
 | |
| /* Bug#11656: cursors, crash on a fetch from a query with distinct. */
 | |
| 
 | |
| static void test_bug11656()
 | |
| {
 | |
|   MYSQL_STMT *stmt;
 | |
|   MYSQL_BIND my_bind[2];
 | |
|   int rc;
 | |
|   const char *stmt_text;
 | |
|   char buf[2][20];
 | |
|   int i= 0;
 | |
|   ulong type;
 | |
| 
 | |
|   myheader("test_bug11656");
 | |
| 
 | |
|   mysql_query(mysql, "drop table if exists t1");
 | |
| 
 | |
|   rc= mysql_query(mysql, "create table t1 ("
 | |
|                   "server varchar(40) not null, "
 | |
|                   "test_kind varchar(1) not null, "
 | |
|                   "test_id varchar(30) not null , "
 | |
|                   "primary key (server,test_kind,test_id))");
 | |
|   myquery(rc);
 | |
| 
 | |
|   stmt_text= "select distinct test_kind, test_id from t1 "
 | |
|              "where server in (?, ?)";
 | |
|   stmt= mysql_stmt_init(mysql);
 | |
|   rc= mysql_stmt_prepare(stmt, stmt_text, strlen(stmt_text));
 | |
|   check_execute(stmt, rc);
 | |
|   type= (ulong) CURSOR_TYPE_READ_ONLY;
 | |
|   mysql_stmt_attr_set(stmt, STMT_ATTR_CURSOR_TYPE, (const void*) &type);
 | |
| 
 | |
|   bzero((char*) my_bind, sizeof(my_bind));
 | |
|   strmov(buf[0], "pcint502_MY2");
 | |
|   strmov(buf[1], "*");
 | |
|   for (i=0; i < 2; i++)
 | |
|   {
 | |
|     my_bind[i].buffer_type= MYSQL_TYPE_STRING;
 | |
|     my_bind[i].buffer= (uchar* *)&buf[i];
 | |
|     my_bind[i].buffer_length= strlen(buf[i]);
 | |
|   }
 | |
|   mysql_stmt_bind_param(stmt, my_bind);
 | |
| 
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= mysql_stmt_fetch(stmt);
 | |
|   DIE_UNLESS(rc == MYSQL_NO_DATA);
 | |
| 
 | |
|   mysql_stmt_close(stmt);
 | |
|   rc= mysql_query(mysql, "drop table t1");
 | |
|   myquery(rc);
 | |
| }
 | |
| 
 | |
| 
 | |
| /*
 | |
|   Check that the server signals when NO_BACKSLASH_ESCAPES mode is in effect,
 | |
|   and mysql_real_escape_string() does the right thing as a result.
 | |
| */
 | |
| 
 | |
| static void test_bug10214()
 | |
| {
 | |
|   int   len;
 | |
|   char  out[8];
 | |
| 
 | |
|   myheader("test_bug10214");
 | |
| 
 | |
|   DIE_UNLESS(!(mysql->server_status & SERVER_STATUS_NO_BACKSLASH_ESCAPES));
 | |
| 
 | |
|   len= mysql_real_escape_string(mysql, out, "a'b\\c", 5);
 | |
|   DIE_UNLESS(memcmp(out, "a\\'b\\\\c", len) == 0);
 | |
| 
 | |
|   mysql_query(mysql, "set sql_mode='NO_BACKSLASH_ESCAPES'");
 | |
|   DIE_UNLESS(mysql->server_status & SERVER_STATUS_NO_BACKSLASH_ESCAPES);
 | |
| 
 | |
|   len= mysql_real_escape_string(mysql, out, "a'b\\c", 5);
 | |
|   DIE_UNLESS(memcmp(out, "a''b\\c", len) == 0);
 | |
| 
 | |
|   mysql_query(mysql, "set sql_mode=''");
 | |
| }
 | |
| 
 | |
| static void test_client_character_set()
 | |
| {
 | |
|   MY_CHARSET_INFO cs;
 | |
|   char *csname= (char*) "utf8";
 | |
|   char *csdefault= (char*)mysql_character_set_name(mysql);
 | |
|   int rc;
 | |
| 
 | |
|   myheader("test_client_character_set");
 | |
| 
 | |
|   rc= mysql_set_character_set(mysql, csname);
 | |
|   DIE_UNLESS(rc == 0);
 | |
| 
 | |
|   mysql_get_character_set_info(mysql, &cs);
 | |
|   DIE_UNLESS(!strcmp(cs.csname, "utf8mb3"));
 | |
|   DIE_UNLESS(!strcmp(cs.name, "utf8mb3_general_ci"));
 | |
|   /* Restore the default character set */
 | |
|   rc= mysql_set_character_set(mysql, csdefault);
 | |
|   myquery(rc);
 | |
| }
 | |
| 
 | |
| /* Test correct max length for MEDIUMTEXT and LONGTEXT columns */
 | |
| 
 | |
| static void test_bug9735()
 | |
| {
 | |
|   MYSQL_RES *res;
 | |
|   int rc;
 | |
| 
 | |
|   myheader("test_bug9735");
 | |
| 
 | |
|   rc= mysql_query(mysql, "drop table if exists t1");
 | |
|   myquery(rc);
 | |
|   rc= mysql_query(mysql, "create table t1 (a mediumtext, b longtext) "
 | |
|                          "character set latin1");
 | |
|   myquery(rc);
 | |
|   rc= mysql_query(mysql, "select * from t1");
 | |
|   myquery(rc);
 | |
|   res= mysql_store_result(mysql);
 | |
|   verify_prepare_field(res, 0, "a", "a", MYSQL_TYPE_BLOB,
 | |
|                        "t1", "t1", current_db, (1U << 24)-1, 0);
 | |
|   verify_prepare_field(res, 1, "b", "b", MYSQL_TYPE_BLOB,
 | |
|                        "t1", "t1", current_db, ~0U, 0);
 | |
|   mysql_free_result(res);
 | |
|   rc= mysql_query(mysql, "drop table t1");
 | |
|   myquery(rc);
 | |
| }
 | |
| 
 | |
| 
 | |
| /* Bug#11183 "mysql_stmt_reset() doesn't reset information about error" */
 | |
| 
 | |
| static void test_bug11183()
 | |
| {
 | |
|   int rc;
 | |
|   MYSQL_STMT *stmt;
 | |
|   char bug_statement[]= "insert into t1 values (1)";
 | |
| 
 | |
|   myheader("test_bug11183");
 | |
| 
 | |
|   mysql_query(mysql, "drop table t1 if exists");
 | |
|   mysql_query(mysql, "create table t1 (a int)");
 | |
| 
 | |
|   stmt= mysql_stmt_init(mysql);
 | |
|   DIE_UNLESS(stmt != 0);
 | |
| 
 | |
|   rc= mysql_stmt_prepare(stmt, bug_statement, strlen(bug_statement));
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "drop table t1");
 | |
|   myquery(rc);
 | |
| 
 | |
|   /* Trying to execute statement that should fail on execute stage */
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   DIE_UNLESS(rc);
 | |
| 
 | |
|   mysql_stmt_reset(stmt);
 | |
|   DIE_UNLESS(mysql_stmt_errno(stmt) == 0);
 | |
| 
 | |
|   mysql_query(mysql, "create table t1 (a int)");
 | |
| 
 | |
|   /* Trying to execute statement that should pass ok */
 | |
|   if (mysql_stmt_execute(stmt))
 | |
|   {
 | |
|     mysql_stmt_reset(stmt);
 | |
|     DIE_UNLESS(mysql_stmt_errno(stmt) == 0);
 | |
|   }
 | |
| 
 | |
|   mysql_stmt_close(stmt);
 | |
| 
 | |
|   rc= mysql_query(mysql, "drop table t1");
 | |
|   myquery(rc);
 | |
| }
 | |
| 
 | |
| static void test_bug11037()
 | |
| {
 | |
|   MYSQL_STMT *stmt;
 | |
|   int rc;
 | |
|   const char *stmt_text;
 | |
| 
 | |
|   myheader("test_bug11037");
 | |
| 
 | |
|   mysql_query(mysql, "drop table if exists t1");
 | |
| 
 | |
|   rc= mysql_query(mysql, "create table t1 (id int not null)");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "insert into t1 values (1)");
 | |
|   myquery(rc);
 | |
| 
 | |
|   stmt_text= "select id FROM t1";
 | |
|   stmt= mysql_stmt_init(mysql);
 | |
|   rc= mysql_stmt_prepare(stmt, stmt_text, strlen(stmt_text));
 | |
| 
 | |
|   /* expected error */
 | |
|   rc = mysql_stmt_fetch(stmt);
 | |
|   DIE_UNLESS(rc==1);
 | |
|   if (!opt_silent)
 | |
|     fprintf(stdout, "Got error, as expected:\n [%d] %s\n",
 | |
|             mysql_stmt_errno(stmt), mysql_stmt_error(stmt));
 | |
| 
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= mysql_stmt_fetch(stmt);
 | |
|   DIE_UNLESS(rc==0);
 | |
| 
 | |
|   rc= mysql_stmt_fetch(stmt);
 | |
|   DIE_UNLESS(rc==MYSQL_NO_DATA);
 | |
| 
 | |
|   rc= mysql_stmt_fetch(stmt);
 | |
|   DIE_UNLESS(rc==MYSQL_NO_DATA);
 | |
| 
 | |
|   mysql_stmt_close(stmt);
 | |
|   rc= mysql_query(mysql, "drop table t1");
 | |
|   myquery(rc);
 | |
| }
 | |
| 
 | |
| /* Bug#10760: cursors, crash in a fetch after rollback. */
 | |
| 
 | |
| static void test_bug10760()
 | |
| {
 | |
|   MYSQL_STMT *stmt;
 | |
|   MYSQL_BIND my_bind[1];
 | |
|   int rc;
 | |
|   const char *stmt_text;
 | |
|   char id_buf[20];
 | |
|   ulong id_len;
 | |
|   int i= 0;
 | |
|   ulong type;
 | |
| 
 | |
|   myheader("test_bug10760");
 | |
| 
 | |
|   mysql_query(mysql, "drop table if exists t1, t2");
 | |
| 
 | |
|   /* create tables */
 | |
|   rc= mysql_query(mysql, "create table t1 (id integer not null primary key)"
 | |
|                          " engine=MyISAM");
 | |
|   myquery(rc);
 | |
|   for (; i < 42; ++i)
 | |
|   {
 | |
|     char buf[100];
 | |
|     sprintf(buf, "insert into t1 (id) values (%d)", i+1);
 | |
|     rc= mysql_query(mysql, buf);
 | |
|     myquery(rc);
 | |
|   }
 | |
|   mysql_autocommit(mysql, FALSE);
 | |
|   /* create statement */
 | |
|   stmt= mysql_stmt_init(mysql);
 | |
|   type= (ulong) CURSOR_TYPE_READ_ONLY;
 | |
|   mysql_stmt_attr_set(stmt, STMT_ATTR_CURSOR_TYPE, (const void*) &type);
 | |
| 
 | |
|   /*
 | |
|     1: check that a deadlock within the same connection
 | |
|     is resolved and an error is returned. The deadlock is modelled
 | |
|     as follows:
 | |
|     con1: open cursor for select * from t1;
 | |
|     con1: insert into t1 (id) values (1)
 | |
|   */
 | |
|   stmt_text= "select id from t1 order by 1";
 | |
|   rc= mysql_stmt_prepare(stmt, stmt_text, strlen(stmt_text));
 | |
|   check_execute(stmt, rc);
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
|   rc= mysql_query(mysql, "update t1 set id=id+100");
 | |
|   /*
 | |
|     If cursors are not materialized, the update will return an error;
 | |
|     we mainly test that it won't deadlock.
 | |
|   */
 | |
|   if (rc && !opt_silent)
 | |
|     printf("Got error (as expected): %s\n", mysql_error(mysql));
 | |
|   /*
 | |
|     2: check that MyISAM tables used in cursors survive
 | |
|     COMMIT/ROLLBACK.
 | |
|   */
 | |
|   rc= mysql_rollback(mysql);                  /* should not close the cursor */
 | |
|   myquery(rc);
 | |
|   rc= mysql_stmt_fetch(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   /*
 | |
|     3: check that cursors to InnoDB tables are closed (for now) by
 | |
|     COMMIT/ROLLBACK.
 | |
|   */
 | |
|   if (! have_innodb)
 | |
|   {
 | |
|     if (!opt_silent)
 | |
|       printf("Testing that cursors are closed at COMMIT/ROLLBACK requires "
 | |
|              "InnoDB.\n");
 | |
|   }
 | |
|   else
 | |
|   {
 | |
|     stmt_text= "select id from t1 order by 1";
 | |
|     rc= mysql_stmt_prepare(stmt, stmt_text, strlen(stmt_text));
 | |
|     check_execute(stmt, rc);
 | |
| 
 | |
|     rc= mysql_query(mysql, "alter table t1 engine=InnoDB");
 | |
|     myquery(rc);
 | |
| 
 | |
|     bzero(my_bind, sizeof(my_bind));
 | |
|     my_bind[0].buffer_type= MYSQL_TYPE_STRING;
 | |
|     my_bind[0].buffer= (void*) id_buf;
 | |
|     my_bind[0].buffer_length= sizeof(id_buf);
 | |
|     my_bind[0].length= &id_len;
 | |
|     check_execute(stmt, rc);
 | |
|     mysql_stmt_bind_result(stmt, my_bind);
 | |
| 
 | |
|     rc= mysql_stmt_execute(stmt);
 | |
|     rc= mysql_stmt_fetch(stmt);
 | |
|     DIE_UNLESS(rc == 0);
 | |
|     if (!opt_silent)
 | |
|       printf("Fetched row %s\n", id_buf);
 | |
|     rc= mysql_rollback(mysql);                  /* should close the cursor */
 | |
|     myquery(rc);
 | |
| #if 0
 | |
|     rc= mysql_stmt_fetch(stmt);
 | |
|     DIE_UNLESS(rc);
 | |
|     if (!opt_silent)
 | |
|       printf("Got error (as expected): %s\n", mysql_error(mysql));
 | |
| #endif
 | |
|   }
 | |
| 
 | |
|   mysql_stmt_close(stmt);
 | |
|   rc= mysql_query(mysql, "drop table t1");
 | |
|   myquery(rc);
 | |
|   mysql_autocommit(mysql, TRUE);                /* restore default */
 | |
| }
 | |
| 
 | |
| static void test_bug12001()
 | |
| {
 | |
|   MYSQL *mysql_local;
 | |
|   MYSQL_RES *result;
 | |
|   const char *query= "DROP TABLE IF EXISTS test_table;"
 | |
|                      "CREATE TABLE test_table(id INT);"
 | |
|                      "INSERT INTO test_table VALUES(10);"
 | |
|                      "UPDATE test_table SET id=20 WHERE id=10;"
 | |
|                      "SELECT * FROM test_table;"
 | |
|                      "INSERT INTO non_existent_table VALUES(11);";
 | |
|   int rc, res;
 | |
| 
 | |
|   myheader("test_bug12001");
 | |
| 
 | |
|   if (!(mysql_local= mysql_client_init(NULL)))
 | |
|   {
 | |
|     fprintf(stdout, "\n mysql_client_init() failed");
 | |
|     exit(1);
 | |
|   }
 | |
| 
 | |
|   /* Create connection that supports multi statements */
 | |
|   if (!mysql_real_connect(mysql_local, opt_host, opt_user,
 | |
|                           opt_password, current_db, opt_port,
 | |
|                           opt_unix_socket, CLIENT_MULTI_STATEMENTS))
 | |
|   {
 | |
|     fprintf(stdout, "\n mysql_real_connect() failed");
 | |
|     exit(1);
 | |
|   }
 | |
| 
 | |
|   rc= mysql_query(mysql_local, query);
 | |
|   myquery(rc);
 | |
| 
 | |
|   do
 | |
|   {
 | |
|     if (mysql_field_count(mysql_local) &&
 | |
|         (result= mysql_use_result(mysql_local)))
 | |
|     {
 | |
|       mysql_free_result(result);
 | |
|     }
 | |
|   }
 | |
|   while (!(res= mysql_next_result(mysql_local)));
 | |
| 
 | |
|   rc= mysql_query(mysql_local, "DROP TABLE IF EXISTS test_table");
 | |
|   myquery(rc);
 | |
| 
 | |
|   mysql_close(mysql_local);
 | |
|   DIE_UNLESS(res==1);
 | |
| }
 | |
| 
 | |
| 
 | |
| /* Bug#11909: wrong metadata if fetching from two cursors */
 | |
| 
 | |
| static void test_bug11909()
 | |
| {
 | |
|   MYSQL_STMT *stmt1, *stmt2;
 | |
|   MYSQL_BIND my_bind[7];
 | |
|   int rc;
 | |
|   char firstname[20], midinit[20], lastname[20], workdept[20];
 | |
|   ulong firstname_len, midinit_len, lastname_len, workdept_len;
 | |
|   uint32 empno;
 | |
|   double salary;
 | |
|   float bonus;
 | |
|   const char *stmt_text;
 | |
| 
 | |
|   myheader("test_bug11909");
 | |
| 
 | |
|   stmt_text= "drop table if exists t1";
 | |
|   rc= mysql_real_query(mysql, stmt_text, strlen(stmt_text));
 | |
|   myquery(rc);
 | |
| 
 | |
|   stmt_text= "create table t1 ("
 | |
|     "  empno int(11) not null, firstname varchar(20) not null,"
 | |
|     "  midinit varchar(20) not null, lastname varchar(20) not null,"
 | |
|     "  workdept varchar(6) not null, salary double not null,"
 | |
|     "  bonus float not null, primary key (empno)"
 | |
|     ") default charset=latin1 collate=latin1_bin";
 | |
|   rc= mysql_real_query(mysql, stmt_text, strlen(stmt_text));
 | |
|   myquery(rc);
 | |
| 
 | |
|   stmt_text= "insert into t1 values "
 | |
|     "(10, 'CHRISTINE', 'I', 'HAAS',     'A00', 52750, 1000), "
 | |
|     "(20, 'MICHAEL',   'L', 'THOMPSON', 'B01', 41250, 800),"
 | |
|     "(30, 'SALLY',     'A', 'KWAN',     'C01', 38250, 800),"
 | |
|     "(50, 'JOHN',      'B', 'GEYER',    'E01', 40175, 800), "
 | |
|     "(60, 'IRVING',    'F', 'STERN',    'D11', 32250, 500)";
 | |
|   rc= mysql_real_query(mysql, stmt_text, strlen(stmt_text));
 | |
|   myquery(rc);
 | |
| 
 | |
|   /* ****** Begin of trace ****** */
 | |
| 
 | |
|   stmt1= open_cursor("SELECT empno, firstname, midinit, lastname,"
 | |
|                      "workdept, salary, bonus FROM t1");
 | |
| 
 | |
|   bzero(my_bind, sizeof(my_bind));
 | |
|   my_bind[0].buffer_type= MYSQL_TYPE_LONG;
 | |
|   my_bind[0].buffer= (void*) &empno;
 | |
| 
 | |
|   my_bind[1].buffer_type= MYSQL_TYPE_VAR_STRING;
 | |
|   my_bind[1].buffer= (void*) firstname;
 | |
|   my_bind[1].buffer_length= sizeof(firstname);
 | |
|   my_bind[1].length= &firstname_len;
 | |
| 
 | |
|   my_bind[2].buffer_type= MYSQL_TYPE_VAR_STRING;
 | |
|   my_bind[2].buffer= (void*) midinit;
 | |
|   my_bind[2].buffer_length= sizeof(midinit);
 | |
|   my_bind[2].length= &midinit_len;
 | |
| 
 | |
|   my_bind[3].buffer_type= MYSQL_TYPE_VAR_STRING;
 | |
|   my_bind[3].buffer= (void*) lastname;
 | |
|   my_bind[3].buffer_length= sizeof(lastname);
 | |
|   my_bind[3].length= &lastname_len;
 | |
| 
 | |
|   my_bind[4].buffer_type= MYSQL_TYPE_VAR_STRING;
 | |
|   my_bind[4].buffer= (void*) workdept;
 | |
|   my_bind[4].buffer_length= sizeof(workdept);
 | |
|   my_bind[4].length= &workdept_len;
 | |
| 
 | |
|   my_bind[5].buffer_type= MYSQL_TYPE_DOUBLE;
 | |
|   my_bind[5].buffer= (void*) &salary;
 | |
| 
 | |
|   my_bind[6].buffer_type= MYSQL_TYPE_FLOAT;
 | |
|   my_bind[6].buffer= (void*) &bonus;
 | |
|   rc= mysql_stmt_bind_result(stmt1, my_bind);
 | |
|   check_execute(stmt1, rc);
 | |
| 
 | |
|   rc= mysql_stmt_execute(stmt1);
 | |
|   check_execute(stmt1, rc);
 | |
| 
 | |
|   rc= mysql_stmt_fetch(stmt1);
 | |
|   DIE_UNLESS(rc == 0);
 | |
|   DIE_UNLESS(empno == 10);
 | |
|   DIE_UNLESS(strcmp(firstname, "CHRISTINE") == 0);
 | |
|   DIE_UNLESS(strcmp(midinit, "I") == 0);
 | |
|   DIE_UNLESS(strcmp(lastname, "HAAS") == 0);
 | |
|   DIE_UNLESS(strcmp(workdept, "A00") == 0);
 | |
|   DIE_UNLESS(salary == (double) 52750.0);
 | |
|   DIE_UNLESS(bonus == (float) 1000.0);
 | |
| 
 | |
|   stmt2= open_cursor("SELECT empno, firstname FROM t1");
 | |
|   rc= mysql_stmt_bind_result(stmt2, my_bind);
 | |
|   check_execute(stmt2, rc);
 | |
| 
 | |
|   rc= mysql_stmt_execute(stmt2);
 | |
|   check_execute(stmt2, rc);
 | |
| 
 | |
|   rc= mysql_stmt_fetch(stmt2);
 | |
|   DIE_UNLESS(rc == 0);
 | |
| 
 | |
|   DIE_UNLESS(empno == 10);
 | |
|   DIE_UNLESS(strcmp(firstname, "CHRISTINE") == 0);
 | |
| 
 | |
|   rc= mysql_stmt_reset(stmt2);
 | |
|   check_execute(stmt2, rc);
 | |
| 
 | |
|   /* ERROR: next statement should return 0 */
 | |
| 
 | |
|   rc= mysql_stmt_fetch(stmt1);
 | |
|   DIE_UNLESS(rc == 0);
 | |
| 
 | |
|   mysql_stmt_close(stmt1);
 | |
|   mysql_stmt_close(stmt2);
 | |
|   rc= mysql_rollback(mysql);
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "drop table t1");
 | |
|   myquery(rc);
 | |
| }
 | |
| 
 | |
| /* Cursors: opening a cursor to a complicated query with ORDER BY */
 | |
| 
 | |
| static void test_bug11901()
 | |
| {
 | |
|   MYSQL_STMT *stmt;
 | |
|   MYSQL_BIND my_bind[2];
 | |
|   int rc;
 | |
|   char workdept[20];
 | |
|   ulong workdept_len;
 | |
|   uint32 empno;
 | |
|   const char *stmt_text;
 | |
| 
 | |
|   myheader("test_bug11901");
 | |
| 
 | |
|   stmt_text= "drop table if exists t1, t2";
 | |
|   rc= mysql_real_query(mysql, stmt_text, strlen(stmt_text));
 | |
|   myquery(rc);
 | |
| 
 | |
|   stmt_text= "create table t1 ("
 | |
|     "  empno int(11) not null, firstname varchar(20) not null,"
 | |
|     "  midinit varchar(20) not null, lastname varchar(20) not null,"
 | |
|     "  workdept varchar(6) not null, salary double not null,"
 | |
|     "  bonus float not null, primary key (empno), "
 | |
|     " unique key (workdept, empno) "
 | |
|     ") default charset=latin1 collate=latin1_bin";
 | |
|   rc= mysql_real_query(mysql, stmt_text, strlen(stmt_text));
 | |
|   myquery(rc);
 | |
| 
 | |
|   stmt_text= "insert into t1 values "
 | |
|      "(10,  'CHRISTINE', 'I', 'HAAS',      'A00', 52750, 1000),"
 | |
|      "(20,  'MICHAEL',   'L', 'THOMPSON',  'B01', 41250, 800), "
 | |
|      "(30,  'SALLY',     'A', 'KWAN',      'C01', 38250, 800), "
 | |
|      "(50,  'JOHN',      'B', 'GEYER',     'E01', 40175, 800), "
 | |
|      "(60,  'IRVING',    'F', 'STERN',     'D11', 32250, 500), "
 | |
|      "(70,  'EVA',       'D', 'PULASKI',   'D21', 36170, 700), "
 | |
|      "(90,  'EILEEN',    'W', 'HENDERSON', 'E11', 29750, 600), "
 | |
|      "(100, 'THEODORE',  'Q', 'SPENSER',   'E21', 26150, 500), "
 | |
|      "(110, 'VINCENZO',  'G', 'LUCCHESSI', 'A00', 46500, 900), "
 | |
|      "(120, 'SEAN',      '',  'O\\'CONNELL', 'A00', 29250, 600), "
 | |
|      "(130, 'DOLORES',   'M', 'QUINTANA',  'C01', 23800, 500), "
 | |
|      "(140, 'HEATHER',   'A', 'NICHOLLS',  'C01', 28420, 600), "
 | |
|      "(150, 'BRUCE',     '',  'ADAMSON',   'D11', 25280, 500), "
 | |
|      "(160, 'ELIZABETH', 'R', 'PIANKA',    'D11', 22250, 400), "
 | |
|      "(170, 'MASATOSHI', 'J', 'YOSHIMURA', 'D11', 24680, 500), "
 | |
|      "(180, 'MARILYN',   'S', 'SCOUTTEN',  'D11', 21340, 500), "
 | |
|      "(190, 'JAMES',     'H', 'WALKER',    'D11', 20450, 400), "
 | |
|      "(200, 'DAVID',     '',  'BROWN',     'D11', 27740, 600), "
 | |
|      "(210, 'WILLIAM',   'T', 'JONES',     'D11', 18270, 400), "
 | |
|      "(220, 'JENNIFER',  'K', 'LUTZ',      'D11', 29840, 600), "
 | |
|      "(230, 'JAMES',     'J', 'JEFFERSON', 'D21', 22180, 400), "
 | |
|      "(240, 'SALVATORE', 'M', 'MARINO',    'D21', 28760, 600), "
 | |
|      "(250, 'DANIEL',    'S', 'SMITH',     'D21', 19180, 400), "
 | |
|      "(260, 'SYBIL',     'P', 'JOHNSON',   'D21', 17250, 300), "
 | |
|      "(270, 'MARIA',     'L', 'PEREZ',     'D21', 27380, 500), "
 | |
|      "(280, 'ETHEL',     'R', 'SCHNEIDER', 'E11', 26250, 500), "
 | |
|      "(290, 'JOHN',      'R', 'PARKER',    'E11', 15340, 300), "
 | |
|      "(300, 'PHILIP',    'X', 'SMITH',     'E11', 17750, 400), "
 | |
|      "(310, 'MAUDE',     'F', 'SETRIGHT',  'E11', 15900, 300), "
 | |
|      "(320, 'RAMLAL',    'V', 'MEHTA',     'E21', 19950, 400), "
 | |
|      "(330, 'WING',      '',  'LEE',       'E21', 25370, 500), "
 | |
|      "(340, 'JASON',     'R', 'GOUNOT',    'E21', 23840, 500)";
 | |
| 
 | |
|   rc= mysql_real_query(mysql, stmt_text, strlen(stmt_text));
 | |
|   myquery(rc);
 | |
| 
 | |
|   stmt_text= "create table t2 ("
 | |
|     " deptno varchar(6) not null, deptname varchar(20) not null,"
 | |
|     " mgrno int(11) not null, location varchar(20) not null,"
 | |
|     " admrdept varchar(6) not null, refcntd int(11) not null,"
 | |
|     " refcntu int(11) not null, primary key (deptno)"
 | |
|     ") default charset=latin1 collate=latin1_bin";
 | |
|   rc= mysql_real_query(mysql, stmt_text, strlen(stmt_text));
 | |
|   myquery(rc);
 | |
| 
 | |
|   stmt_text= "insert into t2 values "
 | |
|     "('A00', 'SPIFFY COMPUTER SERV', 10, '', 'A00', 0, 0), "
 | |
|     "('B01', 'PLANNING',             20, '', 'A00', 0, 0), "
 | |
|     "('C01', 'INFORMATION CENTER',   30, '', 'A00', 0, 0), "
 | |
|     "('D01', 'DEVELOPMENT CENTER',   0,  '', 'A00', 0, 0),"
 | |
|     "('D11', 'MANUFACTURING SYSTEM', 60, '', 'D01', 0, 0), "
 | |
|     "('D21', 'ADMINISTRATION SYSTE', 70, '', 'D01', 0, 0), "
 | |
|     "('E01', 'SUPPORT SERVICES',     50, '', 'A00', 0, 0), "
 | |
|     "('E11', 'OPERATIONS',           90, '', 'E01', 0, 0), "
 | |
|     "('E21', 'SOFTWARE SUPPORT',     100,'', 'E01', 0, 0)";
 | |
|   rc= mysql_real_query(mysql, stmt_text, strlen(stmt_text));
 | |
|   myquery(rc);
 | |
| 
 | |
|   /* ****** Begin of trace ****** */
 | |
| 
 | |
|   stmt= open_cursor("select t1.empno, t1.workdept "
 | |
|                     "from (t1 left join t2 on t2.deptno = t1.workdept) "
 | |
|                     "where t2.deptno in "
 | |
|                     "   (select t2.deptno "
 | |
|                     "    from (t1 left join t2 on t2.deptno = t1.workdept) "
 | |
|                     "    where t1.empno = ?) "
 | |
|                     "order by 1");
 | |
|   bzero(my_bind, sizeof(my_bind));
 | |
| 
 | |
|   my_bind[0].buffer_type= MYSQL_TYPE_LONG;
 | |
|   my_bind[0].buffer= &empno;
 | |
|   rc= mysql_stmt_bind_param(stmt, my_bind);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   my_bind[1].buffer_type= MYSQL_TYPE_VAR_STRING;
 | |
|   my_bind[1].buffer= (void*) workdept;
 | |
|   my_bind[1].buffer_length= sizeof(workdept);
 | |
|   my_bind[1].length= &workdept_len;
 | |
| 
 | |
|   rc= mysql_stmt_bind_result(stmt, my_bind);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   empno= 10;
 | |
|   /* ERROR: next statement causes a server crash */
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   mysql_stmt_close(stmt);
 | |
| 
 | |
|   rc= mysql_query(mysql, "drop table t1, t2");
 | |
|   myquery(rc);
 | |
| }
 | |
| 
 | |
| /* Bug#11904: mysql_stmt_attr_set CURSOR_TYPE_READ_ONLY grouping wrong result */
 | |
| 
 | |
| static void test_bug11904()
 | |
| {
 | |
|   MYSQL_STMT *stmt1;
 | |
|   int rc;
 | |
|   const char *stmt_text;
 | |
|   const ulong type= (ulong)CURSOR_TYPE_READ_ONLY;
 | |
|   MYSQL_BIND my_bind[2];
 | |
|   int country_id=0;
 | |
|   char row_data[11]= {0};
 | |
| 
 | |
|   myheader("test_bug11904");
 | |
| 
 | |
|   /* create tables */
 | |
|   rc= mysql_query(mysql, "DROP TABLE IF EXISTS bug11904b");
 | |
|   myquery(rc);
 | |
|   rc= mysql_query(mysql, "CREATE TABLE bug11904b (id int, name char(10), primary key(id, name))");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "INSERT INTO bug11904b VALUES (1, 'sofia'), (1,'plovdiv'),"
 | |
|                           " (1,'varna'), (2,'LA'), (2,'new york'), (3,'heidelberg'),"
 | |
|                           " (3,'berlin'), (3, 'frankfurt')");
 | |
| 
 | |
|   myquery(rc);
 | |
|   mysql_commit(mysql);
 | |
|   /* create statement */
 | |
|   stmt1= mysql_stmt_init(mysql);
 | |
|   mysql_stmt_attr_set(stmt1, STMT_ATTR_CURSOR_TYPE, (const void*) &type);
 | |
| 
 | |
|   stmt_text= "SELECT id, MIN(name) FROM bug11904b GROUP BY id";
 | |
| 
 | |
|   rc= mysql_stmt_prepare(stmt1, stmt_text, strlen(stmt_text));
 | |
|   check_execute(stmt1, rc);
 | |
| 
 | |
|   memset(my_bind, 0, sizeof(my_bind));
 | |
|   my_bind[0].buffer_type= MYSQL_TYPE_LONG;
 | |
|   my_bind[0].buffer=& country_id;
 | |
|   my_bind[0].buffer_length= 0;
 | |
|   my_bind[0].length= 0;
 | |
| 
 | |
|   my_bind[1].buffer_type= MYSQL_TYPE_STRING;
 | |
|   my_bind[1].buffer=& row_data;
 | |
|   my_bind[1].buffer_length= sizeof(row_data) - 1;
 | |
|   my_bind[1].length= 0;
 | |
| 
 | |
|   rc= mysql_stmt_bind_result(stmt1, my_bind);
 | |
|   check_execute(stmt1, rc);
 | |
| 
 | |
|   rc= mysql_stmt_execute(stmt1);
 | |
|   check_execute(stmt1, rc);
 | |
| 
 | |
|   rc= mysql_stmt_fetch(stmt1);
 | |
|   check_execute(stmt1, rc);
 | |
|   DIE_UNLESS(country_id == 1);
 | |
|   DIE_UNLESS(memcmp(row_data, "plovdiv", 7) == 0);
 | |
| 
 | |
|   rc= mysql_stmt_fetch(stmt1);
 | |
|   check_execute(stmt1, rc);
 | |
|   DIE_UNLESS(country_id == 2);
 | |
|   DIE_UNLESS(memcmp(row_data, "LA", 2) == 0);
 | |
| 
 | |
|   rc= mysql_stmt_fetch(stmt1);
 | |
|   check_execute(stmt1, rc);
 | |
|   DIE_UNLESS(country_id == 3);
 | |
|   DIE_UNLESS(memcmp(row_data, "berlin", 6) == 0);
 | |
| 
 | |
|   rc= mysql_stmt_close(stmt1);
 | |
|   check_execute(stmt1, rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "drop table bug11904b");
 | |
|   myquery(rc);
 | |
| }
 | |
| 
 | |
| 
 | |
| /* Bug#12243: multiple cursors, crash in a fetch after commit. */
 | |
| 
 | |
| static void test_bug12243()
 | |
| {
 | |
|   MYSQL_STMT *stmt1, *stmt2;
 | |
|   int rc;
 | |
|   const char *stmt_text;
 | |
|   ulong type;
 | |
| 
 | |
|   myheader("test_bug12243");
 | |
| 
 | |
|   if (! have_innodb)
 | |
|   {
 | |
|     if (!opt_silent)
 | |
|       printf("This test requires InnoDB.\n");
 | |
|     return;
 | |
|   }
 | |
| 
 | |
|   /* create tables */
 | |
|   mysql_query(mysql, "drop table if exists t1");
 | |
|   mysql_query(mysql, "create table t1 (a int) engine=InnoDB");
 | |
|   rc= mysql_query(mysql, "insert into t1 (a) values (1), (2)");
 | |
|   myquery(rc);
 | |
|   mysql_autocommit(mysql, FALSE);
 | |
|   /* create statement */
 | |
|   stmt1= mysql_stmt_init(mysql);
 | |
|   stmt2= mysql_stmt_init(mysql);
 | |
|   type= (ulong) CURSOR_TYPE_READ_ONLY;
 | |
|   mysql_stmt_attr_set(stmt1, STMT_ATTR_CURSOR_TYPE, (const void*) &type);
 | |
|   mysql_stmt_attr_set(stmt2, STMT_ATTR_CURSOR_TYPE, (const void*) &type);
 | |
| 
 | |
|   stmt_text= "select a from t1";
 | |
| 
 | |
|   rc= mysql_stmt_prepare(stmt1, stmt_text, strlen(stmt_text));
 | |
|   check_execute(stmt1, rc);
 | |
|   rc= mysql_stmt_execute(stmt1);
 | |
|   check_execute(stmt1, rc);
 | |
|   rc= mysql_stmt_fetch(stmt1);
 | |
|   check_execute(stmt1, rc);
 | |
| 
 | |
|   rc= mysql_stmt_prepare(stmt2, stmt_text, strlen(stmt_text));
 | |
|   check_execute(stmt2, rc);
 | |
|   rc= mysql_stmt_execute(stmt2);
 | |
|   check_execute(stmt2, rc);
 | |
|   rc= mysql_stmt_fetch(stmt2);
 | |
|   check_execute(stmt2, rc);
 | |
| 
 | |
|   rc= mysql_stmt_close(stmt1);
 | |
|   check_execute(stmt1, rc);
 | |
|   rc= mysql_commit(mysql);
 | |
|   myquery(rc);
 | |
|   rc= mysql_stmt_fetch(stmt2);
 | |
|   check_execute(stmt2, rc);
 | |
| 
 | |
|   mysql_stmt_close(stmt2);
 | |
|   rc= mysql_query(mysql, "drop table t1");
 | |
|   myquery(rc);
 | |
|   mysql_autocommit(mysql, TRUE);                /* restore default */
 | |
| }
 | |
| 
 | |
| 
 | |
| /*
 | |
|   Bug#11718: query with function, join and order by returns wrong type
 | |
| */
 | |
| 
 | |
| static void test_bug11718()
 | |
| {
 | |
|   MYSQL_RES	*res;
 | |
|   int rc;
 | |
|   const char *query= "select str_to_date(concat(f3),'%Y%m%d') from t1,t2 "
 | |
|                      "where f1=f2 order by f1";
 | |
| 
 | |
|   myheader("test_bug11718");
 | |
| 
 | |
|   rc= mysql_query(mysql, "drop table if exists t1, t2");
 | |
|   myquery(rc);
 | |
|   rc= mysql_query(mysql, "create table t1 (f1 int)");
 | |
|   myquery(rc);
 | |
|   rc= mysql_query(mysql, "create table t2 (f2 int, f3 numeric(8))");
 | |
|   myquery(rc);
 | |
|   rc= mysql_query(mysql, "insert into t1 values (1), (2)");
 | |
|   myquery(rc);
 | |
|   rc= mysql_query(mysql, "insert into t2 values (1,20050101), (2,20050202)");
 | |
|   myquery(rc);
 | |
|   rc= mysql_query(mysql, query);
 | |
|   myquery(rc);
 | |
|   res = mysql_store_result(mysql);
 | |
| 
 | |
|   if (!opt_silent)
 | |
|     printf("return type: %s", (res->fields[0].type == MYSQL_TYPE_DATE)?"DATE":
 | |
|            "not DATE");
 | |
|   DIE_UNLESS(res->fields[0].type == MYSQL_TYPE_DATE);
 | |
|   mysql_free_result(res);
 | |
|   rc= mysql_query(mysql, "drop table t1, t2");
 | |
|   myquery(rc);
 | |
| }
 | |
| 
 | |
| 
 | |
| /*
 | |
|   Bug #12925: Bad handling of maximum values in getopt
 | |
| */
 | |
| static void test_bug12925()
 | |
| {
 | |
|   myheader("test_bug12925");
 | |
|   if (opt_getopt_ll_test)
 | |
|     DIE_UNLESS(opt_getopt_ll_test == 25600LL*1024*1024);
 | |
| }
 | |
| 
 | |
| 
 | |
| /*
 | |
|   Bug#14210 "Simple query with > operator on large table gives server
 | |
|   crash"
 | |
| */
 | |
| 
 | |
| static void test_bug14210()
 | |
| {
 | |
|   MYSQL_STMT *stmt;
 | |
|   int rc, i;
 | |
|   const char *stmt_text;
 | |
|   ulong type;
 | |
| 
 | |
|   myheader("test_bug14210");
 | |
| 
 | |
|   mysql_query(mysql, "drop table if exists t1");
 | |
|   /*
 | |
|     To trigger the problem the table must be InnoDB, although the problem
 | |
|     itself is not InnoDB related. In case the table is MyISAM this test
 | |
|     is harmless.
 | |
|   */
 | |
|   mysql_query(mysql, "create table t1 (a varchar(255)) engine=InnoDB");
 | |
|   rc= mysql_query(mysql, "insert into t1 (a) values (repeat('a', 256))");
 | |
|   myquery(rc);
 | |
|   rc= mysql_query(mysql, "set @@session.max_heap_table_size=16384");
 | |
|   /* Create a big enough table (more than max_heap_table_size) */
 | |
|   for (i= 0; i < 8; i++)
 | |
|   {
 | |
|     rc= mysql_query(mysql, "insert into t1 (a) select a from t1");
 | |
|     myquery(rc);
 | |
|   }
 | |
|   /* create statement */
 | |
|   stmt= mysql_stmt_init(mysql);
 | |
|   type= (ulong) CURSOR_TYPE_READ_ONLY;
 | |
|   mysql_stmt_attr_set(stmt, STMT_ATTR_CURSOR_TYPE, (const void*) &type);
 | |
| 
 | |
|   stmt_text= "select a from t1";
 | |
| 
 | |
|   rc= mysql_stmt_prepare(stmt, stmt_text, strlen(stmt_text));
 | |
|   check_execute(stmt, rc);
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   while ((rc= mysql_stmt_fetch(stmt)) == 0)
 | |
|     ;
 | |
|   DIE_UNLESS(rc == MYSQL_NO_DATA);
 | |
| 
 | |
|   rc= mysql_stmt_close(stmt);
 | |
| 
 | |
|   rc= mysql_query(mysql, "drop table t1");
 | |
|   myquery(rc);
 | |
|   rc= mysql_query(mysql, "set @@session.max_heap_table_size=default");
 | |
|   myquery(rc);
 | |
| }
 | |
| 
 | |
| /* Bug#13488: wrong column metadata when fetching from cursor */
 | |
| 
 | |
| static void test_bug13488()
 | |
| {
 | |
|   MYSQL_BIND my_bind[3];
 | |
|   MYSQL_STMT *stmt1;
 | |
|   int rc, f1, f2, f3, i;
 | |
|   const ulong type= CURSOR_TYPE_READ_ONLY;
 | |
|   const char *query= "select * from t1 left join t2 on f1=f2 where f1=1";
 | |
| 
 | |
|   myheader("test_bug13488");
 | |
| 
 | |
|   rc= mysql_query(mysql, "drop table if exists t1, t2");
 | |
|   myquery(rc);
 | |
|   rc= mysql_query(mysql, "create table t1 (f1 int not null primary key)");
 | |
|   myquery(rc);
 | |
|   rc= mysql_query(mysql, "create table t2 (f2 int not null primary key, "
 | |
|                   "f3 int not null)");
 | |
|   myquery(rc);
 | |
|   rc= mysql_query(mysql, "insert into t1 values (1), (2)");
 | |
|   myquery(rc);
 | |
|   rc= mysql_query(mysql, "insert into t2 values (1,2), (2,4)");
 | |
|   myquery(rc);
 | |
| 
 | |
|   memset(my_bind, 0, sizeof(my_bind));
 | |
|   for (i= 0; i < 3; i++)
 | |
|   {
 | |
|     my_bind[i].buffer_type= MYSQL_TYPE_LONG;
 | |
|     my_bind[i].buffer_length= 4;
 | |
|     my_bind[i].length= 0;
 | |
|   }
 | |
|   my_bind[0].buffer=&f1;
 | |
|   my_bind[1].buffer=&f2;
 | |
|   my_bind[2].buffer=&f3;
 | |
| 
 | |
|   stmt1= mysql_stmt_init(mysql);
 | |
|   rc= mysql_stmt_attr_set(stmt1,STMT_ATTR_CURSOR_TYPE, (const void *)&type);
 | |
|   check_execute(stmt1, rc);
 | |
| 
 | |
|   rc= mysql_stmt_prepare(stmt1, query, strlen(query));
 | |
|   check_execute(stmt1, rc);
 | |
| 
 | |
|   rc= mysql_stmt_execute(stmt1);
 | |
|   check_execute(stmt1, rc);
 | |
| 
 | |
|   rc= mysql_stmt_bind_result(stmt1, my_bind);
 | |
|   check_execute(stmt1, rc);
 | |
| 
 | |
|   rc= mysql_stmt_fetch(stmt1);
 | |
|   check_execute(stmt1, rc);
 | |
| 
 | |
|   rc= mysql_stmt_free_result(stmt1);
 | |
|   check_execute(stmt1, rc);
 | |
| 
 | |
|   rc= mysql_stmt_reset(stmt1);
 | |
|   check_execute(stmt1, rc);
 | |
| 
 | |
|   rc= mysql_stmt_close(stmt1);
 | |
|   check_execute(stmt1, rc);
 | |
| 
 | |
|   if (!opt_silent)
 | |
|   {
 | |
|     printf("data: f1: %d; f2: %d; f3: %d\n", f1, f2, f3);
 | |
|     printf("data is: %s\n",
 | |
|            (f1 == 1 && f2 == 1 && f3 == 2) ? "OK" : "wrong");
 | |
|   }
 | |
|   DIE_UNLESS(f1 == 1 && f2 == 1 && f3 == 2);
 | |
|   rc= mysql_query(mysql, "drop table t1, t2");
 | |
|   myquery(rc);
 | |
| }
 | |
| 
 | |
| /*
 | |
|   Bug#13524: warnings of a previous command are not reset when fetching
 | |
|   from a cursor.
 | |
| */
 | |
| 
 | |
| static void test_bug13524()
 | |
| {
 | |
|   MYSQL_STMT *stmt;
 | |
|   int rc;
 | |
|   unsigned int warning_count;
 | |
|   const ulong type= CURSOR_TYPE_READ_ONLY;
 | |
|   const char *query= "select * from t1";
 | |
| 
 | |
|   myheader("test_bug13524");
 | |
| 
 | |
|   rc= mysql_query(mysql, "drop table if exists t1, t2");
 | |
|   myquery(rc);
 | |
|   rc= mysql_query(mysql, "create table t1 (a int not null primary key)");
 | |
|   myquery(rc);
 | |
|   rc= mysql_query(mysql, "insert into t1 values (1), (2), (3), (4)");
 | |
|   myquery(rc);
 | |
| 
 | |
|   stmt= mysql_stmt_init(mysql);
 | |
|   rc= mysql_stmt_attr_set(stmt, STMT_ATTR_CURSOR_TYPE, (const void*) &type);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= mysql_stmt_prepare(stmt, query, strlen(query));
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= mysql_stmt_fetch(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   warning_count= mysql_warning_count(mysql);
 | |
|   DIE_UNLESS(warning_count == 0);
 | |
| 
 | |
|   /* Check that DROP TABLE produced a warning (no such table) */
 | |
|   rc= mysql_query(mysql, "drop table if exists t2");
 | |
|   myquery(rc);
 | |
|   warning_count= mysql_warning_count(mysql);
 | |
|   DIE_UNLESS(warning_count == 1);
 | |
| 
 | |
|   /*
 | |
|     Check that fetch from a cursor cleared the warning from the previous
 | |
|     command.
 | |
|   */
 | |
|   rc= mysql_stmt_fetch(stmt);
 | |
|   check_execute(stmt, rc);
 | |
|   warning_count= mysql_warning_count(mysql);
 | |
|   DIE_UNLESS(warning_count == 0);
 | |
| 
 | |
|   /* Cleanup */
 | |
|   mysql_stmt_close(stmt);
 | |
|   rc= mysql_query(mysql, "drop table t1");
 | |
|   myquery(rc);
 | |
| }
 | |
| 
 | |
| /*
 | |
|   Bug#14845 "mysql_stmt_fetch returns MYSQL_NO_DATA when COUNT(*) is 0"
 | |
| */
 | |
| 
 | |
| static void test_bug14845()
 | |
| {
 | |
|   MYSQL_STMT *stmt;
 | |
|   int rc;
 | |
|   const ulong type= CURSOR_TYPE_READ_ONLY;
 | |
|   const char *query= "select count(*) from t1 where 1 = 0";
 | |
| 
 | |
|   myheader("test_bug14845");
 | |
| 
 | |
|   rc= mysql_query(mysql, "drop table if exists t1");
 | |
|   myquery(rc);
 | |
|   rc= mysql_query(mysql, "create table t1 (id int(11) default null, "
 | |
|                          "name varchar(20) default null)"
 | |
|                          "engine=MyISAM DEFAULT CHARSET=utf8");
 | |
|   myquery(rc);
 | |
|   rc= mysql_query(mysql, "insert into t1 values (1,'abc'),(2,'def')");
 | |
|   myquery(rc);
 | |
| 
 | |
|   stmt= mysql_stmt_init(mysql);
 | |
|   rc= mysql_stmt_attr_set(stmt, STMT_ATTR_CURSOR_TYPE, (const void*) &type);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= mysql_stmt_prepare(stmt, query, strlen(query));
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= mysql_stmt_fetch(stmt);
 | |
|   DIE_UNLESS(rc == 0);
 | |
| 
 | |
|   rc= mysql_stmt_fetch(stmt);
 | |
|   DIE_UNLESS(rc == MYSQL_NO_DATA);
 | |
| 
 | |
|   /* Cleanup */
 | |
|   mysql_stmt_close(stmt);
 | |
|   rc= mysql_query(mysql, "drop table t1");
 | |
|   myquery(rc);
 | |
| }
 | |
| 
 | |
| 
 | |
| /*
 | |
|   Bug #15510: mysql_warning_count returns 0 after mysql_stmt_fetch which
 | |
|   should warn
 | |
| */
 | |
| static void test_bug15510()
 | |
| {
 | |
|   MYSQL_STMT *stmt;
 | |
|   int rc;
 | |
|   const char *query= "select 1 from dual where 1/0";
 | |
| 
 | |
|   myheader("test_bug15510");
 | |
| 
 | |
|   rc= mysql_query(mysql, "set @@sql_mode='ERROR_FOR_DIVISION_BY_ZERO'");
 | |
|   myquery(rc);
 | |
| 
 | |
|   stmt= mysql_stmt_init(mysql);
 | |
| 
 | |
|   rc= mysql_stmt_prepare(stmt, query, strlen(query));
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= mysql_stmt_fetch(stmt);
 | |
|   DIE_UNLESS(mysql_warning_count(mysql));
 | |
| 
 | |
|   /* Cleanup */
 | |
|   mysql_stmt_close(stmt);
 | |
|   rc= mysql_query(mysql, "set @@sql_mode=''");
 | |
|   myquery(rc);
 | |
| }
 | |
| 
 | |
| 
 | |
| /* Test MYSQL_OPT_RECONNECT, Bug#15719 */
 | |
| 
 | |
| static void test_opt_reconnect()
 | |
| {
 | |
|   MYSQL *lmysql;
 | |
| 
 | |
| 
 | |
|   myheader("test_opt_reconnect");
 | |
| 
 | |
|   if (!(lmysql= mysql_client_init(NULL)))
 | |
|   {
 | |
|     myerror("mysql_client_init() failed");
 | |
|     exit(1);
 | |
|   }
 | |
| 
 | |
|   if (!opt_silent)
 | |
|     fprintf(stdout, "reconnect before mysql_options: %d\n", get_reconnect(lmysql));
 | |
|   DIE_UNLESS(get_reconnect(lmysql) == 0);
 | |
| 
 | |
|   if (mysql_options(lmysql, MYSQL_OPT_RECONNECT, &my_true))
 | |
|   {
 | |
|     myerror("mysql_options failed: unknown option MYSQL_OPT_RECONNECT\n");
 | |
|     DIE_UNLESS(0);
 | |
|   }
 | |
| 
 | |
|   /* reconnect should be 1 */
 | |
|   if (!opt_silent)
 | |
|     fprintf(stdout, "reconnect after mysql_options: %d\n", get_reconnect(lmysql));
 | |
|   DIE_UNLESS(get_reconnect(lmysql) == 1);
 | |
| 
 | |
|   if (!(mysql_real_connect(lmysql, opt_host, opt_user,
 | |
|                            opt_password, current_db, opt_port,
 | |
|                            opt_unix_socket, 0)))
 | |
|   {
 | |
|     myerror("connection failed");
 | |
|     DIE_UNLESS(0);
 | |
|   }
 | |
| 
 | |
|   /* reconnect should still be 1 */
 | |
|   if (!opt_silent)
 | |
|     fprintf(stdout, "reconnect after mysql_real_connect: %d\n",
 | |
| 	    get_reconnect(lmysql));
 | |
|   DIE_UNLESS(get_reconnect(lmysql) == 1);
 | |
| 
 | |
|   mysql_close(lmysql);
 | |
| 
 | |
|   if (!(lmysql= mysql_client_init(NULL)))
 | |
|   {
 | |
|     myerror("mysql_client_init() failed");
 | |
|     DIE_UNLESS(0);
 | |
|   }
 | |
| 
 | |
|   if (!opt_silent)
 | |
|     fprintf(stdout, "reconnect before mysql_real_connect: %d\n", get_reconnect(lmysql));
 | |
|   DIE_UNLESS(get_reconnect(lmysql) == 0);
 | |
| 
 | |
|   if (!(mysql_real_connect(lmysql, opt_host, opt_user,
 | |
|                            opt_password, current_db, opt_port,
 | |
|                            opt_unix_socket, 0)))
 | |
|   {
 | |
|     myerror("connection failed");
 | |
|     DIE_UNLESS(0);
 | |
|   }
 | |
| 
 | |
|   /* reconnect should still be 0 */
 | |
|   if (!opt_silent)
 | |
|     fprintf(stdout, "reconnect after mysql_real_connect: %d\n",
 | |
| 	    get_reconnect(lmysql));
 | |
|   DIE_UNLESS(get_reconnect(lmysql) == 0);
 | |
| 
 | |
|   mysql_close(lmysql);
 | |
| }
 | |
| 
 | |
| 
 | |
| #ifndef EMBEDDED_LIBRARY
 | |
| 
 | |
| static void test_bug12744()
 | |
| {
 | |
|   MYSQL_STMT *prep_stmt = NULL;
 | |
|   MYSQL *lmysql;
 | |
|   int rc;
 | |
|   myheader("test_bug12744");
 | |
| 
 | |
|   lmysql= mysql_client_init(NULL);
 | |
|   DIE_UNLESS(lmysql);
 | |
| 
 | |
|   if (!mysql_real_connect(lmysql, opt_host, opt_user, opt_password,
 | |
|                           current_db, opt_port, opt_unix_socket, 0))
 | |
|   {
 | |
|     fprintf(stderr, "Failed to connect to the database\n");
 | |
|     DIE_UNLESS(0);
 | |
|   }
 | |
| 
 | |
|   prep_stmt= mysql_stmt_init(lmysql);
 | |
|   rc= mysql_stmt_prepare(prep_stmt, "SELECT 1", 8);
 | |
|   DIE_UNLESS(rc == 0);
 | |
| 
 | |
|   mysql_close(lmysql);
 | |
| 
 | |
|   rc= mysql_stmt_execute(prep_stmt);
 | |
|   DIE_UNLESS(rc);
 | |
|   rc= mysql_stmt_reset(prep_stmt);
 | |
|   DIE_UNLESS(rc);
 | |
|   rc= mysql_stmt_close(prep_stmt);
 | |
|   DIE_UNLESS(rc == 0);
 | |
| }
 | |
| 
 | |
| #endif /* EMBEDDED_LIBRARY */
 | |
| 
 | |
| /* Bug #16143: mysql_stmt_sqlstate returns an empty string instead of '00000' */
 | |
| 
 | |
| static void test_bug16143()
 | |
| {
 | |
|   MYSQL_STMT *stmt;
 | |
|   myheader("test_bug16143");
 | |
| 
 | |
|   stmt= mysql_stmt_init(mysql);
 | |
|   /* Check mysql_stmt_sqlstate return "no error" */
 | |
|   DIE_UNLESS(strcmp(mysql_stmt_sqlstate(stmt), "00000") == 0);
 | |
| 
 | |
|   mysql_stmt_close(stmt);
 | |
| }
 | |
| 
 | |
| 
 | |
| /* Bug #16144: mysql_stmt_attr_get type error */
 | |
| 
 | |
| static void test_bug16144()
 | |
| {
 | |
|   const my_bool flag_orig= (my_bool) 0xde;
 | |
|   my_bool flag= flag_orig;
 | |
|   MYSQL_STMT *stmt;
 | |
|   myheader("test_bug16144");
 | |
| 
 | |
|   /* Check that attr_get returns correct data on little and big endian CPUs */
 | |
|   stmt= mysql_stmt_init(mysql);
 | |
|   mysql_stmt_attr_set(stmt, STMT_ATTR_UPDATE_MAX_LENGTH, (const void*) &flag);
 | |
|   mysql_stmt_attr_get(stmt, STMT_ATTR_UPDATE_MAX_LENGTH, (void*) &flag);
 | |
|   DIE_UNLESS(flag == flag_orig);
 | |
| 
 | |
|   mysql_stmt_close(stmt);
 | |
| }
 | |
| 
 | |
| /*
 | |
|   Bug #15613: "libmysqlclient API function mysql_stmt_prepare returns wrong
 | |
|   field length"
 | |
| */
 | |
| 
 | |
| static void test_bug15613()
 | |
| {
 | |
|   MYSQL_STMT *stmt;
 | |
|   const char *stmt_text;
 | |
|   MYSQL_RES *metadata;
 | |
|   MYSQL_FIELD *field;
 | |
|   int rc;
 | |
|   myheader("test_bug15613");
 | |
| 
 | |
|   /* I. Prepare the table */
 | |
|   rc= mysql_query(mysql, "set names latin1");
 | |
|   myquery(rc);
 | |
|   mysql_query(mysql, "drop table if exists t1");
 | |
|   rc= mysql_query(mysql,
 | |
|                   "create table t1 (t text character set utf8, "
 | |
|                                    "tt tinytext character set utf8, "
 | |
|                                    "mt mediumtext character set utf8, "
 | |
|                                    "lt longtext character set utf8, "
 | |
|                                    "vl varchar(255) character set latin1,"
 | |
|                                    "vb varchar(255) character set binary,"
 | |
|                                    "vu varchar(255) character set utf8)");
 | |
|   myquery(rc);
 | |
| 
 | |
|   stmt= mysql_stmt_init(mysql);
 | |
| 
 | |
|   /* II. Check SELECT metadata */
 | |
|   stmt_text= ("select t, tt, mt, lt, vl, vb, vu from t1");
 | |
|   rc= mysql_stmt_prepare(stmt, stmt_text, strlen(stmt_text));
 | |
|   metadata= mysql_stmt_result_metadata(stmt);
 | |
|   field= mysql_fetch_fields(metadata);
 | |
|   if (!opt_silent)
 | |
|   {
 | |
|     printf("Field lengths (client character set is latin1):\n"
 | |
|            "text character set utf8:\t\t%lu\n"
 | |
|            "tinytext character set utf8:\t\t%lu\n"
 | |
|            "mediumtext character set utf8:\t\t%lu\n"
 | |
|            "longtext character set utf8:\t\t%lu\n"
 | |
|            "varchar(255) character set latin1:\t%lu\n"
 | |
|            "varchar(255) character set binary:\t%lu\n"
 | |
|            "varchar(255) character set utf8:\t%lu\n",
 | |
|            field[0].length, field[1].length, field[2].length, field[3].length,
 | |
|            field[4].length, field[5].length, field[6].length);
 | |
|   }
 | |
|   DIE_UNLESS(field[0].length == 65535);
 | |
|   DIE_UNLESS(field[1].length == 255);
 | |
|   DIE_UNLESS(field[2].length == 16777215);
 | |
|   DIE_UNLESS(field[3].length == 4294967295UL);
 | |
|   DIE_UNLESS(field[4].length == 255);
 | |
|   DIE_UNLESS(field[5].length == 255);
 | |
|   DIE_UNLESS(field[6].length == 255);
 | |
|   mysql_free_result(metadata);
 | |
|   mysql_stmt_free_result(stmt);
 | |
| 
 | |
|   /* III. Cleanup */
 | |
|   rc= mysql_query(mysql, "drop table t1");
 | |
|   myquery(rc);
 | |
|   rc= mysql_query(mysql, "set names default");
 | |
|   myquery(rc);
 | |
|   mysql_stmt_close(stmt);
 | |
| }
 | |
| 
 | |
| /*
 | |
|   Bug#17667: An attacker has the opportunity to bypass query logging.
 | |
| 
 | |
|   Note! Also tests Bug#21813, where prepared statements are used to
 | |
|   run queries
 | |
| */
 | |
| static void test_bug17667()
 | |
| {
 | |
|   int rc;
 | |
|   MYSQL_STMT *stmt;
 | |
|   enum query_type { QT_NORMAL, QT_PREPARED};
 | |
|   struct buffer_and_length {
 | |
|     enum query_type qt;
 | |
|     const char *buffer;
 | |
|     const uint length;
 | |
|   } statements[]= {
 | |
|     { QT_NORMAL, "drop table if exists bug17667", 29 },
 | |
|     { QT_NORMAL, "create table bug17667 (c varchar(20))", 37 },
 | |
|     { QT_NORMAL, "insert into bug17667 (c) values ('regular') /* NUL=\0 with comment */", 68 },
 | |
|     { QT_PREPARED,
 | |
|       "insert into bug17667 (c) values ('prepared') /* NUL=\0 with comment */", 69, },
 | |
|     { QT_NORMAL, "insert into bug17667 (c) values ('NUL=\0 in value')", 50 },
 | |
|     { QT_NORMAL, "insert into bug17667 (c) values ('5 NULs=\0\0\0\0\0')", 48 },
 | |
|     { QT_PREPARED, "insert into bug17667 (c) values ('6 NULs=\0\0\0\0\0\0')", 50 },
 | |
|     { QT_NORMAL, "/* NUL=\0 with comment */ insert into bug17667 (c) values ('encore')", 67 },
 | |
|     { QT_NORMAL, "drop table bug17667", 19 },
 | |
|     { QT_NORMAL, NULL, 0 } };
 | |
| 
 | |
|   struct buffer_and_length *statement_cursor;
 | |
|   FILE *log_file;
 | |
|   char *master_log_filename;
 | |
| 
 | |
|   myheader("test_bug17667");
 | |
| 
 | |
|   master_log_filename = (char *) malloc(strlen(opt_vardir) + strlen("/log/master.log") + 1);
 | |
|   strxmov(master_log_filename, opt_vardir, "/log/master.log", NullS);
 | |
|   if (!opt_silent)
 | |
|     printf("Opening '%s'\n", master_log_filename);
 | |
|   log_file= my_fopen(master_log_filename, (int) (O_RDONLY | O_BINARY), MYF(0));
 | |
|   free(master_log_filename);
 | |
| 
 | |
|   if (log_file == NULL)
 | |
|   {
 | |
|     if (!opt_silent)
 | |
|     {
 | |
|       printf("Could not find the log file, VARDIR/log/master.log, so "
 | |
|              "test_bug17667 is not run.\n"
 | |
|              "Run test from the mysql-test/mysql-test-run* program to set up "
 | |
|              "correct environment for this test.\n\n");
 | |
|     }
 | |
|     return;
 | |
|   }
 | |
| 
 | |
|   enable_query_logs(1);
 | |
| 
 | |
|   for (statement_cursor= statements; statement_cursor->buffer != NULL;
 | |
|        statement_cursor++)
 | |
|   {
 | |
|     if (statement_cursor->qt == QT_NORMAL)
 | |
|     {
 | |
|       /* Run statement as normal query */
 | |
|       rc= mysql_real_query(mysql, statement_cursor->buffer,
 | |
|                            statement_cursor->length);
 | |
|       myquery(rc);
 | |
|     }
 | |
|     else if (statement_cursor->qt == QT_PREPARED)
 | |
|     {
 | |
|       /*
 | |
|         Run as prepared statement
 | |
| 
 | |
|         NOTE! All these queries should be in the log twice,
 | |
|         one time for prepare and one time for execute
 | |
|       */
 | |
|       stmt= mysql_stmt_init(mysql);
 | |
| 
 | |
|       rc= mysql_stmt_prepare(stmt, statement_cursor->buffer,
 | |
|                              statement_cursor->length);
 | |
|       check_execute(stmt, rc);
 | |
| 
 | |
|       rc= mysql_stmt_execute(stmt);
 | |
|       check_execute(stmt, rc);
 | |
| 
 | |
|       mysql_stmt_close(stmt);
 | |
|     }
 | |
|     else
 | |
|     {
 | |
|       DIE_UNLESS(0==1);
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   /* Make sure the server has written the logs to disk before reading it */
 | |
|   rc= mysql_query(mysql, "flush logs");
 | |
|   myquery(rc);
 | |
| 
 | |
|   for (statement_cursor= statements; statement_cursor->buffer != NULL;
 | |
|        statement_cursor++)
 | |
|   {
 | |
|     int expected_hits= 1, hits= 0;
 | |
|     char line_buffer[MAX_TEST_QUERY_LENGTH*2];
 | |
|     /* more than enough room for the query and some marginalia. */
 | |
| 
 | |
|     /* Prepared statements always occurs twice in log */
 | |
|     if (statement_cursor->qt == QT_PREPARED)
 | |
|       expected_hits++;
 | |
| 
 | |
|     /* Loop until we found expected number of log entries */
 | |
|     do {
 | |
|       /* Loop until statement is found in log */
 | |
|       do {
 | |
|         memset(line_buffer, '/', MAX_TEST_QUERY_LENGTH*2);
 | |
| 
 | |
|         if(fgets(line_buffer, MAX_TEST_QUERY_LENGTH*2, log_file) == NULL)
 | |
|         {
 | |
|           /* If fgets returned NULL, it indicates either error or EOF */
 | |
|           if (feof(log_file))
 | |
|             DIE("Found EOF before all statements where found");
 | |
| 
 | |
|           fprintf(stderr, "Got error %d while reading from file\n",
 | |
|                   ferror(log_file));
 | |
|           DIE("Read error");
 | |
|         }
 | |
| 
 | |
|       } while (my_memmem(line_buffer, MAX_TEST_QUERY_LENGTH*2,
 | |
|                          statement_cursor->buffer,
 | |
|                          statement_cursor->length) == NULL);
 | |
|       hits++;
 | |
|     } while (hits < expected_hits);
 | |
| 
 | |
|     if (!opt_silent)
 | |
|       printf("Found statement starting with \"%s\"\n",
 | |
|              statement_cursor->buffer);
 | |
|   }
 | |
| 
 | |
|   restore_query_logs();
 | |
| 
 | |
|   if (!opt_silent)
 | |
|     printf("success.  All queries found intact in the log.\n");
 | |
| 
 | |
|   my_fclose(log_file, MYF(0));
 | |
| }
 | |
| 
 | |
| 
 | |
| /*
 | |
|   Bug#14169: type of group_concat() result changed to blob if tmp_table was
 | |
|   used
 | |
| */
 | |
| static void test_bug14169()
 | |
| {
 | |
|   MYSQL_STMT *stmt;
 | |
|   const char *stmt_text;
 | |
|   MYSQL_RES *res;
 | |
|   MYSQL_FIELD *field;
 | |
|   int rc;
 | |
| 
 | |
|   myheader("test_bug14169");
 | |
| 
 | |
|   rc= mysql_query(mysql, "drop table if exists t1");
 | |
|   myquery(rc);
 | |
|   rc= mysql_query(mysql, "set session group_concat_max_len=1024");
 | |
|   myquery(rc);
 | |
|   rc= mysql_query(mysql, "create table t1 (f1 int unsigned, f2 varchar(255))");
 | |
|   myquery(rc);
 | |
|   rc= mysql_query(mysql, "insert into t1 values (1,repeat('a',255)),"
 | |
|                          "(2,repeat('b',255))");
 | |
|   myquery(rc);
 | |
|   stmt= mysql_stmt_init(mysql);
 | |
|   stmt_text= "select f2,group_concat(f1) from t1 group by f2";
 | |
|   rc= mysql_stmt_prepare(stmt, stmt_text, strlen(stmt_text));
 | |
|   myquery(rc);
 | |
|   res= mysql_stmt_result_metadata(stmt);
 | |
|   field= mysql_fetch_fields(res);
 | |
|   if (!opt_silent)
 | |
|     printf("GROUP_CONCAT() result type %i", field[1].type);
 | |
|   DIE_UNLESS(field[1].type == MYSQL_TYPE_BLOB);
 | |
|   mysql_free_result(res);
 | |
|   mysql_stmt_free_result(stmt);
 | |
|   mysql_stmt_close(stmt);
 | |
| 
 | |
|   rc= mysql_query(mysql, "drop table t1");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "set session group_concat_max_len=@@global.group_concat_max_len");
 | |
|   myquery(rc);
 | |
| }
 | |
| 
 | |
| /*
 | |
|    Test that mysql_insert_id() behaves as documented in our manual
 | |
| */
 | |
| static void test_mysql_insert_id()
 | |
| {
 | |
|   my_ulonglong res;
 | |
|   int rc;
 | |
| 
 | |
|   myheader("test_mysql_insert_id");
 | |
| 
 | |
|   rc= mysql_query(mysql, "drop table if exists t1,t2");
 | |
|   myquery(rc);
 | |
|   /* table without auto_increment column */
 | |
|   rc= mysql_query(mysql, "create table t1 (f1 int, f2 varchar(255), key(f1))");
 | |
|   myquery(rc);
 | |
|   rc= mysql_query(mysql, "insert into t1 values (1,'a')");
 | |
|   myquery(rc);
 | |
|   res= mysql_insert_id(mysql);
 | |
|   DIE_UNLESS(res == 0);
 | |
|   rc= mysql_query(mysql, "insert into t1 values (null,'b')");
 | |
|   myquery(rc);
 | |
|   res= mysql_insert_id(mysql);
 | |
|   DIE_UNLESS(res == 0);
 | |
|   rc= mysql_query(mysql, "insert into t1 select 5,'c'");
 | |
|   myquery(rc);
 | |
|   res= mysql_insert_id(mysql);
 | |
|   DIE_UNLESS(res == 0);
 | |
| 
 | |
|   /*
 | |
|     Test for bug #34889: mysql_client_test::test_mysql_insert_id test fails
 | |
|     sporadically
 | |
|   */
 | |
|   rc= mysql_query(mysql, "create table t2 (f1 int not null primary key auto_increment, f2 varchar(255))");
 | |
|   myquery(rc);
 | |
|   rc= mysql_query(mysql, "insert into t2 values (null,'b')");
 | |
|   myquery(rc);
 | |
|   rc= mysql_query(mysql, "insert into t1 select 5,'c'");
 | |
|   myquery(rc);
 | |
|   res= mysql_insert_id(mysql);
 | |
|   DIE_UNLESS(res == 0);
 | |
|   rc= mysql_query(mysql, "drop table t2");
 | |
|   myquery(rc);
 | |
|   
 | |
|   rc= mysql_query(mysql, "insert into t1 select null,'d'");
 | |
|   myquery(rc);
 | |
|   res= mysql_insert_id(mysql);
 | |
|   DIE_UNLESS(res == 0);
 | |
|   rc= mysql_query(mysql, "insert into t1 values (null,last_insert_id(300))");
 | |
|   myquery(rc);
 | |
|   res= mysql_insert_id(mysql);
 | |
|   DIE_UNLESS(res == 300);
 | |
|   rc= mysql_query(mysql, "insert into t1 select null,last_insert_id(400)");
 | |
|   myquery(rc);
 | |
|   res= mysql_insert_id(mysql);
 | |
|   /*
 | |
|     Behaviour change: old code used to return 0; but 400 is consistent
 | |
|     with INSERT VALUES, and the manual's section of mysql_insert_id() does not
 | |
|     say INSERT SELECT should be different.
 | |
|   */
 | |
|   DIE_UNLESS(res == 400);
 | |
| 
 | |
|   /* table with auto_increment column */
 | |
|   rc= mysql_query(mysql, "create table t2 (f1 int not null primary key auto_increment, f2 varchar(255))");
 | |
|   myquery(rc);
 | |
|   rc= mysql_query(mysql, "insert into t2 values (1,'a')");
 | |
|   myquery(rc);
 | |
|   res= mysql_insert_id(mysql);
 | |
|   DIE_UNLESS(res == 1);
 | |
|   /* this should not influence next INSERT if it doesn't have auto_inc */
 | |
|   rc= mysql_query(mysql, "insert into t1 values (10,'e')");
 | |
|   myquery(rc);
 | |
|   res= mysql_insert_id(mysql);
 | |
|   DIE_UNLESS(res == 0);
 | |
| 
 | |
|   rc= mysql_query(mysql, "insert into t2 values (null,'b')");
 | |
|   myquery(rc);
 | |
|   res= mysql_insert_id(mysql);
 | |
|   DIE_UNLESS(res == 2);
 | |
|   rc= mysql_query(mysql, "insert into t2 select 5,'c'");
 | |
|   myquery(rc);
 | |
|   res= mysql_insert_id(mysql);
 | |
|   /*
 | |
|     Manual says that for multirow insert this should have been 5, but does not
 | |
|     say for INSERT SELECT. This is a behaviour change: old code used to return
 | |
|     0. We try to be consistent with INSERT VALUES.
 | |
|   */
 | |
|   DIE_UNLESS(res == 5);
 | |
|   rc= mysql_query(mysql, "insert into t2 select null,'d'");
 | |
|   myquery(rc);
 | |
|   res= mysql_insert_id(mysql);
 | |
|   DIE_UNLESS(res == 6);
 | |
|   /* with more than one row */
 | |
|   rc= mysql_query(mysql, "insert into t2 values (10,'a'),(11,'b')");
 | |
|   myquery(rc);
 | |
|   res= mysql_insert_id(mysql);
 | |
|   DIE_UNLESS(res == 11);
 | |
|   rc= mysql_query(mysql, "insert into t2 select 12,'a' union select 13,'b'");
 | |
|   myquery(rc);
 | |
|   res= mysql_insert_id(mysql);
 | |
|   /*
 | |
|     Manual says that for multirow insert this should have been 13, but does
 | |
|     not say for INSERT SELECT. This is a behaviour change: old code used to
 | |
|     return 0. We try to be consistent with INSERT VALUES.
 | |
|   */
 | |
|   DIE_UNLESS(res == 13);
 | |
|   rc= mysql_query(mysql, "insert into t2 values (null,'a'),(null,'b')");
 | |
|   myquery(rc);
 | |
|   res= mysql_insert_id(mysql);
 | |
|   DIE_UNLESS(res == 14);
 | |
|   rc= mysql_query(mysql, "insert into t2 select null,'a' union select null,'b'");
 | |
|   myquery(rc);
 | |
|   res= mysql_insert_id(mysql);
 | |
|   DIE_UNLESS(res == 16);
 | |
|   rc= mysql_query(mysql, "insert into t2 select 12,'a' union select 13,'b'");
 | |
|   myquery_r(rc);
 | |
|   rc= mysql_query(mysql, "insert ignore into t2 select 12,'a' union select 13,'b'");
 | |
|   myquery(rc);
 | |
|   res= mysql_insert_id(mysql);
 | |
|   DIE_UNLESS(res == 0);
 | |
|   rc= mysql_query(mysql, "insert into t2 values (12,'a'),(13,'b')");
 | |
|   myquery_r(rc);
 | |
|   res= mysql_insert_id(mysql);
 | |
|   DIE_UNLESS(res == 0);
 | |
|   rc= mysql_query(mysql, "insert ignore into t2 values (12,'a'),(13,'b')");
 | |
|   myquery(rc);
 | |
|   res= mysql_insert_id(mysql);
 | |
|   DIE_UNLESS(res == 0);
 | |
|   /* mixing autogenerated and explicit values */
 | |
|   rc= mysql_query(mysql, "insert into t2 values (null,'e'),(12,'a'),(13,'b')");
 | |
|   myquery_r(rc);
 | |
|   rc= mysql_query(mysql, "insert into t2 values (null,'e'),(12,'a'),(13,'b'),(25,'g')");
 | |
|   myquery_r(rc);
 | |
|   rc= mysql_query(mysql, "insert into t2 values (null,last_insert_id(300))");
 | |
|   myquery(rc);
 | |
|   res= mysql_insert_id(mysql);
 | |
|   /*
 | |
|     according to the manual, this might be 20 or 300, but it looks like
 | |
|     auto_increment column takes priority over last_insert_id().
 | |
|   */
 | |
|   DIE_UNLESS(res == 20);
 | |
|   /* If first autogenerated number fails and 2nd works: */
 | |
|   rc= mysql_query(mysql, "drop table t2");
 | |
|   myquery(rc);
 | |
|   rc= mysql_query(mysql, "create table t2 (f1 int not null primary key "
 | |
|                   "auto_increment, f2 varchar(255), unique (f2))");
 | |
|   myquery(rc);
 | |
|   rc= mysql_query(mysql, "insert into t2 values (null,'e')");
 | |
|   res= mysql_insert_id(mysql);
 | |
|   DIE_UNLESS(res == 1);
 | |
|   rc= mysql_query(mysql, "insert ignore into t2 values (null,'e'),(null,'a'),(null,'e')");
 | |
|   myquery(rc);
 | |
|   res= mysql_insert_id(mysql);
 | |
|   DIE_UNLESS(res == 2);
 | |
|   /* If autogenerated fails and explicit works: */
 | |
|   rc= mysql_query(mysql, "insert ignore into t2 values (null,'e'),(12,'c'),(null,'d')");
 | |
|   myquery(rc);
 | |
|   res= mysql_insert_id(mysql);
 | |
|   /*
 | |
|     Behaviour change: old code returned 3 (first autogenerated, even if it
 | |
|     fails); we now return first successful autogenerated.
 | |
|   */
 | |
|   DIE_UNLESS(res == 13);
 | |
|   /* UPDATE may update mysql_insert_id() if it uses LAST_INSERT_ID(#) */
 | |
|   rc= mysql_query(mysql, "update t2 set f1=14 where f1=12");
 | |
|   myquery(rc);
 | |
|   res= mysql_insert_id(mysql);
 | |
|   DIE_UNLESS(res == 0);
 | |
|   rc= mysql_query(mysql, "update t2 set f1=0 where f1=14");
 | |
|   myquery(rc);
 | |
|   res= mysql_insert_id(mysql);
 | |
|   DIE_UNLESS(res == 0);
 | |
|   rc= mysql_query(mysql, "update t2 set f2=last_insert_id(372) where f1=0");
 | |
|   myquery(rc);
 | |
|   res= mysql_insert_id(mysql);
 | |
|   DIE_UNLESS(res == 372);
 | |
|   /* check that LAST_INSERT_ID() does not update mysql_insert_id(): */
 | |
|   rc= mysql_query(mysql, "insert into t2 values (null,'g')");
 | |
|   myquery(rc);
 | |
|   res= mysql_insert_id(mysql);
 | |
|   DIE_UNLESS(res == 15);
 | |
|   rc= mysql_query(mysql, "update t2 set f2=(@li:=last_insert_id()) where f1=15");
 | |
|   myquery(rc);
 | |
|   res= mysql_insert_id(mysql);
 | |
|   DIE_UNLESS(res == 0);
 | |
|   /*
 | |
|     Behaviour change: now if ON DUPLICATE KEY UPDATE updates a row,
 | |
|     mysql_insert_id() returns the id of the row, instead of not being
 | |
|     affected.
 | |
|   */
 | |
|   rc= mysql_query(mysql, "insert into t2 values (null,@li) on duplicate key "
 | |
|                   "update f2=concat('we updated ',f2)");
 | |
|   myquery(rc);
 | |
|   res= mysql_insert_id(mysql);
 | |
|   DIE_UNLESS(res == 15);
 | |
| 
 | |
|   rc= mysql_query(mysql, "drop table t1,t2");
 | |
|   myquery(rc);
 | |
| }
 | |
| 
 | |
| /*
 | |
|   Bug#20152: mysql_stmt_execute() writes to MYSQL_TYPE_DATE buffer
 | |
| */
 | |
| 
 | |
| static void test_bug20152()
 | |
| {
 | |
|   MYSQL_BIND my_bind[1];
 | |
|   MYSQL_STMT *stmt;
 | |
|   MYSQL_TIME tm;
 | |
|   int rc;
 | |
|   const char *query= "INSERT INTO t1 (f1) VALUES (?)";
 | |
| 
 | |
|   myheader("test_bug20152");
 | |
| 
 | |
|   memset(my_bind, 0, sizeof(my_bind));
 | |
|   my_bind[0].buffer_type= MYSQL_TYPE_DATE;
 | |
|   my_bind[0].buffer= (void*)&tm;
 | |
| 
 | |
|   memset(&tm, 0, sizeof tm);
 | |
|   tm.year = 2006;
 | |
|   tm.month = 6;
 | |
|   tm.day = 18;
 | |
|   tm.hour = 14;
 | |
|   tm.minute = 9;
 | |
|   tm.second = 42;
 | |
| 
 | |
|   rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1");
 | |
|   myquery(rc);
 | |
|   rc= mysql_query(mysql, "CREATE TABLE t1 (f1 DATE)");
 | |
|   myquery(rc);
 | |
| 
 | |
|   stmt= mysql_stmt_init(mysql);
 | |
|   rc= mysql_stmt_prepare(stmt, query, strlen(query));
 | |
|   check_execute(stmt, rc);
 | |
|   rc= mysql_stmt_bind_param(stmt, my_bind);
 | |
|   check_execute(stmt, rc);
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
|   rc= mysql_stmt_close(stmt);
 | |
|   check_execute(stmt, rc);
 | |
|   rc= mysql_query(mysql, "DROP TABLE t1");
 | |
|   myquery(rc);
 | |
| 
 | |
|   if (tm.hour == 14 && tm.minute == 9 && tm.second == 42) {
 | |
|     if (!opt_silent)
 | |
|       printf("OK!");
 | |
|   } else {
 | |
|     printf("[14:09:42] != [%02d:%02d:%02d]\n", tm.hour, tm.minute, tm.second);
 | |
|     DIE_UNLESS(0==1);
 | |
|   }
 | |
| }
 | |
| 
 | |
| /* Bug#15752 "Lost connection to MySQL server when calling a SP from C API" */
 | |
| 
 | |
| static void test_bug15752()
 | |
| {
 | |
|   MYSQL mysql_local;
 | |
|   int rc, i;
 | |
|   const int ITERATION_COUNT= 100;
 | |
|   const char *query= "CALL p1()";
 | |
| 
 | |
|   myheader("test_bug15752");
 | |
| 
 | |
|   rc= mysql_query(mysql, "drop procedure if exists p1");
 | |
|   myquery(rc);
 | |
|   rc= mysql_query(mysql, "create procedure p1() select 1");
 | |
|   myquery(rc);
 | |
| 
 | |
|   mysql_client_init(&mysql_local);
 | |
|   if (! mysql_real_connect(&mysql_local, opt_host, opt_user,
 | |
|                            opt_password, current_db, opt_port,
 | |
|                            opt_unix_socket,
 | |
|                            CLIENT_MULTI_STATEMENTS))
 | |
|   {
 | |
|     printf("Unable connect to MariaDB server: %s\n", mysql_error(&mysql_local));
 | |
|     DIE_UNLESS(0);
 | |
|   }
 | |
|   rc= mysql_real_query(&mysql_local, query, strlen(query));
 | |
|   myquery(rc);
 | |
|   mysql_free_result(mysql_store_result(&mysql_local));
 | |
| 
 | |
|   rc= mysql_real_query(&mysql_local, query, strlen(query));
 | |
|   DIE_UNLESS(rc && mysql_errno(&mysql_local) == CR_COMMANDS_OUT_OF_SYNC);
 | |
| 
 | |
|   if (! opt_silent)
 | |
|     printf("Got error (as expected): %s\n", mysql_error(&mysql_local));
 | |
| 
 | |
|   /* Check some other commands too */
 | |
| 
 | |
|   DIE_UNLESS(mysql_next_result(&mysql_local) == 0);
 | |
|   mysql_free_result(mysql_store_result(&mysql_local));
 | |
|   DIE_UNLESS(mysql_next_result(&mysql_local) == -1);
 | |
| 
 | |
|   /* The second problem is not reproducible: add the test case */
 | |
|   for (i = 0; i < ITERATION_COUNT; i++)
 | |
|   {
 | |
|     if (mysql_real_query(&mysql_local, query, strlen(query)))
 | |
|     {
 | |
|       printf("\ni=%d %s failed: %s\n", i, query, mysql_error(&mysql_local));
 | |
|       break;
 | |
|     }
 | |
|     mysql_free_result(mysql_store_result(&mysql_local));
 | |
|     DIE_UNLESS(mysql_next_result(&mysql_local) == 0);
 | |
|     mysql_free_result(mysql_store_result(&mysql_local));
 | |
|     DIE_UNLESS(mysql_next_result(&mysql_local) == -1);
 | |
| 
 | |
|   }
 | |
|   mysql_close(&mysql_local);
 | |
|   rc= mysql_query(mysql, "drop procedure p1");
 | |
|   myquery(rc);
 | |
| }
 | |
| 
 | |
| /*
 | |
|   Bug#21206: memory corruption when too many cursors are opened at once
 | |
| 
 | |
|   Memory corruption happens when more than 1024 cursors are open
 | |
|   simultaneously.
 | |
| */
 | |
| static void test_bug21206()
 | |
| {
 | |
|   const size_t cursor_count= 1025;
 | |
| 
 | |
|   const char *create_table[]=
 | |
|   {
 | |
|     "DROP TABLE IF EXISTS t1",
 | |
|     "CREATE TABLE t1 (i INT)",
 | |
|     "INSERT INTO t1 VALUES (1), (2), (3)"
 | |
|   };
 | |
|   const char *query= "SELECT * FROM t1";
 | |
| 
 | |
|   Stmt_fetch *fetch_array=
 | |
|     (Stmt_fetch*) calloc(cursor_count, sizeof(Stmt_fetch));
 | |
| 
 | |
|   Stmt_fetch *fetch;
 | |
| 
 | |
|   DBUG_ENTER("test_bug21206");
 | |
|   myheader("test_bug21206");
 | |
| 
 | |
|   fill_tables(create_table, sizeof(create_table) / sizeof(*create_table));
 | |
| 
 | |
|   for (fetch= fetch_array; fetch < fetch_array + cursor_count; ++fetch)
 | |
|   {
 | |
|     /* Init will exit(1) in case of error */
 | |
|     stmt_fetch_init(fetch, (uint)(fetch - fetch_array), query);
 | |
|   }
 | |
| 
 | |
|   for (fetch= fetch_array; fetch < fetch_array + cursor_count; ++fetch)
 | |
|     stmt_fetch_close(fetch);
 | |
| 
 | |
|   free(fetch_array);
 | |
| 
 | |
|   DBUG_VOID_RETURN;
 | |
| }
 | |
| 
 | |
| /*
 | |
|   Ensure we execute the status code while testing
 | |
| */
 | |
| 
 | |
| static void test_status()
 | |
| {
 | |
|   DBUG_ENTER("test_status");
 | |
|   myheader("test_status");
 | |
| 
 | |
|   if (!mysql_stat(mysql))
 | |
|   {
 | |
|     myerror("mysql_stat failed");                 /* purecov: inspected */
 | |
|     die(__FILE__, __LINE__, "mysql_stat failed"); /* purecov: inspected */
 | |
|   }
 | |
|   DBUG_VOID_RETURN;
 | |
| }
 | |
| 
 | |
| /*
 | |
|   Bug#21726: Incorrect result with multiple invocations of
 | |
|   LAST_INSERT_ID
 | |
| 
 | |
|   Test that client gets updated value of insert_id on UPDATE that uses
 | |
|   LAST_INSERT_ID(expr).
 | |
|   select_query added to test for bug
 | |
|     #26921 Problem in mysql_insert_id() Embedded C API function
 | |
| */
 | |
| static void test_bug21726()
 | |
| {
 | |
|   const char *create_table[]=
 | |
|   {
 | |
|     "DROP TABLE IF EXISTS t1",
 | |
|     "CREATE TABLE t1 (i INT)",
 | |
|     "INSERT INTO t1 VALUES (1)",
 | |
|   };
 | |
|   const char *update_query= "UPDATE t1 SET i= LAST_INSERT_ID(i + 1)";
 | |
|   int rc;
 | |
|   my_ulonglong insert_id;
 | |
|   const char *select_query= "SELECT * FROM t1";
 | |
|   MYSQL_RES  *result;
 | |
| 
 | |
|   DBUG_ENTER("test_bug21726");
 | |
|   myheader("test_bug21726");
 | |
| 
 | |
|   fill_tables(create_table, sizeof(create_table) / sizeof(*create_table));
 | |
| 
 | |
|   rc= mysql_query(mysql, update_query);
 | |
|   myquery(rc);
 | |
|   insert_id= mysql_insert_id(mysql);
 | |
|   DIE_UNLESS(insert_id == 2);
 | |
| 
 | |
|   rc= mysql_query(mysql, update_query);
 | |
|   myquery(rc);
 | |
|   insert_id= mysql_insert_id(mysql);
 | |
|   DIE_UNLESS(insert_id == 3);
 | |
| 
 | |
|   rc= mysql_query(mysql, select_query);
 | |
|   myquery(rc);
 | |
|   insert_id= mysql_insert_id(mysql);
 | |
|   DIE_UNLESS(insert_id == 3);
 | |
|   result= mysql_store_result(mysql);
 | |
|   mysql_free_result(result);
 | |
| 
 | |
|   DBUG_VOID_RETURN;
 | |
| }
 | |
| 
 | |
| 
 | |
| /*
 | |
|   BUG#23383: mysql_affected_rows() returns different values than
 | |
|   mysql_stmt_affected_rows()
 | |
| 
 | |
|   Test that both mysql_affected_rows() and mysql_stmt_affected_rows()
 | |
|   return -1 on error, 0 when no rows were affected, and (positive) row
 | |
|   count when some rows were affected.
 | |
| */
 | |
| static void test_bug23383()
 | |
| {
 | |
|   const char *insert_query= "INSERT INTO t1 VALUES (1), (2)";
 | |
|   const char *update_query= "UPDATE t1 SET i= 4 WHERE i = 3";
 | |
|   MYSQL_STMT *stmt;
 | |
|   my_ulonglong row_count;
 | |
|   int rc;
 | |
| 
 | |
|   DBUG_ENTER("test_bug23383");
 | |
|   myheader("test_bug23383");
 | |
| 
 | |
|   rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "CREATE TABLE t1 (i INT UNIQUE)");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, insert_query);
 | |
|   myquery(rc);
 | |
|   row_count= mysql_affected_rows(mysql);
 | |
|   DIE_UNLESS(row_count == 2);
 | |
| 
 | |
|   rc= mysql_query(mysql, insert_query);
 | |
|   DIE_UNLESS(rc != 0);
 | |
|   row_count= mysql_affected_rows(mysql);
 | |
|   DIE_UNLESS(row_count == (my_ulonglong)-1);
 | |
| 
 | |
|   rc= mysql_query(mysql, update_query);
 | |
|   myquery(rc);
 | |
|   row_count= mysql_affected_rows(mysql);
 | |
|   DIE_UNLESS(row_count == 0);
 | |
| 
 | |
|   rc= mysql_query(mysql, "DELETE FROM t1");
 | |
|   myquery(rc);
 | |
| 
 | |
|   stmt= mysql_stmt_init(mysql);
 | |
|   DIE_UNLESS(stmt != 0);
 | |
| 
 | |
|   rc= mysql_stmt_prepare(stmt, insert_query, strlen(insert_query));
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
|   row_count= mysql_stmt_affected_rows(stmt);
 | |
|   DIE_UNLESS(row_count == 2);
 | |
| 
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   DIE_UNLESS(rc != 0);
 | |
|   row_count= mysql_stmt_affected_rows(stmt);
 | |
|   DIE_UNLESS(row_count == (my_ulonglong)-1);
 | |
| 
 | |
|   rc= mysql_stmt_prepare(stmt, update_query, strlen(update_query));
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
|   row_count= mysql_stmt_affected_rows(stmt);
 | |
|   DIE_UNLESS(row_count == 0);
 | |
| 
 | |
|   rc= mysql_stmt_close(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "DROP TABLE t1");
 | |
|   myquery(rc);
 | |
| 
 | |
|   DBUG_VOID_RETURN;
 | |
| }
 | |
| 
 | |
| 
 | |
| /*
 | |
|   BUG#21635: MYSQL_FIELD struct's member strings seem to misbehave for
 | |
|   expression cols
 | |
| 
 | |
|   Check that for MIN(), MAX(), COUNT() only MYSQL_FIELD::name is set
 | |
|   to either expression or its alias, and db, org_table, table,
 | |
|   org_name fields are empty strings.
 | |
| */
 | |
| static void test_bug21635()
 | |
| {
 | |
|   const char *expr[]=
 | |
|   {
 | |
|     "MIN(i)", "MIN(i)",
 | |
|     "MIN(i) AS A1", "A1",
 | |
|     "MAX(i)", "MAX(i)",
 | |
|     "MAX(i) AS A2", "A2",
 | |
|     "COUNT(i)", "COUNT(i)",
 | |
|     "COUNT(i) AS A3", "A3",
 | |
|   };
 | |
|   char query[MAX_TEST_QUERY_LENGTH];
 | |
|   char *query_end;
 | |
|   MYSQL_RES *result;
 | |
|   MYSQL_FIELD *field;
 | |
|   unsigned int field_count, i, j;
 | |
|   int rc;
 | |
| 
 | |
|   DBUG_ENTER("test_bug21635");
 | |
|   myheader("test_bug21635");
 | |
| 
 | |
|   query_end= strxmov(query, "SELECT ", NullS);
 | |
|   for (i= 0; i < sizeof(expr) / sizeof(*expr) / 2; ++i)
 | |
|     query_end= strxmov(query_end, expr[i * 2], ", ", NullS);
 | |
|   query_end= strxmov(query_end - 2, " FROM t1 GROUP BY i", NullS);
 | |
|   DIE_UNLESS(query_end - query < MAX_TEST_QUERY_LENGTH);
 | |
| 
 | |
|   rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1");
 | |
|   myquery(rc);
 | |
|   rc= mysql_query(mysql, "CREATE TABLE t1 (i INT)");
 | |
|   myquery(rc);
 | |
|   /*
 | |
|     We need this loop to ensure correct behavior with both constant and
 | |
|     non-constant tables.
 | |
|   */
 | |
|   for (j= 0; j < 2 ; j++)
 | |
|   {
 | |
|     rc= mysql_query(mysql, "INSERT INTO t1 VALUES (1)");
 | |
|     myquery(rc);
 | |
| 
 | |
|     rc= mysql_real_query(mysql, query, (ulong)(query_end - query));
 | |
|     myquery(rc);
 | |
| 
 | |
|     result= mysql_use_result(mysql);
 | |
|     DIE_UNLESS(result);
 | |
| 
 | |
|   field_count= mysql_field_count(mysql);
 | |
|   for (i= 0; i < field_count; ++i)
 | |
|   {
 | |
|     field= mysql_fetch_field_direct(result, i);
 | |
|     if (!opt_silent)
 | |
|       if (!opt_silent)
 | |
|         printf("%s -> %s ... ", expr[i * 2], field->name);
 | |
|     fflush(stdout);
 | |
|     DIE_UNLESS(field->db[0] == 0 && field->org_table[0] == 0 &&
 | |
|                field->table[0] == 0 && field->org_name[0] == 0);
 | |
|     DIE_UNLESS(strcmp(field->name, expr[i * 2 + 1]) == 0);
 | |
|     if (!opt_silent)
 | |
|       if (!opt_silent)
 | |
|         puts("OK");
 | |
|   }
 | |
| 
 | |
|     mysql_free_result(result);
 | |
|   }
 | |
|   rc= mysql_query(mysql, "DROP TABLE t1");
 | |
|   myquery(rc);
 | |
| 
 | |
|   DBUG_VOID_RETURN;
 | |
| }
 | |
| 
 | |
| /*
 | |
|   Bug#24179 "select b into $var" fails with --cursor_protocol"
 | |
|   The failure is correct, check that the returned message is meaningful.
 | |
| */
 | |
| 
 | |
| static void test_bug24179()
 | |
| {
 | |
|   int rc;
 | |
|   MYSQL_STMT *stmt;
 | |
| 
 | |
|   DBUG_ENTER("test_bug24179");
 | |
|   myheader("test_bug24179");
 | |
| 
 | |
|   stmt= open_cursor("select 1 into @a");
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   DIE_UNLESS(rc);
 | |
|   if (!opt_silent)
 | |
|   {
 | |
|     printf("Got error (as expected): %d %s\n",
 | |
|            mysql_stmt_errno(stmt),
 | |
|            mysql_stmt_error(stmt));
 | |
|   }
 | |
|   DIE_UNLESS(mysql_stmt_errno(stmt) == 1323);
 | |
|   mysql_stmt_close(stmt);
 | |
| 
 | |
|   DBUG_VOID_RETURN;
 | |
| }
 | |
| 
 | |
| 
 | |
| /**
 | |
|   Bug#32265 Server returns different metadata if prepared statement is used
 | |
| */
 | |
| 
 | |
| static void test_bug32265()
 | |
| {
 | |
|   int rc;
 | |
|   MYSQL_STMT *stmt;
 | |
|   MYSQL_FIELD *field;
 | |
|   MYSQL_RES *metadata;
 | |
| 
 | |
|   DBUG_ENTER("test_bug32265");
 | |
|   myheader("test_bug32265");
 | |
| 
 | |
|   rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1");
 | |
|   myquery(rc);
 | |
|   rc= mysql_query(mysql, "CREATE  TABLE t1 (a INTEGER)");
 | |
|   myquery(rc);
 | |
|   rc= mysql_query(mysql, "INSERT INTO t1 VALUES (1)");
 | |
|   myquery(rc);
 | |
|   rc= mysql_query(mysql, "CREATE VIEW v1 AS SELECT * FROM t1");
 | |
|   myquery(rc);
 | |
| 
 | |
|   stmt= open_cursor("SELECT * FROM t1");
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   metadata= mysql_stmt_result_metadata(stmt);
 | |
|   field= mysql_fetch_field(metadata);
 | |
|   DIE_UNLESS(field);
 | |
|   DIE_UNLESS(strcmp(field->table, "t1") == 0);
 | |
|   DIE_UNLESS(strcmp(field->org_table, "t1") == 0);
 | |
|   DIE_UNLESS(strcmp(field->db, "client_test_db") == 0);
 | |
|   mysql_free_result(metadata);
 | |
|   mysql_stmt_close(stmt);
 | |
| 
 | |
|   stmt= open_cursor("SELECT a '' FROM t1 ``");
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   metadata= mysql_stmt_result_metadata(stmt);
 | |
|   field= mysql_fetch_field(metadata);
 | |
|   DIE_UNLESS(strcmp(field->table, "") == 0);
 | |
|   DIE_UNLESS(strcmp(field->org_table, "t1") == 0);
 | |
|   DIE_UNLESS(strcmp(field->db, "client_test_db") == 0);
 | |
|   mysql_free_result(metadata);
 | |
|   mysql_stmt_close(stmt);
 | |
| 
 | |
|   stmt= open_cursor("SELECT a '' FROM t1 ``");
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   metadata= mysql_stmt_result_metadata(stmt);
 | |
|   field= mysql_fetch_field(metadata);
 | |
|   DIE_UNLESS(strcmp(field->table, "") == 0);
 | |
|   DIE_UNLESS(strcmp(field->org_table, "t1") == 0);
 | |
|   DIE_UNLESS(strcmp(field->db, "client_test_db") == 0);
 | |
|   mysql_free_result(metadata);
 | |
|   mysql_stmt_close(stmt);
 | |
| 
 | |
|   stmt= open_cursor("SELECT * FROM v1");
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   metadata= mysql_stmt_result_metadata(stmt);
 | |
|   field= mysql_fetch_field(metadata);
 | |
|   DIE_UNLESS(strcmp(field->table, "v1") == 0);
 | |
|   DIE_UNLESS(strcmp(field->org_table, "v1") == 0);
 | |
|   DIE_UNLESS(strcmp(field->db, "client_test_db") == 0);
 | |
|   mysql_free_result(metadata);
 | |
|   mysql_stmt_close(stmt);
 | |
| 
 | |
|   stmt= open_cursor("SELECT * FROM v1 /* SIC */ GROUP BY 1");
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   metadata= mysql_stmt_result_metadata(stmt);
 | |
|   field= mysql_fetch_field(metadata);
 | |
|   DIE_UNLESS(strcmp(field->table, "v1") == 0);
 | |
|   DIE_UNLESS(strcmp(field->org_table, "v1") == 0);
 | |
|   DIE_UNLESS(strcmp(field->db, "client_test_db") == 0);
 | |
|   mysql_free_result(metadata);
 | |
|   mysql_stmt_close(stmt);
 | |
| 
 | |
|   rc= mysql_query(mysql, "DROP VIEW v1");
 | |
|   myquery(rc);
 | |
|   rc= mysql_query(mysql, "DROP TABLE t1");
 | |
|   myquery(rc);
 | |
| 
 | |
|   DBUG_VOID_RETURN;
 | |
| }
 | |
| 
 | |
| /*
 | |
|   Bug#28075 "COM_DEBUG crashes mysqld"
 | |
| */
 | |
| 
 | |
| static void test_bug28075()
 | |
| {
 | |
|   int rc;
 | |
| 
 | |
|   DBUG_ENTER("test_bug28075");
 | |
|   myheader("test_bug28075");
 | |
| 
 | |
|   rc= mysql_dump_debug_info(mysql);
 | |
|   DIE_UNLESS(rc == 0);
 | |
| 
 | |
|   rc= mysql_ping(mysql);
 | |
|   DIE_UNLESS(rc == 0);
 | |
| 
 | |
|   DBUG_VOID_RETURN;
 | |
| }
 | |
| 
 | |
| 
 | |
| /*
 | |
|   Bug#27876 (SF with cyrillic variable name fails during execution (regression))
 | |
| */
 | |
| 
 | |
| static void test_bug27876()
 | |
| {
 | |
|   int rc;
 | |
|   MYSQL_RES *result;
 | |
| 
 | |
|   uchar utf8_func[] =
 | |
|   {
 | |
|     0xd1, 0x84, 0xd1, 0x83, 0xd0, 0xbd, 0xd0, 0xba,
 | |
|     0xd1, 0x86, 0xd0, 0xb8, 0xd0, 0xb9, 0xd0, 0xba,
 | |
|     0xd0, 0xb0,
 | |
|     0x00
 | |
|   };
 | |
| 
 | |
|   uchar utf8_param[] =
 | |
|   {
 | |
|     0xd0, 0xbf, 0xd0, 0xb0, 0xd1, 0x80, 0xd0, 0xb0,
 | |
|     0xd0, 0xbc, 0xd0, 0xb5, 0xd1, 0x82, 0xd1, 0x8a,
 | |
|     0xd1, 0x80, 0x5f, 0xd0, 0xb2, 0xd0, 0xb5, 0xd1,
 | |
|     0x80, 0xd1, 0x81, 0xd0, 0xb8, 0xd1, 0x8f,
 | |
|     0x00
 | |
|   };
 | |
| 
 | |
|   char query[500];
 | |
| 
 | |
|   DBUG_ENTER("test_bug27876");
 | |
|   myheader("test_bug27876");
 | |
| 
 | |
|   rc= mysql_query(mysql, "set names utf8");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "select version()");
 | |
|   myquery(rc);
 | |
|   result= mysql_store_result(mysql);
 | |
|   mytest(result);
 | |
|   mysql_free_result(result);
 | |
| 
 | |
|   sprintf(query, "DROP FUNCTION IF EXISTS %s", (char*) utf8_func);
 | |
|   rc= mysql_query(mysql, query);
 | |
|   myquery(rc);
 | |
| 
 | |
|   sprintf(query,
 | |
|           "CREATE FUNCTION %s( %s VARCHAR(25))"
 | |
|           " RETURNS VARCHAR(25) DETERMINISTIC RETURN %s",
 | |
|           (char*) utf8_func, (char*) utf8_param, (char*) utf8_param);
 | |
|   rc= mysql_query(mysql, query);
 | |
|   myquery(rc);
 | |
|   sprintf(query, "SELECT %s(VERSION())", (char*) utf8_func);
 | |
|   rc= mysql_query(mysql, query);
 | |
|   myquery(rc);
 | |
|   result= mysql_store_result(mysql);
 | |
|   mytest(result);
 | |
|   mysql_free_result(result);
 | |
| 
 | |
|   sprintf(query, "DROP FUNCTION %s", (char*) utf8_func);
 | |
|   rc= mysql_query(mysql, query);
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "set names default");
 | |
|   myquery(rc);
 | |
| 
 | |
|   DBUG_VOID_RETURN;
 | |
| }
 | |
| 
 | |
| 
 | |
| /*
 | |
|   Bug#28505: mysql_affected_rows() returns wrong value if CLIENT_FOUND_ROWS
 | |
|   flag is set.
 | |
| */
 | |
| 
 | |
| static void test_bug28505()
 | |
| {
 | |
|   my_ulonglong res;
 | |
| 
 | |
|   myquery(mysql_query(mysql, "drop table if exists t1"));
 | |
|   myquery(mysql_query(mysql, "create table t1(f1 int primary key)"));
 | |
|   myquery(mysql_query(mysql, "insert into t1 values(1)"));
 | |
|   myquery(mysql_query(mysql,
 | |
|                   "insert into t1 values(1) on duplicate key update f1=1"));
 | |
|   res= mysql_affected_rows(mysql);
 | |
|   DIE_UNLESS(!res);
 | |
|   myquery(mysql_query(mysql, "drop table t1"));
 | |
| }
 | |
| 
 | |
| 
 | |
| /*
 | |
|   Bug#28934: server crash when receiving malformed com_execute packets
 | |
| */
 | |
| 
 | |
| static void test_bug28934()
 | |
| {
 | |
|   my_bool error= 0;
 | |
|   MYSQL_BIND bind[5];
 | |
|   MYSQL_STMT *stmt;
 | |
|   int cnt;
 | |
| 
 | |
|   myquery(mysql_query(mysql, "drop table if exists t1"));
 | |
|   myquery(mysql_query(mysql, "create table t1(id int)"));
 | |
| 
 | |
|   myquery(mysql_query(mysql, "insert into t1 values(1),(2),(3),(4),(5)"));
 | |
|   stmt= mysql_simple_prepare(mysql,"select * from t1 where id in(?,?,?,?,?)");
 | |
|   check_stmt(stmt);
 | |
| 
 | |
|   memset (&bind, 0, sizeof (bind));
 | |
|   for (cnt= 0; cnt < 5; cnt++)
 | |
|   {
 | |
|     bind[cnt].buffer_type= MYSQL_TYPE_LONG;
 | |
|     bind[cnt].buffer= (char*)&cnt;
 | |
|     bind[cnt].buffer_length= 0;
 | |
|   }
 | |
|   myquery(mysql_stmt_bind_param(stmt, bind));
 | |
| 
 | |
|   stmt->param_count=2;
 | |
|   error= mysql_stmt_execute(stmt);
 | |
|   DIE_UNLESS(error != 0);
 | |
|   myerror(NULL);
 | |
|   mysql_stmt_close(stmt);
 | |
| 
 | |
|   myquery(mysql_query(mysql, "drop table t1"));
 | |
| }
 | |
| 
 | |
| /*
 | |
|   Test mysql_change_user() C API and COM_CHANGE_USER
 | |
| */
 | |
| 
 | |
| static void test_change_user()
 | |
| {
 | |
|   char buff[256];
 | |
|   const char *user_pw= "mysqltest_pw";
 | |
|   const char *user_no_pw= "mysqltest_no_pw";
 | |
|   const char *pw= "password";
 | |
|   const char *db= "mysqltest_user_test_database";
 | |
|   int rc;
 | |
|   MYSQL*       conn;
 | |
|   MYSQL_RES* res;
 | |
|   DBUG_ENTER("test_change_user");
 | |
|   myheader("test_change_user");
 | |
| 
 | |
|   /* Prepare environment */
 | |
|   sprintf(buff, "drop database if exists %s", db);
 | |
|   rc= mysql_query(mysql, buff);
 | |
|   myquery(rc);
 | |
| 
 | |
|   sprintf(buff, "create database %s", db);
 | |
|   rc= mysql_query(mysql, buff);
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "SET SQL_MODE=''");
 | |
|   myquery(rc);
 | |
| 
 | |
|   sprintf(buff,
 | |
|           "grant select on %s.* to %s@'%%' identified by '%s'",
 | |
|           db,
 | |
|           user_pw,
 | |
|           pw);
 | |
|   rc= mysql_query(mysql, buff);
 | |
|   myquery(rc);
 | |
| 
 | |
|   sprintf(buff,
 | |
|           "grant select on %s.* to %s@'localhost' identified by '%s'",
 | |
|           db,
 | |
|           user_pw,
 | |
|           pw);
 | |
|   rc= mysql_query(mysql, buff);
 | |
|   myquery(rc);
 | |
| 
 | |
|   sprintf(buff,
 | |
|           "grant select on %s.* to %s@'%%'",
 | |
|           db,
 | |
|           user_no_pw);
 | |
|   rc= mysql_query(mysql, buff);
 | |
|   myquery(rc);
 | |
| 
 | |
|   sprintf(buff,
 | |
|           "grant select on %s.* to %s@'localhost'",
 | |
|           db,
 | |
|           user_no_pw);
 | |
|   rc= mysql_query(mysql, buff);
 | |
|   myquery(rc);
 | |
| 
 | |
|   conn= client_connect(0, MYSQL_PROTOCOL_TCP, 0);
 | |
| 
 | |
|   /* Try some combinations */
 | |
|   rc= mysql_change_user(conn, NULL, NULL, NULL);
 | |
|   DIE_UNLESS(rc);
 | |
|   if (! opt_silent)
 | |
|     printf("Got error (as expected): %s\n", mysql_error(conn));
 | |
| 
 | |
| 
 | |
|   rc= mysql_change_user(conn, "", NULL, NULL);
 | |
|   DIE_UNLESS(rc);
 | |
|   if (! opt_silent)
 | |
|     printf("Got error (as expected): %s\n", mysql_error(conn));
 | |
| 
 | |
|   rc= mysql_change_user(conn, "", "", NULL);
 | |
|   DIE_UNLESS(rc);
 | |
|   if (! opt_silent)
 | |
|     printf("Got error (as expected): %s\n", mysql_error(conn));
 | |
| 
 | |
|   mysql_close(conn);
 | |
|   conn= client_connect(0, MYSQL_PROTOCOL_TCP, 0);
 | |
| 
 | |
|   rc= mysql_change_user(conn, "", "", "");
 | |
|   DIE_UNLESS(rc);
 | |
|   if (! opt_silent)
 | |
|     printf("Got error (as expected): %s\n", mysql_error(conn));
 | |
| 
 | |
|   rc= mysql_change_user(conn, NULL, "", "");
 | |
|   DIE_UNLESS(rc);
 | |
|   if (! opt_silent)
 | |
|     printf("Got error (as expected): %s\n", mysql_error(conn));
 | |
| 
 | |
| 
 | |
|   rc= mysql_change_user(conn, NULL, NULL, "");
 | |
|   DIE_UNLESS(rc);
 | |
|   if (! opt_silent)
 | |
|     printf("Got error (as expected): %s\n", mysql_error(conn));
 | |
| 
 | |
|   mysql_close(conn);
 | |
|   conn= client_connect(0, MYSQL_PROTOCOL_TCP, 0);
 | |
| 
 | |
|   rc= mysql_change_user(conn, "", NULL, "");
 | |
|   DIE_UNLESS(rc);
 | |
|   if (! opt_silent)
 | |
|     printf("Got error (as expected): %s\n", mysql_error(conn));
 | |
| 
 | |
|   rc= mysql_change_user(conn, user_pw, NULL, "");
 | |
|   DIE_UNLESS(rc);
 | |
|   if (! opt_silent)
 | |
|     printf("Got error (as expected): %s\n", mysql_error(conn));
 | |
| 
 | |
|   rc= mysql_change_user(conn, user_pw, "", "");
 | |
|   DIE_UNLESS(rc);
 | |
|   if (! opt_silent)
 | |
|     printf("Got error (as expected): %s\n", mysql_error(conn));
 | |
| 
 | |
|   mysql_close(conn);
 | |
|   conn= client_connect(0, MYSQL_PROTOCOL_TCP, 0);
 | |
| 
 | |
|   rc= mysql_change_user(conn, user_pw, "", NULL);
 | |
|   DIE_UNLESS(rc);
 | |
|   if (! opt_silent)
 | |
|     printf("Got error (as expected): %s\n", mysql_error(conn));
 | |
| 
 | |
|   rc= mysql_change_user(conn, user_pw, NULL, NULL);
 | |
|   DIE_UNLESS(rc);
 | |
|   if (! opt_silent)
 | |
|     printf("Got error (as expected): %s\n", mysql_error(conn));
 | |
| 
 | |
|   rc= mysql_change_user(conn, user_pw, "", db);
 | |
|   DIE_UNLESS(rc);
 | |
|   if (! opt_silent)
 | |
|     printf("Got error (as expected): %s\n", mysql_error(conn));
 | |
| 
 | |
|   mysql_close(conn);
 | |
|   conn= client_connect(0, MYSQL_PROTOCOL_TCP, 0);
 | |
| 
 | |
|   rc= mysql_change_user(conn, user_pw, NULL, db);
 | |
|   DIE_UNLESS(rc);
 | |
|   if (! opt_silent)
 | |
|     printf("Got error (as expected): %s\n", mysql_error(conn));
 | |
| 
 | |
|   rc= mysql_change_user(conn, user_pw, pw, db);
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_change_user(conn, user_pw, pw, NULL);
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_change_user(conn, user_pw, pw, "");
 | |
|   myquery(rc);
 | |
| 
 | |
|   /* MDEV-14581 : Check that there are no warnings after change user.*/
 | |
|   rc = mysql_query(conn,"SIGNAL SQLSTATE '01000'");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc = mysql_change_user(conn, user_pw, pw, "");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc = mysql_query(conn, "SHOW WARNINGS");
 | |
|   myquery(rc);
 | |
|   res = mysql_store_result(conn);
 | |
|   rc = my_process_result_set(res);
 | |
|   DIE_UNLESS(rc == 0);
 | |
|   mysql_free_result(res);
 | |
| 
 | |
|   rc= mysql_change_user(conn, user_no_pw, pw, db);
 | |
|   DIE_UNLESS(rc);
 | |
|   if (! opt_silent)
 | |
|     printf("Got error (as expected): %s\n", mysql_error(conn));
 | |
| 
 | |
|   rc= mysql_change_user(conn, user_no_pw, pw, "");
 | |
|   DIE_UNLESS(rc);
 | |
|   if (! opt_silent)
 | |
|     printf("Got error (as expected): %s\n", mysql_error(conn));
 | |
| 
 | |
|   mysql_close(conn);
 | |
|   conn= client_connect(0, MYSQL_PROTOCOL_TCP, 0);
 | |
| 
 | |
|   rc= mysql_change_user(conn, user_no_pw, pw, NULL);
 | |
|   DIE_UNLESS(rc);
 | |
|   if (! opt_silent)
 | |
|     printf("Got error (as expected): %s\n", mysql_error(conn));
 | |
| 
 | |
|   rc= mysql_change_user(conn, user_no_pw, "", NULL);
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_change_user(conn, user_no_pw, "", "");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_change_user(conn, user_no_pw, "", db);
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_change_user(conn, user_no_pw, NULL, db);
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_change_user(conn, "", pw, db);
 | |
|   DIE_UNLESS(rc);
 | |
|   if (! opt_silent)
 | |
|     printf("Got error (as expected): %s\n", mysql_error(conn));
 | |
| 
 | |
|   rc= mysql_change_user(conn, "", pw, "");
 | |
|   DIE_UNLESS(rc);
 | |
|   if (! opt_silent)
 | |
|     printf("Got error (as expected): %s\n", mysql_error(conn));
 | |
| 
 | |
|   mysql_close(conn);
 | |
|   conn= client_connect(0, MYSQL_PROTOCOL_TCP, 0);
 | |
| 
 | |
|   rc= mysql_change_user(conn, "", pw, NULL);
 | |
|   DIE_UNLESS(rc);
 | |
|   if (! opt_silent)
 | |
|     printf("Got error (as expected): %s\n", mysql_error(conn));
 | |
| 
 | |
|   rc= mysql_change_user(conn, NULL, pw, NULL);
 | |
|   DIE_UNLESS(rc);
 | |
|   if (! opt_silent)
 | |
|     printf("Got error (as expected): %s\n", mysql_error(conn));
 | |
| 
 | |
|   rc= mysql_change_user(conn, NULL, NULL, db);
 | |
|   DIE_UNLESS(rc);
 | |
|   if (! opt_silent)
 | |
|     printf("Got error (as expected): %s\n", mysql_error(conn));
 | |
| 
 | |
|   mysql_close(conn);
 | |
|   conn= client_connect(0, MYSQL_PROTOCOL_TCP, 0);
 | |
| 
 | |
|   rc= mysql_change_user(conn, NULL, "", db);
 | |
|   DIE_UNLESS(rc);
 | |
|   if (! opt_silent)
 | |
|     printf("Got error (as expected): %s\n", mysql_error(conn));
 | |
| 
 | |
|   rc= mysql_change_user(conn, "", "", db);
 | |
|   DIE_UNLESS(rc);
 | |
|   if (! opt_silent)
 | |
|     printf("Got error (as expected): %s\n", mysql_error(conn));
 | |
| 
 | |
|   /* Cleanup the environment */
 | |
| 
 | |
|   mysql_change_user(conn, opt_user, opt_password, current_db);
 | |
| 
 | |
|   mysql_close(conn);
 | |
| 
 | |
|   sprintf(buff, "drop database %s", db);
 | |
|   rc= mysql_query(mysql, buff);
 | |
|   myquery(rc);
 | |
| 
 | |
|   sprintf(buff, "drop user %s@'%%'", user_pw);
 | |
|   rc= mysql_query(mysql, buff);
 | |
|   myquery(rc);
 | |
| 
 | |
|   sprintf(buff, "drop user %s@'%%'", user_no_pw);
 | |
|   rc= mysql_query(mysql, buff);
 | |
|   myquery(rc);
 | |
| 
 | |
|   sprintf(buff, "drop user %s@'localhost'", user_pw);
 | |
|   rc= mysql_query(mysql, buff);
 | |
|   myquery(rc);
 | |
| 
 | |
|   sprintf(buff, "drop user %s@'localhost'", user_no_pw);
 | |
|   rc= mysql_query(mysql, buff);
 | |
|   myquery(rc);
 | |
| 
 | |
|   DBUG_VOID_RETURN;
 | |
| }
 | |
| 
 | |
| /*
 | |
|   Bug#27592 (stack overrun when storing datetime value using prepared statements)
 | |
| */
 | |
| 
 | |
| static void test_bug27592()
 | |
| {
 | |
|   const int NUM_ITERATIONS= 40;
 | |
|   int i;
 | |
|   int rc;
 | |
|   MYSQL_STMT *stmt= NULL;
 | |
|   MYSQL_BIND bind[1];
 | |
|   MYSQL_TIME time_val;
 | |
| 
 | |
|   DBUG_ENTER("test_bug27592");
 | |
|   myheader("test_bug27592");
 | |
| 
 | |
|   mysql_query(mysql, "DROP TABLE IF EXISTS t1");
 | |
|   mysql_query(mysql, "CREATE TABLE t1(c2 DATETIME)");
 | |
| 
 | |
|   stmt= mysql_simple_prepare(mysql, "INSERT INTO t1 VALUES (?)");
 | |
|   DIE_UNLESS(stmt);
 | |
| 
 | |
|   memset(bind, 0, sizeof(bind));
 | |
| 
 | |
|   bind[0].buffer_type= MYSQL_TYPE_DATETIME;
 | |
|   bind[0].buffer= (char *) &time_val;
 | |
|   bind[0].length= NULL;
 | |
| 
 | |
|   for (i= 0; i < NUM_ITERATIONS; i++)
 | |
|   {
 | |
|     time_val.year= 2007;
 | |
|     time_val.month= 6;
 | |
|     time_val.day= 7;
 | |
|     time_val.hour= 18;
 | |
|     time_val.minute= 41;
 | |
|     time_val.second= 3;
 | |
| 
 | |
|     time_val.second_part=0;
 | |
|     time_val.neg=0;
 | |
| 
 | |
|     rc= mysql_stmt_bind_param(stmt, bind);
 | |
|     check_execute(stmt, rc);
 | |
| 
 | |
|     rc= mysql_stmt_execute(stmt);
 | |
|     check_execute(stmt, rc);
 | |
|   }
 | |
| 
 | |
|   mysql_stmt_close(stmt);
 | |
| 
 | |
|   DBUG_VOID_RETURN;
 | |
| }
 | |
| 
 | |
| /*
 | |
|   Bug#29687 mysql_stmt_store_result memory leak in libmysqld
 | |
| */
 | |
| 
 | |
| static void test_bug29687()
 | |
| {
 | |
|   const int NUM_ITERATIONS= 40;
 | |
|   int i;
 | |
|   int rc;
 | |
|   MYSQL_STMT *stmt= NULL;
 | |
| 
 | |
|   DBUG_ENTER("test_bug29687");
 | |
|   myheader("test_bug29687");
 | |
| 
 | |
|   stmt= mysql_simple_prepare(mysql, "SELECT 1 FROM dual WHERE 0=2");
 | |
|   DIE_UNLESS(stmt);
 | |
| 
 | |
|   for (i= 0; i < NUM_ITERATIONS; i++)
 | |
|   {
 | |
|     rc= mysql_stmt_execute(stmt);
 | |
|     check_execute(stmt, rc);
 | |
|     mysql_stmt_store_result(stmt);
 | |
|     while (mysql_stmt_fetch(stmt)==0);
 | |
|     mysql_stmt_free_result(stmt);
 | |
|   }
 | |
| 
 | |
|   mysql_stmt_close(stmt);
 | |
|   DBUG_VOID_RETURN;
 | |
| }
 | |
| 
 | |
| 
 | |
| /*
 | |
|   Bug #29692  	Single row inserts can incorrectly report a huge number of 
 | |
|   row insertions
 | |
| */
 | |
| 
 | |
| static void test_bug29692()
 | |
| {
 | |
|   MYSQL* conn;
 | |
| 
 | |
|   if (!(conn= mysql_client_init(NULL)))
 | |
|   {
 | |
|     myerror("test_bug29692 init failed");
 | |
|     exit(1);
 | |
|   }
 | |
| 
 | |
|   if (!(mysql_real_connect(conn, opt_host, opt_user,
 | |
|                            opt_password, opt_db ? opt_db:"test", opt_port,
 | |
|                            opt_unix_socket,  CLIENT_FOUND_ROWS)))
 | |
|   {
 | |
|     myerror("test_bug29692 connection failed");
 | |
|     mysql_close(mysql);
 | |
|     exit(1);
 | |
|   }
 | |
|   myquery(mysql_query(conn, "drop table if exists t1"));
 | |
|   myquery(mysql_query(conn, "create table t1(f1 int)"));
 | |
|   myquery(mysql_query(conn, "insert into t1 values(1)"));
 | |
|   DIE_UNLESS(1 == mysql_affected_rows(conn));
 | |
|   myquery(mysql_query(conn, "drop table t1"));
 | |
|   mysql_close(conn);
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Bug#29306 Truncated data in MS Access with decimal (3,1) columns in a VIEW
 | |
| */
 | |
| 
 | |
| static void test_bug29306()
 | |
| {
 | |
|   MYSQL_FIELD *field;
 | |
|   int rc;
 | |
|   MYSQL_RES *res;
 | |
| 
 | |
|   DBUG_ENTER("test_bug29306");
 | |
|   myheader("test_bug29306");
 | |
| 
 | |
|   rc= mysql_query(mysql, "DROP TABLE IF EXISTS tab17557");
 | |
|   myquery(rc);
 | |
|   rc= mysql_query(mysql, "DROP VIEW IF EXISTS view17557");
 | |
|   myquery(rc);
 | |
|   rc= mysql_query(mysql, "CREATE TABLE tab17557 (dd decimal (3,1))");
 | |
|   myquery(rc);
 | |
|   rc= mysql_query(mysql, "CREATE VIEW view17557 as SELECT dd FROM tab17557");
 | |
|   myquery(rc);
 | |
|   rc= mysql_query(mysql, "INSERT INTO tab17557 VALUES (7.6)");
 | |
|   myquery(rc);
 | |
| 
 | |
|   /* Checking the view */
 | |
|   res= mysql_list_fields(mysql, "view17557", NULL);
 | |
|   while ((field= mysql_fetch_field(res)))
 | |
|   {
 | |
|     if (! opt_silent)
 | |
|     {
 | |
|       printf("field name %s\n", field->name);
 | |
|       printf("field table %s\n", field->table);
 | |
|       printf("field decimals %d\n", field->decimals);
 | |
|       if (field->decimals < 1)
 | |
|         printf("Error! No decimals! \n");
 | |
|       printf("\n\n");
 | |
|     }
 | |
|     DIE_UNLESS(field->decimals == 1);
 | |
|   }
 | |
|   mysql_free_result(res);
 | |
| 
 | |
|   rc= mysql_query(mysql, "DROP TABLE tab17557");
 | |
|   myquery(rc);
 | |
|   rc= mysql_query(mysql, "DROP VIEW view17557");
 | |
|   myquery(rc);
 | |
| 
 | |
|   DBUG_VOID_RETURN;
 | |
| }
 | |
| /*
 | |
|   Bug#30472: libmysql doesn't reset charset, insert_id after succ.
 | |
|   mysql_change_user() call row insertions.
 | |
| */
 | |
| 
 | |
| static void bug30472_retrieve_charset_info(MYSQL *con,
 | |
|                                            char *character_set_name,
 | |
|                                            char *character_set_client,
 | |
|                                            char *character_set_results,
 | |
|                                            char *collation_connection)
 | |
| {
 | |
|   MYSQL_RES *rs;
 | |
|   MYSQL_ROW row;
 | |
| 
 | |
|   /* Get the cached client character set name. */
 | |
| 
 | |
|   strcpy(character_set_name, mysql_character_set_name(con));
 | |
| 
 | |
|   /* Retrieve server character set information. */
 | |
| 
 | |
|   DIE_IF(mysql_query(con, "SHOW VARIABLES LIKE 'character_set_client'"));
 | |
|   DIE_UNLESS(rs= mysql_store_result(con));
 | |
|   DIE_UNLESS(row= mysql_fetch_row(rs));
 | |
|   strcpy(character_set_client, row[1]);
 | |
|   mysql_free_result(rs);
 | |
| 
 | |
|   DIE_IF(mysql_query(con, "SHOW VARIABLES LIKE 'character_set_results'"));
 | |
|   DIE_UNLESS(rs= mysql_store_result(con));
 | |
|   DIE_UNLESS(row= mysql_fetch_row(rs));
 | |
|   strcpy(character_set_results, row[1]);
 | |
|   mysql_free_result(rs);
 | |
| 
 | |
|   DIE_IF(mysql_query(con, "SHOW VARIABLES LIKE 'collation_connection'"));
 | |
|   DIE_UNLESS(rs= mysql_store_result(con));
 | |
|   DIE_UNLESS(row= mysql_fetch_row(rs));
 | |
|   strcpy(collation_connection, row[1]);
 | |
|   mysql_free_result(rs);
 | |
| }
 | |
| 
 | |
| static void test_bug30472()
 | |
| {
 | |
|   MYSQL con;
 | |
| 
 | |
|   char character_set_name_1[MY_CS_CHARACTER_SET_NAME_SIZE];
 | |
|   char character_set_client_1[MY_CS_CHARACTER_SET_NAME_SIZE];
 | |
|   char character_set_results_1[MY_CS_CHARACTER_SET_NAME_SIZE];
 | |
|   char collation_connnection_1[MY_CS_COLLATION_NAME_SIZE];
 | |
| 
 | |
|   char character_set_name_2[MY_CS_CHARACTER_SET_NAME_SIZE];
 | |
|   char character_set_client_2[MY_CS_CHARACTER_SET_NAME_SIZE];
 | |
|   char character_set_results_2[MY_CS_CHARACTER_SET_NAME_SIZE];
 | |
|   char collation_connnection_2[MY_CS_COLLATION_NAME_SIZE];
 | |
| 
 | |
|   char character_set_name_3[MY_CS_CHARACTER_SET_NAME_SIZE];
 | |
|   char character_set_client_3[MY_CS_CHARACTER_SET_NAME_SIZE];
 | |
|   char character_set_results_3[MY_CS_CHARACTER_SET_NAME_SIZE];
 | |
|   char collation_connnection_3[MY_CS_COLLATION_NAME_SIZE];
 | |
| 
 | |
|   char character_set_name_4[MY_CS_CHARACTER_SET_NAME_SIZE];
 | |
|   char character_set_client_4[MY_CS_CHARACTER_SET_NAME_SIZE];
 | |
|   char character_set_results_4[MY_CS_CHARACTER_SET_NAME_SIZE];
 | |
|   char collation_connnection_4[MY_CS_COLLATION_NAME_SIZE];
 | |
| 
 | |
|   /* Create a new connection. */
 | |
| 
 | |
|   DIE_UNLESS(mysql_client_init(&con));
 | |
| 
 | |
|   DIE_UNLESS(mysql_real_connect(&con,
 | |
|                                 opt_host,
 | |
|                                 opt_user,
 | |
|                                 opt_password,
 | |
|                                 opt_db ? opt_db : "test",
 | |
|                                 opt_port,
 | |
|                                 opt_unix_socket,
 | |
|                                 CLIENT_FOUND_ROWS));
 | |
| 
 | |
|   /* Retrieve character set information. */
 | |
| 
 | |
|   bug30472_retrieve_charset_info(&con,
 | |
|                                  character_set_name_1,
 | |
|                                  character_set_client_1,
 | |
|                                  character_set_results_1,
 | |
|                                  collation_connnection_1);
 | |
| 
 | |
|   /* Switch client character set. */
 | |
| 
 | |
|   DIE_IF(mysql_set_character_set(&con, "latin2"));
 | |
| 
 | |
|   /* Retrieve character set information. */
 | |
| 
 | |
|   bug30472_retrieve_charset_info(&con,
 | |
|                                  character_set_name_2,
 | |
|                                  character_set_client_2,
 | |
|                                  character_set_results_2,
 | |
|                                  collation_connnection_2);
 | |
| 
 | |
|   /*
 | |
|     Check that
 | |
|       1) character set has been switched and
 | |
|       2) new character set is different from the original one.
 | |
|   */
 | |
| 
 | |
|   DIE_UNLESS(strcmp(character_set_name_2, "latin2") == 0);
 | |
|   DIE_UNLESS(strcmp(character_set_client_2, "latin2") == 0);
 | |
|   DIE_UNLESS(strcmp(character_set_results_2, "latin2") == 0);
 | |
|   DIE_UNLESS(strcmp(collation_connnection_2, "latin2_general_ci") == 0);
 | |
| 
 | |
|   DIE_UNLESS(strcmp(character_set_name_1, character_set_name_2) != 0);
 | |
|   DIE_UNLESS(strcmp(character_set_client_1, character_set_client_2) != 0);
 | |
|   DIE_UNLESS(strcmp(character_set_results_1, character_set_results_2) != 0);
 | |
|   DIE_UNLESS(strcmp(collation_connnection_1, collation_connnection_2) != 0);
 | |
| 
 | |
|   /* Call mysql_change_user() with the same username, password, database. */
 | |
| 
 | |
|   DIE_IF(mysql_change_user(&con,
 | |
|                            opt_user,
 | |
|                            opt_password,
 | |
|                            opt_db ? opt_db : "test"));
 | |
| 
 | |
|   /* Retrieve character set information. */
 | |
| 
 | |
|   bug30472_retrieve_charset_info(&con,
 | |
|                                  character_set_name_3,
 | |
|                                  character_set_client_3,
 | |
|                                  character_set_results_3,
 | |
|                                  collation_connnection_3);
 | |
| 
 | |
|   /* Check that character set information has been reset. */
 | |
| 
 | |
|   DIE_UNLESS(strcmp(character_set_name_1, character_set_name_3) == 0);
 | |
|   DIE_UNLESS(strcmp(character_set_client_1, character_set_client_3) == 0);
 | |
|   DIE_UNLESS(strcmp(character_set_results_1, character_set_results_3) == 0);
 | |
|   DIE_UNLESS(strcmp(collation_connnection_1, collation_connnection_3) == 0);
 | |
| 
 | |
|   /* Change connection-default character set in the client. */
 | |
| 
 | |
|   mysql_options(&con, MYSQL_SET_CHARSET_NAME, "utf8");
 | |
| 
 | |
|   /*
 | |
|     Call mysql_change_user() in order to check that new connection will
 | |
|     have UTF8 character set on the client and on the server.
 | |
|   */
 | |
| 
 | |
|   DIE_IF(mysql_change_user(&con,
 | |
|                            opt_user,
 | |
|                            opt_password,
 | |
|                            opt_db ? opt_db : "test"));
 | |
| 
 | |
|   /* Retrieve character set information. */
 | |
| 
 | |
|   bug30472_retrieve_charset_info(&con,
 | |
|                                  character_set_name_4,
 | |
|                                  character_set_client_4,
 | |
|                                  character_set_results_4,
 | |
|                                  collation_connnection_4);
 | |
| 
 | |
|   /* Check that we have UTF8 on the server and on the client. */
 | |
| 
 | |
|   DIE_UNLESS(strcmp(character_set_name_4, "utf8mb3") == 0);
 | |
|   DIE_UNLESS(strcmp(character_set_client_4, "utf8mb3") == 0);
 | |
|   DIE_UNLESS(strcmp(character_set_results_4, "utf8mb3") == 0);
 | |
|   DIE_UNLESS(strcmp(collation_connnection_4, "utf8mb3_uca1400_ai_ci") == 0);
 | |
| 
 | |
|   /* That's it. Cleanup. */
 | |
| 
 | |
|   mysql_close(&con);
 | |
| }
 | |
| 
 | |
| static void bug20023_change_user(MYSQL *con)
 | |
| {
 | |
|   DIE_IF(mysql_change_user(con,
 | |
|                            opt_user,
 | |
|                            opt_password,
 | |
|                            opt_db ? opt_db : "test"));
 | |
| }
 | |
| 
 | |
| static my_bool query_str_variable(MYSQL *con,
 | |
|                                   const char *var_name,
 | |
|                                   char *str,
 | |
|                                   size_t len)
 | |
| {
 | |
|   MYSQL_RES *rs;
 | |
|   MYSQL_ROW row;
 | |
| 
 | |
|   char query_buffer[MAX_TEST_QUERY_LENGTH];
 | |
| 
 | |
|   my_bool is_null;
 | |
| 
 | |
|   my_snprintf(query_buffer, sizeof (query_buffer),
 | |
|               "SELECT %s", var_name);
 | |
| 
 | |
|   DIE_IF(mysql_query(con, query_buffer));
 | |
|   DIE_UNLESS(rs= mysql_store_result(con));
 | |
|   DIE_UNLESS(row= mysql_fetch_row(rs));
 | |
| 
 | |
|   is_null= row[0] == NULL;
 | |
| 
 | |
|   if (!is_null)
 | |
|     my_snprintf(str, len, "%s", row[0]);
 | |
| 
 | |
|   mysql_free_result(rs);
 | |
| 
 | |
|   return is_null;
 | |
| }
 | |
| 
 | |
| static my_bool query_int_variable(MYSQL *con,
 | |
|                                   const char *var_name,
 | |
|                                   int *var_value)
 | |
| {
 | |
|   char str[32];
 | |
|   my_bool is_null= query_str_variable(con, var_name, str, sizeof(str));
 | |
| 
 | |
|   if (!is_null)
 | |
|     *var_value= atoi(str);
 | |
| 
 | |
|   return is_null;
 | |
| }
 | |
| 
 | |
| static void test_bug20023()
 | |
| {
 | |
|   MYSQL con;
 | |
| 
 | |
|   int sql_big_selects_orig= 0;
 | |
|   /*
 | |
|     Type of max_join_size is ha_rows, which might be ulong or off_t
 | |
|     depending on the platform or configure options. Preserve the string
 | |
|     to avoid type overflow pitfalls.
 | |
|   */
 | |
|   char max_join_size_orig[32];
 | |
| 
 | |
|   int sql_big_selects_2= 0;
 | |
|   int sql_big_selects_3= 0;
 | |
|   int sql_big_selects_4= 0;
 | |
|   int sql_big_selects_5= 0;
 | |
| 
 | |
|   char query_buffer[MAX_TEST_QUERY_LENGTH];
 | |
| 
 | |
|   /* Create a new connection. */
 | |
| 
 | |
|   DIE_UNLESS(mysql_client_init(&con));
 | |
| 
 | |
|   DIE_UNLESS(mysql_real_connect(&con,
 | |
|                                 opt_host,
 | |
|                                 opt_user,
 | |
|                                 opt_password,
 | |
|                                 opt_db ? opt_db : "test",
 | |
|                                 opt_port,
 | |
|                                 opt_unix_socket,
 | |
|                                 CLIENT_FOUND_ROWS));
 | |
| 
 | |
|   /***********************************************************************
 | |
|     Remember original SQL_BIG_SELECTS, MAX_JOIN_SIZE values.
 | |
|   ***********************************************************************/
 | |
| 
 | |
|   query_int_variable(&con,
 | |
|                      "@@session.sql_big_selects",
 | |
|                      &sql_big_selects_orig);
 | |
| 
 | |
|   query_str_variable(&con,
 | |
|                      "@@global.max_join_size",
 | |
|                      max_join_size_orig,
 | |
|                      sizeof(max_join_size_orig));
 | |
| 
 | |
|   /***********************************************************************
 | |
|     Test that COM_CHANGE_USER resets the SQL_BIG_SELECTS to the initial value.
 | |
|   ***********************************************************************/
 | |
| 
 | |
|   /* Issue COM_CHANGE_USER. */
 | |
| 
 | |
|   bug20023_change_user(&con);
 | |
| 
 | |
|   /* Query SQL_BIG_SELECTS. */
 | |
| 
 | |
|   query_int_variable(&con,
 | |
|                      "@@session.sql_big_selects",
 | |
|                      &sql_big_selects_2);
 | |
| 
 | |
|   /* Check that SQL_BIG_SELECTS is reset properly. */
 | |
| 
 | |
|   DIE_UNLESS(sql_big_selects_orig == sql_big_selects_2);
 | |
| 
 | |
|   /***********************************************************************
 | |
|     Test that if MAX_JOIN_SIZE set to non-default value,
 | |
|     SQL_BIG_SELECTS will be 0.
 | |
|   ***********************************************************************/
 | |
| 
 | |
|   /* Set MAX_JOIN_SIZE to some non-default value. */
 | |
| 
 | |
|   DIE_IF(mysql_query(&con, "SET @@global.max_join_size = 10000"));
 | |
|   DIE_IF(mysql_query(&con, "SET @@session.max_join_size = default"));
 | |
| 
 | |
|   /* Issue COM_CHANGE_USER. */
 | |
| 
 | |
|   bug20023_change_user(&con);
 | |
| 
 | |
|   /* Query SQL_BIG_SELECTS. */
 | |
| 
 | |
|   query_int_variable(&con,
 | |
|                      "@@session.sql_big_selects",
 | |
|                      &sql_big_selects_3);
 | |
| 
 | |
|   /* Check that SQL_BIG_SELECTS is 0. */
 | |
| 
 | |
|   DIE_UNLESS(sql_big_selects_3 == 0);
 | |
| 
 | |
|   /***********************************************************************
 | |
|     Test that if MAX_JOIN_SIZE set to default value,
 | |
|     SQL_BIG_SELECTS will be 1.
 | |
|   ***********************************************************************/
 | |
| 
 | |
|   /* Set MAX_JOIN_SIZE to the default value (2^64-1). */
 | |
| 
 | |
|   DIE_IF(mysql_query(&con, "SET @@global.max_join_size = cast(-1 as unsigned int)"));
 | |
|   DIE_IF(mysql_query(&con, "SET @@session.max_join_size = default"));
 | |
| 
 | |
|   /* Issue COM_CHANGE_USER. */
 | |
| 
 | |
|   bug20023_change_user(&con);
 | |
| 
 | |
|   /* Query SQL_BIG_SELECTS. */
 | |
| 
 | |
|   query_int_variable(&con,
 | |
|                      "@@session.sql_big_selects",
 | |
|                      &sql_big_selects_4);
 | |
| 
 | |
|   /* Check that SQL_BIG_SELECTS is 1. */
 | |
| 
 | |
|   DIE_UNLESS(sql_big_selects_4 == 1);
 | |
| 
 | |
|   /***********************************************************************
 | |
|     Restore MAX_JOIN_SIZE.
 | |
|     Check that SQL_BIG_SELECTS will be the original one.
 | |
|   ***********************************************************************/
 | |
| 
 | |
|   /* Restore MAX_JOIN_SIZE. */
 | |
| 
 | |
|   my_snprintf(query_buffer,
 | |
|            sizeof (query_buffer),
 | |
|            "SET @@global.max_join_size = %s",
 | |
|            max_join_size_orig);
 | |
| 
 | |
|   DIE_IF(mysql_query(&con, query_buffer));
 | |
| 
 | |
|   DIE_IF(mysql_query(&con, "SET @@global.max_join_size = cast(-1 as unsigned int)"));
 | |
|   DIE_IF(mysql_query(&con, "SET @@session.max_join_size = default"));
 | |
| 
 | |
|   /* Issue COM_CHANGE_USER. */
 | |
| 
 | |
|   bug20023_change_user(&con);
 | |
| 
 | |
|   /* Query SQL_BIG_SELECTS. */
 | |
| 
 | |
|   query_int_variable(&con,
 | |
|                      "@@session.sql_big_selects",
 | |
|                      &sql_big_selects_5);
 | |
| 
 | |
|   /* Check that SQL_BIG_SELECTS is 1. */
 | |
| 
 | |
|   DIE_UNLESS(sql_big_selects_5 == sql_big_selects_orig);
 | |
| 
 | |
|   /***********************************************************************
 | |
|     That's it. Cleanup.
 | |
|   ***********************************************************************/
 | |
| 
 | |
|   mysql_close(&con);
 | |
| }
 | |
| 
 | |
| static void bug31418_impl()
 | |
| {
 | |
|   MYSQL con;
 | |
| 
 | |
|   my_bool is_null;
 | |
|   int rc= 0;
 | |
| 
 | |
|   /* Create a new connection. */
 | |
| 
 | |
|   DIE_UNLESS(mysql_client_init(&con));
 | |
| 
 | |
|   DIE_UNLESS(mysql_real_connect(&con,
 | |
|                                 opt_host,
 | |
|                                 opt_user,
 | |
|                                 opt_password,
 | |
|                                 opt_db ? opt_db : "test",
 | |
|                                 opt_port,
 | |
|                                 opt_unix_socket,
 | |
|                                 CLIENT_FOUND_ROWS));
 | |
| 
 | |
|   /***********************************************************************
 | |
|     Check that lock is free:
 | |
|       - IS_FREE_LOCK() should return 1;
 | |
|       - IS_USED_LOCK() should return NULL;
 | |
|   ***********************************************************************/
 | |
| 
 | |
|   is_null= query_int_variable(&con,
 | |
|                               "IS_FREE_LOCK('bug31418')",
 | |
|                               &rc);
 | |
|   DIE_UNLESS(!is_null && rc);
 | |
| 
 | |
|   is_null= query_int_variable(&con,
 | |
|                               "IS_USED_LOCK('bug31418')",
 | |
|                               &rc);
 | |
|   DIE_UNLESS(is_null);
 | |
| 
 | |
|   /***********************************************************************
 | |
|     Acquire lock and check the lock status (the lock must be in use):
 | |
|       - IS_FREE_LOCK() should return 0;
 | |
|       - IS_USED_LOCK() should return non-zero thread id;
 | |
|   ***********************************************************************/
 | |
| 
 | |
|   query_int_variable(&con, "GET_LOCK('bug31418', 1)", &rc);
 | |
|   DIE_UNLESS(rc);
 | |
| 
 | |
|   is_null= query_int_variable(&con,
 | |
|                               "IS_FREE_LOCK('bug31418')",
 | |
|                               &rc);
 | |
|   DIE_UNLESS(!is_null && !rc);
 | |
| 
 | |
|   is_null= query_int_variable(&con,
 | |
|                               "IS_USED_LOCK('bug31418')",
 | |
|                               &rc);
 | |
|   DIE_UNLESS(!is_null && rc);
 | |
| 
 | |
|   /***********************************************************************
 | |
|     Issue COM_CHANGE_USER command and check the lock status
 | |
|     (the lock must be free):
 | |
|       - IS_FREE_LOCK() should return 1;
 | |
|       - IS_USED_LOCK() should return NULL;
 | |
|   **********************************************************************/
 | |
| 
 | |
|   bug20023_change_user(&con);
 | |
| 
 | |
|   is_null= query_int_variable(&con,
 | |
|                               "IS_FREE_LOCK('bug31418')",
 | |
|                               &rc);
 | |
|   DIE_UNLESS(!is_null && rc);
 | |
| 
 | |
|   is_null= query_int_variable(&con,
 | |
|                               "IS_USED_LOCK('bug31418')",
 | |
|                               &rc);
 | |
|   DIE_UNLESS(is_null);
 | |
| 
 | |
|   /***********************************************************************
 | |
|    That's it. Cleanup.
 | |
|   ***********************************************************************/
 | |
| 
 | |
|   mysql_close(&con);
 | |
| }
 | |
| 
 | |
| static void test_bug31418()
 | |
| {
 | |
|   /* Run test case for BUG#31418 for three different connections. */
 | |
| 
 | |
|   bug31418_impl();
 | |
| 
 | |
|   bug31418_impl();
 | |
| 
 | |
|   bug31418_impl();
 | |
| }
 | |
| 
 | |
| 
 | |
| 
 | |
| /**
 | |
|   Bug#31669 Buffer overflow in mysql_change_user()
 | |
| */
 | |
| 
 | |
| #define LARGE_BUFFER_SIZE 2048
 | |
| #define OLD_USERNAME_CHAR_LENGTH 16
 | |
| 
 | |
| static void test_bug31669()
 | |
| {
 | |
|   int rc;
 | |
|   static char buff[LARGE_BUFFER_SIZE+1];
 | |
| #ifndef EMBEDDED_LIBRARY
 | |
|   static char user[OLD_USERNAME_CHAR_LENGTH+1];
 | |
|   static char db[NAME_CHAR_LEN+1];
 | |
|   static char query[LARGE_BUFFER_SIZE*2];
 | |
| #endif
 | |
|   MYSQL* conn;
 | |
| 
 | |
|   DBUG_ENTER("test_bug31669");
 | |
|   myheader("test_bug31669");
 | |
| 
 | |
|   conn= client_connect(0, MYSQL_PROTOCOL_TCP, 0);
 | |
| 
 | |
|   rc= mysql_change_user(conn, NULL, NULL, NULL);
 | |
|   DIE_UNLESS(rc);
 | |
| 
 | |
|   rc= mysql_change_user(conn, "", "", "");
 | |
|   DIE_UNLESS(rc);
 | |
| 
 | |
|   memset(buff, 'a', sizeof(buff) -  1);
 | |
|   buff[sizeof(buff) -  1]= 0;
 | |
| 
 | |
|   mysql_close(conn);
 | |
|   conn= client_connect(0, MYSQL_PROTOCOL_TCP, 0);
 | |
| 
 | |
|   rc= mysql_change_user(conn, buff, buff, buff);
 | |
|   DIE_UNLESS(rc);
 | |
| 
 | |
|   rc = mysql_change_user(conn, opt_user, opt_password, current_db);
 | |
|   DIE_UNLESS(!rc);
 | |
| 
 | |
| #ifndef EMBEDDED_LIBRARY
 | |
|   memset(db, 'a', sizeof(db));
 | |
|   db[NAME_CHAR_LEN]= 0;
 | |
|   strxmov(query, "CREATE DATABASE IF NOT EXISTS ", db, NullS);
 | |
|   rc= mysql_query(conn, query);
 | |
|   myquery(rc);
 | |
| 
 | |
|   memset(user, 'b', sizeof(user));
 | |
|   user[OLD_USERNAME_CHAR_LENGTH]= 0;
 | |
|   memset(buff, 'c', sizeof(buff));
 | |
|   buff[LARGE_BUFFER_SIZE]= 0;
 | |
|   strxmov(query, "GRANT ALL PRIVILEGES ON *.* TO '", user, "'@'%' IDENTIFIED BY "
 | |
|                  "'", buff, "' WITH GRANT OPTION", NullS);
 | |
|   rc= mysql_query(conn, query);
 | |
|   myquery(rc);
 | |
| 
 | |
|   strxmov(query, "GRANT ALL PRIVILEGES ON *.* TO '", user, "'@'localhost' IDENTIFIED BY "
 | |
|                  "'", buff, "' WITH GRANT OPTION", NullS);
 | |
|   rc= mysql_query(conn, query);
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(conn, "FLUSH PRIVILEGES");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_change_user(conn, user, buff, db);
 | |
|   DIE_UNLESS(!rc);
 | |
| 
 | |
|   user[OLD_USERNAME_CHAR_LENGTH-1]= 'a';
 | |
|   rc= mysql_change_user(conn, user, buff, db);
 | |
|   DIE_UNLESS(rc);
 | |
| 
 | |
|   user[OLD_USERNAME_CHAR_LENGTH-1]= 'b';
 | |
|   buff[LARGE_BUFFER_SIZE-1]= 'd';
 | |
|   rc= mysql_change_user(conn, user, buff, db);
 | |
|   DIE_UNLESS(rc);
 | |
| 
 | |
|   buff[LARGE_BUFFER_SIZE-1]= 'c';
 | |
|   db[NAME_CHAR_LEN-1]= 'e';
 | |
|   rc= mysql_change_user(conn, user, buff, db);
 | |
|   DIE_UNLESS(rc);
 | |
| 
 | |
|   mysql_close(conn);
 | |
|   conn= client_connect(0, MYSQL_PROTOCOL_TCP, 0);
 | |
| 
 | |
|   db[NAME_CHAR_LEN-1]= 'a';
 | |
|   rc= mysql_change_user(conn, user, buff, db);
 | |
|   DIE_UNLESS(!rc);
 | |
| 
 | |
|   rc= mysql_change_user(conn, user + 1, buff + 1, db + 1);
 | |
|   DIE_UNLESS(rc);
 | |
| 
 | |
|   rc = mysql_change_user(conn, opt_user, opt_password, current_db);
 | |
|   DIE_UNLESS(!rc);
 | |
| 
 | |
|   strxmov(query, "DROP DATABASE ", db, NullS);
 | |
|   rc= mysql_query(conn, query);
 | |
|   myquery(rc);
 | |
| 
 | |
|   strxmov(query, "DELETE FROM mysql.user WHERE User='", user, "'", NullS);
 | |
|   rc= mysql_query(conn, query);
 | |
|   myquery(rc);
 | |
|   DIE_UNLESS(mysql_affected_rows(conn) == 2);
 | |
| #endif
 | |
| 
 | |
|   mysql_close(conn);
 | |
| 
 | |
|   DBUG_VOID_RETURN;
 | |
| }
 | |
| 
 | |
| 
 | |
| /**
 | |
|   Bug#28386 the general log is incomplete
 | |
| */
 | |
| 
 | |
| static void test_bug28386()
 | |
| {
 | |
|   int rc;
 | |
|   MYSQL_STMT *stmt;
 | |
|   MYSQL_RES *result;
 | |
|   MYSQL_ROW row;
 | |
|   MYSQL_BIND bind;
 | |
|   const char hello[]= "hello world!";
 | |
| 
 | |
|   DBUG_ENTER("test_bug28386");
 | |
|   myheader("test_bug28386");
 | |
| 
 | |
|   rc= mysql_query(mysql, "select @@global.log_output");
 | |
|   myquery(rc);
 | |
| 
 | |
|   result= mysql_store_result(mysql);
 | |
|   DIE_UNLESS(result);
 | |
| 
 | |
|   row= mysql_fetch_row(result);
 | |
|   if (! strstr(row[0], "TABLE"))
 | |
|   {
 | |
|     mysql_free_result(result);
 | |
|     if (! opt_silent)
 | |
|       printf("Skipping the test since logging to tables is not enabled\n");
 | |
|     /* Log output is not to tables */
 | |
|     DBUG_VOID_RETURN;
 | |
|   }
 | |
|   mysql_free_result(result);
 | |
| 
 | |
|   enable_query_logs(1);
 | |
| 
 | |
|   stmt= mysql_simple_prepare(mysql, "SELECT ?");
 | |
|   check_stmt(stmt);
 | |
| 
 | |
|   memset(&bind, 0, sizeof(bind));
 | |
| 
 | |
|   bind.buffer_type= MYSQL_TYPE_STRING;
 | |
|   bind.buffer= (void *) hello;
 | |
|   bind.buffer_length= sizeof(hello);
 | |
| 
 | |
|   mysql_stmt_bind_param(stmt, &bind);
 | |
|   mysql_stmt_send_long_data(stmt, 0, hello, sizeof(hello));
 | |
| 
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= my_process_stmt_result(stmt);
 | |
|   DIE_UNLESS(rc == 1);
 | |
| 
 | |
|   rc= mysql_stmt_reset(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= mysql_stmt_close(stmt);
 | |
|   DIE_UNLESS(!rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "select * from mysql.general_log where "
 | |
|                          "command_type='Close stmt' or "
 | |
|                          "command_type='Reset stmt' or "
 | |
|                          "command_type='Long Data'");
 | |
|   myquery(rc);
 | |
| 
 | |
|   result= mysql_store_result(mysql);
 | |
|   mytest(result);
 | |
| 
 | |
|   DIE_UNLESS(mysql_num_rows(result) == 3);
 | |
| 
 | |
|   mysql_free_result(result);
 | |
| 
 | |
|   restore_query_logs();
 | |
| 
 | |
|   DBUG_VOID_RETURN;
 | |
| }
 | |
| 
 | |
| 
 | |
| static void test_wl4166_1()
 | |
| {
 | |
|   MYSQL_STMT *stmt;
 | |
|   int        int_data;
 | |
|   char       str_data[50];
 | |
|   char       tiny_data;
 | |
|   short      small_data;
 | |
|   longlong   big_data;
 | |
|   float      real_data;
 | |
|   double     double_data;
 | |
|   ulong      length[7];
 | |
|   my_bool    is_null[7];
 | |
|   MYSQL_BIND my_bind[7];
 | |
|   int rc;
 | |
|   int i;
 | |
| 
 | |
|   myheader("test_wl4166_1");
 | |
| 
 | |
|   rc= mysql_query(mysql, "DROP TABLE IF EXISTS table_4166");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "CREATE TABLE table_4166(col1 tinyint NOT NULL, "
 | |
|                          "col2 varchar(15), col3 int, "
 | |
|                          "col4 smallint, col5 bigint, "
 | |
|                          "col6 float, col7 double, "
 | |
|                          "colX varchar(10) default NULL)");
 | |
|   myquery(rc);
 | |
| 
 | |
|   stmt= mysql_simple_prepare(mysql,
 | |
|     "INSERT INTO table_4166(col1, col2, col3, col4, col5, col6, col7) "
 | |
|     "VALUES(?, ?, ?, ?, ?, ?, ?)");
 | |
|   check_stmt(stmt);
 | |
| 
 | |
|   verify_param_count(stmt, 7);
 | |
| 
 | |
|   bzero(my_bind, sizeof(my_bind));
 | |
|   /* tinyint */
 | |
|   my_bind[0].buffer_type= MYSQL_TYPE_TINY;
 | |
|   my_bind[0].buffer= (void *)&tiny_data;
 | |
|   /* string */
 | |
|   my_bind[1].buffer_type= MYSQL_TYPE_STRING;
 | |
|   my_bind[1].buffer= (void *)str_data;
 | |
|   my_bind[1].buffer_length= 1000;                  /* Max string length */
 | |
|   /* integer */
 | |
|   my_bind[2].buffer_type= MYSQL_TYPE_LONG;
 | |
|   my_bind[2].buffer= (void *)&int_data;
 | |
|   /* short */
 | |
|   my_bind[3].buffer_type= MYSQL_TYPE_SHORT;
 | |
|   my_bind[3].buffer= (void *)&small_data;
 | |
|   /* bigint */
 | |
|   my_bind[4].buffer_type= MYSQL_TYPE_LONGLONG;
 | |
|   my_bind[4].buffer= (void *)&big_data;
 | |
|   /* float */
 | |
|   my_bind[5].buffer_type= MYSQL_TYPE_FLOAT;
 | |
|   my_bind[5].buffer= (void *)&real_data;
 | |
|   /* double */
 | |
|   my_bind[6].buffer_type= MYSQL_TYPE_DOUBLE;
 | |
|   my_bind[6].buffer= (void *)&double_data;
 | |
| 
 | |
|   for (i= 0; i < (int) array_elements(my_bind); i++)
 | |
|   {
 | |
|     my_bind[i].length= &length[i];
 | |
|     my_bind[i].is_null= &is_null[i];
 | |
|     is_null[i]= 0;
 | |
|   }
 | |
| 
 | |
|   rc= mysql_stmt_bind_param(stmt, my_bind);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   int_data= 320;
 | |
|   small_data= 1867;
 | |
|   big_data= 1000;
 | |
|   real_data= 2;
 | |
|   double_data= 6578.001;
 | |
| 
 | |
|   /* now, execute the prepared statement to insert 10 records.. */
 | |
|   for (tiny_data= 0; tiny_data < 10; tiny_data++)
 | |
|   {
 | |
|     length[1]= sprintf(str_data, "MySQL%d", int_data);
 | |
|     rc= mysql_stmt_execute(stmt);
 | |
|     check_execute(stmt, rc);
 | |
|     int_data += 25;
 | |
|     small_data += 10;
 | |
|     big_data += 100;
 | |
|     real_data += 1;
 | |
|     double_data += 10.09;
 | |
|   }
 | |
| 
 | |
|   /* force a re-prepare with some DDL */
 | |
| 
 | |
|   rc= mysql_query(mysql,
 | |
|     "ALTER TABLE table_4166 change colX colX varchar(20) default NULL");
 | |
|   myquery(rc);
 | |
| 
 | |
|   /*
 | |
|     execute the prepared statement again,
 | |
|     without changing the types of parameters already bound.
 | |
|   */
 | |
| 
 | |
|   for (tiny_data= 50; tiny_data < 60; tiny_data++)
 | |
|   {
 | |
|     length[1]= sprintf(str_data, "MySQL%d", int_data);
 | |
|     rc= mysql_stmt_execute(stmt);
 | |
|     check_execute(stmt, rc);
 | |
|     int_data += 25;
 | |
|     small_data += 10;
 | |
|     big_data += 100;
 | |
|     real_data += 1;
 | |
|     double_data += 10.09;
 | |
|   }
 | |
| 
 | |
|   mysql_stmt_close(stmt);
 | |
| 
 | |
|   rc= mysql_query(mysql, "DROP TABLE table_4166");
 | |
|   myquery(rc);
 | |
| }
 | |
| 
 | |
| 
 | |
| static void test_wl4166_2()
 | |
| {
 | |
|   MYSQL_STMT *stmt;
 | |
|   int        c_int;
 | |
|   MYSQL_TIME d_date;
 | |
|   MYSQL_BIND bind_out[2];
 | |
|   int rc;
 | |
| 
 | |
|   myheader("test_wl4166_2");
 | |
| 
 | |
|   rc= mysql_query(mysql, "SET SQL_MODE=''");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "drop table if exists t1");
 | |
|   myquery(rc);
 | |
|   rc= mysql_query(mysql, "create table t1 (c_int int, d_date date)");
 | |
|   myquery(rc);
 | |
|   rc= mysql_query(mysql,
 | |
|                   "insert into t1 (c_int, d_date) values (42, '1948-05-15')");
 | |
|   myquery(rc);
 | |
| 
 | |
|   stmt= mysql_simple_prepare(mysql, "select * from t1");
 | |
|   check_stmt(stmt);
 | |
| 
 | |
|   bzero(bind_out, sizeof(bind_out));
 | |
|   bind_out[0].buffer_type= MYSQL_TYPE_LONG;
 | |
|   bind_out[0].buffer= (void*) &c_int;
 | |
| 
 | |
|   bind_out[1].buffer_type= MYSQL_TYPE_DATE;
 | |
|   bind_out[1].buffer= (void*) &d_date;
 | |
| 
 | |
|   rc= mysql_stmt_bind_result(stmt, bind_out);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   /* int -> varchar transition */
 | |
| 
 | |
|   rc= mysql_query(mysql,
 | |
|                   "alter table t1 change column c_int c_int varchar(11)");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= mysql_stmt_fetch(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   DIE_UNLESS(c_int == 42);
 | |
|   DIE_UNLESS(d_date.year == 1948);
 | |
|   DIE_UNLESS(d_date.month == 5);
 | |
|   DIE_UNLESS(d_date.day == 15);
 | |
| 
 | |
|   rc= mysql_stmt_fetch(stmt);
 | |
|   DIE_UNLESS(rc == MYSQL_NO_DATA);
 | |
| 
 | |
|   /* varchar to int retrieval with truncation */
 | |
| 
 | |
|   rc= mysql_query(mysql, "update t1 set c_int='abcde'");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= mysql_stmt_fetch(stmt);
 | |
|   check_execute_r(stmt, rc);
 | |
| 
 | |
|   DIE_UNLESS(c_int == 0);
 | |
| 
 | |
|   rc= mysql_stmt_fetch(stmt);
 | |
|   DIE_UNLESS(rc == MYSQL_NO_DATA);
 | |
| 
 | |
|   /* alter table and increase the number of columns */
 | |
|   rc= mysql_query(mysql, "alter table t1 add column d_int int");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute_r(stmt, rc);
 | |
| 
 | |
|   rc= mysql_stmt_reset(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   /* decrease the number of columns */
 | |
|   rc= mysql_query(mysql, "alter table t1 drop d_date, drop d_int");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute_r(stmt, rc);
 | |
| 
 | |
|   mysql_stmt_close(stmt);
 | |
|   rc= mysql_query(mysql, "drop table t1");
 | |
|   myquery(rc);
 | |
| }
 | |
| 
 | |
| 
 | |
| /**
 | |
|   Test how warnings generated during assignment of parameters
 | |
|   are (currently not) preserve in case of reprepare.
 | |
| */
 | |
| 
 | |
| static void test_wl4166_3()
 | |
| {
 | |
|   int rc;
 | |
|   MYSQL_STMT *stmt;
 | |
|   MYSQL_BIND my_bind[1];
 | |
|   MYSQL_TIME tm[1];
 | |
| 
 | |
|   myheader("test_wl4166_3");
 | |
| 
 | |
|   rc= mysql_query(mysql, "drop table if exists t1");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "create table t1 (year datetime)");
 | |
|   myquery(rc);
 | |
| 
 | |
|   stmt= mysql_simple_prepare(mysql, "insert into t1 (year) values (?)");
 | |
|   check_stmt(stmt);
 | |
|   verify_param_count(stmt, 1);
 | |
| 
 | |
|   bzero((char*) my_bind, sizeof(my_bind));
 | |
|   my_bind[0].buffer_type= MYSQL_TYPE_DATETIME;
 | |
|   my_bind[0].buffer= &tm[0];
 | |
| 
 | |
|   rc= mysql_stmt_bind_param(stmt, my_bind);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   tm[0].year= 10000;
 | |
|   tm[0].month= 1; tm[0].day= 1;
 | |
|   tm[0].hour= 1; tm[0].minute= 1; tm[0].second= 1;
 | |
|   tm[0].second_part= 0; tm[0].neg= 0;
 | |
| 
 | |
|   /* Cause a statement reprepare */
 | |
|   rc= mysql_query(mysql, "alter table t1 add column c int");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
|   /*
 | |
|     The warning about data truncation when assigning a parameter is lost.
 | |
|     This is a bug.
 | |
|   */
 | |
|   my_process_warnings(mysql, 0);
 | |
| 
 | |
|   verify_col_data("t1", "year", "0000-00-00 00:00:00");
 | |
| 
 | |
|   mysql_stmt_close(stmt);
 | |
| 
 | |
|   rc= mysql_query(mysql, "drop table t1");
 | |
|   myquery(rc);
 | |
| }
 | |
| 
 | |
| 
 | |
| /**
 | |
|   Test that long data parameters, as well as parameters
 | |
|   that were originally in a different character set, are
 | |
|   preserved in case of reprepare.
 | |
| */
 | |
| 
 | |
| static void test_wl4166_4()
 | |
| {
 | |
|   MYSQL_STMT *stmt;
 | |
|   int rc;
 | |
|   const char *stmt_text;
 | |
|   MYSQL_BIND bind_array[2];
 | |
| 
 | |
|   /* Represented as numbers to keep UTF8 tools from clobbering them. */
 | |
|   const char *koi8= "\xee\xd5\x2c\x20\xda\xc1\x20\xd2\xd9\xc2\xc1\xcc\xcb\xd5";
 | |
|   const char *cp1251= "\xcd\xf3\x2c\x20\xe7\xe0\x20\xf0\xfb\xe1\xe0\xeb\xea\xf3";
 | |
|   char buf1[16], buf2[16];
 | |
|   ulong buf1_len, buf2_len;
 | |
| 
 | |
|   myheader("test_wl4166_4");
 | |
| 
 | |
|   rc= mysql_query(mysql, "drop table if exists t1");
 | |
|   myquery(rc);
 | |
| 
 | |
|   /*
 | |
|     Create table with binary columns, set session character set to cp1251,
 | |
|     client character set to koi8, and make sure that there is conversion
 | |
|     on insert and no conversion on select
 | |
|   */
 | |
|   rc= mysql_query(mysql,
 | |
|                   "create table t1 (c1 varbinary(255), c2 varbinary(255))");
 | |
|   myquery(rc);
 | |
|   rc= mysql_query(mysql, "set character_set_client=koi8r, "
 | |
|                          "character_set_connection=cp1251, "
 | |
|                          "character_set_results=koi8r");
 | |
|   myquery(rc);
 | |
| 
 | |
|   bzero((char*) bind_array, sizeof(bind_array));
 | |
| 
 | |
|   bind_array[0].buffer_type= MYSQL_TYPE_STRING;
 | |
| 
 | |
|   bind_array[1].buffer_type= MYSQL_TYPE_STRING;
 | |
|   bind_array[1].buffer= (void *) koi8;
 | |
|   bind_array[1].buffer_length= strlen(koi8);
 | |
| 
 | |
|   stmt= mysql_stmt_init(mysql);
 | |
|   check_stmt(stmt);
 | |
| 
 | |
|   stmt_text= "insert into t1 (c1, c2) values (?, ?)";
 | |
| 
 | |
|   rc= mysql_stmt_prepare(stmt, stmt_text, strlen(stmt_text));
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   mysql_stmt_bind_param(stmt, bind_array);
 | |
| 
 | |
|   mysql_stmt_send_long_data(stmt, 0, koi8, strlen(koi8));
 | |
| 
 | |
|   /* Cause a reprepare at statement execute */
 | |
|   rc= mysql_query(mysql, "alter table t1 add column d int");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   stmt_text= "select c1, c2 from t1";
 | |
| 
 | |
|   /* c1 and c2 are binary so no conversion will be done on select */
 | |
|   rc= mysql_stmt_prepare(stmt, stmt_text, strlen(stmt_text));
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   bind_array[0].buffer= buf1;
 | |
|   bind_array[0].buffer_length= sizeof(buf1);
 | |
|   bind_array[0].length= &buf1_len;
 | |
| 
 | |
|   bind_array[1].buffer= buf2;
 | |
|   bind_array[1].buffer_length= sizeof(buf2);
 | |
|   bind_array[1].length= &buf2_len;
 | |
| 
 | |
|   mysql_stmt_bind_result(stmt, bind_array);
 | |
| 
 | |
|   rc= mysql_stmt_fetch(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   DIE_UNLESS(buf1_len == strlen(cp1251));
 | |
|   DIE_UNLESS(buf2_len == strlen(cp1251));
 | |
|   DIE_UNLESS(!memcmp(buf1, cp1251, buf1_len));
 | |
|   DIE_UNLESS(!memcmp(buf2, cp1251, buf1_len));
 | |
| 
 | |
|   rc= mysql_stmt_fetch(stmt);
 | |
|   DIE_UNLESS(rc == MYSQL_NO_DATA);
 | |
| 
 | |
|   mysql_stmt_close(stmt);
 | |
| 
 | |
|   rc= mysql_query(mysql, "drop table t1");
 | |
|   myquery(rc);
 | |
|   rc= mysql_query(mysql, "set names default");
 | |
|   myquery(rc);
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Bug#36004 mysql_stmt_prepare resets the list of warnings
 | |
| */
 | |
| 
 | |
| static void test_bug36004()
 | |
| {
 | |
|   int rc, warning_count= 0;
 | |
|   MYSQL_STMT *stmt;
 | |
| 
 | |
|   DBUG_ENTER("test_bug36004");
 | |
|   myheader("test_bug36004");
 | |
| 
 | |
|   rc= mysql_query(mysql, "drop table if exists inexistant");
 | |
|   myquery(rc);
 | |
| 
 | |
|   DIE_UNLESS(mysql_warning_count(mysql) == 1);
 | |
|   query_int_variable(mysql, "@@warning_count", &warning_count);
 | |
|   DIE_UNLESS(warning_count);
 | |
| 
 | |
|   stmt= mysql_simple_prepare(mysql, "select 1");
 | |
|   check_stmt(stmt);
 | |
| 
 | |
|   DIE_UNLESS(mysql_warning_count(mysql) == 0);
 | |
|   query_int_variable(mysql, "@@warning_count", &warning_count);
 | |
|   DIE_UNLESS(warning_count);
 | |
| 
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   DIE_UNLESS(mysql_warning_count(mysql) == 0);
 | |
|   mysql_stmt_close(stmt);
 | |
| 
 | |
|   query_int_variable(mysql, "@@warning_count", &warning_count);
 | |
|   DIE_UNLESS(warning_count);
 | |
| 
 | |
|   stmt= mysql_simple_prepare(mysql, "drop table if exists inexistant");
 | |
|   check_stmt(stmt);
 | |
| 
 | |
|   query_int_variable(mysql, "@@warning_count", &warning_count);
 | |
|   DIE_UNLESS(warning_count == 0);
 | |
|   mysql_stmt_close(stmt);
 | |
| 
 | |
|   DBUG_VOID_RETURN;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Test that COM_REFRESH issues a implicit commit.
 | |
| */
 | |
| 
 | |
| static void test_wl4284_1()
 | |
| {
 | |
|   int rc;
 | |
|   MYSQL_ROW row;
 | |
|   MYSQL_RES *result;
 | |
| 
 | |
|   DBUG_ENTER("test_wl4284_1");
 | |
|   myheader("test_wl4284_1");
 | |
| 
 | |
|   /* set AUTOCOMMIT to OFF */
 | |
|   rc= mysql_autocommit(mysql, FALSE);
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "DROP TABLE IF EXISTS trans");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "CREATE TABLE trans (a INT) ENGINE= InnoDB");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "INSERT INTO trans VALUES(1)");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_refresh(mysql, REFRESH_GRANT | REFRESH_TABLES);
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_rollback(mysql);
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "SELECT * FROM trans");
 | |
|   myquery(rc);
 | |
| 
 | |
|   result= mysql_use_result(mysql);
 | |
|   mytest(result);
 | |
| 
 | |
|   row= mysql_fetch_row(result);
 | |
|   mytest(row);
 | |
| 
 | |
|   mysql_free_result(result);
 | |
| 
 | |
|   /* set AUTOCOMMIT to ON */
 | |
|   rc= mysql_autocommit(mysql, TRUE);
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "DROP TABLE trans");
 | |
|   myquery(rc);
 | |
| 
 | |
|   DBUG_VOID_RETURN;
 | |
| }
 | |
| 
 | |
| 
 | |
| static void test_bug38486(void)
 | |
| {
 | |
|   MYSQL_STMT *stmt;
 | |
|   const char *stmt_text;
 | |
|   unsigned long type= CURSOR_TYPE_READ_ONLY;
 | |
| 
 | |
|   DBUG_ENTER("test_bug38486");
 | |
|   myheader("test_bug38486");
 | |
| 
 | |
|   stmt= mysql_stmt_init(mysql);
 | |
|   mysql_stmt_attr_set(stmt, STMT_ATTR_CURSOR_TYPE, (void*)&type);
 | |
|   stmt_text= "CREATE TABLE t1 (a INT)";
 | |
|   mysql_stmt_prepare(stmt, stmt_text, strlen(stmt_text));
 | |
|   mysql_stmt_execute(stmt);
 | |
|   mysql_stmt_close(stmt);
 | |
| 
 | |
|   stmt= mysql_stmt_init(mysql);
 | |
|   mysql_stmt_attr_set(stmt, STMT_ATTR_CURSOR_TYPE, (void*)&type);
 | |
|   stmt_text= "INSERT INTO t1 VALUES (1)";
 | |
|   mysql_stmt_prepare(stmt, stmt_text, strlen(stmt_text));
 | |
|   mysql_stmt_execute(stmt);
 | |
|   mysql_stmt_close(stmt);
 | |
| 
 | |
|   DBUG_VOID_RETURN;
 | |
| }
 | |
| 
 | |
| 
 | |
| /**
 | |
|      Bug# 33831 mysql_real_connect() should fail if
 | |
|      given an already connected MYSQL handle.
 | |
| */
 | |
| 
 | |
| static void test_bug33831(void)
 | |
| {
 | |
|   MYSQL *l_mysql;
 | |
| 
 | |
|   DBUG_ENTER("test_bug33831");
 | |
| 
 | |
|   if (!(l_mysql= mysql_client_init(NULL)))
 | |
|   {
 | |
|     myerror("mysql_client_init() failed");
 | |
|     DIE_UNLESS(0);
 | |
|   }
 | |
|   if (!(mysql_real_connect(l_mysql, opt_host, opt_user,
 | |
|                            opt_password, current_db, opt_port,
 | |
|                            opt_unix_socket, 0)))
 | |
|   {
 | |
|     myerror("connection failed");
 | |
|     DIE_UNLESS(0);
 | |
|   }
 | |
| 
 | |
|   if (mysql_real_connect(l_mysql, opt_host, opt_user,
 | |
|                          opt_password, current_db, opt_port,
 | |
|                          opt_unix_socket, 0))
 | |
|   {
 | |
|     myerror("connection should have failed");
 | |
|     DIE_UNLESS(0);
 | |
|   }
 | |
| 
 | |
|   mysql_close(l_mysql);
 | |
| 
 | |
|   DBUG_VOID_RETURN;
 | |
| }
 | |
| 
 | |
| 
 | |
| static void test_bug40365(void)
 | |
| {
 | |
|   uint         rc, i;
 | |
|   MYSQL_STMT   *stmt= 0;
 | |
|   MYSQL_BIND   my_bind[2];
 | |
|   my_bool      is_null[2]= {0};
 | |
|   MYSQL_TIME   tm[2];
 | |
| 
 | |
|   DBUG_ENTER("test_bug40365");
 | |
| 
 | |
|   rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1");
 | |
|   myquery(rc);
 | |
|   rc= mysql_query(mysql, "CREATE TABLE t1(c1 DATETIME, \
 | |
|                                           c2 DATE)");
 | |
|   myquery(rc);
 | |
| 
 | |
|   stmt= mysql_simple_prepare(mysql, "INSERT INTO t1 VALUES(?, ?)");
 | |
|   check_stmt(stmt);
 | |
|   verify_param_count(stmt, 2);
 | |
| 
 | |
|   bzero((char*) my_bind, sizeof(my_bind));
 | |
|   my_bind[0].buffer_type= MYSQL_TYPE_DATETIME;
 | |
|   my_bind[1].buffer_type= MYSQL_TYPE_DATE;
 | |
|   for (i= 0; i < (int) array_elements(my_bind); i++)
 | |
|   {
 | |
|     my_bind[i].buffer= (void *) &tm[i];
 | |
|     my_bind[i].is_null= &is_null[i];
 | |
|   }
 | |
| 
 | |
|   rc= mysql_stmt_bind_param(stmt, my_bind);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   for (i= 0; i < (int) array_elements(my_bind); i++)
 | |
|   {
 | |
|     tm[i].neg= 0;
 | |
|     tm[i].second_part= 0;
 | |
|     tm[i].year= 2009;
 | |
|     tm[i].month= 2;
 | |
|     tm[i].day= 29;
 | |
|     tm[i].hour= 0;
 | |
|     tm[i].minute= 0;
 | |
|     tm[i].second= 0;
 | |
|   }
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= mysql_commit(mysql);
 | |
|   myquery(rc);
 | |
|   mysql_stmt_close(stmt);
 | |
| 
 | |
|   stmt= mysql_simple_prepare(mysql, "SELECT * FROM t1");
 | |
|   check_stmt(stmt);
 | |
| 
 | |
|   rc= mysql_stmt_bind_result(stmt, my_bind);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= mysql_stmt_store_result(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= mysql_stmt_fetch(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   if (!opt_silent)
 | |
|     fprintf(stdout, "\n");
 | |
| 
 | |
|   for (i= 0; i < array_elements(my_bind); i++)
 | |
|   {
 | |
|     if (!opt_silent)
 | |
|       fprintf(stdout, "\ntime[%d]: %02d-%02d-%02d ",
 | |
|               i, tm[i].year, tm[i].month, tm[i].day);
 | |
|     DIE_UNLESS(tm[i].year == 0);
 | |
|     DIE_UNLESS(tm[i].month == 0);
 | |
|     DIE_UNLESS(tm[i].day == 0);
 | |
|   }
 | |
|   mysql_stmt_close(stmt);
 | |
|   rc= mysql_commit(mysql);
 | |
|   myquery(rc);
 | |
| 
 | |
|   DBUG_VOID_RETURN;
 | |
| }
 | |
| 
 | |
| 
 | |
| /**
 | |
|   Subtest for Bug#43560. Verifies that a loss of connection on the server side
 | |
|   is handled well by the mysql_stmt_execute() call, i.e., no SIGSEGV due to
 | |
|   a vio socket that is cleared upon closed connection.
 | |
| 
 | |
|   Assumes the presence of the close_conn_after_stmt_execute debug feature in
 | |
|   the server. Verifies that it is connected to a debug server before proceeding
 | |
|   with the test.
 | |
|  */
 | |
| static void test_bug43560(void)
 | |
| {
 | |
|   MYSQL*       conn;
 | |
|   uint         rc;
 | |
|   MYSQL_STMT   *stmt= 0;
 | |
|   MYSQL_BIND   bind;
 | |
|   my_bool      is_null= 0;
 | |
|   char         buffer[256];
 | |
|   const uint   BUFSIZE= sizeof(buffer);
 | |
|   const char*  values[] = {"eins", "zwei", "drei", "viele", NULL};
 | |
|   const char   insert_str[] = "INSERT INTO t1 (c2) VALUES (?)";
 | |
|   unsigned long length;
 | |
|   const unsigned int drop_db= opt_drop_db;
 | |
| 
 | |
|   DBUG_ENTER("test_bug43560");
 | |
|   myheader("test_bug43560");
 | |
| 
 | |
|   /* Make sure we only run against a debug server. */
 | |
|   if (!strstr(mysql->server_version, "debug"))
 | |
|   {
 | |
|     fprintf(stdout, "Skipping test_bug43560: server not DEBUG version\n");
 | |
|     DBUG_VOID_RETURN;
 | |
|   }
 | |
|   if (opt_unix_socket)
 | |
|   {
 | |
|     fprintf(stdout, "Skipping test_bug43560: connected via UNIX socket\n");
 | |
|     DBUG_VOID_RETURN;
 | |
|   }
 | |
|   /*
 | |
|     Set up a separate connection for this test to avoid messing up the
 | |
|     general MYSQL object used in other subtests. Use TCP protocol to avoid
 | |
|     problems with the buffer semantics of AF_UNIX, and turn off auto reconnect.
 | |
|   */
 | |
|   conn= client_connect(0, MYSQL_PROTOCOL_TCP, 0);
 | |
| 
 | |
|   rc= mysql_query(conn, "DROP TABLE IF EXISTS t1");
 | |
|   myquery(rc);
 | |
|   rc= mysql_query(conn,
 | |
|     "CREATE TABLE t1 (c1 INT PRIMARY KEY AUTO_INCREMENT, c2 CHAR(10))");
 | |
|   myquery(rc);
 | |
| 
 | |
|   stmt= mysql_stmt_init(conn);
 | |
|   check_stmt(stmt);
 | |
|   rc= mysql_stmt_prepare(stmt, insert_str, strlen(insert_str));
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   bind.buffer_type= MYSQL_TYPE_STRING;
 | |
|   bind.buffer_length= BUFSIZE;
 | |
|   bind.buffer= buffer;
 | |
|   bind.is_null= &is_null;
 | |
|   bind.length= &length;
 | |
|   rc= mysql_stmt_bind_param(stmt, &bind);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   /* First execute; should succeed. */
 | |
|   strncpy(buffer, values[0], BUFSIZE);
 | |
|   length= strlen(buffer);
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   /* 
 | |
|     Set up the server to close this session's server-side socket after
 | |
|     next execution of prep statement.
 | |
|   */
 | |
|   rc= mysql_query(conn,"SET SESSION debug='+d,close_conn_after_stmt_execute'");
 | |
|   myquery(rc);
 | |
| 
 | |
|   /* Second execute; should fail due to socket closed during execution. */
 | |
|   strncpy(buffer, values[1], BUFSIZE);
 | |
|   length= strlen(buffer);
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   DIE_UNLESS(rc && mysql_stmt_errno(stmt) == CR_SERVER_LOST);
 | |
| 
 | |
|   /* 
 | |
|     Third execute; should fail (connection already closed), or SIGSEGV in
 | |
|     case of a Bug#43560 type regression in which case the whole test fails.
 | |
|   */
 | |
|   strncpy(buffer, values[2], BUFSIZE);
 | |
|   length= strlen(buffer);
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   DIE_UNLESS(rc && (mysql_stmt_errno(stmt) == CR_SERVER_LOST ||
 | |
|                     mysql_stmt_errno(stmt) == CR_SERVER_GONE_ERROR));
 | |
| 
 | |
|   opt_drop_db= 0;
 | |
|   client_disconnect(conn);
 | |
|   rc= mysql_query(mysql, "DROP TABLE t1");
 | |
|   myquery(rc);
 | |
|   opt_drop_db= drop_db;
 | |
| 
 | |
|   DBUG_VOID_RETURN;
 | |
| }
 | |
| 
 | |
| 
 | |
| /**
 | |
|   Bug#36326: nested transaction and select
 | |
| */
 | |
| 
 | |
| static void test_bug36326()
 | |
| {
 | |
|   int rc;
 | |
| 
 | |
|   DBUG_ENTER("test_bug36326");
 | |
|   myheader("test_bug36326");
 | |
| 
 | |
|   if (! is_query_cache_available())
 | |
|   {
 | |
|     fprintf(stdout, "Skipping test_bug36326: Query cache not available.\n");
 | |
|     DBUG_VOID_RETURN;
 | |
|   }
 | |
| 
 | |
|   rc= mysql_autocommit(mysql, TRUE);
 | |
|   myquery(rc);
 | |
|   rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1");
 | |
|   myquery(rc);
 | |
|   rc= mysql_query(mysql, "CREATE  TABLE t1 (a INTEGER)");
 | |
|   myquery(rc);
 | |
|   rc= mysql_query(mysql, "INSERT INTO t1 VALUES (1)");
 | |
|   myquery(rc);
 | |
|   rc= mysql_query(mysql,
 | |
|                   "set @save_query_cache_type="
 | |
|                   "@@global.query_cache_type,"
 | |
|                   "@save_query_cache_size="
 | |
|                   "@@global.query_cache_size");
 | |
|   myquery(rc);
 | |
|   rc= mysql_query(mysql, "SET GLOBAL query_cache_type = 1");
 | |
|   myquery(rc);
 | |
|   rc= mysql_query(mysql, "SET LOCAL query_cache_type = 1");
 | |
|   myquery(rc);
 | |
|   rc= mysql_query(mysql, "SET GLOBAL query_cache_size = 1048576");
 | |
|   myquery(rc);
 | |
|   DIE_UNLESS(!(mysql->server_status & SERVER_STATUS_IN_TRANS));
 | |
|   DIE_UNLESS(mysql->server_status & SERVER_STATUS_AUTOCOMMIT);
 | |
|   rc= mysql_query(mysql, "BEGIN");
 | |
|   myquery(rc);
 | |
|   DIE_UNLESS(mysql->server_status & SERVER_STATUS_IN_TRANS);
 | |
|   rc= mysql_query(mysql, "SELECT * FROM t1");
 | |
|   myquery(rc);
 | |
|   rc= my_process_result(mysql);
 | |
|   DIE_UNLESS(rc == 1);
 | |
|   rc= mysql_rollback(mysql);
 | |
|   myquery(rc);
 | |
|   rc= mysql_query(mysql, "ROLLBACK");
 | |
|   myquery(rc);
 | |
|   DIE_UNLESS(!(mysql->server_status & SERVER_STATUS_IN_TRANS));
 | |
|   rc= mysql_query(mysql, "SELECT * FROM t1");
 | |
|   myquery(rc);
 | |
|   DIE_UNLESS(!(mysql->server_status & SERVER_STATUS_IN_TRANS));
 | |
|   rc= my_process_result(mysql);
 | |
|   DIE_UNLESS(rc == 1);
 | |
|   rc= mysql_query(mysql, "DROP TABLE t1");
 | |
|   myquery(rc);
 | |
|   rc= mysql_query(mysql, "SET GLOBAL query_cache_size = @save_query_cache_size");
 | |
|   rc= mysql_query(mysql, "SET GLOBAL query_cache_type = @save_query_cache_type");
 | |
|   myquery(rc);
 | |
| 
 | |
|   DBUG_VOID_RETURN;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Bug#41078: With CURSOR_TYPE_READ_ONLY mysql_stmt_fetch() returns short
 | |
|              string value.
 | |
| */
 | |
| 
 | |
| static void test_bug41078(void)
 | |
| {
 | |
|   uint         rc;
 | |
|   MYSQL_STMT   *stmt= 0;
 | |
|   MYSQL_BIND   param, result;
 | |
|   ulong        cursor_type= CURSOR_TYPE_READ_ONLY;
 | |
|   ulong        len;
 | |
|   char         str[64];
 | |
|   const char   param_str[]= "abcdefghijklmn";
 | |
|   my_bool      is_null, error;
 | |
| 
 | |
|   DBUG_ENTER("test_bug41078");
 | |
| 
 | |
|   rc= mysql_query(mysql, "SET NAMES UTF8");
 | |
|   myquery(rc);
 | |
| 
 | |
|   stmt= mysql_simple_prepare(mysql, "SELECT ?");
 | |
|   check_stmt(stmt);
 | |
|   verify_param_count(stmt, 1);
 | |
| 
 | |
|   rc= mysql_stmt_attr_set(stmt, STMT_ATTR_CURSOR_TYPE, &cursor_type);
 | |
|   check_execute(stmt, rc);
 | |
|   
 | |
|   bzero(¶m, sizeof(param));
 | |
|   param.buffer_type= MYSQL_TYPE_STRING;
 | |
|   param.buffer= (void *) param_str;
 | |
|   len= sizeof(param_str) - 1;
 | |
|   param.length= &len;
 | |
| 
 | |
|   rc= mysql_stmt_bind_param(stmt, ¶m);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   bzero(&result, sizeof(result));
 | |
|   result.buffer_type= MYSQL_TYPE_STRING;
 | |
|   result.buffer= str;
 | |
|   result.buffer_length= sizeof(str);
 | |
|   result.is_null= &is_null;
 | |
|   result.length= &len;
 | |
|   result.error=  &error;
 | |
|   
 | |
|   rc= mysql_stmt_bind_result(stmt, &result);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= mysql_stmt_store_result(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= mysql_stmt_fetch(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   DIE_UNLESS(len == sizeof(param_str) - 1 && !strcmp(str, param_str));
 | |
| 
 | |
|   mysql_stmt_close(stmt);
 | |
| 
 | |
|   DBUG_VOID_RETURN;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Bug#45010: invalid memory reads during parsing some strange statements
 | |
| */
 | |
| static void test_bug45010()
 | |
| {
 | |
|   int rc;
 | |
|   const char query1[]= "select a.\x80",
 | |
|              query2[]= "describe `table\xef";
 | |
| 
 | |
|   DBUG_ENTER("test_bug45010");
 | |
|   myheader("test_bug45010");
 | |
| 
 | |
|   rc= mysql_query(mysql, "set names utf8");
 | |
|   myquery(rc);
 | |
| 
 | |
|   /* \x80 (-128) could be used as a index of ident_map. */
 | |
|   rc= mysql_real_query(mysql, query1, sizeof(query1) - 1);
 | |
|   DIE_UNLESS(rc);
 | |
| 
 | |
|   /* \xef (-17) could be used to skip 3 bytes past the buffer end. */
 | |
|   rc= mysql_real_query(mysql, query2, sizeof(query2) - 1);
 | |
|   DIE_UNLESS(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "set names default");
 | |
|   myquery(rc);
 | |
| 
 | |
|   DBUG_VOID_RETURN;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Bug#44495: Prepared Statement:
 | |
|              CALL p(<x>) - `thd->protocol == &thd->protocol_text' failed
 | |
| */
 | |
| 
 | |
| static void test_bug44495()
 | |
| {
 | |
|   int rc;
 | |
|   MYSQL con;
 | |
|   MYSQL_STMT *stmt;
 | |
| 
 | |
|   DBUG_ENTER("test_bug44495");
 | |
|   myheader("test_44495");
 | |
| 
 | |
|   rc= mysql_query(mysql, "DROP PROCEDURE IF EXISTS p1");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "CREATE PROCEDURE p1(IN arg VARCHAR(25))"
 | |
|                          "  BEGIN SET @stmt = CONCAT('SELECT \"', arg, '\"');"
 | |
|                          "  PREPARE ps1 FROM @stmt;"
 | |
|                          "  EXECUTE ps1;"
 | |
|                          "  DROP PREPARE ps1;"
 | |
|                          "END;");
 | |
|   myquery(rc);
 | |
| 
 | |
|   DIE_UNLESS(mysql_client_init(&con));
 | |
| 
 | |
|   DIE_UNLESS(mysql_real_connect(&con, opt_host, opt_user, opt_password,
 | |
|                                 current_db, opt_port, opt_unix_socket,
 | |
|                                 CLIENT_MULTI_RESULTS));
 | |
| 
 | |
|   stmt= mysql_simple_prepare(&con, "CALL p1('abc')");
 | |
|   check_stmt(stmt);
 | |
| 
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= my_process_stmt_result(stmt);
 | |
|   DIE_UNLESS(rc == 1);
 | |
| 
 | |
|   mysql_stmt_close(stmt);
 | |
| 
 | |
|   mysql_close(&con);
 | |
| 
 | |
|   rc= mysql_query(mysql, "DROP PROCEDURE p1");
 | |
|   myquery(rc);
 | |
| 
 | |
|   DBUG_VOID_RETURN;
 | |
| }
 | |
| 
 | |
| static void test_bug53371()
 | |
| {
 | |
|   int rc;
 | |
|   MYSQL_RES *result;
 | |
| 
 | |
|   myheader("test_bug53371");
 | |
| 
 | |
|   rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1");
 | |
|   myquery(rc);
 | |
|   rc= mysql_query(mysql, "DROP DATABASE IF EXISTS bug53371");
 | |
|   myquery(rc);
 | |
|   rc= mysql_query(mysql, "DROP USER 'testbug'@localhost");
 | |
| 
 | |
|   rc= mysql_query(mysql, "CREATE TABLE t1 (a INT)");
 | |
|   myquery(rc);
 | |
|   rc= mysql_query(mysql, "CREATE DATABASE bug53371");
 | |
|   myquery(rc);
 | |
|   rc= mysql_query(mysql, "GRANT SELECT ON bug53371.* to 'testbug'@localhost");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_change_user(mysql, "testbug", NULL, "bug53371");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "SHOW COLUMNS FROM client_test_db.t1");
 | |
|   DIE_UNLESS(rc);
 | |
|   DIE_UNLESS(mysql_errno(mysql) == 1142);
 | |
| 
 | |
|   result= mysql_list_fields(mysql, "../client_test_db/t1", NULL);
 | |
|   DIE_IF(result);
 | |
| 
 | |
|   result= mysql_list_fields(mysql, "#mysql50#/../client_test_db/t1", NULL);
 | |
|   DIE_IF(result);
 | |
| 
 | |
|   rc= mysql_change_user(mysql, opt_user, opt_password, current_db);
 | |
|   myquery(rc);
 | |
|   rc= mysql_query(mysql, "DROP TABLE t1");
 | |
|   myquery(rc);
 | |
|   rc= mysql_query(mysql, "DROP DATABASE bug53371");
 | |
|   myquery(rc);
 | |
|   rc= mysql_query(mysql, "DROP USER 'testbug'@localhost");
 | |
|   myquery(rc);
 | |
| }
 | |
| 
 | |
| 
 | |
| 
 | |
| /**
 | |
|   Bug#42373: libmysql can mess a connection at connect
 | |
| */
 | |
| static void test_bug42373()
 | |
| {
 | |
|   int rc;
 | |
|   MYSQL con;
 | |
|   MYSQL_STMT *stmt;
 | |
| 
 | |
|   DBUG_ENTER("test_bug42373");
 | |
|   myheader("test_42373");
 | |
| 
 | |
|   rc= mysql_query(mysql, "DROP PROCEDURE IF EXISTS p1");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "CREATE PROCEDURE p1()"
 | |
|                          "  BEGIN"
 | |
|                          "  SELECT 1;"
 | |
|                          "  INSERT INTO t1 VALUES (2);"
 | |
|                          "END;");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "CREATE TABLE t1 (a INT)");
 | |
|   myquery(rc);
 | |
| 
 | |
|   /* Try with a stored procedure. */
 | |
|   DIE_UNLESS(mysql_client_init(&con));
 | |
| 
 | |
|   mysql_options(&con, MYSQL_INIT_COMMAND, "CALL p1()");
 | |
| 
 | |
|   DIE_UNLESS(mysql_real_connect(&con, opt_host, opt_user, opt_password,
 | |
|                                 current_db, opt_port, opt_unix_socket,
 | |
|                                 CLIENT_MULTI_STATEMENTS|CLIENT_MULTI_RESULTS));
 | |
| 
 | |
|   stmt= mysql_simple_prepare(&con, "SELECT a FROM t1");
 | |
|   check_stmt(stmt);
 | |
| 
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= my_process_stmt_result(stmt);
 | |
|   DIE_UNLESS(rc == 1);
 | |
| 
 | |
|   mysql_stmt_close(stmt);
 | |
|   mysql_close(&con);
 | |
| 
 | |
|   /* Now try with a multi-statement. */
 | |
|   DIE_UNLESS(mysql_client_init(&con));
 | |
| 
 | |
|   mysql_options(&con, MYSQL_INIT_COMMAND,
 | |
|                 "SELECT 3; INSERT INTO t1 VALUES (4)");
 | |
| 
 | |
|   DIE_UNLESS(mysql_real_connect(&con, opt_host, opt_user, opt_password,
 | |
|                                 current_db, opt_port, opt_unix_socket,
 | |
|                                 CLIENT_MULTI_STATEMENTS|CLIENT_MULTI_RESULTS));
 | |
| 
 | |
|   stmt= mysql_simple_prepare(&con, "SELECT a FROM t1");
 | |
|   check_stmt(stmt);
 | |
| 
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= my_process_stmt_result(stmt);
 | |
|   DIE_UNLESS(rc == 2);
 | |
| 
 | |
|   mysql_stmt_close(stmt);
 | |
|   mysql_close(&con);
 | |
| 
 | |
|   rc= mysql_query(mysql, "DROP TABLE t1");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "DROP PROCEDURE p1");
 | |
|   myquery(rc);
 | |
| 
 | |
|   DBUG_VOID_RETURN;
 | |
| }
 | |
| 
 | |
| 
 | |
| /**
 | |
|   Bug#54041: MySQL 5.0.92 fails when tests from Connector/C suite run
 | |
| */
 | |
| 
 | |
| static void test_bug54041_impl()
 | |
| {
 | |
|   int rc;
 | |
|   MYSQL_STMT *stmt;
 | |
|   MYSQL_BIND bind;
 | |
| 
 | |
|   DBUG_ENTER("test_bug54041");
 | |
|   myheader("test_bug54041");
 | |
| 
 | |
|   rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "CREATE TABLE t1 (a INT)");
 | |
|   myquery(rc);
 | |
| 
 | |
|   stmt= mysql_simple_prepare(mysql, "SELECT a FROM t1 WHERE a > ?");
 | |
|   check_stmt(stmt);
 | |
|   verify_param_count(stmt, 1);
 | |
| 
 | |
|   memset(&bind, 0, sizeof(bind));
 | |
| 
 | |
|   /* Any type that does not support long data handling. */
 | |
|   bind.buffer_type= MYSQL_TYPE_LONG;
 | |
| 
 | |
|   rc= mysql_stmt_bind_param(stmt, &bind);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   /*
 | |
|     Trick the client API into sending a long data packet for
 | |
|     the parameter. Long data is only supported for string and
 | |
|     binary types.
 | |
|   */
 | |
|   stmt->params[0].buffer_type= MYSQL_TYPE_STRING;
 | |
| 
 | |
|   rc= mysql_stmt_send_long_data(stmt, 0, "data", 5);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   /* Undo API violation. */
 | |
|   stmt->params[0].buffer_type= MYSQL_TYPE_LONG;
 | |
| 
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   /* Incorrect arguments. */
 | |
|   check_execute_r(stmt, rc);
 | |
| 
 | |
|   mysql_stmt_close(stmt);
 | |
| 
 | |
|   rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1");
 | |
|   myquery(rc);
 | |
| 
 | |
|   DBUG_VOID_RETURN;
 | |
| }
 | |
| 
 | |
| 
 | |
| /**
 | |
|   Bug#54041: MySQL 5.0.92 fails when tests from Connector/C suite run
 | |
| */
 | |
| 
 | |
| static void test_bug54041()
 | |
| {
 | |
|   enable_query_logs(0);
 | |
|   test_bug54041_impl();
 | |
|   disable_query_logs();
 | |
|   test_bug54041_impl();
 | |
|   restore_query_logs();
 | |
| }
 | |
| 
 | |
| 
 | |
| /**
 | |
|   Bug#47485: mysql_store_result returns a result set for a prepared statement
 | |
| */
 | |
| static void test_bug47485()
 | |
| {
 | |
|   MYSQL_STMT   *stmt;
 | |
|   MYSQL_RES    *res;
 | |
|   MYSQL_BIND    bind[2];
 | |
|   int           rc;
 | |
|   const char*   sql_select = "SELECT 1, 'a'";
 | |
|   int           int_data;
 | |
|   char          str_data[16];
 | |
|   my_bool       is_null[2];
 | |
|   my_bool       error[2];
 | |
|   unsigned long length[2];
 | |
| 
 | |
|   DBUG_ENTER("test_bug47485");
 | |
|   myheader("test_bug47485");
 | |
| 
 | |
|   stmt= mysql_stmt_init(mysql);
 | |
|   check_stmt(stmt);
 | |
|   rc= mysql_stmt_prepare(stmt, sql_select, strlen(sql_select));
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   res = mysql_store_result(mysql);
 | |
|   DIE_UNLESS(res == NULL);
 | |
| 
 | |
|   mysql_stmt_reset(stmt);
 | |
| 
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   res = mysql_use_result(mysql);
 | |
|   DIE_UNLESS(res == NULL);
 | |
| 
 | |
|   mysql_stmt_reset(stmt);
 | |
| 
 | |
|   memset(bind, 0, sizeof(bind));
 | |
|   bind[0].buffer_type= MYSQL_TYPE_LONG;
 | |
|   bind[0].buffer= (char *)&int_data;
 | |
|   bind[0].is_null= &is_null[0];
 | |
|   bind[0].length= &length[0];
 | |
|   bind[0].error= &error[0];
 | |
| 
 | |
|   bind[1].buffer_type= MYSQL_TYPE_STRING;
 | |
|   bind[1].buffer= (char *)str_data;
 | |
|   bind[1].buffer_length= sizeof(str_data);
 | |
|   bind[1].is_null= &is_null[1];
 | |
|   bind[1].length= &length[1];
 | |
|   bind[1].error= &error[1];
 | |
| 
 | |
|   rc= mysql_stmt_bind_result(stmt, bind);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= mysql_stmt_store_result(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   while (!(rc= mysql_stmt_fetch(stmt)))
 | |
|     ;
 | |
| 
 | |
|   DIE_UNLESS(rc == MYSQL_NO_DATA);
 | |
| 
 | |
|   mysql_stmt_reset(stmt);
 | |
| 
 | |
|   memset(bind, 0, sizeof(bind));
 | |
|   bind[0].buffer_type= MYSQL_TYPE_LONG;
 | |
|   bind[0].buffer= (char *)&int_data;
 | |
|   bind[0].is_null= &is_null[0];
 | |
|   bind[0].length= &length[0];
 | |
|   bind[0].error= &error[0];
 | |
| 
 | |
|   bind[1].buffer_type= MYSQL_TYPE_STRING;
 | |
|   bind[1].buffer= (char *)str_data;
 | |
|   bind[1].buffer_length= sizeof(str_data);
 | |
|   bind[1].is_null= &is_null[1];
 | |
|   bind[1].length= &length[1];
 | |
|   bind[1].error= &error[1];
 | |
| 
 | |
|   rc= mysql_stmt_bind_result(stmt, bind);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   while (!(rc= mysql_stmt_fetch(stmt)))
 | |
|     ;
 | |
| 
 | |
|   DIE_UNLESS(rc == MYSQL_NO_DATA);
 | |
| 
 | |
|   mysql_stmt_close(stmt);
 | |
| 
 | |
|   DBUG_VOID_RETURN;
 | |
| }
 | |
| 
 | |
| 
 | |
| /*
 | |
|   Bug#58036 client utf32, utf16, ucs2 should be disallowed, they crash server
 | |
| */
 | |
| static void test_bug58036()
 | |
| {
 | |
|   MYSQL *conn;
 | |
|   DBUG_ENTER("test_bug58036");
 | |
|   myheader("test_bug58036");
 | |
| 
 | |
|   /* Part1: try to connect with ucs2 client character set */
 | |
|   conn= mysql_client_init(NULL);
 | |
|   mysql_options(conn, MYSQL_SET_CHARSET_NAME, "ucs2");
 | |
| 
 | |
|   if (mysql_real_connect(conn, opt_host, opt_user,
 | |
|                          opt_password,  opt_db ? opt_db : "test",
 | |
|                          opt_port, opt_unix_socket, 0))
 | |
|   {
 | |
|     if (!opt_silent)
 | |
|       printf("mysql_real_connect() succeeded (failure expected)\n");
 | |
|     mysql_close(conn);
 | |
|     DIE("");
 | |
|   }
 | |
| 
 | |
|   if (!opt_silent)
 | |
|     printf("Got mysql_real_connect() error (expected): %s (%d)\n",
 | |
|            mysql_error(conn), mysql_errno(conn));  
 | |
|   DIE_UNLESS(mysql_errno(conn) == ER_WRONG_VALUE_FOR_VAR ||
 | |
|              mysql_errno(conn)== CR_CANT_READ_CHARSET);
 | |
|   mysql_close(conn);
 | |
| 
 | |
| 
 | |
|   /*
 | |
|     Part2:
 | |
|     - connect with latin1
 | |
|     - then change client character set to ucs2
 | |
|     - then try mysql_change_user()
 | |
|   */
 | |
|   conn= mysql_client_init(NULL);
 | |
|   mysql_options(conn, MYSQL_SET_CHARSET_NAME, "latin1");
 | |
|   if (!mysql_real_connect(conn, opt_host, opt_user,
 | |
|                          opt_password, opt_db ? opt_db : "test",
 | |
|                          opt_port, opt_unix_socket, 0))
 | |
|   {
 | |
|     if (!opt_silent)
 | |
|       printf("mysql_real_connect() failed: %s (%d)\n",
 | |
|              mysql_error(conn), mysql_errno(conn));
 | |
|     mysql_close(conn);
 | |
|     DIE("");
 | |
|   }
 | |
| 
 | |
|   mysql_options(conn, MYSQL_SET_CHARSET_NAME, "ucs2");
 | |
|   if (!mysql_change_user(conn, opt_user, opt_password, NULL))
 | |
|   {
 | |
|     if (!opt_silent)
 | |
|       printf("mysql_change_user() succeeded, error expected!");
 | |
|     mysql_close(conn);
 | |
|     DIE("");
 | |
|   }
 | |
| 
 | |
|   if (!opt_silent)
 | |
|     printf("Got mysql_change_user() error (expected): %s (%d)\n",
 | |
|            mysql_error(conn), mysql_errno(conn));
 | |
|   mysql_close(conn);
 | |
|   DBUG_VOID_RETURN;
 | |
| }
 | |
| 
 | |
| 
 | |
| /*
 | |
|   Bug#49972: Crash in prepared statements.
 | |
| 
 | |
|   The following case lead to a server crash:
 | |
|     - Use binary protocol;
 | |
|     - Prepare a statement with OUT-parameter;
 | |
|     - Execute the statement;
 | |
|     - Cause re-prepare of the statement (change dependencies);
 | |
|     - Execute the statement again -- crash here.
 | |
| */
 | |
| 
 | |
| static void test_bug49972()
 | |
| {
 | |
|   int rc;
 | |
|   MYSQL_STMT *stmt;
 | |
| 
 | |
|   MYSQL_BIND in_param_bind;
 | |
|   MYSQL_BIND out_param_bind;
 | |
|   int int_data;
 | |
|   my_bool is_null;
 | |
| 
 | |
|   DBUG_ENTER("test_bug49972");
 | |
|   myheader("test_bug49972");
 | |
| 
 | |
|   rc= mysql_query(mysql, "DROP FUNCTION IF EXISTS f1");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "DROP PROCEDURE IF EXISTS p1");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "CREATE FUNCTION f1() RETURNS INT RETURN 1");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "CREATE PROCEDURE p1(IN a INT, OUT b INT) SET b = a");
 | |
|   myquery(rc);
 | |
| 
 | |
|   stmt= mysql_simple_prepare(mysql, "CALL p1((SELECT f1()), ?)");
 | |
|   check_stmt(stmt);
 | |
| 
 | |
|   bzero((char *) &in_param_bind, sizeof (in_param_bind));
 | |
| 
 | |
|   in_param_bind.buffer_type= MYSQL_TYPE_LONG;
 | |
|   in_param_bind.buffer= (char *) &int_data;
 | |
|   int_data= 0;
 | |
|   in_param_bind.length= 0;
 | |
|   in_param_bind.is_null= 0;
 | |
| 
 | |
|   rc= mysql_stmt_bind_param(stmt, &in_param_bind);
 | |
| 
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   {
 | |
|     bzero(&out_param_bind, sizeof (out_param_bind));
 | |
| 
 | |
|     out_param_bind.buffer_type= MYSQL_TYPE_LONG;
 | |
|     out_param_bind.is_null= &is_null;
 | |
|     out_param_bind.buffer= &int_data;
 | |
|     out_param_bind.buffer_length= sizeof (int_data);
 | |
| 
 | |
|     rc= mysql_stmt_bind_result(stmt, &out_param_bind);
 | |
|     check_execute(stmt, rc);
 | |
| 
 | |
|     rc= mysql_stmt_fetch(stmt);
 | |
|     rc= mysql_stmt_fetch(stmt);
 | |
|     DBUG_ASSERT(rc == MYSQL_NO_DATA);
 | |
| 
 | |
|     mysql_stmt_next_result(stmt);
 | |
|     mysql_stmt_fetch(stmt);
 | |
|   }
 | |
| 
 | |
|   rc= mysql_query(mysql, "DROP FUNCTION f1");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "CREATE FUNCTION f1() RETURNS INT RETURN 1");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   {
 | |
|     bzero(&out_param_bind, sizeof (out_param_bind));
 | |
| 
 | |
|     out_param_bind.buffer_type= MYSQL_TYPE_LONG;
 | |
|     out_param_bind.is_null= &is_null;
 | |
|     out_param_bind.buffer= &int_data;
 | |
|     out_param_bind.buffer_length= sizeof (int_data);
 | |
| 
 | |
|     rc= mysql_stmt_bind_result(stmt, &out_param_bind);
 | |
|     check_execute(stmt, rc);
 | |
| 
 | |
|     rc= mysql_stmt_fetch(stmt);
 | |
|     rc= mysql_stmt_fetch(stmt);
 | |
|     DBUG_ASSERT(rc == MYSQL_NO_DATA);
 | |
| 
 | |
|     mysql_stmt_next_result(stmt);
 | |
|     mysql_stmt_fetch(stmt);
 | |
|   }
 | |
| 
 | |
|   mysql_stmt_close(stmt);
 | |
| 
 | |
|   rc= mysql_query(mysql, "DROP PROCEDURE p1");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "DROP FUNCTION f1");
 | |
|   myquery(rc);
 | |
| 
 | |
|   DBUG_VOID_RETURN;
 | |
| }
 | |
| 
 | |
| 
 | |
| /*
 | |
|   Bug #56976:   Severe Denial Of Service in prepared statements
 | |
| */
 | |
| static void test_bug56976()
 | |
| {
 | |
|   MYSQL_STMT   *stmt;
 | |
|   MYSQL_BIND    bind[1];
 | |
|   int           rc;
 | |
|   const char*   query = "SELECT LENGTH(?)";
 | |
|   char *long_buffer;
 | |
|   unsigned long i, packet_len = 256 * 1024L;
 | |
|   unsigned long dos_len    = 35000000;
 | |
| 
 | |
|   DBUG_ENTER("test_bug56976");
 | |
|   myheader("test_bug56976");
 | |
| 
 | |
|   stmt= mysql_stmt_init(mysql);
 | |
|   check_stmt(stmt);
 | |
| 
 | |
|   rc= mysql_stmt_prepare(stmt, query, strlen(query));
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   memset(bind, 0, sizeof(bind));
 | |
|   bind[0].buffer_type = MYSQL_TYPE_TINY_BLOB;
 | |
| 
 | |
|   rc= mysql_stmt_bind_param(stmt, bind);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   long_buffer= (char*) my_malloc(PSI_NOT_INSTRUMENTED, packet_len, MYF(0));
 | |
|   DIE_UNLESS(long_buffer);
 | |
| 
 | |
|   memset(long_buffer, 'a', packet_len);
 | |
| 
 | |
|   for (i= 0; i < dos_len / packet_len; i++)
 | |
|   {
 | |
|     rc= mysql_stmt_send_long_data(stmt, 0, long_buffer, packet_len);
 | |
|     check_execute(stmt, rc);
 | |
|   }
 | |
| 
 | |
|   my_free(long_buffer);
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
| 
 | |
|   DIE_UNLESS(rc && mysql_stmt_errno(stmt) == ER_UNKNOWN_ERROR);
 | |
| 
 | |
|   mysql_stmt_close(stmt);
 | |
| 
 | |
|   DBUG_VOID_RETURN;
 | |
| }
 | |
| 
 | |
| /*
 | |
|   Test that CLIENT_PROGRESS works.
 | |
| */
 | |
| 
 | |
| uint progress_stage, progress_max_stage, progress_count;
 | |
| 
 | |
| static void report_progress(const MYSQL *mysql __attribute__((unused)),
 | |
|                             uint stage, uint max_stage,
 | |
|                             double progress __attribute__((unused)),
 | |
|                             const char *proc_info __attribute__((unused)),
 | |
|                             uint proc_info_length __attribute__((unused)))
 | |
| {
 | |
|   progress_stage= stage;
 | |
|   progress_max_stage= max_stage;
 | |
|   progress_count++;
 | |
| }
 | |
| 
 | |
| 
 | |
| static void test_progress_reporting()
 | |
| {
 | |
|   int rc, i;
 | |
|   MYSQL*       conn;
 | |
| 
 | |
|   /* Progress reporting doesn't work yet with embedded server */
 | |
|   if (embedded_server_arg_count)
 | |
|     return;
 | |
| 
 | |
|   myheader("test_progress_reporting");
 | |
| 
 | |
| 
 | |
|   conn= client_connect(CLIENT_PROGRESS_OBSOLETE, MYSQL_PROTOCOL_TCP, 0);
 | |
|   DIE_UNLESS(conn->client_flag & CLIENT_PROGRESS_OBSOLETE);
 | |
| 
 | |
|   mysql_options(conn, MYSQL_PROGRESS_CALLBACK, (void*) report_progress);
 | |
|   rc= mysql_query(conn, "set @save=@@global.progress_report_time");
 | |
|   myquery(rc);
 | |
|   rc= mysql_query(conn, "set @@global.progress_report_time=1");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(conn, "drop table if exists t1,t2");
 | |
|   myquery(rc);
 | |
|   rc= mysql_query(conn, "create table t1 (f2 varchar(255)) engine=aria");
 | |
|   myquery(rc);
 | |
|   rc= mysql_query(conn, "create table t2 like t1");
 | |
|   myquery(rc);
 | |
|   rc= mysql_query(conn, "insert into t1 (f2) values (repeat('a',100)),(repeat('b',200)),(repeat('c',202)),(repeat('d',202)),(repeat('e',202)),(repeat('f',202)),(repeat('g',23))");
 | |
|   myquery(rc);
 | |
|   for (i= 0 ; i < 5 ; i++)
 | |
|   {
 | |
|     rc= mysql_query(conn, "insert into t2 (f2) select f2 from t1");
 | |
|     myquery(rc);
 | |
|     rc= mysql_query(conn, "insert into t1 (f2) select f2 from t2");
 | |
|     myquery(rc);
 | |
|   }
 | |
|   
 | |
|   progress_stage= progress_max_stage= progress_count= 0;
 | |
|   rc= mysql_query(conn, "alter table t1 add f1 int primary key auto_increment, lock=shared, order by f2");
 | |
|   myquery(rc);
 | |
|   if (!opt_silent)
 | |
|     printf("Got progress_count: %u  stage: %u  max_stage: %u\n",
 | |
|            progress_count, progress_stage, progress_max_stage);
 | |
|   DIE_UNLESS(progress_count > 0 && progress_stage >=2 && progress_max_stage == 3);
 | |
| 
 | |
|   progress_stage= progress_max_stage= progress_count= 0;
 | |
|   rc= mysql_query(conn, "create index f2 on t1 (f2) lock=shared");
 | |
|   myquery(rc);
 | |
|   if (!opt_silent)
 | |
|     printf("Got progress_count: %u  stage: %u  max_stage: %u\n",
 | |
|            progress_count, progress_stage, progress_max_stage);
 | |
|   DIE_UNLESS(progress_count > 0 && progress_stage >=2 && progress_max_stage == 2);
 | |
| 
 | |
|   progress_stage= progress_max_stage= progress_count= 0;
 | |
|   rc= mysql_query(conn, "drop index f2 on t1");
 | |
|   myquery(rc);
 | |
|   if (!opt_silent)
 | |
|     printf("Got progress_count: %u  stage: %u  max_stage: %u\n",
 | |
|            progress_count, progress_stage, progress_max_stage);
 | |
|   DIE_UNLESS(progress_count > 0 && progress_stage >=2 && progress_max_stage == 4);
 | |
| 
 | |
|   rc= mysql_query(conn, "set @@global.progress_report_time=@save");
 | |
|   myquery(rc);
 | |
|   mysql_close(conn);
 | |
| }
 | |
| 
 | |
| /**
 | |
|   MDEV-3885 - connection suicide via mysql_kill() causes assertion in server
 | |
| */
 | |
| 
 | |
| static void test_mdev3885() 
 | |
| {
 | |
|   int rc;
 | |
|   MYSQL *conn;
 | |
| 
 | |
|   myheader("test_mdev3885");
 | |
|   conn= client_connect(0, MYSQL_PROTOCOL_TCP, 0);
 | |
|   rc= mysql_kill(conn, mysql_thread_id(conn));
 | |
|   DIE_UNLESS(rc);
 | |
|   mysql_close(conn);
 | |
| }
 | |
| 
 | |
| 
 | |
| /**
 | |
|   Bug#57058 SERVER_QUERY_WAS_SLOW not wired up.
 | |
| */
 | |
| 
 | |
| static void test_bug57058()
 | |
| {
 | |
|   MYSQL_RES *res;
 | |
|   int rc;
 | |
| 
 | |
|   DBUG_ENTER("test_bug57058");
 | |
|   myheader("test_bug57058");
 | |
| 
 | |
|   rc= mysql_query(mysql, "set @@session.long_query_time=0.1");
 | |
|   myquery(rc);
 | |
| 
 | |
|   DIE_UNLESS(!(mysql->server_status & SERVER_QUERY_WAS_SLOW));
 | |
| 
 | |
|   rc= mysql_query(mysql, "select sleep(1)");
 | |
|   myquery(rc);
 | |
| 
 | |
|   /*
 | |
|     Important: the flag is sent in the last EOF packet of
 | |
|     the query, the one which ends the result. Read the
 | |
|     result to see the "slow" status.
 | |
|   */
 | |
|   res= mysql_store_result(mysql);
 | |
| 
 | |
|   DIE_UNLESS(mysql->server_status & SERVER_QUERY_WAS_SLOW);
 | |
| 
 | |
|   mysql_free_result(res);
 | |
| 
 | |
|   rc= mysql_query(mysql, "set @@session.long_query_time=default");
 | |
|   myquery(rc);
 | |
| 
 | |
|   DBUG_VOID_RETURN;
 | |
| }
 | |
| 
 | |
| 
 | |
| /**
 | |
|   Bug#11766854: 60075: MYSQL_LOAD_CLIENT_PLUGIN DOESN'T CLEAR ERROR 
 | |
| */
 | |
| 
 | |
| static void test_bug11766854()
 | |
| {
 | |
|   struct st_mysql_client_plugin *plugin;
 | |
| 
 | |
|   DBUG_ENTER("test_bug11766854");
 | |
|   if (!getenv("QA_AUTH_CLIENT_SO"))
 | |
|     DBUG_VOID_RETURN;
 | |
| 
 | |
|   myheader("test_bug11766854");
 | |
| 
 | |
|   plugin= mysql_load_plugin(mysql, "foo", -1, 0);
 | |
|   DIE_UNLESS(plugin == 0);
 | |
| 
 | |
|   plugin= mysql_load_plugin(mysql, "qa_auth_client", -1, 0);
 | |
|   DIE_UNLESS(plugin != 0);
 | |
|   DIE_IF(mysql_errno(mysql));
 | |
| 
 | |
|   DBUG_VOID_RETURN;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Bug#12337762: 60075: MYSQL_LIST_FIELDS() RETURNS WRONG CHARSET FOR 
 | |
|                        CHAR/VARCHAR/TEXT COLUMNS IN VIEWS 
 | |
| */
 | |
| static void test_bug12337762()
 | |
| {
 | |
|   int rc,i=0;
 | |
|   MYSQL_RES *result;
 | |
|   MYSQL_FIELD *field;
 | |
|   unsigned int tab_charsetnr[3]= {0};
 | |
| 
 | |
|   DBUG_ENTER("test_bug12337762");
 | |
|   myheader("test_bug12337762");
 | |
| 
 | |
|   /*
 | |
|     Creating table with specific charset.
 | |
|   */
 | |
|   rc= mysql_query(mysql, "drop table if exists charset_tab");
 | |
|   rc= mysql_query(mysql, "create table charset_tab("\
 | |
|                          "txt1 varchar(32) character set Latin1,"\
 | |
|                          "txt2 varchar(32) character set Latin1 collate latin1_bin,"\
 | |
|                          "txt3 varchar(32) character set utf8 collate utf8_bin"\
 | |
| 						 ")");
 | |
|   
 | |
|   DIE_UNLESS(rc == 0);
 | |
|   DIE_IF(mysql_errno(mysql));
 | |
| 
 | |
|   /*
 | |
|     Creating view from table created earlier.
 | |
|   */
 | |
|   rc= mysql_query(mysql, "drop view if exists charset_view");
 | |
|   rc= mysql_query(mysql, "create view charset_view as "\
 | |
|                          "select * from charset_tab;");
 | |
|   DIE_UNLESS(rc == 0);
 | |
|   DIE_IF(mysql_errno(mysql));
 | |
| 
 | |
|   /*
 | |
|     Checking field information for table.
 | |
|   */
 | |
|   result= mysql_list_fields(mysql, "charset_tab", NULL);
 | |
|   DIE_IF(mysql_errno(mysql));
 | |
|   i=0;
 | |
|   while((field= mysql_fetch_field(result)))
 | |
|   {
 | |
|     printf("field name %s\n", field->name);
 | |
|     printf("field table %s\n", field->table);
 | |
|     printf("field type %d\n", field->type);
 | |
|     printf("field charset %d\n", field->charsetnr);
 | |
|     tab_charsetnr[i++]= field->charsetnr;
 | |
|     printf("\n");
 | |
|   }
 | |
|   mysql_free_result(result);
 | |
| 
 | |
|   /*
 | |
|     Checking field information for view.
 | |
|   */
 | |
|   result= mysql_list_fields(mysql, "charset_view", NULL);
 | |
|   DIE_IF(mysql_errno(mysql));
 | |
|   i=0;
 | |
|   while((field= mysql_fetch_field(result)))
 | |
|   {
 | |
|     printf("field name %s\n", field->name);
 | |
|     printf("field table %s\n", field->table);
 | |
|     printf("field type %d\n", field->type);
 | |
|     printf("field charset %d\n", field->charsetnr);
 | |
|     printf("\n");
 | |
|     /* 
 | |
|       charset value for field must be same for both, view and table.
 | |
|     */
 | |
|     DIE_UNLESS(field->charsetnr == tab_charsetnr[i++]);
 | |
|   }
 | |
|   mysql_free_result(result);
 | |
| 
 | |
|   DBUG_VOID_RETURN;
 | |
| }
 | |
| 
 | |
| /* 
 | |
|    MDEV-4603: mysql_stmt_reset doesn't clear
 | |
|               all result sets (from stored procedures).
 | |
|    This test requires also fix for MDEV-4604
 | |
| */
 | |
| static void test_mdev4603()
 | |
| {
 | |
|   MYSQL *my;
 | |
|   MYSQL_STMT *stmt;
 | |
|   int i, rc;
 | |
|   int a[] = {10,20,30};
 | |
|   MYSQL_BIND bind[3];
 | |
| 
 | |
|   myheader("test_mdev4603");
 | |
|   my= mysql_client_init(NULL);
 | |
| 
 | |
|   if (!mysql_real_connect(my, opt_host, opt_user,
 | |
|                                opt_password, current_db, opt_port,
 | |
|                                opt_unix_socket, CLIENT_MULTI_RESULTS))
 | |
|     DIE("mysql_real_connect failed");
 | |
| 
 | |
|   /* 1st test:
 | |
|      use a procedure with out param
 | |
|   */
 | |
|   rc= mysql_query(my, "DROP PROCEDURE IF EXISTS p1");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "CREATE PROCEDURE p1(OUT p_out VARCHAR(19), IN p_in INT, INOUT p_inout INT)" 
 | |
|                          "BEGIN "
 | |
|                           "  SET p_in = 300, p_out := 'This is OUT param', p_inout = 200; "
 | |
|                           "  SELECT p_inout, p_in, substring(p_out, 9);"
 | |
|                          "END");
 | |
|   myquery(rc);
 | |
| 
 | |
|   stmt= mysql_stmt_init(mysql);
 | |
|   DIE_UNLESS(stmt != NULL);
 | |
| 
 | |
|   rc= mysql_stmt_prepare(stmt, "CALL P1(?,?,?)", 14);
 | |
|   DIE_UNLESS(rc == 0);
 | |
| 
 | |
|   DIE_UNLESS(mysql_stmt_param_count(stmt) == 3);
 | |
| 
 | |
|   memset(bind, 0, sizeof(MYSQL_BIND) * 3);
 | |
|   for (i=0; i < 3; i++)
 | |
|   {
 | |
|     bind[i].buffer= &a[i];
 | |
|     bind[i].buffer_type= MYSQL_TYPE_LONG;
 | |
|   }
 | |
|   bind[0].buffer_type= MYSQL_TYPE_NULL;
 | |
|   rc= mysql_stmt_bind_param(stmt, bind);
 | |
|   DIE_UNLESS(rc == 0);
 | |
| 
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   DIE_UNLESS(rc == 0);
 | |
| 
 | |
|   rc= mysql_stmt_fetch(stmt);
 | |
|   DIE_UNLESS(rc == 0);
 | |
| 
 | |
|   rc= mysql_stmt_reset(stmt);
 | |
|   DIE_UNLESS(rc == 0);
 | |
| 
 | |
|   /*connection shouldn't be blocked now */
 | |
| 
 | |
|   rc= mysql_query(mysql, "DROP PROCEDURE p1");
 | |
|   myquery(rc);
 | |
| 
 | |
|   /* 2nd test:
 | |
|      reset all result sets */
 | |
|   rc= mysql_query(my, "CREATE PROCEDURE p1() "
 | |
|                       "BEGIN"
 | |
|                       "  SELECT 1,2,3 FROM DUAL;"
 | |
|                       "  SELECT 'foo' FROM DUAL;"
 | |
|                       "END");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_stmt_prepare(stmt, "CALL P1()", 9);
 | |
|   DIE_UNLESS(rc == 0);
 | |
| 
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   DIE_UNLESS(rc == 0);
 | |
| 
 | |
|   rc= mysql_stmt_reset(stmt);
 | |
|   DIE_UNLESS(rc == 0);
 | |
| 
 | |
|   /* 3rd test:
 | |
|      mysql_stmt_close should also flush all pending
 | |
|      result sets
 | |
|   */
 | |
|   
 | |
|   rc= mysql_stmt_prepare(stmt, "CALL P1()", 9);
 | |
|   DIE_UNLESS(rc == 0);
 | |
| 
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   DIE_UNLESS(rc == 0);
 | |
| 
 | |
|   rc= mysql_stmt_close(stmt);
 | |
|   DIE_UNLESS(rc == 0);
 | |
| 
 | |
|   rc= mysql_query(my, "DROP PROCEDURE p1");
 | |
|   myquery(rc);
 | |
| 
 | |
|   mysql_close(my);
 | |
| }
 | |
| 
 | |
| /*
 | |
|   BUG 11754979 - 46675: ON DUPLICATE KEY UPDATE AND UPDATECOUNT() POSSIBLY WRONG
 | |
| */
 | |
| 
 | |
| static void test_bug11754979()
 | |
| {
 | |
|   MYSQL* conn;
 | |
|   DBUG_ENTER("test_bug11754979");
 | |
| 
 | |
|   myheader("test_bug11754979");
 | |
|   DIE_UNLESS((conn= mysql_client_init(NULL)));
 | |
|   DIE_UNLESS(mysql_real_connect(conn, opt_host, opt_user,
 | |
|              opt_password, opt_db ? opt_db:"test", opt_port,
 | |
|              opt_unix_socket,  CLIENT_FOUND_ROWS));
 | |
|   myquery(mysql_query(conn, "DROP TABLE IF EXISTS t1"));
 | |
|   myquery(mysql_query(conn, "CREATE TABLE t1(id INT, label CHAR(1), PRIMARY KEY(id))"));
 | |
|   myquery(mysql_query(conn, "INSERT INTO t1(id, label) VALUES (1, 'a')"));
 | |
|   myquery(mysql_query(conn, "INSERT INTO t1(id, label) VALUES (1, 'a') "
 | |
|                             "ON DUPLICATE KEY UPDATE id = 4"));
 | |
|   DIE_UNLESS(mysql_affected_rows(conn) == 2);
 | |
|   myquery(mysql_query(conn, "DROP TABLE t1"));
 | |
|   mysql_close(conn);
 | |
| 
 | |
|   DBUG_VOID_RETURN;
 | |
| }
 | |
| 
 | |
| static void test_ps_sp_out_params()
 | |
| {
 | |
|   MYSQL *my;
 | |
|   MYSQL_STMT *stmt;
 | |
|   MYSQL_BIND bind[1];
 | |
|   char buffer[20];
 | |
|   int status, rc;
 | |
| 
 | |
|   myheader("test_ps_sp_out_params");
 | |
|   my= mysql_client_init(NULL);
 | |
| 
 | |
|   if (!mysql_real_connect(my, opt_host, opt_user,
 | |
|                                opt_password, current_db, opt_port,
 | |
|                                opt_unix_socket, CLIENT_MULTI_RESULTS))
 | |
|     DIE("mysql_real_connect failed");
 | |
| 
 | |
|   rc= mysql_query(my, "DROP PROCEDURE IF EXISTS p1");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(my,
 | |
|     "CREATE PROCEDURE p1(OUT out_param VARCHAR(19)) "
 | |
|     "BEGIN"
 | |
|     " SELECT 'foo' FROM DUAL;"
 | |
|     " SET out_param='foo';"
 | |
|     " SELECT 'foo' FROM DUAL;"
 | |
|     "END");
 | |
|   myquery(rc);
 | |
| 
 | |
|   stmt= mysql_stmt_init(my);
 | |
| 
 | |
|   rc= mysql_stmt_prepare(stmt, "CALL P1(?)", 10);
 | |
|   DIE_UNLESS(rc==0);
 | |
| 
 | |
|   DIE_UNLESS(mysql_stmt_param_count(stmt) == 1);
 | |
| 
 | |
|   memset(bind, 0, sizeof(MYSQL_BIND));
 | |
|   memset(buffer, 0, sizeof buffer);
 | |
|   bind[0].buffer= buffer;
 | |
|   bind[0].buffer_length= sizeof(buffer);
 | |
|   bind[0].buffer_type= MYSQL_TYPE_STRING;
 | |
| 
 | |
|   mysql_stmt_bind_param(stmt, bind);
 | |
| 
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   do {
 | |
|     if (mysql_stmt_field_count(stmt))
 | |
|     {
 | |
|       /* since server sends a status packet at the end,
 | |
|          there must follow at least one additional packet */
 | |
|       DIE_UNLESS(mysql_more_results(stmt->mysql));
 | |
| 
 | |
|       mysql_stmt_bind_result(stmt, bind);
 | |
| 
 | |
|       rc= mysql_stmt_fetch(stmt);
 | |
|       DIE_UNLESS(rc== 0);
 | |
| 
 | |
|       DIE_UNLESS(strcmp(buffer, "foo") == 0);
 | |
|     }
 | |
|     status= mysql_stmt_next_result(stmt);
 | |
|   } while (status == 0);
 | |
| 
 | |
|   rc= mysql_stmt_reset(stmt);
 | |
|   DIE_UNLESS(rc== 0);
 | |
| 
 | |
|   mysql_stmt_close(stmt);
 | |
|   mysql_close(my);
 | |
| 
 | |
|   printf("end\n");
 | |
| }
 | |
| 
 | |
| /*
 | |
|   Bug#13001491: MYSQL_REFRESH CRASHES WHEN STORED ROUTINES ARE RUN CONCURRENTLY.
 | |
| */
 | |
| static void test_bug13001491()
 | |
| {
 | |
|   int rc;
 | |
|   char query[MAX_TEST_QUERY_LENGTH];
 | |
|   MYSQL *c;
 | |
| 
 | |
|   myheader("test_bug13001491");
 | |
| 
 | |
|   my_snprintf(query, MAX_TEST_QUERY_LENGTH,
 | |
|            "GRANT ALL PRIVILEGES ON *.* TO mysqltest_u1@%s",
 | |
|            opt_host ? opt_host : "'localhost'");
 | |
|            
 | |
|   rc= mysql_query(mysql, query);
 | |
|   myquery(rc);
 | |
| 
 | |
|   my_snprintf(query, MAX_TEST_QUERY_LENGTH,
 | |
|            "GRANT RELOAD ON *.* TO mysqltest_u1@%s",
 | |
|            opt_host ? opt_host : "'localhost'");
 | |
|            
 | |
|   rc= mysql_query(mysql, query);
 | |
|   myquery(rc);
 | |
| 
 | |
|   c= mysql_client_init(NULL);
 | |
| 
 | |
|   DIE_UNLESS(mysql_real_connect(c, opt_host, "mysqltest_u1", NULL,
 | |
|                                 current_db, opt_port, opt_unix_socket,
 | |
|                                 CLIENT_MULTI_STATEMENTS |
 | |
|                                 CLIENT_MULTI_RESULTS));
 | |
| 
 | |
|   rc= mysql_query(c, "DROP PROCEDURE IF EXISTS p1");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(c,
 | |
|     "CREATE PROCEDURE p1() "
 | |
|     "BEGIN "
 | |
|     " DECLARE CONTINUE HANDLER FOR SQLEXCEPTION BEGIN END; "
 | |
|     " SELECT COUNT(*) "
 | |
|     " FROM INFORMATION_SCHEMA.PROCESSLIST "
 | |
|     " GROUP BY user "
 | |
|     " ORDER BY NULL "
 | |
|     " INTO @a; "
 | |
|     "END");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(c, "CALL p1()");
 | |
|   myquery(rc);
 | |
| 
 | |
|   mysql_free_result(mysql_store_result(c));
 | |
| 
 | |
|   /* Check that mysql_refresh() succeeds without REFRESH_LOG. */
 | |
|   rc= mysql_refresh(c, REFRESH_GRANT |
 | |
|                        REFRESH_TABLES | REFRESH_HOSTS |
 | |
|                        REFRESH_STATUS | REFRESH_THREADS);
 | |
|   myquery(rc);
 | |
| 
 | |
|   /*
 | |
|     Check that mysql_refresh(REFRESH_LOG) does not crash the server even if it
 | |
|     fails. mysql_refresh(REFRESH_LOG) fails when error log points to unavailable
 | |
|     location.
 | |
|   */
 | |
|   mysql_refresh(c, REFRESH_LOG);
 | |
| 
 | |
|   rc= mysql_query(c, "DROP PROCEDURE p1");
 | |
|   myquery(rc);
 | |
| 
 | |
|   mysql_close(c);
 | |
|   c= NULL;
 | |
| 
 | |
|   my_snprintf(query, MAX_TEST_QUERY_LENGTH,
 | |
|            "DROP USER mysqltest_u1@%s",
 | |
|            opt_host ? opt_host : "'localhost'");
 | |
|            
 | |
|   rc= mysql_query(mysql, query);
 | |
|   myquery(rc);
 | |
| }
 | |
| 
 | |
| static void test_mdev4326()
 | |
| {
 | |
|   MYSQL_STMT   *stmt;
 | |
|   MYSQL_BIND    bind;
 | |
|   char query[]= "SELECT * FROM mysql.user LIMIT ?";
 | |
|   char str_data[]= "1";
 | |
|   unsigned long length= 0;
 | |
|   int int_data= 1;
 | |
|   int rc, count;
 | |
|   my_bool is_null= 0;
 | |
|   my_bool error= 0;
 | |
|   myheader("test_mdev4326");
 | |
| 
 | |
|   rc= mysql_change_user(mysql, opt_user, opt_password, "mysql");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "SET GLOBAL general_log = 1");
 | |
|   myquery(rc);
 | |
| 
 | |
|   stmt= mysql_stmt_init(mysql);
 | |
|   check_stmt(stmt);
 | |
| 
 | |
|   /* Numeric parameter test */
 | |
| 
 | |
|   rc= mysql_stmt_prepare(stmt, query, strlen(query));
 | |
|   check_execute(stmt, rc);
 | |
|   check_stmt(stmt);
 | |
|   verify_param_count(stmt, 1);
 | |
| 
 | |
|   memset((char *)&bind, 0, sizeof(bind));
 | |
|   bind.buffer_type= MYSQL_TYPE_LONG;
 | |
|   bind.buffer= (char *)&int_data;
 | |
|   bind.is_null= &is_null;
 | |
|   bind.length= &length;
 | |
|   bind.error= &error;
 | |
| 
 | |
|   rc= mysql_stmt_bind_param(stmt, &bind);
 | |
|   check_execute(stmt, rc);
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
|   count= 0;
 | |
|   while (!(rc= mysql_stmt_fetch(stmt)))
 | |
|     count++;
 | |
|   DIE_UNLESS(count == 1);
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
|   count= 0;
 | |
|   while (!(rc= mysql_stmt_fetch(stmt)))
 | |
|     count++;
 | |
|   DIE_UNLESS(count == 1);
 | |
|   int_data= 0;
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
|   count= 0;
 | |
|   while (!(rc= mysql_stmt_fetch(stmt)))
 | |
|     count++;
 | |
|   DIE_UNLESS(count == 0);
 | |
|   rc= mysql_stmt_close(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   /* String parameter test */
 | |
| 
 | |
|   stmt= mysql_stmt_init(mysql);
 | |
|   rc= mysql_stmt_prepare(stmt, query, strlen(query));
 | |
|   check_execute(stmt, rc);
 | |
|   check_stmt(stmt);
 | |
|   verify_param_count(stmt, 1);
 | |
| 
 | |
|   memset((char *)&bind, 0, sizeof(bind));
 | |
|   bind.buffer_type= MYSQL_TYPE_STRING;
 | |
|   bind.buffer= (char *)str_data;
 | |
|   length= bind.buffer_length= sizeof(str_data);
 | |
|   bind.is_null= &is_null;
 | |
|   bind.length= &length;
 | |
|   bind.error= &error;
 | |
| 
 | |
|   rc= mysql_stmt_bind_param(stmt, &bind);
 | |
|   check_execute(stmt, rc);
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
|   count= 0;
 | |
|   while (!(rc= mysql_stmt_fetch(stmt)))
 | |
|     count++;
 | |
|   DIE_UNLESS(count == 1);
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
|   count= 0;
 | |
|   while (!(rc= mysql_stmt_fetch(stmt)))
 | |
|     count++;
 | |
|   DIE_UNLESS(count == 1);
 | |
|   str_data[0]= '0';
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
|   count= 0;
 | |
|   while (!(rc= mysql_stmt_fetch(stmt)))
 | |
|     count++;
 | |
|   DIE_UNLESS(count == 0);
 | |
|   rc= mysql_stmt_close(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= mysql_change_user(mysql, opt_user, opt_password, current_db);
 | |
|   myquery(rc);
 | |
| }
 | |
| 
 | |
| /* Test uses MYSQL_PROTOCOL_SOCKET, not on Windows */
 | |
| 
 | |
| #ifndef _WIN32
 | |
| /**
 | |
|    BUG#17512527: LIST HANDLING INCORRECT IN MYSQL_PRUNE_STMT_LIST()
 | |
| */
 | |
| static void test_bug17512527()
 | |
| {
 | |
|   MYSQL *conn;
 | |
|   MYSQL_STMT *stmt1, *stmt2;
 | |
|   unsigned long thread_id;
 | |
|   char query[MAX_TEST_QUERY_LENGTH];
 | |
|   int rc;
 | |
| 
 | |
|   conn= client_connect(0, MYSQL_PROTOCOL_SOCKET, 1);
 | |
| 
 | |
|   stmt1 = mysql_stmt_init(conn);
 | |
|   check_stmt(stmt1);
 | |
|   rc= mysql_stmt_prepare(stmt1, STRING_WITH_LEN("SELECT 1"));
 | |
|   check_execute(stmt1, rc);
 | |
| 
 | |
|   stmt2 = mysql_stmt_init(conn);
 | |
|   check_stmt(stmt2);
 | |
| 
 | |
|   thread_id= mysql_thread_id(conn);
 | |
|   sprintf(query, "KILL %lu", thread_id);
 | |
|   if (thread_query(query))
 | |
|     exit(1);
 | |
| 
 | |
|   rc= mysql_stmt_prepare(stmt2, STRING_WITH_LEN("SELECT 2"));
 | |
|   check_execute(stmt2, rc);
 | |
| 
 | |
|   rc= mysql_stmt_execute(stmt1);
 | |
|   check_execute_r(stmt1, rc);
 | |
| 
 | |
|   rc= mysql_stmt_execute(stmt2);
 | |
|   check_execute(stmt2, rc);
 | |
| 
 | |
|   mysql_close(conn);
 | |
| 
 | |
|   mysql_stmt_close(stmt2);
 | |
|   mysql_stmt_close(stmt1);
 | |
| }
 | |
| #endif
 | |
| 
 | |
| 
 | |
| /*
 | |
|   Check compressed protocol
 | |
| */
 | |
| 
 | |
| static void test_compressed_protocol()
 | |
| {
 | |
|   MYSQL *mysql_local;
 | |
|   MYSQL_STMT *stmt;
 | |
|   char query[4096], *end;
 | |
|   int i;
 | |
|   int rc;
 | |
|   myheader("test_compressed_protocol");
 | |
| 
 | |
|   if (!(mysql_local= mysql_client_init(NULL)))
 | |
|   {
 | |
|     fprintf(stderr, "\n mysql_client_init() failed");
 | |
|     exit(1);
 | |
|   }
 | |
| 
 | |
|   if (!(mysql_real_connect(mysql_local, opt_host, opt_user,
 | |
|                            opt_password, current_db, opt_port,
 | |
|                            opt_unix_socket, CLIENT_COMPRESS)))
 | |
|   {
 | |
|     fprintf(stderr, "\n connection failed(%s)", mysql_error(mysql_local));
 | |
|     exit(1);
 | |
|   }
 | |
|   mysql_options(mysql_local,MYSQL_OPT_COMPRESS,NullS);
 | |
| 
 | |
|   end= strmov(strfill(strmov(query, "select length(\""),1000,'a'),"\")");
 | |
| 
 | |
|   for (i=0 ; i < 2 ; i++)
 | |
|   {
 | |
|     MYSQL_RES *res;
 | |
|     rc= mysql_real_query(mysql, query, (int) (end-query));
 | |
|     myquery(rc);
 | |
|     res= mysql_store_result(mysql);
 | |
|     DBUG_ASSERT(res != 0);
 | |
|     mysql_free_result(res);
 | |
|   }
 | |
| 
 | |
|   /*
 | |
|     Special compression protocol feature - it can pack
 | |
|     multiple protocol commands inside the same compression packet.
 | |
| 
 | |
|     mariadbclient does it when MYSQL_STMT is reused in multiple
 | |
|     mysql_stmt_prepare() calls. It sends then COM_STMT_CLOSE and
 | |
|     COM_STMT_PREPARE together in a single compression packet.
 | |
| 
 | |
|     Let's test, how server can handle that. There can be bugs
 | |
|     (MDEV-28561)
 | |
|   */
 | |
|   stmt= mysql_stmt_init(mysql_local);
 | |
|   check_stmt(stmt);
 | |
|   for (i= 0; i < 2; i++)
 | |
|   {
 | |
|     rc= mysql_stmt_prepare(stmt, "DO 1", -1);
 | |
|     myquery(rc);
 | |
|   }
 | |
|   rc= mysql_stmt_close(stmt);
 | |
|   myquery(rc);
 | |
| 
 | |
|   mysql_close(mysql_local);
 | |
| }
 | |
| 
 | |
| /*
 | |
|   Check big packets
 | |
| */
 | |
| 
 | |
| static void test_big_packet()
 | |
| {
 | |
|   MYSQL *mysql_local;
 | |
|   char *query, *end;
 | |
|   /* We run the tests with a server with max packet size of 3200000 */
 | |
|   size_t big_packet= 31000000L;
 | |
|   int i;
 | |
|   MYSQL_PARAMETERS *mysql_params= mysql_get_parameters();
 | |
|   long org_max_allowed_packet= *mysql_params->p_max_allowed_packet;
 | |
|   long opt_net_buffer_length= *mysql_params->p_net_buffer_length;
 | |
| 
 | |
|   myheader("test_big_packet");
 | |
| 
 | |
|   query= (char*) my_malloc(PSI_NOT_INSTRUMENTED, big_packet+1024, MYF(MY_WME));
 | |
|   DIE_UNLESS(query);
 | |
|   
 | |
|   if (!(mysql_local= mysql_client_init(NULL)))
 | |
|   {
 | |
|     fprintf(stderr, "\n mysql_client_init() failed");
 | |
|     exit(1);
 | |
|   }
 | |
| 
 | |
|   if (!(mysql_real_connect(mysql_local, opt_host, opt_user,
 | |
|                            opt_password, current_db, opt_port,
 | |
|                            opt_unix_socket, 0)))
 | |
|   {
 | |
|     fprintf(stderr, "\n connection failed(%s)", mysql_error(mysql_local));
 | |
|     mysql_close(mysql_local);
 | |
|     exit(1);
 | |
|   }
 | |
| 
 | |
|   *mysql_params->p_max_allowed_packet= big_packet+1000;
 | |
|   *mysql_params->p_net_buffer_length=  8L*256L*256L;
 | |
| 
 | |
|   end= strmov(strfill(strmov(query, "select length(\""), big_packet,'a'),"\")");
 | |
| 
 | |
|   for (i=0 ; i < 2 ; i++)
 | |
|   {
 | |
|     MYSQL_RES *res;
 | |
|     int rc= mysql_real_query(mysql, query, (int) (end-query));
 | |
|     myquery(rc);
 | |
|     res= mysql_store_result(mysql);
 | |
|     DBUG_ASSERT(res != 0);
 | |
|     mysql_free_result(res);
 | |
|   }
 | |
| 
 | |
|   mysql_close(mysql_local);
 | |
|   my_free(query);
 | |
|   
 | |
|   *mysql_params->p_max_allowed_packet= org_max_allowed_packet;
 | |
|   *mysql_params->p_net_buffer_length = opt_net_buffer_length;
 | |
| }
 | |
| 
 | |
| 
 | |
| static void test_prepare_analyze()
 | |
| {
 | |
|   MYSQL_STMT *stmt;
 | |
|   const char *query= "ANALYZE SELECT 1";
 | |
|   int rc;
 | |
|   myheader("test_prepare_analyze");
 | |
| 
 | |
|   stmt= mysql_stmt_init(mysql);
 | |
|   check_stmt(stmt);
 | |
|   rc= mysql_stmt_prepare(stmt, query, strlen(query));
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= mysql_stmt_store_result(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   while (!(rc= mysql_stmt_fetch(stmt)))
 | |
|     ;
 | |
| 
 | |
|   DIE_UNLESS(rc == MYSQL_NO_DATA);
 | |
| 
 | |
|   rc= mysql_stmt_close(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| }
 | |
| 
 | |
| static void test_mdev12579()
 | |
| {
 | |
|   MYSQL_STMT *stmt= mysql_stmt_init(mysql);
 | |
|   MYSQL_BIND bind[2];
 | |
|   int rc;
 | |
|   long l=3;
 | |
|   const char *data = "123456";
 | |
| 
 | |
|   rc= mysql_query(mysql, "CREATE TABLE mdev12579 (k integer,t LONGTEXT,b LONGBLOB,x integer)");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_stmt_prepare(stmt, "INSERT INTO mdev12579 VALUES (1,?,NULL,?)", -1);
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_stmt_send_long_data(stmt, 0, data, 6);
 | |
|   rc= mysql_stmt_send_long_data(stmt, 0, data, 6);
 | |
|   rc= mysql_stmt_send_long_data(stmt, 0, data, 6);
 | |
| 
 | |
|   memset(bind, 0, sizeof(MYSQL_BIND) * 2);
 | |
|   bind[0].buffer_type= MYSQL_TYPE_VAR_STRING;
 | |
|   bind[1].buffer_type= MYSQL_TYPE_LONG;
 | |
|   bind[1].buffer= &l;
 | |
|   mysql_stmt_bind_param(stmt, bind);
 | |
| 
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   mysql_stmt_close(stmt);
 | |
| 
 | |
|   rc= mysql_query(mysql, "DROP TABLE mdev12579");
 | |
|   myquery(rc);
 | |
| }
 | |
| 
 | |
| /* Test test_mdev14013 sql_mode=EMPTY_STRING_IS_NULL */
 | |
| 
 | |
| static void test_mdev14013()
 | |
| {
 | |
|   MYSQL *lmysql;
 | |
|   MYSQL_STMT *stmt1;
 | |
|   MYSQL_BIND  my_bind[2];
 | |
|   MYSQL_RES   *result;
 | |
|   char       str_data[20];
 | |
|   unsigned int  count;
 | |
|   int   rc;
 | |
|   char query[MAX_TEST_QUERY_LENGTH];
 | |
| 
 | |
|   myheader("test_mdev14013");
 | |
| 
 | |
|   if (!opt_silent)
 | |
|     fprintf(stdout, "\n Establishing a test connection ...");
 | |
|   if (!(lmysql= mysql_client_init(NULL)))
 | |
|   {
 | |
|     myerror("mysql_client_init() failed");
 | |
|     exit(1);
 | |
|   }
 | |
|   if (!(mysql_real_connect(lmysql, opt_host, opt_user,
 | |
|                            opt_password, current_db, opt_port,
 | |
|                            opt_unix_socket, 0)))
 | |
|   {
 | |
|     myerror("connection failed");
 | |
|     exit(1);
 | |
|   }
 | |
|   mysql_options(lmysql, MYSQL_OPT_RECONNECT, &my_true);
 | |
|   if (!opt_silent)
 | |
|     fprintf(stdout, "OK");
 | |
| 
 | |
|   /* set AUTOCOMMIT to ON*/
 | |
|   mysql_autocommit(lmysql, TRUE);
 | |
| 
 | |
|   strmov(query, "SET SQL_MODE= \"EMPTY_STRING_IS_NULL\"");
 | |
|   if (!opt_silent)
 | |
|     fprintf(stdout, "\n With %s", query);
 | |
|   rc= mysql_query(mysql, query);
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(lmysql, "DROP TABLE IF EXISTS test_mdev14013");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(lmysql, "CREATE TABLE test_mdev14013(id int, val varchar(10))");
 | |
|   myquery(rc);
 | |
| 
 | |
|   strmov(query, "INSERT INTO test_mdev14013(id,val) VALUES(?,?)");
 | |
|   stmt1= mysql_simple_prepare(mysql, query);
 | |
|   check_stmt(stmt1);
 | |
| 
 | |
|   verify_param_count(stmt1, 2);
 | |
| 
 | |
|   /*
 | |
|     We need to bzero bind structure because mysql_stmt_bind_param checks all
 | |
|     its members.
 | |
|   */
 | |
|   bzero((char*) my_bind, sizeof(my_bind));
 | |
| 
 | |
|   my_bind[0].buffer= (void *)&count;
 | |
|   my_bind[0].buffer_type= MYSQL_TYPE_LONG;
 | |
|   count= 100;
 | |
| 
 | |
|   strcpy(str_data,"");
 | |
|   my_bind[1].buffer_type= MYSQL_TYPE_STRING;
 | |
|   my_bind[1].buffer= (char *) str_data;
 | |
|   my_bind[1].buffer_length= strlen(str_data);
 | |
| 
 | |
|   rc= mysql_stmt_bind_param(stmt1, my_bind);
 | |
| 
 | |
|   rc= mysql_stmt_execute(stmt1);
 | |
|   check_execute(stmt1, rc);
 | |
| 
 | |
|   verify_st_affected_rows(stmt1, 1);
 | |
| 
 | |
|   rc= mysql_stmt_close(stmt1);
 | |
| 
 | |
|   strmov(query, "SET SQL_MODE= default");
 | |
|   if (!opt_silent)
 | |
|     fprintf(stdout, "\n With %s\n", query);
 | |
|   rc= mysql_query(mysql, query);
 | |
|   myquery(rc);
 | |
| 
 | |
|   strmov(query, "INSERT INTO test_mdev14013(id,val) VALUES(?,?)");
 | |
|   stmt1= mysql_simple_prepare(mysql, query);
 | |
|   check_stmt(stmt1);
 | |
| 
 | |
|   count= 200;
 | |
|   rc= mysql_stmt_bind_param(stmt1, my_bind);
 | |
| 
 | |
|   rc= mysql_stmt_execute(stmt1);
 | |
|   check_execute(stmt1, rc);
 | |
| 
 | |
|   verify_st_affected_rows(stmt1, 1);
 | |
| 
 | |
|   rc= mysql_stmt_close(stmt1);
 | |
|   if (!opt_silent)
 | |
|     fprintf(stdout, "\n test_mdev14013(x) returned: %d", rc);
 | |
|   DIE_UNLESS( rc == 0);
 | |
| 
 | |
|   rc= mysql_query(mysql, "SELECT id, val FROM test_mdev14013 order by id");
 | |
|   myquery(rc);
 | |
| 
 | |
|   result= mysql_store_result(mysql);
 | |
|   mytest(result);
 | |
| 
 | |
|   rc= my_process_result_set(result);
 | |
|   DIE_UNLESS(rc == 2);
 | |
|   mysql_free_result(result);
 | |
| 
 | |
|   rc= mysql_query(mysql, "SELECT id, val FROM test_mdev14013 where val is null");
 | |
|   myquery(rc);
 | |
| 
 | |
|   result= mysql_store_result(mysql);
 | |
|   mytest(result);
 | |
| 
 | |
|   rc= my_process_result_set(result);
 | |
|   DIE_UNLESS(rc == 1);
 | |
|   mysql_free_result(result);
 | |
| 
 | |
|   myquery(mysql_query(mysql, "drop table test_mdev14013"));
 | |
|   mysql_close(lmysql);
 | |
| }
 | |
| 
 | |
| static void test_mdev14013_1()
 | |
| {
 | |
|   MYSQL *lmysql;
 | |
|   MYSQL_STMT *stmt1;
 | |
|   MYSQL_BIND  my_bind[3];
 | |
|   char       str_data[3][255];
 | |
|   int  rc;
 | |
|   char query[MAX_TEST_QUERY_LENGTH];
 | |
| 
 | |
|   myheader("test_mdev14013_1");
 | |
| 
 | |
|   if (!opt_silent)
 | |
|     fprintf(stdout, "\n Establishing a test connection ...");
 | |
|   if (!(lmysql= mysql_client_init(NULL)))
 | |
|   {
 | |
|     myerror("mysql_client_init() failed");
 | |
|     exit(1);
 | |
|   }
 | |
|   if (!(mysql_real_connect(lmysql, opt_host, opt_user,
 | |
|                            opt_password, current_db, opt_port,
 | |
|                            opt_unix_socket, 0)))
 | |
|   {
 | |
|     myerror("connection failed");
 | |
|     exit(1);
 | |
|   }
 | |
|   mysql_options(lmysql, MYSQL_OPT_RECONNECT, &my_true);
 | |
|   if (!opt_silent)
 | |
|     fprintf(stdout, "OK");
 | |
| 
 | |
|   /* set AUTOCOMMIT to ON*/
 | |
|   mysql_autocommit(lmysql, TRUE);
 | |
| 
 | |
|   strmov(query, "SET SQL_MODE= \"EMPTY_STRING_IS_NULL\"");
 | |
|   if (!opt_silent)
 | |
|     fprintf(stdout, "\n With %s", query);
 | |
|   rc= mysql_query(mysql, query);
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql,
 | |
|     "CREATE OR REPLACE PROCEDURE test_mdev14013_p1("
 | |
|     "   IN i1 VARCHAR(255) , "
 | |
|     "   INOUT io1 VARCHAR(255), "
 | |
|     "   OUT o2 VARBINARY(255)) "
 | |
|     "BEGIN "
 | |
|     "   SET o2 = concat(concat(coalesce(i1,'i1 is null'),' - '),coalesce(i1,'io1 is null')); "
 | |
|     "END");
 | |
|   myquery(rc);
 | |
| 
 | |
|   strmov(query, "CALL test_mdev14013_p1(?, ?, ?)");
 | |
|   stmt1= mysql_simple_prepare(mysql, query);
 | |
|   check_stmt(stmt1);
 | |
| 
 | |
|   /* Init PS-parameters. */
 | |
| 
 | |
|   bzero((char *) my_bind, sizeof (my_bind));
 | |
| 
 | |
|   strcpy(str_data[0],"");
 | |
|   my_bind[0].buffer_type= MYSQL_TYPE_STRING;
 | |
|   my_bind[0].buffer= (char *) str_data[0];
 | |
|   my_bind[0].buffer_length= strlen(str_data[0]);
 | |
| 
 | |
|   strcpy(str_data[1],"");
 | |
|   my_bind[1].buffer_type= MYSQL_TYPE_STRING;
 | |
|   my_bind[1].buffer= (char *) str_data[1];
 | |
|   my_bind[1].buffer_length= strlen(str_data[1]);
 | |
| 
 | |
|   strcpy(str_data[2],"");
 | |
|   my_bind[2].buffer_type= MYSQL_TYPE_STRING;
 | |
|   my_bind[2].buffer= (char *) str_data[2];
 | |
|   my_bind[2].buffer_length= strlen(str_data[2]);
 | |
| 
 | |
|   /* Bind parameters. */
 | |
| 
 | |
|   rc= mysql_stmt_bind_param(stmt1, my_bind);
 | |
|   check_execute(stmt1, rc);
 | |
|   /* Execute */
 | |
| 
 | |
|   rc= mysql_stmt_execute(stmt1);
 | |
|   check_execute(stmt1, rc);
 | |
| 
 | |
|   my_bind[0].buffer_length= sizeof(str_data[0]);
 | |
|   my_bind[1].buffer_length= sizeof(str_data[1]);
 | |
| 
 | |
|   mysql_stmt_bind_result(stmt1, my_bind);
 | |
|   rc= mysql_stmt_fetch(stmt1);
 | |
| 
 | |
|   if (!opt_silent)
 | |
|     fprintf(stdout,"\nstr_data[1]=%s\n",str_data[1]);
 | |
| 
 | |
|   DIE_UNLESS(strcmp(str_data[1], "i1 is null - io1 is null") == 0);
 | |
| 
 | |
|   rc= mysql_stmt_close(stmt1);
 | |
|   DIE_UNLESS( rc == 0);
 | |
| 
 | |
|   myquery(mysql_query(mysql, "drop procedure test_mdev14013_p1"));
 | |
|   mysql_close(lmysql);
 | |
| }
 | |
| 
 | |
| 
 | |
| static void test_mdev14454_internal(const char *init,
 | |
|                                     unsigned int csid,
 | |
|                                     const char *value)
 | |
| {
 | |
|   MYSQL_STMT *stmt;
 | |
|   MYSQL_BIND bind;
 | |
|   const char *stmtstr= "CALL P1(?)";
 | |
|   char res[20];
 | |
|   int rc;
 | |
| 
 | |
|   if ((rc= mysql_query_or_error(mysql, init)) ||
 | |
|       (rc= mysql_query_or_error(mysql, "DROP PROCEDURE IF EXISTS p1")) ||
 | |
|       (rc= mysql_query_or_error(mysql,
 | |
|                                "CREATE PROCEDURE p1"
 | |
|                                "("
 | |
|                                "  OUT param1 TEXT CHARACTER SET utf8"
 | |
|                                ")"
 | |
|                                "BEGIN "
 | |
|                                "  SET param1 = _latin1'test\xFF'; "
 | |
|                                "END")))
 | |
|     DIE("Initiation failed");
 | |
| 
 | |
|   stmt= mysql_stmt_init(mysql);
 | |
|   rc= mysql_stmt_prepare(stmt, stmtstr, strlen(stmtstr));
 | |
|   DIE_UNLESS(rc == 0);
 | |
|   DIE_UNLESS(mysql_stmt_param_count(stmt) == 1);
 | |
| 
 | |
|   memset(&bind, 0, sizeof bind);
 | |
|   bind.buffer_type= MYSQL_TYPE_NULL;
 | |
|   rc= mysql_stmt_bind_param(stmt, &bind);
 | |
|   DIE_UNLESS(rc == 0);
 | |
| 
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   DIE_UNLESS(rc == 0);
 | |
| 
 | |
|   memset(res, 0, sizeof(res));
 | |
|   bind.buffer_type= MYSQL_TYPE_STRING;
 | |
|   bind.buffer_length= sizeof(res);
 | |
|   bind.buffer= res;
 | |
| 
 | |
|   do {
 | |
|     if (mysql->server_status & SERVER_PS_OUT_PARAMS)
 | |
|     {
 | |
|       MYSQL_FIELD *field;
 | |
|       printf("\nOUT param result set:\n");
 | |
|       DIE_UNLESS(mysql_stmt_field_count(stmt) == 1);
 | |
|       field= &stmt->fields[0];
 | |
|       printf("Field: %s\n", field->name);
 | |
|       printf("Type: %d\n", field->type);
 | |
|       printf("Collation: %d\n", field->charsetnr);
 | |
|       printf("Length: %lu\n", field->length);
 | |
|       DIE_UNLESS(stmt->fields[0].charsetnr == csid);
 | |
| 
 | |
|       rc= mysql_stmt_bind_result(stmt, &bind);
 | |
|       DIE_UNLESS(rc == 0);
 | |
|       rc= mysql_stmt_fetch(stmt);
 | |
|       DIE_UNLESS(rc == 0);
 | |
|       printf("Value: %s\n", res);
 | |
|       DIE_UNLESS(strcmp(res, value) == 0);
 | |
|     }
 | |
|     else if (mysql_stmt_field_count(stmt))
 | |
|     {
 | |
|       printf("sp result set\n");
 | |
|     }
 | |
|   } while (mysql_stmt_next_result(stmt) == 0);
 | |
| 
 | |
|   mysql_stmt_close(stmt);
 | |
|   DIE_UNLESS(mysql_query_or_error(mysql, "DROP PROCEDURE p1") == 0);
 | |
| }
 | |
| 
 | |
| 
 | |
| static void test_mdev14454()
 | |
| {
 | |
|   myheader("test_mdev14454");
 | |
|   test_mdev14454_internal("SET NAMES latin1", 8, "test\xFF");
 | |
|   test_mdev14454_internal("SET NAMES utf8 COLLATE utf8_general_ci", 33, "test\xC3\xBF");
 | |
| }
 | |
| 
 | |
| 
 | |
| typedef struct {
 | |
|   char sig[12];
 | |
|   char ver_cmd;
 | |
|   char fam;
 | |
|   short len;
 | |
|   union {
 | |
|     struct {  /* for TCP/UDP over IPv4, len = 12 */
 | |
|       int src_addr;
 | |
|       int dst_addr;
 | |
|       short src_port;
 | |
|       short dst_port;
 | |
|     } ip4;
 | |
|     struct {  /* for TCP/UDP over IPv6, len = 36 */
 | |
|       char  src_addr[16];
 | |
|       char  dst_addr[16];
 | |
|       short src_port;
 | |
|       short dst_port;
 | |
|     } ip6;
 | |
|     struct {  /* for AF_UNIX sockets, len = 216 */
 | |
|       char src_addr[108];
 | |
|       char dst_addr[108];
 | |
|     } unx;
 | |
|   } addr;
 | |
| } v2_proxy_header;
 | |
| 
 | |
| #ifndef EMBEDDED_LIBRARY
 | |
| static void test_proxy_header_tcp(const char *ipaddr, int port)
 | |
| {
 | |
|   int rc;
 | |
|   MYSQL_RES *result;
 | |
|   int family = (strchr(ipaddr,':') == NULL)?AF_INET:AF_INET6;
 | |
|   char query[256];
 | |
|   char text_header[256];
 | |
|   char addr_bin[16];
 | |
|   v2_proxy_header v2_header;
 | |
|   void *header_data[2];
 | |
|   size_t header_lengths[2];
 | |
|   int i;
 | |
| 
 | |
|   // normalize IPv4-mapped IPv6 addresses, e.g ::ffff:127.0.0.2 to 127.0.0.2
 | |
|   const char *normalized_addr= strncmp(ipaddr, "::ffff:", 7)?ipaddr : ipaddr + 7;
 | |
|   myheader("test_proxy_header_tcp");
 | |
| 
 | |
|   memset(&v2_header, 0, sizeof(v2_header));
 | |
|   sprintf(text_header,"PROXY %s %s %s %d 3306\r\n",family == AF_INET?"TCP4":"TCP6", ipaddr, ipaddr, port);
 | |
|  
 | |
|   inet_pton(family,ipaddr,addr_bin);
 | |
| 
 | |
|   memcpy(v2_header.sig, "\x0D\x0A\x0D\x0A\x00\x0D\x0A\x51\x55\x49\x54\x0A", 12);
 | |
|   v2_header.ver_cmd = (0x2 << 4) | 0x1; /* Version (0x2) , Command = PROXY (0x1) */
 | |
|   if(family == AF_INET)
 | |
|   {
 | |
|     v2_header.fam= 0x11;
 | |
|     v2_header.len= htons(12);
 | |
|     v2_header.addr.ip4.src_port= htons(port);
 | |
|     v2_header.addr.ip4.dst_port= htons(3306);
 | |
|     memcpy(&v2_header.addr.ip4.src_addr,addr_bin, sizeof (v2_header.addr.ip4.src_addr));
 | |
|     memcpy(&v2_header.addr.ip4.dst_addr,addr_bin, sizeof (v2_header.addr.ip4.dst_addr));
 | |
|   }
 | |
|   else
 | |
|   {
 | |
|     v2_header.fam= 0x21;
 | |
|     v2_header.len= htons(36);
 | |
|     v2_header.addr.ip6.src_port= htons(port);
 | |
|     v2_header.addr.ip6.dst_port= htons(3306);
 | |
|     memcpy(v2_header.addr.ip6.src_addr,addr_bin, sizeof (v2_header.addr.ip6.src_addr));
 | |
|     memcpy(v2_header.addr.ip6.dst_addr,addr_bin, sizeof (v2_header.addr.ip6.dst_addr));
 | |
|   }
 | |
| 
 | |
|   sprintf(query,"CREATE USER 'u'@'%s' IDENTIFIED BY 'password'",normalized_addr);
 | |
|   rc= mysql_query(mysql, query);
 | |
|   myquery(rc);
 | |
| 
 | |
|   header_data[0]= text_header;
 | |
|   header_data[1]= &v2_header;
 | |
| 
 | |
|   header_lengths[0]= strlen(text_header);
 | |
|   header_lengths[1]= family == AF_INET ? 28 : 52;
 | |
| 
 | |
|   for (i = 0; i < 2; i++)
 | |
|   {
 | |
|     MYSQL *m;
 | |
|     size_t addrlen;
 | |
|     MYSQL_ROW row;
 | |
|     m = mysql_client_init(NULL);
 | |
|     DIE_UNLESS(m);
 | |
|     mysql_optionsv(m, MARIADB_OPT_PROXY_HEADER, header_data[i], header_lengths[i]);
 | |
|     if (!mysql_real_connect(m, opt_host, "u", "password", NULL, opt_port, opt_unix_socket, 0))
 | |
|     {
 | |
|        DIE_UNLESS(0);
 | |
|     }
 | |
|     rc= mysql_query(m, "select host from information_schema.processlist WHERE ID = connection_id()");
 | |
|     myquery(rc);
 | |
|     /* get the result */
 | |
|     result= mysql_store_result(m);
 | |
|     mytest(result);
 | |
|     row = mysql_fetch_row(result);
 | |
|     addrlen = strlen(normalized_addr);
 | |
|     printf("%.*s %.*s\n", (int)addrlen, row[0], (int)addrlen, normalized_addr);
 | |
|     DIE_UNLESS(strncmp(row[0], normalized_addr, addrlen) == 0);
 | |
|     DIE_UNLESS(atoi(row[0] + addrlen+1) == port);
 | |
|     mysql_free_result(result);
 | |
|     if (i == 0 && !strcmp(ipaddr,"192.0.2.1"))
 | |
|     {
 | |
|      /* do "dirty" close, to get aborted message in error log.*/
 | |
|       mariadb_cancel(m);
 | |
|     }
 | |
|     mysql_close(m);
 | |
|   }
 | |
|   sprintf(query,"DROP USER 'u'@'%s'",normalized_addr);
 | |
|   rc = mysql_query(mysql, query);
 | |
|   myquery(rc);
 | |
| }
 | |
| 
 | |
| 
 | |
| /* Test proxy protocol with AF_UNIX (localhost) */
 | |
| static void test_proxy_header_localhost()
 | |
| {
 | |
|   v2_proxy_header v2_header;
 | |
|   void *header_data = &v2_header;
 | |
|   size_t header_length= 216 + 16;
 | |
|   MYSQL *m;
 | |
|   MYSQL_RES *result;
 | |
|   MYSQL_ROW row;
 | |
|   int rc;
 | |
|   myheader("test_proxy_header_localhost");
 | |
| 
 | |
|   memset(&v2_header, 0, sizeof(v2_header));
 | |
|   memcpy(v2_header.sig, "\x0D\x0A\x0D\x0A\x00\x0D\x0A\x51\x55\x49\x54\x0A", 12);
 | |
|   v2_header.ver_cmd = (0x2 << 4) | 0x1; /* Version (0x2) , Command = PROXY (0x1) */
 | |
|   v2_header.fam= 0x31;
 | |
|   v2_header.len= htons(216);
 | |
|   strcpy(v2_header.addr.unx.src_addr,"/tmp/mysql.sock");
 | |
|   strcpy(v2_header.addr.unx.dst_addr,"/tmp/mysql.sock");
 | |
|   rc = mysql_query(mysql, "CREATE USER 'u'@'localhost' IDENTIFIED BY 'password'");
 | |
|   myquery(rc);
 | |
|   m = mysql_client_init(NULL);
 | |
|   DIE_UNLESS(m != NULL);
 | |
|   mysql_optionsv(m, MARIADB_OPT_PROXY_HEADER, header_data, header_length);
 | |
|   DIE_UNLESS(mysql_real_connect(m, opt_host, "u", "password", NULL, opt_port, opt_unix_socket, 0) == m);
 | |
|   DIE_UNLESS(mysql_query(m, "select host from information_schema.processlist WHERE ID = connection_id()") == 0);
 | |
|   /* get the result */
 | |
|   result= mysql_store_result(m);
 | |
|   mytest(result);
 | |
|   row = mysql_fetch_row(result);
 | |
|   DIE_UNLESS(strcmp(row[0], "localhost") == 0);
 | |
|   mysql_free_result(result);
 | |
|   mysql_close(m);
 | |
|   rc = mysql_query(mysql,  "DROP USER 'u'@'localhost'");
 | |
|   myquery(rc);
 | |
| }
 | |
| 
 | |
| /* Proxy header ignoring */
 | |
| static void test_proxy_header_ignore()
 | |
| {
 | |
|   int rc;
 | |
|   MYSQL *m = mysql_client_init(NULL);
 | |
|   v2_proxy_header v2_header;
 | |
|   myheader("test_ps_params_in_ctes");
 | |
|   DIE_UNLESS(m != NULL);
 | |
|   mysql_optionsv(m, MARIADB_OPT_PROXY_HEADER, "PROXY UNKNOWN\r\n",15);
 | |
|   DIE_UNLESS(mysql_real_connect(m, opt_host, "root", "", NULL, opt_port, opt_unix_socket, 0) == m);
 | |
|   mysql_close(m);
 | |
| 
 | |
|   memcpy(v2_header.sig, "\x0D\x0A\x0D\x0A\x00\x0D\x0A\x51\x55\x49\x54\x0A", 12);
 | |
|   v2_header.ver_cmd = (0x2 << 4) | 0x0; /* Version (0x2) , Command = LOCAL (0x0) */
 | |
|   v2_header.fam= 0x0; /* AF_UNSPEC*/
 | |
|   v2_header.len= htons(0);
 | |
|   m = mysql_client_init(NULL);
 | |
|   mysql_optionsv(m, MARIADB_OPT_PROXY_HEADER, &v2_header,16);
 | |
|   DIE_UNLESS(mysql_real_connect(m, opt_host, "root", "", NULL, opt_port, opt_unix_socket, 0) == m);
 | |
|   mysql_close(m);
 | |
| 
 | |
|   /* test for connection denied with empty proxy_protocol_networks */
 | |
|   rc = mysql_query(mysql, "select @@proxy_protocol_networks into @sv_proxy_protocol_networks");
 | |
|   myquery(rc);
 | |
|   mysql_query(mysql, "set global proxy_protocol_networks=default");
 | |
|   myquery(rc);
 | |
|   m = mysql_client_init(NULL);
 | |
|   mysql_optionsv(m, MARIADB_OPT_PROXY_HEADER, &v2_header,16);
 | |
|   DIE_UNLESS(mysql_real_connect(m, opt_host, "root", "", NULL, opt_port, opt_unix_socket, 0) == 0);
 | |
|   mysql_close(m);
 | |
|   mysql_query(mysql, "set global proxy_protocol_networks= @sv_proxy_protocol_networks");
 | |
|   myquery(rc);
 | |
| }
 | |
| 
 | |
| 
 | |
| static void test_proxy_header()
 | |
| {
 | |
|   myheader("test_proxy_header");
 | |
|   test_proxy_header_tcp("192.0.2.1",3333);
 | |
|   test_proxy_header_tcp("2001:db8:85a3::8a2e:370:7334",2222);
 | |
|   test_proxy_header_tcp("::ffff:192.0.2.1",2222);
 | |
|   test_proxy_header_localhost();
 | |
|   test_proxy_header_ignore();
 | |
| }
 | |
| 
 | |
| 
 | |
| static void test_bulk_autoinc()
 | |
| {
 | |
|   int rc;
 | |
|   MYSQL_STMT *stmt;
 | |
|   MYSQL_BIND bind[1];
 | |
|   MYSQL_ROW  row;
 | |
|   char       indicator[]= {0, STMT_INDICATOR_NULL, 0/*STMT_INDICATOR_IGNORE*/};
 | |
|   my_bool   error[1];
 | |
|   int        i, id[]= {2, 3, 777}, count= sizeof(id)/sizeof(id[0]);
 | |
|   MYSQL_RES *result;
 | |
| 
 | |
|   myheader("test_bulk_autoinc");
 | |
|   rc= mysql_query(mysql, "DROP TABLE IF EXISTS ai_field_value");
 | |
|   myquery(rc);
 | |
|   rc= mysql_query(mysql, "CREATE TABLE ai_field_value (id int not null primary key auto_increment)");
 | |
|   myquery(rc);
 | |
|   stmt= mysql_stmt_init(mysql);
 | |
|   rc= mysql_stmt_prepare(stmt, "INSERT INTO ai_field_value(id) values(?)", -1);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   memset(bind, 0, sizeof(bind));
 | |
|   bind[0].buffer_type = MYSQL_TYPE_LONG;
 | |
|   bind[0].buffer = (void *)id;
 | |
|   bind[0].buffer_length = 0;
 | |
|   bind[0].is_null = NULL;
 | |
|   bind[0].length = NULL;
 | |
|   bind[0].error = error;
 | |
|   bind[0].u.indicator= indicator;
 | |
| 
 | |
|   mysql_stmt_attr_set(stmt, STMT_ATTR_ARRAY_SIZE, (void*)&count);
 | |
|   rc= mysql_stmt_bind_param(stmt, bind);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   mysql_stmt_close(stmt);
 | |
| 
 | |
|   rc= mysql_query(mysql, "SELECT id FROM ai_field_value");
 | |
|   myquery(rc);
 | |
| 
 | |
|   result= mysql_store_result(mysql);
 | |
|   mytest(result);
 | |
| 
 | |
|   i= 0;
 | |
|   while ((row= mysql_fetch_row(result)))
 | |
|   {
 | |
|     DIE_IF(atoi(row[0]) != id[i++]);
 | |
|   }
 | |
|   mysql_free_result(result);
 | |
|   rc= mysql_query(mysql, "DROP TABLE ai_field_value");
 | |
|   myquery(rc);
 | |
| }
 | |
| 
 | |
| static void test_bulk_delete()
 | |
| {
 | |
|   int rc;
 | |
|   MYSQL_STMT *stmt;
 | |
|   MYSQL_BIND bind[1];
 | |
|   MYSQL_ROW  row;
 | |
|   char       indicator[]= {0, 0, 0};
 | |
|   my_bool   error[1];
 | |
|   int        i, id[]= {1, 2, 4}, count= sizeof(id)/sizeof(id[0]);
 | |
|   MYSQL_RES *result;
 | |
| 
 | |
|   myheader("test_bulk_delete");
 | |
|   rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1");
 | |
|   myquery(rc);
 | |
|   rc= mysql_query(mysql, "CREATE TABLE t1 (id int not null primary key)");
 | |
|   myquery(rc);
 | |
|   rc= mysql_query(mysql, "INSERT INTO t1 VALUES (1),(2),(3),(4)");
 | |
|   myquery(rc);
 | |
|   verify_affected_rows(4);
 | |
| 
 | |
|   stmt= mysql_stmt_init(mysql);
 | |
|   rc= mysql_stmt_prepare(stmt, "DELETE FROM t1 where id=?", -1);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   memset(bind, 0, sizeof(bind));
 | |
|   bind[0].buffer_type = MYSQL_TYPE_LONG;
 | |
|   bind[0].buffer = (void *)id;
 | |
|   bind[0].buffer_length = 0;
 | |
|   bind[0].is_null = NULL;
 | |
|   bind[0].length = NULL;
 | |
|   bind[0].error = error;
 | |
|   bind[0].u.indicator= indicator;
 | |
| 
 | |
|   mysql_stmt_attr_set(stmt, STMT_ATTR_ARRAY_SIZE, (void*)&count);
 | |
|   rc= mysql_stmt_bind_param(stmt, bind);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
|   verify_affected_rows(3);
 | |
| 
 | |
|   mysql_stmt_close(stmt);
 | |
| 
 | |
|   rc= mysql_query(mysql, "SELECT id FROM t1");
 | |
|   myquery(rc);
 | |
| 
 | |
|   result= mysql_store_result(mysql);
 | |
|   mytest(result);
 | |
| 
 | |
|   i= 0;
 | |
|   while ((row= mysql_fetch_row(result)))
 | |
|   {
 | |
|     i++;
 | |
|     DIE_IF(atoi(row[0]) != 3);
 | |
|   }
 | |
|   DIE_IF(i != 1);
 | |
|   mysql_free_result(result);
 | |
| 
 | |
|   rc= mysql_query(mysql, "DROP TABLE t1");
 | |
|   myquery(rc);
 | |
| }
 | |
| 
 | |
| static void test_bulk_replace()
 | |
| {
 | |
|   int rc;
 | |
|   MYSQL_STMT *stmt;
 | |
|   MYSQL_BIND bind[2];
 | |
|   MYSQL_ROW  row;
 | |
|   int        i,
 | |
|              id[]= {1, 2, 3, 4},
 | |
|              val[]= {1, 1, 1, 1},
 | |
|              count= sizeof(id)/sizeof(id[0]);
 | |
|   MYSQL_RES *result;
 | |
| 
 | |
|   myheader("test_bulk_replace");
 | |
|   rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1");
 | |
|   myquery(rc);
 | |
|   rc= mysql_query(mysql, "CREATE TABLE t1 (id int not null primary key, active int)");
 | |
|   myquery(rc);
 | |
|   rc= mysql_query(mysql, "insert into t1 values (1, 0), (2, 0), (3, 0)");
 | |
|   myquery(rc);
 | |
|   verify_affected_rows(3);
 | |
| 
 | |
|   stmt= mysql_stmt_init(mysql);
 | |
|   rc= mysql_stmt_prepare(stmt, "replace into t1 (id, active) values (?, ?)", -1);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   memset(bind, 0, sizeof(bind));
 | |
|   bind[0].buffer_type = MYSQL_TYPE_LONG;
 | |
|   bind[0].buffer = (void *)id;
 | |
|   bind[0].buffer_length = 0;
 | |
|   bind[1].buffer_type = MYSQL_TYPE_LONG;
 | |
|   bind[1].buffer = (void *)val;
 | |
|   bind[1].buffer_length = 0;
 | |
| 
 | |
|   mysql_stmt_attr_set(stmt, STMT_ATTR_ARRAY_SIZE, (void*)&count);
 | |
|   rc= mysql_stmt_bind_param(stmt, bind);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   mysql_stmt_close(stmt);
 | |
| 
 | |
|   rc= mysql_query(mysql, "SELECT active FROM t1");
 | |
|   myquery(rc);
 | |
| 
 | |
|   result= mysql_store_result(mysql);
 | |
|   mytest(result);
 | |
| 
 | |
|   i= 0;
 | |
|   while ((row= mysql_fetch_row(result)))
 | |
|   {
 | |
|     i++;
 | |
|     DIE_IF(atoi(row[0]) != 1);
 | |
|   }
 | |
|   DIE_IF(i != 4);
 | |
|   mysql_free_result(result);
 | |
| 
 | |
|   rc= mysql_query(mysql, "DROP TABLE t1");
 | |
|   myquery(rc);
 | |
| }
 | |
| 
 | |
| 
 | |
| static void test_bulk_insert_returning()
 | |
| {
 | |
|   int rc;
 | |
|   MYSQL_STMT *stmt;
 | |
|   MYSQL_BIND bind[2], res_bind[2];
 | |
|   MYSQL_ROW  row;
 | |
|   MYSQL_RES *result;
 | |
|   int        i,
 | |
|              id[]= {1, 2, 3, 4},
 | |
|              val[]= {1, 1, 1, 1},
 | |
|              count= sizeof(id)/sizeof(id[0]);
 | |
|   unsigned long length[2];
 | |
|   my_bool       is_null[2];
 | |
|   my_bool       error[2];
 | |
|   int32         res[2];
 | |
| 
 | |
|   rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1");
 | |
|   myquery(rc);
 | |
|   rc= mysql_query(mysql,
 | |
|                   "CREATE TABLE t1 (id int not null primary key, active int)");
 | |
|   myquery(rc);
 | |
| 
 | |
|   stmt= mysql_stmt_init(mysql);
 | |
|   rc= mysql_stmt_prepare(stmt,
 | |
|                          "insert into t1  values (?, ?) returning id, active",
 | |
|                          -1);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   memset(bind, 0, sizeof(bind));
 | |
|   bind[0].buffer_type = MYSQL_TYPE_LONG;
 | |
|   bind[0].buffer = (void *)id;
 | |
|   bind[0].buffer_length = 0;
 | |
|   bind[1].buffer_type = MYSQL_TYPE_LONG;
 | |
|   bind[1].buffer = (void *)val;
 | |
|   bind[1].buffer_length = 0;
 | |
| 
 | |
|   mysql_stmt_attr_set(stmt, STMT_ATTR_ARRAY_SIZE, (void*)&count);
 | |
|   rc= mysql_stmt_bind_param(stmt, bind);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   myquery(rc);
 | |
| 
 | |
|   memset(res_bind, 0, sizeof(res_bind));
 | |
|   for (i= 0; i < 2; i++)
 | |
|   {
 | |
|     res_bind[i].buffer_type= MYSQL_TYPE_LONG;
 | |
|     res_bind[i].buffer= (char *)&res[i];
 | |
|     res_bind[i].is_null= &is_null[i];
 | |
|     res_bind[i].length= &length[i];
 | |
|     res_bind[i].error= &error[i];
 | |
|   }
 | |
|   rc= mysql_stmt_bind_result(stmt, res_bind);
 | |
|   myquery(rc);
 | |
|   rc= mysql_stmt_store_result(stmt);
 | |
|   myquery(rc);
 | |
| 
 | |
|   i= 0;
 | |
|   while (!mysql_stmt_fetch(stmt))
 | |
|   {
 | |
|     i++;
 | |
|     DIE_IF(is_null[0] || is_null[1]);
 | |
|     DIE_IF(res[0] != i);
 | |
|     DIE_IF(res[1] != 1);
 | |
|   }
 | |
|   DIE_IF(i != 4);
 | |
| 
 | |
|   mysql_stmt_close(stmt);
 | |
| 
 | |
|   rc= mysql_query(mysql, "SELECT id,active FROM t1");
 | |
|   myquery(rc);
 | |
| 
 | |
|   result= mysql_store_result(mysql);
 | |
|   mytest(result);
 | |
| 
 | |
|   i= 0;
 | |
|   while ((row= mysql_fetch_row(result)))
 | |
|   {
 | |
|     i++;
 | |
|     DIE_IF(atoi(row[0]) != i);
 | |
|     DIE_IF(atoi(row[1]) != 1);
 | |
|   }
 | |
|   DIE_IF(i != 4);
 | |
|   mysql_free_result(result);
 | |
| 
 | |
| 
 | |
|   rc= mysql_query(mysql, "DROP TABLE t1");
 | |
|   myquery(rc);
 | |
| }
 | |
| 
 | |
| static void test_bulk_delete_returning()
 | |
| {
 | |
|   int rc;
 | |
|   MYSQL_STMT *stmt;
 | |
|   MYSQL_BIND bind[2], res_bind[2];
 | |
|   MYSQL_ROW  row;
 | |
|   MYSQL_RES *result;
 | |
|   int        i,
 | |
|              id[]= {1, 2, 3, 4},
 | |
|              count= sizeof(id)/sizeof(id[0]);
 | |
|   unsigned long length[1];
 | |
|   my_bool       is_null[1];
 | |
|   my_bool       error[1];
 | |
|   int32         res[1];
 | |
| 
 | |
|   rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1");
 | |
|   myquery(rc);
 | |
|   rc= mysql_query(mysql, "CREATE TABLE t1 (id int not null primary key)");
 | |
|   myquery(rc);
 | |
|   rc= mysql_query(mysql, "insert into t1 values (1), (2), (3), (4)");
 | |
|   myquery(rc);
 | |
|   verify_affected_rows(4);
 | |
| 
 | |
|   stmt= mysql_stmt_init(mysql);
 | |
|   rc= mysql_stmt_prepare(stmt, "DELETE FROM t1 WHERE id=? RETURNING id", -1);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   memset(bind, 0, sizeof(bind));
 | |
|   bind[0].buffer_type = MYSQL_TYPE_LONG;
 | |
|   bind[0].buffer = (void *)id;
 | |
|   bind[0].buffer_length = 0;
 | |
| 
 | |
|   mysql_stmt_attr_set(stmt, STMT_ATTR_ARRAY_SIZE, (void*)&count);
 | |
|   rc= mysql_stmt_bind_param(stmt, bind);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   myquery(rc);
 | |
| 
 | |
|   memset(res_bind, 0, sizeof(res_bind));
 | |
|   res_bind[0].buffer_type= MYSQL_TYPE_LONG;
 | |
|   res_bind[0].buffer= (char *)&res[0];
 | |
|   res_bind[0].is_null= &is_null[0];
 | |
|   res_bind[0].length= &length[0];
 | |
|   res_bind[0].error= &error[0];
 | |
|   rc= mysql_stmt_bind_result(stmt, res_bind);
 | |
|   myquery(rc);
 | |
|   rc= mysql_stmt_store_result(stmt);
 | |
|   myquery(rc);
 | |
| 
 | |
|   i= 0;
 | |
|   while (!mysql_stmt_fetch(stmt))
 | |
|   {
 | |
|     i++;
 | |
|     DIE_IF(is_null[0]);
 | |
|     DIE_IF(res[0] != i);
 | |
|   }
 | |
|   DIE_IF(i != 4);
 | |
| 
 | |
|   mysql_stmt_close(stmt);
 | |
| 
 | |
|   rc= mysql_query(mysql, "SELECT id FROM t1");
 | |
|   myquery(rc);
 | |
| 
 | |
|   result= mysql_store_result(mysql);
 | |
|   mytest(result);
 | |
| 
 | |
|   i= 0;
 | |
|   while ((row= mysql_fetch_row(result)))
 | |
|   {
 | |
|     i++;
 | |
|     printf("\nResult (SHOULD NOT BE HERE!!!) %d %s \n", i, row[0]);
 | |
|   }
 | |
|   DIE_IF(i != 0 );
 | |
|   mysql_free_result(result);
 | |
| 
 | |
| 
 | |
|   rc= mysql_query(mysql, "DROP TABLE t1");
 | |
|   myquery(rc);
 | |
| }
 | |
| #endif
 | |
| 
 | |
| 
 | |
| static void test_ps_params_in_ctes()
 | |
| {
 | |
|   int rc;
 | |
|   const char *query;
 | |
|   MYSQL_BIND ps_params[1];
 | |
|   int int_data[1];
 | |
|   MYSQL_STMT *stmt;
 | |
| 
 | |
|   myheader("test_ps_params_in_ctes");
 | |
|   rc= mysql_query(mysql, "create table t1(a int, b int, key(a))");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "insert into t1 (a) values "
 | |
|                          "(0),(1),(2),(3),(4),(5),(6),(7),(8),(9)");
 | |
|   myquery(rc);
 | |
| 
 | |
|   query=
 | |
|     "explain "
 | |
|     "with T as "
 | |
|     "( "
 | |
|     "  select * from t1 where t1.a=? limit 2 "
 | |
|     ") "
 | |
|     "select * from T as TA, T as TB;";
 | |
| 
 | |
|   stmt= mysql_stmt_init(mysql);
 | |
|   check_stmt(stmt);
 | |
| 
 | |
|   rc= mysql_stmt_prepare(stmt, query, (uint) strlen(query));
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   int_data[0]=2;
 | |
| 
 | |
|   memset(ps_params, 0, sizeof ps_params);
 | |
|   ps_params[0].buffer_type= MYSQL_TYPE_LONG;
 | |
|   ps_params[0].buffer= (char *) &int_data[0];
 | |
|   ps_params[0].length= 0;
 | |
|   ps_params[0].is_null= 0;
 | |
| 
 | |
|   rc= mysql_stmt_bind_param(stmt, ps_params);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= mysql_stmt_store_result(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   mysql_stmt_close(stmt);
 | |
| 
 | |
|   rc= mysql_query(mysql, "drop table t1");
 | |
|   myquery(rc);
 | |
| }
 | |
| 
 | |
| void display_result_metadata(MYSQL_FIELD *field,
 | |
|                              uint num_fields)
 | |
| {
 | |
|   MYSQL_FIELD* field_end;
 | |
| 
 | |
|   mct_log("Catalog\tDatabase\tTable\tTable_alias\tColumn\t"
 | |
|           "Column_alias\tType\tLength\tMax length\tIs_null\t"
 | |
|           "Flags\tDecimals\tCharsetnr\n");
 | |
|   for (field_end= field+num_fields; field < field_end; field++)
 | |
|   {
 | |
|     mct_log("%s\t", field->catalog);
 | |
|     mct_log("%s\t", field->db);
 | |
|     mct_log("%s\t", field->org_table);
 | |
|     mct_log("%s\t", field->table);
 | |
|     mct_log("%s\t", field->org_name);
 | |
|     mct_log("%s\t", field->name);
 | |
|     mct_log("%u\t", field->type);
 | |
|     mct_log("%lu\t", field->length);
 | |
|     mct_log("%lu\t", field->max_length);
 | |
|     mct_log("%s\t", (IS_NOT_NULL(field->flags) ?  "N" : "Y"));
 | |
|     mct_log("%u\t", field->flags);
 | |
|     mct_log("%u\t", field->decimals);
 | |
|     mct_log("%u\n", field->charsetnr);
 | |
|   }
 | |
| }
 | |
| 
 | |
| static void test_mdev_26145()
 | |
| {
 | |
|   MYSQL_STMT *stmt;
 | |
|   MYSQL_RES *result;
 | |
|   MYSQL_FIELD *fields;
 | |
|   int        rc, num_fields;
 | |
| 
 | |
|   myheader("test_mdev_26145");
 | |
| 
 | |
|   rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "CREATE TABLE t1(a INT)");
 | |
|   myquery(rc);
 | |
| 
 | |
|   stmt= mysql_simple_prepare(
 | |
|     mysql, "(SELECT MAX(a) FROM t1) UNION (SELECT MAX(a) FROM t1)");
 | |
|   check_stmt(stmt);
 | |
| 
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   result= mysql_stmt_result_metadata(stmt);
 | |
|   DIE_UNLESS(result);
 | |
| 
 | |
|   num_fields= mysql_stmt_field_count(stmt);
 | |
|   fields= mysql_fetch_fields(result);
 | |
| 
 | |
|   mct_start_logging("test_mdev26145");
 | |
|   display_result_metadata(fields, num_fields);
 | |
|   mct_close_log();
 | |
| 
 | |
|   mysql_free_result(result);
 | |
|   mysql_stmt_close(stmt);
 | |
| 
 | |
|   rc= mysql_query(mysql, "DROP TABLE t1");
 | |
| 
 | |
|   myquery(rc);
 | |
| }
 | |
| 
 | |
| static void test_mdev24827()
 | |
| {
 | |
|   int rc;
 | |
|   MYSQL_STMT *stmt;
 | |
|   unsigned long cursor = CURSOR_TYPE_READ_ONLY;
 | |
|   const char* query=
 | |
|     "SELECT t2.c1 AS c1 FROM t1 LEFT JOIN t2 ON t1.c1 = t2.c1 "
 | |
|     "WHERE EXISTS (SELECT 1 FROM t1 WHERE c2 = -1) ORDER BY c1";
 | |
| 
 | |
|   myheader("test_mdev24827");
 | |
| 
 | |
|   rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "DROP TABLE IF EXISTS t2");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "CREATE TABLE t1 (c1 INT PRIMARY KEY, c2 INT)");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "CREATE TABLE t2 (c1 INT PRIMARY KEY, c2 INT, "
 | |
|                   "KEY idx_c2(c2))");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "INSERT INTO t1 (c1, c2) "
 | |
|                   "SELECT seq, seq FROM seq_1_to_10000");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "INSERT INTO t2 (c1, c2) "
 | |
|                   "SELECT seq, seq FROM seq_1_to_20000");
 | |
|   myquery(rc);
 | |
| 
 | |
|   stmt= mysql_stmt_init(mysql);
 | |
|   check_stmt(stmt);
 | |
| 
 | |
|   rc= mysql_stmt_prepare(stmt, query, strlen(query));
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= mysql_stmt_attr_set(stmt, STMT_ATTR_CURSOR_TYPE, &cursor);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
|   mysql_stmt_close(stmt);
 | |
| 
 | |
|   rc= mysql_query(mysql, "DROP TABLE t1");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "DROP TABLE t2");
 | |
|   myquery(rc);
 | |
| }
 | |
| 
 | |
| static void test_mdev_20516()
 | |
| {
 | |
|   MYSQL_STMT *stmt;
 | |
|   int        rc;
 | |
|   unsigned long cursor= CURSOR_TYPE_READ_ONLY;
 | |
|   const char* query=
 | |
|     "CREATE VIEW v1 AS SELECT * FROM t1";
 | |
| 
 | |
|   myheader("test_mdev_20516");
 | |
| 
 | |
|   rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "CREATE TABLE t1(a INT)");
 | |
|   myquery(rc);
 | |
| 
 | |
|   stmt= mysql_stmt_init(mysql);
 | |
|   check_stmt(stmt);
 | |
| 
 | |
|   rc= mysql_stmt_prepare(stmt, query, strlen(query));
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= mysql_stmt_attr_set(stmt, STMT_ATTR_CURSOR_TYPE, &cursor);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
|   mysql_stmt_close(stmt);
 | |
| 
 | |
|   rc= mysql_query(mysql, "DROP TABLE t1");
 | |
|   myquery(rc);
 | |
| }
 | |
| 
 | |
| static void print_metadata(MYSQL_RES *rs_metadata, int num_fields)
 | |
| {
 | |
|   int i;
 | |
|   MYSQL_FIELD *fields= mysql_fetch_fields(rs_metadata);
 | |
| 
 | |
|   for (i = 0; i < num_fields; ++i)
 | |
|   {
 | |
|     mct_log("  - %d: name: '%s'/'%s'; table: '%s'/'%s'; "
 | |
|         "db: '%s'; catalog: '%s'; length: %d; max_length: %d; "
 | |
|         "type: %d; decimals: %d\n",
 | |
|         (int) i,
 | |
|         (const char *) fields[i].name,
 | |
|         (const char *) fields[i].org_name,
 | |
|         (const char *) fields[i].table,
 | |
|         (const char *) fields[i].org_table,
 | |
|         (const char *) fields[i].db,
 | |
|         (const char *) fields[i].catalog,
 | |
|         (int) fields[i].length,
 | |
|         (int) fields[i].max_length,
 | |
|         (int) fields[i].type,
 | |
|         (int) fields[i].decimals);
 | |
| 
 | |
|   }
 | |
| }
 | |
| 
 | |
| static void test_explain_meta()
 | |
| {
 | |
|   MYSQL_STMT *stmt;
 | |
|   int num_fields;
 | |
|   char query[MAX_TEST_QUERY_LENGTH];
 | |
|   MYSQL_RES *rs_metadata;
 | |
|   int rc;
 | |
| 
 | |
|   myheader("test_explain_meta");
 | |
|   mct_start_logging("test_explain_meta");
 | |
| 
 | |
|   strmov(query, "SELECT 1");
 | |
|   stmt= mysql_simple_prepare(mysql, query);
 | |
|   check_stmt(stmt);
 | |
| 
 | |
|   rs_metadata= mysql_stmt_result_metadata(stmt);
 | |
| 
 | |
|   num_fields= mysql_stmt_field_count(stmt);
 | |
|   mct_log("SELECT number of fields: %d\n", (int) num_fields);
 | |
|   if (num_fields != 1)
 | |
|   {
 | |
|     mct_close_log();
 | |
|     DIE("num_fields != 1");
 | |
|   }
 | |
|   mysql_free_result(rs_metadata);
 | |
|   mysql_stmt_close(stmt);
 | |
| 
 | |
|   strmov(query, "EXPLAIN SELECT 1");
 | |
|   stmt= mysql_simple_prepare(mysql, query);
 | |
|   check_stmt(stmt);
 | |
| 
 | |
|   rs_metadata= mysql_stmt_result_metadata(stmt);
 | |
| 
 | |
|   num_fields= mysql_stmt_field_count(stmt);
 | |
|   mct_log("EXPALIN number of fields: %d\n", (int) num_fields);
 | |
|   if (num_fields != 10)
 | |
|   {
 | |
|     mct_close_log();
 | |
|     DIE("num_fields != 10");
 | |
|   }
 | |
|   print_metadata(rs_metadata, num_fields);
 | |
|   mysql_free_result(rs_metadata);
 | |
|   mysql_stmt_close(stmt);
 | |
| 
 | |
|   strmov(query, "EXPLAIN format=json SELECT 1");
 | |
|   stmt= mysql_simple_prepare(mysql, query);
 | |
|   check_stmt(stmt);
 | |
| 
 | |
|   rs_metadata= mysql_stmt_result_metadata(stmt);
 | |
| 
 | |
|   num_fields= mysql_stmt_field_count(stmt);
 | |
|   mct_log("EXPALIN JSON number of fields: %d\n", (int) num_fields);
 | |
|   if (num_fields != 1)
 | |
|   {
 | |
|     mct_close_log();
 | |
|     DIE("num_fields != 1");
 | |
|   }
 | |
|   print_metadata(rs_metadata, num_fields);
 | |
|   mysql_free_result(rs_metadata);
 | |
|   mysql_stmt_close(stmt);
 | |
| 
 | |
| 
 | |
|   strmov(query, "ANALYZE SELECT 1");
 | |
|   stmt= mysql_simple_prepare(mysql, query);
 | |
|   check_stmt(stmt);
 | |
| 
 | |
|   rs_metadata= mysql_stmt_result_metadata(stmt);
 | |
| 
 | |
|   num_fields= mysql_stmt_field_count(stmt);
 | |
|   mct_log("ANALYZE number of fields: %d\n", (int) num_fields);
 | |
|   if (num_fields != 13)
 | |
|   {
 | |
|     mct_close_log();
 | |
|     DIE("num_fields != 13");
 | |
|   }
 | |
|   print_metadata(rs_metadata, num_fields);
 | |
|   mysql_free_result(rs_metadata);
 | |
|   mysql_stmt_close(stmt);
 | |
| 
 | |
|   strmov(query, "ANALYZE format=json SELECT 1");
 | |
|   stmt= mysql_simple_prepare(mysql, query);
 | |
|   check_stmt(stmt);
 | |
| 
 | |
|   rs_metadata= mysql_stmt_result_metadata(stmt);
 | |
| 
 | |
|   num_fields= mysql_stmt_field_count(stmt);
 | |
|   mct_log("ANALYZE JSON number of fields: %d\n", (int) num_fields);
 | |
|   if (num_fields != 1)
 | |
|   {
 | |
|     mct_close_log();
 | |
|     DIE("num_fields != 1");
 | |
|   }
 | |
|   print_metadata(rs_metadata, num_fields);
 | |
|   mysql_free_result(rs_metadata);
 | |
|   mysql_stmt_close(stmt);
 | |
| 
 | |
|   rc= mysql_query(mysql, "CREATE TABLE t1 (a int)");
 | |
|   myquery(rc);
 | |
| 
 | |
|   strmov(query, "EXPLAIN INSERT INTO t1 values (1)");
 | |
|   stmt= mysql_simple_prepare(mysql, query);
 | |
|   check_stmt(stmt);
 | |
| 
 | |
|   rs_metadata= mysql_stmt_result_metadata(stmt);
 | |
| 
 | |
|   num_fields= mysql_stmt_field_count(stmt);
 | |
|   mct_log("EXPALIN INSERT number of fields: %d\n", (int) num_fields);
 | |
|   if (num_fields != 10)
 | |
|   {
 | |
|     mct_close_log();
 | |
|     DIE("num_fields != 10");
 | |
|   }
 | |
|   print_metadata(rs_metadata, num_fields);
 | |
|   mysql_free_result(rs_metadata);
 | |
|   mysql_stmt_close(stmt);
 | |
| 
 | |
|   strmov(query, "EXPLAIN format=json INSERT INTO t1 values(1)");
 | |
|   stmt= mysql_simple_prepare(mysql, query);
 | |
|   check_stmt(stmt);
 | |
| 
 | |
|   rs_metadata= mysql_stmt_result_metadata(stmt);
 | |
| 
 | |
|   num_fields= mysql_stmt_field_count(stmt);
 | |
|   mct_log("EXPALIN JSON INSERT number of fields: %d\n", (int) num_fields);
 | |
|   if (num_fields != 1)
 | |
|   {
 | |
|     mct_close_log();
 | |
|     DIE("num_fields != 1");
 | |
|   }
 | |
|   print_metadata(rs_metadata, num_fields);
 | |
|   mysql_free_result(rs_metadata);
 | |
|   mysql_stmt_close(stmt);
 | |
| 
 | |
| 
 | |
|   strmov(query, "ANALYZE INSERT INTO t1 values(1)");
 | |
|   stmt= mysql_simple_prepare(mysql, query);
 | |
|   check_stmt(stmt);
 | |
| 
 | |
|   rs_metadata= mysql_stmt_result_metadata(stmt);
 | |
| 
 | |
|   num_fields= mysql_stmt_field_count(stmt);
 | |
|   mct_log("ANALYZE INSERT number of fields: %d\n", (int) num_fields);
 | |
|   if (num_fields != 13)
 | |
|   {
 | |
|     mct_close_log();
 | |
|     DIE("num_fields != 13");
 | |
|   }
 | |
|   print_metadata(rs_metadata, num_fields);
 | |
|   mysql_free_result(rs_metadata);
 | |
|   mysql_stmt_close(stmt);
 | |
| 
 | |
|   strmov(query, "ANALYZE format=json INSERT INTO t1 values(1)");
 | |
|   stmt= mysql_simple_prepare(mysql, query);
 | |
|   check_stmt(stmt);
 | |
| 
 | |
|   rs_metadata= mysql_stmt_result_metadata(stmt);
 | |
| 
 | |
|   num_fields= mysql_stmt_field_count(stmt);
 | |
|   mct_log("ANALYZE JSON INSERT number of fields: %d\n", (int) num_fields);
 | |
|   if (num_fields != 1)
 | |
|   {
 | |
|     mct_close_log();
 | |
|     DIE("num_fields != 1");
 | |
|   }
 | |
|   print_metadata(rs_metadata, num_fields);
 | |
|   mysql_free_result(rs_metadata);
 | |
|   mysql_stmt_close(stmt);
 | |
| 
 | |
| 
 | |
|   strmov(query, "EXPLAIN UPDATE t1 set a=2");
 | |
|   stmt= mysql_simple_prepare(mysql, query);
 | |
|   check_stmt(stmt);
 | |
| 
 | |
|   rs_metadata= mysql_stmt_result_metadata(stmt);
 | |
| 
 | |
|   num_fields= mysql_stmt_field_count(stmt);
 | |
|   mct_log("EXPALIN UPDATE number of fields: %d\n", (int) num_fields);
 | |
|   if (num_fields != 10)
 | |
|   {
 | |
|     mct_close_log();
 | |
|     DIE("num_fields != 10");
 | |
|   }
 | |
|   print_metadata(rs_metadata, num_fields);
 | |
|   mysql_free_result(rs_metadata);
 | |
|   mysql_stmt_close(stmt);
 | |
| 
 | |
|   strmov(query, "EXPLAIN format=json  UPDATE t1 set a=2");
 | |
|   stmt= mysql_simple_prepare(mysql, query);
 | |
|   check_stmt(stmt);
 | |
| 
 | |
|   rs_metadata= mysql_stmt_result_metadata(stmt);
 | |
| 
 | |
|   num_fields= mysql_stmt_field_count(stmt);
 | |
|   mct_log("EXPALIN JSON UPDATE number of fields: %d\n", (int) num_fields);
 | |
|   if (num_fields != 1)
 | |
|   {
 | |
|     mct_close_log();
 | |
|     DIE("num_fields != 1");
 | |
|   }
 | |
|   print_metadata(rs_metadata, num_fields);
 | |
|   mysql_free_result(rs_metadata);
 | |
|   mysql_stmt_close(stmt);
 | |
| 
 | |
| 
 | |
|   strmov(query, "ANALYZE UPDATE t1 set a=2");
 | |
|   stmt= mysql_simple_prepare(mysql, query);
 | |
|   check_stmt(stmt);
 | |
| 
 | |
|   rs_metadata= mysql_stmt_result_metadata(stmt);
 | |
| 
 | |
|   num_fields= mysql_stmt_field_count(stmt);
 | |
|   mct_log("ANALYZE UPDATE number of fields: %d\n", (int) num_fields);
 | |
|   if (num_fields != 13)
 | |
|   {
 | |
|     mct_close_log();
 | |
|     DIE("num_fields != 13");
 | |
|   }
 | |
|   print_metadata(rs_metadata, num_fields);
 | |
|   mysql_free_result(rs_metadata);
 | |
|   mysql_stmt_close(stmt);
 | |
| 
 | |
|   strmov(query, "ANALYZE format=json UPDATE t1 set a=2");
 | |
|   stmt= mysql_simple_prepare(mysql, query);
 | |
|   check_stmt(stmt);
 | |
| 
 | |
|   rs_metadata= mysql_stmt_result_metadata(stmt);
 | |
| 
 | |
|   num_fields= mysql_stmt_field_count(stmt);
 | |
|   mct_log("ANALYZE JSON UPDATE number of fields: %d\n", (int) num_fields);
 | |
|   if (num_fields != 1)
 | |
|   {
 | |
|     mct_close_log();
 | |
|     DIE("num_fields != 1");
 | |
|   }
 | |
|   print_metadata(rs_metadata, num_fields);
 | |
|   mysql_free_result(rs_metadata);
 | |
|   mysql_stmt_close(stmt);
 | |
| 
 | |
| 
 | |
|   strmov(query, "EXPLAIN DELETE FROM t1");
 | |
|   stmt= mysql_simple_prepare(mysql, query);
 | |
|   check_stmt(stmt);
 | |
| 
 | |
|   rs_metadata= mysql_stmt_result_metadata(stmt);
 | |
| 
 | |
|   num_fields= mysql_stmt_field_count(stmt);
 | |
|   mct_log("EXPALIN DELETE number of fields: %d\n", (int) num_fields);
 | |
|   if (num_fields != 10)
 | |
|   {
 | |
|     mct_close_log();
 | |
|     DIE("num_fields != 10");
 | |
|   }
 | |
|   print_metadata(rs_metadata, num_fields);
 | |
|   mysql_free_result(rs_metadata);
 | |
|   mysql_stmt_close(stmt);
 | |
| 
 | |
|   strmov(query, "EXPLAIN format=json DELETE FROM t1");
 | |
|   stmt= mysql_simple_prepare(mysql, query);
 | |
|   check_stmt(stmt);
 | |
| 
 | |
|   rs_metadata= mysql_stmt_result_metadata(stmt);
 | |
| 
 | |
|   num_fields= mysql_stmt_field_count(stmt);
 | |
|   mct_log("EXPALIN JSON DELETE number of fields: %d\n", (int) num_fields);
 | |
|   if (num_fields != 1)
 | |
|   {
 | |
|     mct_close_log();
 | |
|     DIE("num_fields != 1");
 | |
|   }
 | |
|   print_metadata(rs_metadata, num_fields);
 | |
|   mysql_free_result(rs_metadata);
 | |
|   mysql_stmt_close(stmt);
 | |
| 
 | |
| 
 | |
|   strmov(query, "ANALYZE DELETE FROM t1");
 | |
|   stmt= mysql_simple_prepare(mysql, query);
 | |
|   check_stmt(stmt);
 | |
| 
 | |
|   rs_metadata= mysql_stmt_result_metadata(stmt);
 | |
| 
 | |
|   num_fields= mysql_stmt_field_count(stmt);
 | |
|   mct_log("ANALYZE DELETE number of fields: %d\n", (int) num_fields);
 | |
|   if (num_fields != 13)
 | |
|   {
 | |
|     mct_close_log();
 | |
|     DIE("num_fields != 13");
 | |
|   }
 | |
|   print_metadata(rs_metadata, num_fields);
 | |
|   mysql_free_result(rs_metadata);
 | |
|   mysql_stmt_close(stmt);
 | |
| 
 | |
|   strmov(query, "ANALYZE format=json DELETE FROM t1");
 | |
|   stmt= mysql_simple_prepare(mysql, query);
 | |
|   check_stmt(stmt);
 | |
| 
 | |
|   rs_metadata= mysql_stmt_result_metadata(stmt);
 | |
| 
 | |
|   num_fields= mysql_stmt_field_count(stmt);
 | |
|   mct_log("ANALYZE JSON DELETE number of fields: %d\n", (int) num_fields);
 | |
|   if (num_fields != 1)
 | |
|   {
 | |
|     mct_close_log();
 | |
|     DIE("num_fields != 1");
 | |
|   }
 | |
|   print_metadata(rs_metadata, num_fields);
 | |
|   mysql_free_result(rs_metadata);
 | |
|   mysql_stmt_close(stmt);
 | |
| 
 | |
|   rc= mysql_query(mysql, "DROP TABLE t1");
 | |
|   myquery(rc);
 | |
|   mct_close_log();
 | |
| }
 | |
| 
 | |
| static void test_mdev_16128()
 | |
| {
 | |
|   int        rc, res;
 | |
|   MYSQL_STMT *stmt;
 | |
|   MYSQL_BIND bind, bind_res;
 | |
|   char bind_arg_1[]="d", bind_arg_2[]="b";
 | |
|   ulong length= 0;
 | |
|   const char *query=
 | |
|     "SELECT 300 FROM t1 WHERE EXISTS (SELECT 100 FROM t2 WHERE t2.b = ?)";
 | |
| 
 | |
|   myheader("test_mdev_16128");
 | |
| 
 | |
|   rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "DROP TABLE IF EXISTS t2");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "CREATE TABLE t1 (a VARCHAR(10))");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "CREATE TABLE t2 (b VARCHAR(10) CHARACTER SET utf8)");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "INSERT INTO t1 VALUES('b')");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "INSERT INTO t2 VALUES('d')");
 | |
|   myquery(rc);
 | |
| 
 | |
|   stmt= mysql_stmt_init(mysql);
 | |
|   check_stmt(stmt);
 | |
| 
 | |
|   rc= mysql_stmt_prepare(stmt, query, strlen(query));
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   memset(&bind, 0, sizeof(bind));
 | |
|   bind.buffer_type= MYSQL_TYPE_STRING;
 | |
|   bind.buffer_length= strlen(bind_arg_1);
 | |
|   bind.buffer= bind_arg_1;
 | |
| 
 | |
|   rc= mysql_stmt_bind_param(stmt, &bind);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   memset(&bind_res, 0, sizeof(bind_res));
 | |
|   bind_res.buffer_type= MYSQL_TYPE_LONG;
 | |
|   bind_res.buffer= &res;
 | |
|   bind_res.is_null= NULL;
 | |
|   bind_res.length= &length;
 | |
| 
 | |
|   rc= mysql_stmt_bind_result(stmt, &bind_res);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= mysql_stmt_store_result(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= mysql_stmt_fetch(stmt);
 | |
| 
 | |
|   /**
 | |
|     It's expected that the query
 | |
|       SELECT 300 FROM t1 WHERE EXISTS (SELECT 100 FROM t2 WHERE t2.b = ?)"
 | |
|     executed in PS-mode and bound with the value 'd' returns exactly
 | |
|     one row containing the value (300).
 | |
|    */
 | |
|   check_execute(stmt, rc);
 | |
|   DIE_UNLESS(bind_res.buffer_type == MYSQL_TYPE_LONG);
 | |
|   DIE_UNLESS(res == 300);
 | |
| 
 | |
|   memset(&bind, 0, sizeof(bind));
 | |
|   bind.buffer_type= MYSQL_TYPE_STRING;
 | |
|   bind.buffer_length= strlen(bind_arg_2);
 | |
|   bind.buffer= bind_arg_2;
 | |
| 
 | |
|   rc= mysql_stmt_bind_param(stmt, &bind);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= mysql_stmt_store_result(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= mysql_stmt_fetch(stmt);
 | |
|   /**
 | |
|     It's expected that the query
 | |
|       SELECT 300 FROM t1 WHERE EXISTS (SELECT 100 FROM t2 WHERE t2.b = ?)"
 | |
|     executed in PS-mode and bound with the value 'd' returns empty result set.
 | |
|    */
 | |
|   DIE_UNLESS(rc == MYSQL_NO_DATA);
 | |
| 
 | |
|   mysql_stmt_close(stmt);
 | |
| 
 | |
|   rc= mysql_query(mysql, "DROP TABLE t1, t2");
 | |
|   myquery(rc);
 | |
| }
 | |
| 
 | |
| #ifndef EMBEDDED_LIBRARY
 | |
| #define MDEV19838_MAX_PARAM_COUNT 32
 | |
| #define MDEV19838_FIELDS_COUNT 17
 | |
| static void test_mdev19838()
 | |
| {
 | |
|   int rc;
 | |
|   MYSQL_BIND bind[MDEV19838_MAX_PARAM_COUNT];
 | |
|   unsigned int i, paramCount = 1;
 | |
|   char charvalue[] = "012345678901234567890123456789012345";
 | |
|   MYSQL_STMT *stmt;
 | |
| 
 | |
|   myheader("test_mdev19838");
 | |
| 
 | |
|   rc = mysql_query(mysql, "CREATE TABLE mdev19838("
 | |
|           "f1  char(36),"
 | |
|           "f2  char(36),"
 | |
|           "f3  char(36),"
 | |
|           "f4  char(36),"
 | |
|           "f5  char(36),"
 | |
|           "f6  char(36),"
 | |
|           "f7  char(36),"
 | |
|           "f8  char(36),"
 | |
|           "f9  char(36),"
 | |
|           "f10 char(36),"
 | |
|           "f11 char(36),"
 | |
|           "f12 char(36),"
 | |
|           "f13 char(36),"
 | |
|           "f14 char(36),"
 | |
|           "f15 char(36),"
 | |
|           "f16 char(36),"
 | |
|           "f17 char(36)"
 | |
|     ")");
 | |
|   myquery(rc);
 | |
| 
 | |
|   stmt = mysql_stmt_init(mysql);
 | |
|   check_stmt(stmt);
 | |
| 
 | |
|   memset(bind, 0, sizeof(bind));
 | |
| 
 | |
|   for (i = 0; i < MDEV19838_MAX_PARAM_COUNT; ++i)
 | |
|   {
 | |
|     bind[i].buffer = charvalue;
 | |
|     bind[i].buffer_type = MYSQL_TYPE_STRING;
 | |
|     bind[i].buffer_length = strlen(charvalue) + 1;
 | |
|     bind[i].length = &bind[i].length_value;
 | |
|     bind[i].length_value = bind[i].buffer_length - 1;
 | |
|   }
 | |
| 
 | |
|   for (paramCount = 1; paramCount < MDEV19838_FIELDS_COUNT; ++paramCount)
 | |
|   {
 | |
|     mysql_stmt_attr_set(stmt, STMT_ATTR_PREBIND_PARAMS, ¶mCount);
 | |
| 
 | |
|     rc = mysql_stmt_bind_param(stmt, bind);
 | |
|     check_execute(stmt, rc);
 | |
| 
 | |
|     rc = mariadb_stmt_execute_direct(stmt, "INSERT INTO mdev19838"
 | |
|       "(f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13, f14, f15, f16, f17)"
 | |
|       " VALUES "
 | |
|       "(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", -1);
 | |
| 
 | |
|     /* Expecting an error */
 | |
|     DIE_UNLESS(rc != 0);
 | |
| 
 | |
|     mysql_stmt_close(stmt);
 | |
|     stmt = mysql_stmt_init(mysql);
 | |
|     check_stmt(stmt);
 | |
|   }
 | |
| 
 | |
|   paramCount = 0;
 | |
|   mysql_stmt_attr_set(stmt, STMT_ATTR_PREBIND_PARAMS, ¶mCount);
 | |
|   rc = mariadb_stmt_execute_direct(stmt, "INSERT INTO mdev19838(f1)"
 | |
|     " VALUES (?)", -1);
 | |
|   /* Expecting an error */
 | |
|   DIE_UNLESS(rc != 0);
 | |
|   mysql_stmt_close(stmt);
 | |
| 
 | |
|   stmt = mysql_stmt_init(mysql);
 | |
|   check_stmt(stmt);
 | |
|   /* Correct number of parameters */
 | |
|   paramCount = MDEV19838_FIELDS_COUNT;
 | |
|   mysql_stmt_attr_set(stmt, STMT_ATTR_PREBIND_PARAMS, ¶mCount);
 | |
|   mysql_stmt_bind_param(stmt, bind);
 | |
| 
 | |
|   rc = mariadb_stmt_execute_direct(stmt, "INSERT INTO mdev19838"
 | |
|     "(f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13, f14, f15, f16, f17)"
 | |
|     " VALUES "
 | |
|     "(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", -1);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   /* MYSQL_TYPE_TINY = 1. This parameter byte can be read as "parameters send" flag byte.
 | |
|      Checking that wrong packet is still detected */
 | |
|   bind[0].buffer_type = MYSQL_TYPE_TINY;
 | |
|   bind[0].length_value = 1;
 | |
|   bind[0].buffer_length = 1;
 | |
| 
 | |
|   for (paramCount = 8; paramCount > 0; --paramCount)
 | |
|   {
 | |
|     mysql_stmt_close(stmt);
 | |
|     stmt = mysql_stmt_init(mysql);
 | |
|     check_stmt(stmt);
 | |
| 
 | |
|     mysql_stmt_attr_set(stmt, STMT_ATTR_PREBIND_PARAMS, ¶mCount);
 | |
| 
 | |
|     rc = mysql_stmt_bind_param(stmt, bind);
 | |
|     check_execute(stmt, rc);
 | |
| 
 | |
|     rc = mariadb_stmt_execute_direct(stmt, "INSERT INTO mdev19838"
 | |
|       "(f1, f2, f3, f4, f5, f6, f7, f8, f9)"
 | |
|       " VALUES "
 | |
|       "(?, ?, ?, ?, ?, ?, ?, ?, ?)", -1);
 | |
| 
 | |
|     /* Expecting an error */
 | |
|     DIE_UNLESS(rc != 0);
 | |
|   }
 | |
| 
 | |
|   /* Test of query w/out parameters, with parameter sent and not sent */
 | |
|   for (paramCount = MDEV19838_MAX_PARAM_COUNT; paramCount != (unsigned int)-1; --paramCount)
 | |
|   {
 | |
|     mysql_stmt_close(stmt);
 | |
|     stmt = mysql_stmt_init(mysql);
 | |
|     check_stmt(stmt);
 | |
| 
 | |
|     mysql_stmt_attr_set(stmt, STMT_ATTR_PREBIND_PARAMS, ¶mCount);
 | |
| 
 | |
|     if (paramCount > 0)
 | |
|     {
 | |
|       rc = mysql_stmt_bind_param(stmt, bind);
 | |
|       check_execute(stmt, rc);
 | |
|     }
 | |
| 
 | |
|     rc = mariadb_stmt_execute_direct(stmt, "INSERT INTO mdev19838"
 | |
|       "(f1)"
 | |
|       " VALUES "
 | |
|       "(0x1111111111111111)", -1);
 | |
| 
 | |
|     /*
 | |
|       We allow junk at the end of the packet in case of
 | |
|       no parameters. So it will succeed.
 | |
|     */
 | |
|     DIE_UNLESS(rc == 0);
 | |
|   }
 | |
| 
 | |
|   mysql_stmt_close(stmt);
 | |
| 
 | |
|   rc = mysql_query(mysql, "drop table mdev19838");
 | |
|   myquery(rc);
 | |
| }
 | |
| 
 | |
| static void test_mdev_24411()
 | |
| {
 | |
|   int        rc;
 | |
|   MYSQL_STMT *stmt;
 | |
|   MYSQL_BIND bind;
 | |
|   MYSQL_RES *result;
 | |
|   MYSQL_ROW row;
 | |
|   my_ulonglong row_count;
 | |
|   unsigned int vals[] = { 1, 2, 3};
 | |
|   unsigned int vals_array_len = 3;
 | |
|   const char *insert_stmt= "INSERT INTO t1 VALUES (?)";
 | |
| 
 | |
|   myheader("test_mdev_24411");
 | |
| 
 | |
|   rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "DROP TABLE IF EXISTS t2");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "CREATE TABLE t1 (a INT)");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "CREATE TABLE t2 (a INT)");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql,
 | |
|   "CREATE TRIGGER t1_bi BEFORE INSERT ON t1 FOR EACH ROW "
 | |
|   "BEGIN INSERT INTO t2 (a) VALUES (NEW.a); END;");
 | |
|   myquery(rc);
 | |
| 
 | |
|   stmt= mysql_stmt_init(mysql);
 | |
|   check_stmt(stmt);
 | |
| 
 | |
|   rc= mysql_stmt_prepare(stmt, insert_stmt, strlen(insert_stmt));
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   memset(&bind, 0, sizeof(bind));
 | |
|   bind.buffer_type= MYSQL_TYPE_LONG;
 | |
|   bind.buffer= vals;
 | |
| 
 | |
|   rc= mysql_stmt_attr_set(stmt, STMT_ATTR_ARRAY_SIZE, &vals_array_len);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= mysql_stmt_bind_param(stmt, &bind);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   /*
 | |
|     It's expected that the INSERT statement adds three rows into
 | |
|     the table t1
 | |
|   */
 | |
|   row_count = mysql_stmt_affected_rows(stmt);
 | |
|   DIE_UNLESS(row_count == 3);
 | |
| 
 | |
|   /*
 | |
|    * Check that the BEFORE INSERT trigger of the table t1 does work correct
 | |
|    * and inserted the rows (1), (2), (3) into the table t2.
 | |
|   */
 | |
|   rc= mysql_query(mysql, "SELECT 't1' tname, a FROM t1 "
 | |
|                   "UNION SELECT 't2' tname, a FROM t2 ORDER BY tname,a");
 | |
|   myquery(rc);
 | |
| 
 | |
|   result= mysql_store_result(mysql);
 | |
| 
 | |
|   row = mysql_fetch_row(result);
 | |
|   DIE_UNLESS(strcmp(row[0], "t1") == 0 && atoi(row[1]) == 1);
 | |
| 
 | |
|   row = mysql_fetch_row(result);
 | |
|   DIE_UNLESS(strcmp(row[0], "t1") == 0 && atoi(row[1]) == 2);
 | |
| 
 | |
|   row = mysql_fetch_row(result);
 | |
|   DIE_UNLESS(strcmp(row[0], "t1") == 0 && atoi(row[1]) == 3);
 | |
| 
 | |
|   row = mysql_fetch_row(result);
 | |
|   DIE_UNLESS(strcmp(row[0], "t2") == 0 && atoi(row[1]) == 1);
 | |
| 
 | |
|   row = mysql_fetch_row(result);
 | |
|   DIE_UNLESS(strcmp(row[0], "t2") == 0 && atoi(row[1]) == 2);
 | |
| 
 | |
|   row = mysql_fetch_row(result);
 | |
|   DIE_UNLESS(strcmp(row[0], "t2") == 0 && atoi(row[1]) == 3);
 | |
| 
 | |
|   row= mysql_fetch_row(result);
 | |
|   DIE_UNLESS(row == NULL);
 | |
| 
 | |
|   mysql_free_result(result);
 | |
| 
 | |
|   mysql_stmt_close(stmt);
 | |
| 
 | |
|   rc= mysql_query(mysql, "DROP TABLE t1, t2");
 | |
|   myquery(rc);
 | |
| }
 | |
| 
 | |
| #endif // EMBEDDED_LIBRARY
 | |
| 
 | |
| 
 | |
| /*
 | |
|   MDEV-20261 NULL passed to String::eq, SEGV, server crash, regression in 10.4
 | |
| */
 | |
| static void test_mdev20261()
 | |
| {
 | |
|   int rc;
 | |
|   MYSQL_STMT *stmt;
 | |
|   MYSQL_BIND param[1];
 | |
|   const char *query= "SELECT * FROM t1 WHERE f = ? OR f = 'foo'";
 | |
|   char val[]= "";
 | |
|   my_bool is_null= TRUE;
 | |
| 
 | |
|   myheader("test_mdev20261");
 | |
| 
 | |
|   rc= mysql_query(mysql, "CREATE OR REPLACE TABLE t1 (f varchar(64)) ENGINE=MyISAM");
 | |
|   myquery(rc);
 | |
| 
 | |
|   stmt= mysql_stmt_init(mysql);
 | |
|   check_stmt(stmt);
 | |
|   rc= mysql_stmt_prepare(stmt, query, strlen(query));
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   verify_param_count(stmt, 1);
 | |
| 
 | |
|   bzero((char*) param, sizeof(param));
 | |
| 
 | |
|   param[0].buffer= &val;
 | |
|   param[0].buffer_type= MYSQL_TYPE_STRING;
 | |
|   param[0].is_null= &is_null;
 | |
| 
 | |
|   rc= mysql_stmt_bind_param(stmt, param);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= mysql_stmt_store_result(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   mysql_stmt_close(stmt);
 | |
| 
 | |
|   rc= mysql_query(mysql, "DROP TABLE t1");
 | |
|   myquery(rc);
 | |
| }
 | |
| 
 | |
| static void test_mdev_30159()
 | |
| {
 | |
|   MYSQL_RES *result;
 | |
|   int rc;
 | |
| 
 | |
|   myheader("test_mdev_30159");
 | |
| 
 | |
|   rc= mysql_query(mysql, "create table t1 ("
 | |
|                           "  name  varchar(100),"
 | |
|                           "  typ varchar(100)"
 | |
|                           ")");
 | |
|   myquery(rc);
 | |
|   rc= mysql_query(mysql, "insert into t1 values (1,1),(2,2),(3,3),(4,4),(5,5),"
 | |
|                           "(6,6),(7,7),(8,8),(9,9),(10,10)");
 | |
|   myquery(rc);
 | |
|   rc= mysql_query(mysql, "insert into t1 values ('', 'value'),('', 'value')");
 | |
|   myquery(rc);
 | |
|   rc= mysql_query(mysql, "create table t2 ("
 | |
|                          "  servername varchar(100)"
 | |
|                          ")");
 | |
|   myquery(rc);
 | |
|   rc= mysql_query(mysql, "insert into t2 values (1),(2),(3),(4),(5),"
 | |
|                           "(6),(7),(8),(9),(10)");
 | |
|   myquery(rc);
 | |
|   rc= mysql_query(mysql, "create view v1 as"
 | |
|                          "  select * from t2"
 | |
|                          "    where"
 | |
|                          "      `t2`.`servername` regexp (  select"
 | |
|                          "          group_concat(`t1`.`name` separator '|')"
 | |
|                          "          from `t1`"
 | |
|                          "          where `t1`.`typ`"
 | |
|                          "          like 'value')");
 | |
|   myquery(rc);
 | |
| 
 | |
|   result= mysql_list_fields(mysql, "v1", NULL);
 | |
|   mytest(result);
 | |
|   mysql_free_result(result);
 | |
| 
 | |
|   rc= mysql_query(mysql, "drop view v1");
 | |
|   myquery(rc);
 | |
|   rc= mysql_query(mysql, "drop table t1, t2");
 | |
|   myquery(rc);
 | |
| }
 | |
| 
 | |
| 
 | |
| #ifndef EMBEDDED_LIBRARY
 | |
| /**
 | |
|   Test case for bulk UPDATE against a table with an active AFTER UPDATE
 | |
|   trigger.
 | |
| */
 | |
| 
 | |
| static void  test_mdev_34718_au()
 | |
| {
 | |
|   int rc;
 | |
|   MYSQL_STMT *stmt_update;
 | |
|   MYSQL_BIND bind[2];
 | |
|   unsigned int vals[]= { 1, 2, 3};
 | |
|   unsigned int new_vals[]= { 5, 6, 7};
 | |
|   unsigned int vals_array_len= 3;
 | |
|   my_ulonglong row_count;
 | |
|   MYSQL_RES *result;
 | |
|   MYSQL_ROW row;
 | |
|   const char *update_stmt= "UPDATE t1 SET a = ? WHERE a = ?";
 | |
|   const char *update_stmt_state_info;
 | |
| 
 | |
|   myheader("test_mdev_34718_au");
 | |
| 
 | |
|   /* Set up test's environment */
 | |
|   rc= mysql_query(mysql, "CREATE TABLE t1 (a INT)");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "CREATE TABLE t2 (a INT)");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "INSERT INTO t1 VALUES (1), (2), (3)");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "CREATE TRIGGER t1_au AFTER UPDATE ON t1 "
 | |
|                   "FOR EACH ROW BEGIN INSERT INTO t2 (a) VALUES (NEW.a); END;");
 | |
| 
 | |
|   stmt_update= mysql_stmt_init(mysql);
 | |
|   check_stmt(stmt_update);
 | |
| 
 | |
|   rc= mysql_stmt_prepare(stmt_update, update_stmt, strlen(update_stmt));
 | |
|   check_execute(stmt_update, rc);
 | |
| 
 | |
|   memset(&bind[0], 0, sizeof(MYSQL_BIND));
 | |
|   memset(&bind[1], 0, sizeof(MYSQL_BIND));
 | |
| 
 | |
|   bind[0].buffer_type= MYSQL_TYPE_LONG;
 | |
|   bind[0].buffer= new_vals;
 | |
| 
 | |
|   bind[1].buffer_type= MYSQL_TYPE_LONG;
 | |
|   bind[1].buffer= vals;
 | |
| 
 | |
|   /*
 | |
|     Every input positional parameter is bound with array of 3 elements
 | |
|     containing actual values for positional parameters
 | |
|   */
 | |
|   rc= mysql_stmt_attr_set(stmt_update, STMT_ATTR_ARRAY_SIZE, &vals_array_len);
 | |
|   check_execute(stmt_update, rc);
 | |
| 
 | |
|   rc= mysql_stmt_bind_param(stmt_update, bind);
 | |
|   check_execute(stmt_update, rc);
 | |
| 
 | |
|   /*
 | |
|     Execution of this prepared statement replaces the table rows (1), (2), (3)
 | |
|     with values (5), (6), (7)
 | |
|   */
 | |
|   rc= mysql_stmt_execute(stmt_update);
 | |
|   check_execute(stmt_update, rc);
 | |
| 
 | |
|   /*
 | |
|     Check that the BULK UPDATE statement affects exactly 3 rows
 | |
|   */
 | |
|   row_count = mysql_stmt_affected_rows(stmt_update);
 | |
|   DIE_UNLESS(row_count == 3);
 | |
| 
 | |
|   update_stmt_state_info= mysql_info(mysql);
 | |
| 
 | |
|   /*
 | |
|     Check that information about executed operation is matched with
 | |
|     the expected result
 | |
|   */
 | |
|   DIE_UNLESS(!strcmp("Rows matched: 3  Changed: 3  Warnings: 0",
 | |
|                      update_stmt_state_info));
 | |
| 
 | |
|   /*
 | |
|    * Check that the AFTER UPDATE trigger of the table t1 does work correctly
 | |
|    * and inserts the rows (5), (6), (7) into the table t2.
 | |
|   */
 | |
|   rc= mysql_query(mysql, "SELECT 't1' tname, a FROM t1 "
 | |
|                   "UNION SELECT 't2' tname, a FROM t2 ORDER BY tname, a");
 | |
|   myquery(rc);
 | |
| 
 | |
|   result= mysql_store_result(mysql);
 | |
| 
 | |
|   row = mysql_fetch_row(result);
 | |
|   DIE_UNLESS(strcmp(row[0], "t1") == 0 && atoi(row[1]) == 5);
 | |
| 
 | |
|   row = mysql_fetch_row(result);
 | |
|   DIE_UNLESS(strcmp(row[0], "t1") == 0 && atoi(row[1]) == 6);
 | |
| 
 | |
|   row = mysql_fetch_row(result);
 | |
|   DIE_UNLESS(strcmp(row[0], "t1") == 0 && atoi(row[1]) == 7);
 | |
| 
 | |
|   row = mysql_fetch_row(result);
 | |
|   DIE_UNLESS(strcmp(row[0], "t2") == 0 && atoi(row[1]) == 5);
 | |
| 
 | |
|   row = mysql_fetch_row(result);
 | |
|   DIE_UNLESS(strcmp(row[0], "t2") == 0 && atoi(row[1]) == 6);
 | |
| 
 | |
|   row = mysql_fetch_row(result);
 | |
|   DIE_UNLESS(strcmp(row[0], "t2") == 0 && atoi(row[1]) == 7);
 | |
| 
 | |
|   row= mysql_fetch_row(result);
 | |
|   DIE_UNLESS(row == NULL);
 | |
| 
 | |
|   mysql_free_result(result);
 | |
| 
 | |
|   mysql_stmt_close(stmt_update);
 | |
| 
 | |
|   /* Clean up */
 | |
|   rc= mysql_query(mysql, "DROP TABLE t1, t2");
 | |
|   myquery(rc);
 | |
| }
 | |
| 
 | |
| 
 | |
| /**
 | |
|   Test case for bulk UPDATE against a table with an active BEFORE UPDATE
 | |
|   trigger.
 | |
| */
 | |
| 
 | |
| static void  test_mdev_34718_bu()
 | |
| {
 | |
|   int rc;
 | |
|   MYSQL_STMT *stmt_update;
 | |
|   MYSQL_BIND bind[2];
 | |
|   unsigned int vals[]= { 1, 2, 3};
 | |
|   unsigned int new_vals[]= { 5, 6, 7};
 | |
|   unsigned int vals_array_len= 3;
 | |
|   my_ulonglong row_count;
 | |
|   MYSQL_RES *result;
 | |
|   MYSQL_ROW row;
 | |
|   const char *update_stmt= "UPDATE t1 SET a = ? WHERE a = ?";
 | |
|   const char *update_stmt_state_info;
 | |
| 
 | |
|   myheader("test_mdev_34718_bu");
 | |
| 
 | |
|   /* Set up test's environment */
 | |
|   rc= mysql_query(mysql, "CREATE TABLE t1 (a INT)");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "CREATE TABLE t2 (a INT)");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "INSERT INTO t1 VALUES (1), (2), (3)");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "CREATE TRIGGER t1_au BEFORE UPDATE ON t1 "
 | |
|                   "FOR EACH ROW BEGIN INSERT INTO t2 (a) VALUES (NEW.a); END;");
 | |
| 
 | |
|   /* Initialize the prepared statement and set it up for bulk operations */
 | |
|   stmt_update= mysql_stmt_init(mysql);
 | |
|   check_stmt(stmt_update);
 | |
| 
 | |
|   rc= mysql_stmt_prepare(stmt_update, update_stmt, strlen(update_stmt));
 | |
|   check_execute(stmt_update, rc);
 | |
| 
 | |
|   memset(&bind[0], 0, sizeof(MYSQL_BIND));
 | |
|   memset(&bind[1], 0, sizeof(MYSQL_BIND));
 | |
| 
 | |
|   bind[0].buffer_type= MYSQL_TYPE_LONG;
 | |
|   bind[0].buffer= new_vals;
 | |
| 
 | |
|   bind[1].buffer_type= MYSQL_TYPE_LONG;
 | |
|   bind[1].buffer= vals;
 | |
| 
 | |
|   /*
 | |
|     Every input positional parameter is bound with array of 3 elements
 | |
|     containing actual values for positional parameters
 | |
|   */
 | |
|   rc= mysql_stmt_attr_set(stmt_update, STMT_ATTR_ARRAY_SIZE, &vals_array_len);
 | |
|   check_execute(stmt_update, rc);
 | |
| 
 | |
|   rc= mysql_stmt_bind_param(stmt_update, bind);
 | |
|   check_execute(stmt_update, rc);
 | |
| 
 | |
|   /*
 | |
|     Execution of this prepared statement replaces the table rows (1), (2), (3)
 | |
|     with values (5), (6), (7)
 | |
|   */
 | |
|   rc= mysql_stmt_execute(stmt_update);
 | |
|   check_execute(stmt_update, rc);
 | |
| 
 | |
|   /*
 | |
|     Check that the BULK UPDATE statement affects exactly 3 rows
 | |
|   */
 | |
|   row_count= mysql_stmt_affected_rows(stmt_update);
 | |
|   DIE_UNLESS(row_count == 3);
 | |
| 
 | |
|   update_stmt_state_info= mysql_info(mysql);
 | |
| 
 | |
|   /*
 | |
|     Check that information about executed operation is matched with
 | |
|     the expected result
 | |
|   */
 | |
|   DIE_UNLESS(!strcmp("Rows matched: 3  Changed: 3  Warnings: 0",
 | |
|                      update_stmt_state_info));
 | |
| 
 | |
|   /*
 | |
|    * Check that the BEFORE UPDATE trigger of the table t1 does work correctly
 | |
|    * and inserts the rows (5), (6), (7) into the table t2.
 | |
|   */
 | |
|   rc= mysql_query(mysql, "SELECT 't1' tname, a FROM t1 "
 | |
|                   "UNION SELECT 't2' tname, a FROM t2 ORDER BY tname, a");
 | |
|   myquery(rc);
 | |
| 
 | |
|   result= mysql_store_result(mysql);
 | |
| 
 | |
|   row= mysql_fetch_row(result);
 | |
|   DIE_UNLESS(strcmp(row[0], "t1") == 0 && atoi(row[1]) == 5);
 | |
| 
 | |
|   row= mysql_fetch_row(result);
 | |
|   DIE_UNLESS(strcmp(row[0], "t1") == 0 && atoi(row[1]) == 6);
 | |
| 
 | |
|   row= mysql_fetch_row(result);
 | |
|   DIE_UNLESS(strcmp(row[0], "t1") == 0 && atoi(row[1]) == 7);
 | |
| 
 | |
|   row= mysql_fetch_row(result);
 | |
|   DIE_UNLESS(strcmp(row[0], "t2") == 0 && atoi(row[1]) == 5);
 | |
| 
 | |
|   row= mysql_fetch_row(result);
 | |
|   DIE_UNLESS(strcmp(row[0], "t2") == 0 && atoi(row[1]) == 6);
 | |
| 
 | |
|   row= mysql_fetch_row(result);
 | |
|   DIE_UNLESS(strcmp(row[0], "t2") == 0 && atoi(row[1]) == 7);
 | |
| 
 | |
|   row= mysql_fetch_row(result);
 | |
|   DIE_UNLESS(row == NULL);
 | |
| 
 | |
|   mysql_free_result(result);
 | |
| 
 | |
|   mysql_stmt_close(stmt_update);
 | |
| 
 | |
|   /* Clean up */
 | |
|   rc= mysql_query(mysql, "DROP TABLE t1, t2");
 | |
|   myquery(rc);
 | |
| }
 | |
| 
 | |
| 
 | |
| /**
 | |
|   Test case for bulk DELETE against a table with an active BEFORE DELETE
 | |
|   trigger.
 | |
| */
 | |
| 
 | |
| static void  test_mdev_34718_bd()
 | |
| {
 | |
|   int rc;
 | |
|   MYSQL_STMT *stmt_delete;
 | |
|   MYSQL_BIND bind[1];
 | |
|   unsigned int vals[]= { 1, 2, 3};
 | |
|   unsigned int vals_array_len= 3;
 | |
|   my_ulonglong row_count;
 | |
|   MYSQL_RES *result;
 | |
|   MYSQL_ROW row;
 | |
|   const char *delete_stmt= "DELETE FROM t1 WHERE a = ?";
 | |
| 
 | |
|   myheader("test_mdev_34718_bd");
 | |
| 
 | |
|   /* Set up test's environment */
 | |
|   rc= mysql_query(mysql, "CREATE TABLE t1 (a INT)");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "CREATE TABLE t2 (a INT)");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "INSERT INTO t1 VALUES (1), (2), (3)");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "CREATE TRIGGER t1_bd BEFORE DELETE ON t1 "
 | |
|                   "FOR EACH ROW BEGIN INSERT INTO t2 (a) VALUES (OLD.a); END;");
 | |
| 
 | |
|   /* Initialize the prepared statement and set it up for bulk operations */
 | |
|   stmt_delete= mysql_stmt_init(mysql);
 | |
|   check_stmt(stmt_delete);
 | |
| 
 | |
|   rc= mysql_stmt_prepare(stmt_delete, delete_stmt, strlen(delete_stmt));
 | |
|   check_execute(stmt_delete, rc);
 | |
| 
 | |
|   memset(&bind[0], 0, sizeof(MYSQL_BIND));
 | |
| 
 | |
|   bind[0].buffer_type= MYSQL_TYPE_LONG;
 | |
|   bind[0].buffer= vals;
 | |
| 
 | |
|   /*
 | |
|     Input positional parameter is bound with array of 3 elements
 | |
|     containing actual values for the positional parameter
 | |
|   */
 | |
|   rc= mysql_stmt_attr_set(stmt_delete, STMT_ATTR_ARRAY_SIZE, &vals_array_len);
 | |
|   check_execute(stmt_delete, rc);
 | |
| 
 | |
|   rc= mysql_stmt_bind_param(stmt_delete, bind);
 | |
|   check_execute(stmt_delete, rc);
 | |
| 
 | |
|   /*
 | |
|     Execution of this prepared statement deletes the rows (1), (2), (3)
 | |
|     from the table t1 and inserts the rows (1), (2), (3) into the table t2
 | |
|     in result of firing the BEFORE DELETE trigger
 | |
|   */
 | |
|   rc= mysql_stmt_execute(stmt_delete);
 | |
|   check_execute(stmt_delete, rc);
 | |
| 
 | |
|   /*
 | |
|     Check that the BULK DELETE statement affects exactly 3 rows
 | |
|   */
 | |
|   row_count= mysql_stmt_affected_rows(stmt_delete);
 | |
|   DIE_UNLESS(row_count == 3);
 | |
| 
 | |
|   /*
 | |
|    * Check that the BEFORE DELETE trigger of the table t1 does work correctly
 | |
|    * and inserts the rows (1), (2), (3) into the table t2.
 | |
|   */
 | |
|   rc= mysql_query(mysql, "SELECT 't1' tname, a FROM t1 "
 | |
|                   "UNION SELECT 't2' tname, a FROM t2 ORDER BY tname, a");
 | |
|   myquery(rc);
 | |
| 
 | |
|   result= mysql_store_result(mysql);
 | |
| 
 | |
|   row= mysql_fetch_row(result);
 | |
|   DIE_UNLESS(strcmp(row[0], "t2") == 0 && atoi(row[1]) == 1);
 | |
| 
 | |
|   row= mysql_fetch_row(result);
 | |
|   DIE_UNLESS(strcmp(row[0], "t2") == 0 && atoi(row[1]) == 2);
 | |
| 
 | |
|   row= mysql_fetch_row(result);
 | |
|   DIE_UNLESS(strcmp(row[0], "t2") == 0 && atoi(row[1]) == 3);
 | |
| 
 | |
|   row= mysql_fetch_row(result);
 | |
|   DIE_UNLESS(row == NULL);
 | |
| 
 | |
|   mysql_free_result(result);
 | |
| 
 | |
|   mysql_stmt_close(stmt_delete);
 | |
| 
 | |
|   /* Clean up */
 | |
|   rc= mysql_query(mysql, "DROP TABLE t1, t2");
 | |
|   myquery(rc);
 | |
| }
 | |
| 
 | |
| 
 | |
| /**
 | |
|   Test case for bulk DELETE against a table with an active AFTER DELETE
 | |
|   trigger.
 | |
| */
 | |
| static void  test_mdev_34718_ad()
 | |
| {
 | |
|   int rc;
 | |
|   MYSQL_STMT *stmt_delete;
 | |
|   MYSQL_BIND bind[1];
 | |
|   unsigned int vals[]= { 1, 2, 3};
 | |
|   unsigned int vals_array_len= 3;
 | |
|   my_ulonglong row_count;
 | |
|   MYSQL_RES *result;
 | |
|   MYSQL_ROW row;
 | |
|   const char *delete_stmt= "DELETE FROM t1 WHERE a = ?";
 | |
| 
 | |
|   myheader("test_mdev_34718_bd");
 | |
| 
 | |
|   /* Set up test's environment */
 | |
|   rc= mysql_query(mysql, "CREATE TABLE t1 (a INT)");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "CREATE TABLE t2 (a INT)");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "INSERT INTO t1 VALUES (1), (2), (3)");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "CREATE TRIGGER t1_bd AFTER DELETE ON t1 "
 | |
|                   "FOR EACH ROW BEGIN INSERT INTO t2 (a) VALUES (OLD.a); END;");
 | |
| 
 | |
|   /* Initialize the prepared statement and set it up for bulk operations */
 | |
|   stmt_delete= mysql_stmt_init(mysql);
 | |
|   check_stmt(stmt_delete);
 | |
| 
 | |
|   rc= mysql_stmt_prepare(stmt_delete, delete_stmt, strlen(delete_stmt));
 | |
|   check_execute(stmt_delete, rc);
 | |
| 
 | |
|   memset(&bind[0], 0, sizeof(MYSQL_BIND));
 | |
| 
 | |
|   bind[0].buffer_type= MYSQL_TYPE_LONG;
 | |
|   bind[0].buffer= vals;
 | |
| 
 | |
|   /*
 | |
|     Input positional parameter is bound with array of 3 elements
 | |
|     containing actual values for the positional parameter
 | |
|   */
 | |
|   rc= mysql_stmt_attr_set(stmt_delete, STMT_ATTR_ARRAY_SIZE, &vals_array_len);
 | |
|   check_execute(stmt_delete, rc);
 | |
| 
 | |
|   rc= mysql_stmt_bind_param(stmt_delete, bind);
 | |
|   check_execute(stmt_delete, rc);
 | |
| 
 | |
|   /*
 | |
|     Execution of this prepared statement deletes the rows (1), (2), (3)
 | |
|     from the table t1 and inserts the rows (1), (2), (3) into the table t2
 | |
|     in result of firing the BEFORE DELETE trigger
 | |
|   */
 | |
|   rc= mysql_stmt_execute(stmt_delete);
 | |
|   check_execute(stmt_delete, rc);
 | |
| 
 | |
|   /*
 | |
|     Check that the BULK DELETE statement affects exactly 3 rows
 | |
|   */
 | |
|   row_count= mysql_stmt_affected_rows(stmt_delete);
 | |
|   DIE_UNLESS(row_count == 3);
 | |
| 
 | |
|   /*
 | |
|    * Check that the AFTER DELETE trigger of the table t1 does work correctly
 | |
|    * and inserts the rows (1), (2), (3) into the table t2.
 | |
|   */
 | |
|   rc= mysql_query(mysql, "SELECT 't1' tname, a FROM t1 "
 | |
|                   "UNION SELECT 't2' tname, a FROM t2 ORDER BY tname, a");
 | |
|   myquery(rc);
 | |
| 
 | |
|   result= mysql_store_result(mysql);
 | |
| 
 | |
|   row= mysql_fetch_row(result);
 | |
|   DIE_UNLESS(strcmp(row[0], "t2") == 0 && atoi(row[1]) == 1);
 | |
| 
 | |
|   row= mysql_fetch_row(result);
 | |
|   DIE_UNLESS(strcmp(row[0], "t2") == 0 && atoi(row[1]) == 2);
 | |
| 
 | |
|   row= mysql_fetch_row(result);
 | |
|   DIE_UNLESS(strcmp(row[0], "t2") == 0 && atoi(row[1]) == 3);
 | |
| 
 | |
|   row= mysql_fetch_row(result);
 | |
|   DIE_UNLESS(row == NULL);
 | |
| 
 | |
|   mysql_free_result(result);
 | |
| 
 | |
|   mysql_stmt_close(stmt_delete);
 | |
| 
 | |
|   /* Clean up */
 | |
|   rc= mysql_query(mysql, "DROP TABLE t1, t2");
 | |
|   myquery(rc);
 | |
| }
 | |
| 
 | |
| /* Test case for bulk INSERT in presence of AFTER INSERT trigger */
 | |
| static void test_mdev_34958()
 | |
| {
 | |
|   int        rc;
 | |
|   MYSQL_STMT *stmt_insert;
 | |
|   MYSQL_BIND bind[2];
 | |
|   MYSQL_RES *result;
 | |
|   MYSQL_ROW row;
 | |
|   my_ulonglong row_count;
 | |
|   unsigned int vals[] = { 1, 2, 3};
 | |
|   unsigned int vals_array_len = 3;
 | |
|   const char *insert_stmt= "INSERT INTO t1 VALUES (?)";
 | |
| 
 | |
|   /* Set up test's environment */
 | |
|   rc= mysql_query(mysql, "CREATE TABLE t1 (a INT)");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "CREATE TABLE t2 (a INT)");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "CREATE TRIGGER t1_ai AFTER INSERT ON t1 "
 | |
|                   "FOR EACH ROW INSERT INTO t2 VALUES (NEW.a);");
 | |
| 
 | |
|   stmt_insert = mysql_stmt_init(mysql);
 | |
|   if (!stmt_insert)
 | |
|   {
 | |
|     fprintf(stderr, "mysql_stmt_init failed: Error: %s\n",
 | |
|             mysql_error(mysql));
 | |
|     exit(1);
 | |
|   }
 | |
| 
 | |
|   rc= mysql_stmt_prepare(stmt_insert, insert_stmt, strlen(insert_stmt));
 | |
|   if (rc)
 | |
|   {
 | |
|     fprintf(stderr, "mysql_stmt_prepare failed: %s\n",
 | |
|             mysql_stmt_error(stmt_insert));
 | |
|     exit(1);
 | |
|   }
 | |
| 
 | |
|   memset(&bind[0], 0, sizeof(MYSQL_BIND));
 | |
| 
 | |
|   bind[0].buffer_type= MYSQL_TYPE_LONG;
 | |
|   bind[0].buffer= vals;
 | |
| 
 | |
|   rc= mysql_stmt_attr_set(stmt_insert, STMT_ATTR_ARRAY_SIZE, &vals_array_len);
 | |
|   if (rc)
 | |
|   {
 | |
|     fprintf(stderr, "mysql_stmt_prepare failed: %s\n",
 | |
|             mysql_stmt_error(stmt_insert));
 | |
|     exit(1);
 | |
|   }
 | |
| 
 | |
|   rc= mysql_stmt_bind_param(stmt_insert, bind);
 | |
|   if (rc)
 | |
|   {
 | |
|     fprintf(stderr, "mysql_stmt_bind_param failed: %s\n",
 | |
|             mysql_stmt_error(stmt_insert));
 | |
|     exit(1);
 | |
|   }
 | |
| 
 | |
|   rc= mysql_stmt_execute(stmt_insert);
 | |
|   if (rc)
 | |
|   {
 | |
|     fprintf(stderr, "mysql_stmt_execute failed: %s\n",
 | |
|             mysql_stmt_error(stmt_insert));
 | |
|     exit(1);
 | |
|   }
 | |
| 
 | |
|   /*
 | |
|     It's expected that the INSERT statement adds three rows into
 | |
|     the table t1
 | |
|   */
 | |
|   row_count = mysql_stmt_affected_rows(stmt_insert);
 | |
|   if (row_count != 3)
 | |
|   {
 | |
|     fprintf(stderr, "Wrong number of affected rows (%llu), expected 3\n",
 | |
|             row_count);
 | |
|     exit(1);
 | |
|   }
 | |
| 
 | |
|   /*
 | |
|    * Check that the AFTER INSERT trigger of the table t1 does work correct
 | |
|    * and inserted the rows (1), (2), (3) into the table t2.
 | |
|    */
 | |
|   rc= mysql_query(mysql, "SELECT 't1' tname, a FROM t1 "
 | |
|                   "UNION SELECT 't2' tname, a FROM t2 ORDER BY tname, a");
 | |
|   if (rc)
 | |
|   {
 | |
|     fprintf(stderr, "Query failed: %s\n", mysql_error(mysql));
 | |
|   }
 | |
| 
 | |
|   result= mysql_store_result(mysql);
 | |
| 
 | |
|   row= mysql_fetch_row(result);
 | |
|   DIE_UNLESS(strcmp(row[0], "t1") == 0 && atoi(row[1]) == 1);
 | |
| 
 | |
|   row= mysql_fetch_row(result);
 | |
|   DIE_UNLESS(strcmp(row[0], "t1") == 0 && atoi(row[1]) == 2);
 | |
| 
 | |
|   row= mysql_fetch_row(result);
 | |
|   DIE_UNLESS(strcmp(row[0], "t1") == 0 && atoi(row[1]) == 3);
 | |
| 
 | |
|   row= mysql_fetch_row(result);
 | |
|   DIE_UNLESS(strcmp(row[0], "t2") == 0 && atoi(row[1]) == 1);
 | |
| 
 | |
|   row= mysql_fetch_row(result);
 | |
|   DIE_UNLESS(strcmp(row[0], "t2") == 0 && atoi(row[1]) == 2);
 | |
| 
 | |
|   row= mysql_fetch_row(result);
 | |
|   DIE_UNLESS(strcmp(row[0], "t2") == 0 && atoi(row[1]) == 3);
 | |
| 
 | |
|   row= mysql_fetch_row(result);
 | |
|   DIE_UNLESS(row == NULL);
 | |
| 
 | |
|   mysql_free_result(result);
 | |
| 
 | |
|   mysql_stmt_close(stmt_insert);
 | |
| 
 | |
|   /* Clean up */
 | |
|   rc= mysql_query(mysql, "DROP TABLE t1, t2");
 | |
|   myquery(rc);
 | |
| }
 | |
| #endif // EMBEDDED_LIBRARY
 | |
| 
 | |
| /*
 | |
|   Check that server_status returned after connecting to server
 | |
|   is consistent with the value of autocommit variable.
 | |
| */
 | |
| static void test_connect_autocommit()
 | |
| {
 | |
|   int rc;
 | |
|   my_bool autocommit[]= {0, 1};
 | |
|   int i;
 | |
|   rc= mysql_query(mysql, "SET @save_autocommit=@@global.autocommit");
 | |
|   myquery(rc);
 | |
|   for (i= 0; i < 2; i++)
 | |
|   {
 | |
|     MYSQL *con;
 | |
|     char query[100];
 | |
|     int autocommit_val;
 | |
| 
 | |
|     con= mysql_client_init(NULL);
 | |
|     DIE_UNLESS(con);
 | |
|     autocommit_val = autocommit[i];
 | |
|     snprintf(query, sizeof(query), "SET global autocommit=%d", autocommit_val);
 | |
|     rc= mysql_query(mysql, query);
 | |
|     myquery(rc);
 | |
| 
 | |
|     if (!(mysql_real_connect(con, opt_host, opt_user, opt_password, current_db,
 | |
|                              opt_port, opt_unix_socket, 0)))
 | |
|     {
 | |
|       fprintf(stderr, "Failed to connect to database: Error: %s\n",
 | |
|               mysql_error(con));
 | |
|       exit(1);
 | |
|     }
 | |
|     DIE_UNLESS(!!(con->server_status & SERVER_STATUS_AUTOCOMMIT) == autocommit_val);
 | |
|     mysql_close(con);
 | |
|   }
 | |
|   rc= mysql_query(mysql, "SET global autocommit=@save_autocommit");
 | |
|   myquery(rc);
 | |
| }
 | |
| 
 | |
| 
 | |
| static void test_execute_direct()
 | |
| {
 | |
| #ifndef EMBEDDED_LIBRARY
 | |
|   MYSQL_STMT* stmt= mysql_stmt_init(mysql);
 | |
|   int rc= mariadb_stmt_execute_direct(stmt,"do 1",-1);
 | |
|   myquery(rc);
 | |
|   mysql_stmt_close(stmt);
 | |
| #endif
 | |
| }
 | |
| 
 | |
| 
 | |
| static void assert_metadata_skipped_count_equals(MYSQL *mysql, int val)
 | |
| {
 | |
|   MYSQL_ROW row;
 | |
|   MYSQL_RES *result;
 | |
|   int rc= mysql_query(mysql, "SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.SESSION_STATUS WHERE "
 | |
|                          "VARIABLE_NAME='Resultset_metadata_skipped'");
 | |
|   myquery(rc);
 | |
|   result= mysql_use_result(mysql);
 | |
|   mytest(result);
 | |
|   row= mysql_fetch_row(result);
 | |
|   DIE_UNLESS(atoi(row[0]) == val);
 | |
|   mysql_free_result(result);
 | |
| }
 | |
| 
 | |
| 
 | |
| static void flush_session_status(MYSQL* mysql)
 | |
| {
 | |
|   int rc= mysql_query(mysql, "flush status");
 | |
|   myquery(rc);
 | |
| }
 | |
| 
 | |
| 
 | |
| static void exec_stmt(MYSQL_STMT* stmt)
 | |
| {
 | |
|   int rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
|   rc= mysql_stmt_store_result(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| }
 | |
| 
 | |
| 
 | |
| 
 | |
| static void test_cache_metadata()
 | |
| {
 | |
|   char char_val[]= "blah";
 | |
|   int int_val = 1;
 | |
|   int rc;
 | |
|   MYSQL_BIND param= {0};
 | |
|   my_bool is_null= FALSE;
 | |
| 
 | |
| 
 | |
|   MYSQL_STMT* stmt= mysql_stmt_init(mysql);
 | |
|   check_stmt(stmt);
 | |
|   rc= mysql_stmt_prepare(stmt, "SELECT ?", -1);
 | |
|   myquery(rc);
 | |
| 
 | |
|   param.buffer= char_val;
 | |
|   param.buffer_type= MYSQL_TYPE_STRING;
 | |
|   param.is_null= &is_null;
 | |
|   param.buffer_length = 4;
 | |
| 
 | |
|   rc= mysql_stmt_bind_param(stmt,¶m);
 | |
|   exec_stmt(stmt);
 | |
| 
 | |
|   flush_session_status(mysql);
 | |
|   /* Execute the statement again, check that metadata is skipped*/
 | |
|   exec_stmt(stmt);
 | |
|   assert_metadata_skipped_count_equals(mysql, 1);
 | |
| 
 | |
|   flush_session_status(mysql);
 | |
|   /*
 | |
|     Execute the statement again, such that metadata changes,
 | |
|     (using LONG parameter in bind for "SELECT ?", instead of string.
 | |
|     Check that metadata is NOT skipped.
 | |
|   */
 | |
|   param.buffer= &int_val;
 | |
|   param.buffer_type= MYSQL_TYPE_LONG;
 | |
|   param.is_null= &is_null;
 | |
|   rc= mysql_stmt_bind_param(stmt, ¶m);
 | |
|   exec_stmt(stmt);
 | |
|   assert_metadata_skipped_count_equals(mysql, 0);
 | |
|   mysql_stmt_close(stmt);
 | |
| 
 | |
| 
 | |
|   /*
 | |
|     Test with real table, and DDL which causes column info to be
 | |
|     changed.
 | |
|   */
 | |
|   stmt= mysql_stmt_init(mysql);
 | |
| 
 | |
|   rc= mysql_query(
 | |
|       mysql, "CREATE OR REPLACE TABLE t1 (a int, b bigint) engine=memory");
 | |
|   myquery(rc);
 | |
| 
 | |
|   flush_session_status(mysql);
 | |
|   check_stmt(stmt);
 | |
|   rc= mysql_stmt_prepare(stmt, "SELECT * from t1", -1);
 | |
|   myquery(rc);
 | |
| 
 | |
|   exec_stmt(stmt);
 | |
|   /* Metadata skipped, since already sent with COM_STMT_PREPARE result.*/
 | |
|   assert_metadata_skipped_count_equals(mysql, 1);
 | |
| 
 | |
|   flush_session_status(mysql);
 | |
|   exec_stmt(stmt);
 | |
|   /* Metadata skipped again*/
 | |
|   assert_metadata_skipped_count_equals(mysql, 1);
 | |
| 
 | |
|   rc= mysql_query(mysql, "ALTER TABLE t1 MODIFY b CHAR(10)");
 | |
|   myquery(rc);
 | |
| 
 | |
|   /* Column metadata WILL change for the next execution due to DDL*/
 | |
|   flush_session_status(mysql);
 | |
|   exec_stmt(stmt);
 | |
|   assert_metadata_skipped_count_equals(mysql, 0);
 | |
| 
 | |
|   /* On reexecution, PS column metadata will NOT change. */
 | |
|   flush_session_status(mysql);
 | |
|   exec_stmt(stmt);
 | |
|   assert_metadata_skipped_count_equals(mysql, 1);
 | |
| 
 | |
|   rc= mysql_query(mysql, "DROP TABLE t1");
 | |
|   myquery(rc);
 | |
| 
 | |
|   mysql_stmt_close(stmt);
 | |
| }
 | |
| 
 | |
| void test_mdev_10075()
 | |
| {
 | |
|   MYSQL_STMT *stmt;
 | |
|   int        rc;
 | |
|   MYSQL_RES  *result;
 | |
|   MYSQL_BIND my_bind[1];
 | |
|   MYSQL_BIND my_bind2[1];
 | |
| 
 | |
|   struct st_data {
 | |
|     unsigned long id;
 | |
|     char id_ind;
 | |
|   };
 | |
| 
 | |
|   struct st_data data[]= {
 | |
|     {0, STMT_INDICATOR_NONE},
 | |
|     {1, STMT_INDICATOR_NONE},
 | |
|     {2, STMT_INDICATOR_NONE}
 | |
|   };
 | |
| 
 | |
|   struct st_data data2[]= {
 | |
|     {3, STMT_INDICATOR_NONE},
 | |
|     {2, STMT_INDICATOR_NONE},
 | |
|     {4, STMT_INDICATOR_NONE}
 | |
|   };
 | |
| 
 | |
|   myheader("test_mdev_10075");
 | |
| 
 | |
|   rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "CREATE TABLE t1(id INT PRIMARY KEY)");
 | |
|   myquery(rc);
 | |
| 
 | |
|   /* insert by prepare */
 | |
|   stmt= mysql_simple_prepare(mysql,
 | |
|                              "INSERT INTO t1 VALUES(?)");
 | |
|   check_stmt(stmt);
 | |
|   verify_param_count(stmt, 1);
 | |
| 
 | |
|   /* bzero bind structure */
 | |
|   bzero((char*) my_bind, sizeof(my_bind));
 | |
|   my_bind[0].buffer_type= MYSQL_TYPE_LONG;
 | |
|   my_bind[0].buffer= (void *)&data[0].id;
 | |
| 
 | |
|   rc= mysql_stmt_bind_param(stmt, my_bind);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   /* Set array size, row size and bind the parameter */
 | |
|   mysql_stmt_bind_param(stmt, my_bind);
 | |
| 
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   mysql_stmt_close(stmt);
 | |
| 
 | |
|   stmt= mysql_simple_prepare(mysql,
 | |
|                              "INSERT IGNORE INTO t1 VALUES(?)");
 | |
|   check_stmt(stmt);
 | |
|   verify_param_count(stmt, 1);
 | |
| 
 | |
|   /* bzero bind structure */
 | |
|   bzero((char*) my_bind2, sizeof(my_bind2));
 | |
|   my_bind2[0].buffer_type= MYSQL_TYPE_LONG;
 | |
|   my_bind2[0].buffer= (void *)&data2[0].id;
 | |
| 
 | |
|   rc= mysql_stmt_bind_param(stmt, my_bind2);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   mysql_stmt_bind_param(stmt, my_bind2);
 | |
| 
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   mysql_stmt_close(stmt);
 | |
| 
 | |
|   rc= mysql_query(mysql, "GET DIAGNOSTICS CONDITION 1 @var1 = ROW_NUMBER");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "SELECT @var1");
 | |
|   myquery(rc);
 | |
| 
 | |
|   result= mysql_store_result(mysql);
 | |
|   mytest(result);
 | |
| 
 | |
|   rc= my_process_result_set(result);
 | |
|   DIE_UNLESS(rc == 1);
 | |
| 
 | |
|   mysql_free_result(result);
 | |
|   mysql_query(mysql, "drop table t1");
 | |
| }
 | |
| 
 | |
| #ifndef EMBEDDED_LIBRARY
 | |
| /*
 | |
|   MDEV-36080: Run a Prepared Statement that hits a failure when the query
 | |
|     optimizer is doing once-per-statement-life optimization. The server should
 | |
|     re-prepare the statement. Make sure the re-prepare happens when the
 | |
|     statement parameters are supplied through Array Binding.
 | |
| */
 | |
| static void test_mdev_36080()
 | |
| {
 | |
|   MYSQL_STMT *stmt;
 | |
|   int rc;
 | |
|   const char *stmt_text;
 | |
|   MYSQL_BIND bind[1];
 | |
|   char       indicator[]= {0, STMT_INDICATOR_NULL, 0/*STMT_INDICATOR_IGNORE*/};
 | |
|   my_bool    error[1];
 | |
|   int        id[]= {2, 3, 777}, count= sizeof(id)/sizeof(id[0]);
 | |
| 
 | |
|   myheader("mdev_36080");
 | |
|   rc= mysql_query(mysql, "SET SQL_MODE=DEFAULT");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "drop table if exists t0");
 | |
|   myquery(rc);
 | |
|   rc= mysql_query(mysql, "create table t0(z int);");
 | |
|   myquery(rc);
 | |
|   rc= mysql_query(mysql, "insert into t0 values (1);");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "drop table if exists t1");
 | |
|   myquery(rc);
 | |
|   rc= mysql_query(mysql, "create table t1 (a int, b int)");
 | |
|   myquery(rc);
 | |
|   rc= mysql_query(mysql, "insert into t1 values (1,1)");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "drop table if exists t2");
 | |
|   myquery(rc);
 | |
|   rc= mysql_query(mysql, "create table t2 (a int)");
 | |
|   myquery(rc);
 | |
|   rc= mysql_query(mysql, "insert into t2 values (1),(2)");
 | |
|   myquery(rc);
 | |
| 
 | |
|   stmt= mysql_stmt_init(mysql);
 | |
|   check_stmt(stmt);
 | |
|   stmt_text=
 | |
|     "update t0,t1 set a = a +? "
 | |
|     "  where b = (SELECT * "
 | |
|     "             FROM (select t_10.* from t2 t_10 join t2 t_11 on(t_10.a = t_11.a)) sq "
 | |
|     "             WHERE 'x'=0 LIMIT 1"
 | |
|     "            )";
 | |
| 
 | |
|   rc= mysql_stmt_prepare(stmt, stmt_text, strlen(stmt_text));
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   memset(bind, 0, sizeof(bind));
 | |
|   bind[0].buffer_type = MYSQL_TYPE_LONG;
 | |
|   bind[0].buffer = (void *)id;
 | |
|   bind[0].buffer_length = 0;
 | |
|   bind[0].is_null = NULL;
 | |
|   bind[0].length = NULL;
 | |
|   bind[0].error = error;
 | |
|   bind[0].u.indicator= indicator;
 | |
| 
 | |
|   mysql_stmt_attr_set(stmt, STMT_ATTR_ARRAY_SIZE, (void*)&count);
 | |
|   rc= mysql_stmt_bind_param(stmt, bind);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute_r(stmt, rc);
 | |
| 
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute_r(stmt, rc);
 | |
| 
 | |
|   mysql_stmt_close(stmt);
 | |
| 
 | |
|   rc= mysql_query(mysql, "drop table t0, t1, t2");
 | |
|   myquery(rc);
 | |
| }
 | |
| 
 | |
| 
 | |
| static void test_mdev35953()
 | |
| {
 | |
|   int rc;
 | |
|   MYSQL_STMT *stmt;
 | |
|   MYSQL_BIND bind[1];
 | |
|   int        vals[]= {1, 2}, count= array_elements(vals);
 | |
|   MYSQL *con= mysql_client_init(NULL);
 | |
|   DIE_UNLESS(con);
 | |
|   if (!mysql_real_connect(con, opt_host, opt_user, opt_password, current_db,
 | |
|                           opt_port, opt_unix_socket, 0))
 | |
|   {
 | |
|     fprintf(stderr, "Failed to connect to database: Error: %s\n",
 | |
|             mysql_error(con));
 | |
|     exit(1);
 | |
|   }
 | |
|   rc= mysql_query(mysql, "create table t1 (a int)");
 | |
|   myquery(rc);
 | |
| 
 | |
|   stmt= mysql_stmt_init(con);
 | |
|   rc= mysql_stmt_prepare(stmt, "insert into t1 (a) values (?)", -1);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   memset(bind, 0, sizeof(bind));
 | |
|   bind[0].buffer_type = MYSQL_TYPE_LONG;
 | |
|   bind[0].buffer = vals;
 | |
| 
 | |
|   mysql_stmt_attr_set(stmt, STMT_ATTR_ARRAY_SIZE, &count);
 | |
|   rc= mysql_stmt_bind_param(stmt, bind);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   rc= mysql_query(mysql, "alter table t1 add xx int");
 | |
|   myquery(rc);
 | |
| 
 | |
|   rc= mysql_stmt_execute(stmt);
 | |
|   check_execute(stmt, rc);
 | |
| 
 | |
|   mysql_stmt_close(stmt);
 | |
|   mysql_close(con);
 | |
| 
 | |
|   mysql_query(mysql, "drop table t1");
 | |
| }
 | |
| #endif
 | |
| 
 | |
| static struct my_tests_st my_tests[]= {
 | |
|   { "test_mdev_20516", test_mdev_20516 },
 | |
|   { "test_mdev24827", test_mdev24827 },
 | |
|   { "test_mdev_26145", test_mdev_26145 },
 | |
|   { "disable_query_logs", disable_query_logs },
 | |
|   { "test_view_sp_list_fields", test_view_sp_list_fields },
 | |
|   { "client_query", client_query },
 | |
|   { "test_prepare_insert_update", test_prepare_insert_update},
 | |
| #ifdef EMBEDDED_LIBRARY
 | |
|   { "test_embedded_start_stop", test_embedded_start_stop },
 | |
| #endif
 | |
| #ifdef NOT_YET_WORKING
 | |
|   { "test_drop_temp", test_drop_temp },
 | |
| #endif
 | |
|   { "test_fetch_seek", test_fetch_seek },
 | |
|   { "test_fetch_nobuffs", test_fetch_nobuffs },
 | |
|   { "test_open_direct", test_open_direct },
 | |
|   { "test_fetch_null", test_fetch_null },
 | |
|   { "test_ps_null_param", test_ps_null_param },
 | |
|   { "test_fetch_date", test_fetch_date },
 | |
|   { "test_fetch_str", test_fetch_str },
 | |
|   { "test_fetch_long", test_fetch_long },
 | |
|   { "test_fetch_short", test_fetch_short },
 | |
|   { "test_fetch_tiny", test_fetch_tiny },
 | |
|   { "test_fetch_bigint", test_fetch_bigint },
 | |
|   { "test_fetch_float", test_fetch_float },
 | |
|   { "test_fetch_double", test_fetch_double },
 | |
|   { "test_bind_result_ext", test_bind_result_ext },
 | |
|   { "test_bind_result_ext1", test_bind_result_ext1 },
 | |
|   { "test_select_direct", test_select_direct },
 | |
|   { "test_select_prepare", test_select_prepare },
 | |
|   { "test_select", test_select },
 | |
|   { "test_select_version", test_select_version },
 | |
|   { "test_ps_conj_select", test_ps_conj_select },
 | |
|   { "test_select_show_table", test_select_show_table },
 | |
|   { "test_func_fields", test_func_fields },
 | |
|   { "test_long_data", test_long_data },
 | |
|   { "test_insert", test_insert },
 | |
|   { "test_set_variable", test_set_variable },
 | |
|   { "test_select_show", test_select_show },
 | |
|   { "test_prepare_noparam", test_prepare_noparam },
 | |
|   { "test_bind_result", test_bind_result },
 | |
|   { "test_prepare_simple", test_prepare_simple },
 | |
|   { "test_prepare", test_prepare },
 | |
|   { "test_null", test_null },
 | |
|   { "test_debug_example", test_debug_example },
 | |
|   { "test_update", test_update },
 | |
|   { "test_simple_update", test_simple_update },
 | |
|   { "test_simple_delete", test_simple_delete },
 | |
|   { "test_double_compare", test_double_compare },
 | |
|   { "client_store_result", client_store_result },
 | |
|   { "client_use_result", client_use_result },
 | |
|   { "test_tran_bdb", test_tran_bdb },
 | |
|   { "test_tran_innodb", test_tran_innodb },
 | |
|   { "test_prepare_ext", test_prepare_ext },
 | |
|   { "test_prepare_syntax", test_prepare_syntax },
 | |
|   { "test_field_names", test_field_names },
 | |
|   { "test_field_flags", test_field_flags },
 | |
|   { "test_long_data_str", test_long_data_str },
 | |
|   { "test_long_data_str1", test_long_data_str1 },
 | |
|   { "test_long_data_bin", test_long_data_bin },
 | |
|   { "test_warnings", test_warnings },
 | |
|   { "test_errors", test_errors },
 | |
|   { "test_prepare_resultset", test_prepare_resultset },
 | |
|   { "test_stmt_close", test_stmt_close },
 | |
|   { "test_prepare_field_result", test_prepare_field_result },
 | |
|   { "test_multi_stmt", test_multi_stmt },
 | |
|   { "test_multi_statements", test_multi_statements },
 | |
|   { "test_prepare_multi_statements", test_prepare_multi_statements },
 | |
|   { "test_store_result", test_store_result },
 | |
|   { "test_store_result1", test_store_result1 },
 | |
|   { "test_store_result2", test_store_result2 },
 | |
|   { "test_subselect", test_subselect },
 | |
|   { "test_date", test_date },
 | |
|   { "test_simple_temporal", test_simple_temporal },
 | |
|   { "test_date_date", test_date_date },
 | |
|   { "test_date_time", test_date_time },
 | |
|   { "test_date_ts", test_date_ts },
 | |
|   { "test_date_dt", test_date_dt },
 | |
|   { "test_prepare_alter", test_prepare_alter },
 | |
|   { "test_manual_sample", test_manual_sample },
 | |
|   { "test_pure_coverage", test_pure_coverage },
 | |
|   { "test_buffers", test_buffers },
 | |
|   { "test_ushort_bug", test_ushort_bug },
 | |
|   { "test_sshort_bug", test_sshort_bug },
 | |
|   { "test_stiny_bug", test_stiny_bug },
 | |
|   { "test_field_misc", test_field_misc },
 | |
|   { "test_set_option", test_set_option },
 | |
| #ifndef EMBEDDED_LIBRARY
 | |
|   { "test_prepare_grant", test_prepare_grant },
 | |
| 
 | |
| #endif
 | |
|   { "test_frm_bug", test_frm_bug },
 | |
|   { "test_explain_bug", test_explain_bug },
 | |
|   { "test_decimal_bug", test_decimal_bug },
 | |
|   { "test_nstmts", test_nstmts },
 | |
|   { "test_logs;", test_logs },
 | |
|   { "test_cuted_rows", test_cuted_rows },
 | |
|   { "test_fetch_offset", test_fetch_offset },
 | |
|   { "test_fetch_column", test_fetch_column },
 | |
|   { "test_mem_overun", test_mem_overun },
 | |
|   { "test_list_fields", test_list_fields },
 | |
|   { "test_list_information_schema_fields", test_list_information_schema_fields },
 | |
|   { "test_list_fields_blob", test_list_fields_blob },
 | |
|   { "test_list_fields_default", test_list_fields_default },
 | |
|   { "test_free_result", test_free_result },
 | |
|   { "test_free_store_result", test_free_store_result },
 | |
|   { "test_sqlmode", test_sqlmode },
 | |
|   { "test_ts", test_ts },
 | |
|   { "test_bug1115", test_bug1115 },
 | |
|   { "test_bug1180", test_bug1180 },
 | |
|   { "test_bug1500", test_bug1500 },
 | |
|   { "test_bug1644", test_bug1644 },
 | |
|   { "test_bug1946", test_bug1946 },
 | |
|   { "test_bug2248", test_bug2248 },
 | |
|   { "test_parse_error_and_bad_length", test_parse_error_and_bad_length },
 | |
|   { "test_bug2247", test_bug2247 },
 | |
|   { "test_subqueries", test_subqueries },
 | |
|   { "test_bad_union", test_bad_union },
 | |
|   { "test_distinct", test_distinct },
 | |
|   { "test_subqueries_ref", test_subqueries_ref },
 | |
|   { "test_union", test_union },
 | |
|   { "test_bug3117", test_bug3117 },
 | |
|   { "test_join", test_join },
 | |
|   { "test_selecttmp", test_selecttmp },
 | |
|   { "test_create_drop", test_create_drop },
 | |
|   { "test_rename", test_rename },
 | |
|   { "test_do_set", test_do_set },
 | |
|   { "test_multi", test_multi },
 | |
|   { "test_insert_select", test_insert_select },
 | |
|   { "test_bind_nagative", test_bind_nagative },
 | |
|   { "test_derived", test_derived },
 | |
|   { "test_xjoin", test_xjoin },
 | |
|   { "test_bug3035", test_bug3035 },
 | |
|   { "test_union2", test_union2 },
 | |
|   { "test_bug1664", test_bug1664 },
 | |
|   { "test_union_param", test_union_param },
 | |
|   { "test_order_param", test_order_param },
 | |
|   { "test_ps_i18n", test_ps_i18n },
 | |
|   { "test_bug3796", test_bug3796 },
 | |
|   { "test_bug4026", test_bug4026 },
 | |
|   { "test_bug4079", test_bug4079 },
 | |
|   { "test_bug4236", test_bug4236 },
 | |
|   { "test_bug4030", test_bug4030 },
 | |
|   { "test_bug5126", test_bug5126 },
 | |
|   { "test_bug4231", test_bug4231 },
 | |
|   { "test_bug5399", test_bug5399 },
 | |
|   { "test_bug5194", test_bug5194 },
 | |
|   { "test_bug5315", test_bug5315 },
 | |
|   { "test_bug6049", test_bug6049 },
 | |
|   { "test_bug6058", test_bug6058 },
 | |
|   { "test_bug6059", test_bug6059 },
 | |
|   { "test_bug6046", test_bug6046 },
 | |
|   { "test_bug6081", test_bug6081 },
 | |
|   { "test_bug6096", test_bug6096 },
 | |
|   { "test_datetime_ranges", test_datetime_ranges },
 | |
|   { "test_datetime_ranges_mdev15289", test_datetime_ranges_mdev15289 },
 | |
|   { "test_bug4172", test_bug4172 },
 | |
|   { "test_conversion", test_conversion },
 | |
|   { "test_rewind", test_rewind },
 | |
|   { "test_bug6761", test_bug6761 },
 | |
|   { "test_view", test_view },
 | |
|   { "test_view_where", test_view_where },
 | |
|   { "test_view_2where", test_view_2where },
 | |
|   { "test_view_star", test_view_star },
 | |
|   { "test_view_insert", test_view_insert },
 | |
|   { "test_left_join_view", test_left_join_view },
 | |
|   { "test_view_insert_fields", test_view_insert_fields },
 | |
|   { "test_basic_cursors", test_basic_cursors },
 | |
|   { "test_cursors_with_union", test_cursors_with_union },
 | |
|   { "test_cursors_with_procedure", test_cursors_with_procedure },
 | |
|   { "test_truncation", test_truncation },
 | |
|   { "test_truncation_option", test_truncation_option },
 | |
|   { "test_client_character_set", test_client_character_set },
 | |
|   { "test_bug8330", test_bug8330 },
 | |
|   { "test_bug7990", test_bug7990 },
 | |
|   { "test_bug8378", test_bug8378 },
 | |
|   { "test_bug8722", test_bug8722 },
 | |
|   { "test_bug8880", test_bug8880 },
 | |
|   { "test_open_cursor_prepared_statement_query_cache",
 | |
|     test_open_cursor_prepared_statement_query_cache },
 | |
|   { "test_bug9159", test_bug9159 },
 | |
|   { "test_bug9520", test_bug9520 },
 | |
|   { "test_bug9478", test_bug9478 },
 | |
|   { "test_bug9643", test_bug9643 },
 | |
|   { "test_bug10729", test_bug10729 },
 | |
|   { "test_bug11111", test_bug11111 },
 | |
|   { "test_bug9992", test_bug9992 },
 | |
|   { "test_bug10736", test_bug10736 },
 | |
|   { "test_bug10794", test_bug10794 },
 | |
|   { "test_bug11172", test_bug11172 },
 | |
|   { "test_bug11656", test_bug11656 },
 | |
|   { "test_bug10214", test_bug10214 },
 | |
|   { "test_bug9735", test_bug9735 },
 | |
|   { "test_bug11183", test_bug11183 },
 | |
|   { "test_bug11037", test_bug11037 },
 | |
|   { "test_bug10760", test_bug10760 },
 | |
|   { "test_bug12001", test_bug12001 },
 | |
|   { "test_bug11718", test_bug11718 },
 | |
|   { "test_bug12925", test_bug12925 },
 | |
|   { "test_bug11909", test_bug11909 },
 | |
|   { "test_bug11901", test_bug11901 },
 | |
|   { "test_bug11904", test_bug11904 },
 | |
|   { "test_bug12243", test_bug12243 },
 | |
|   { "test_bug14210", test_bug14210 },
 | |
|   { "test_bug13488", test_bug13488 },
 | |
|   { "test_bug13524", test_bug13524 },
 | |
|   { "test_bug14845", test_bug14845 },
 | |
|   { "test_opt_reconnect", test_opt_reconnect },
 | |
|   { "test_bug15510", test_bug15510},
 | |
| #ifndef EMBEDDED_LIBRARY
 | |
|   { "test_bug12744", test_bug12744 },
 | |
| #endif
 | |
|   { "test_bug16143", test_bug16143 },
 | |
|   { "test_bug16144", test_bug16144 },
 | |
|   { "test_bug15613", test_bug15613 },
 | |
|   { "test_bug20152", test_bug20152 },
 | |
|   { "test_bug14169", test_bug14169 },
 | |
|   { "test_bug17667", test_bug17667 },
 | |
|   { "test_bug15752", test_bug15752 },
 | |
|   { "test_mysql_insert_id", test_mysql_insert_id },
 | |
|   { "test_bug19671", test_bug19671 },
 | |
|   { "test_bug21206", test_bug21206 },
 | |
|   { "test_bug21726", test_bug21726 },
 | |
|   { "test_bug15518", test_bug15518 },
 | |
|   { "test_bug23383", test_bug23383 },
 | |
|   { "test_bug32265", test_bug32265 },
 | |
|   { "test_bug21635", test_bug21635 },
 | |
|   { "test_status",   test_status   },
 | |
|   { "test_bug24179", test_bug24179 },
 | |
|   { "test_ps_query_cache", test_ps_query_cache },
 | |
|   { "test_bug28075", test_bug28075 },
 | |
|   { "test_bug27876", test_bug27876 },
 | |
|   { "test_bug28505", test_bug28505 },
 | |
|   { "test_bug28934", test_bug28934 },
 | |
|   { "test_bug27592", test_bug27592 },
 | |
|   { "test_bug29687", test_bug29687 },
 | |
|   { "test_bug29692", test_bug29692 },
 | |
|   { "test_bug29306", test_bug29306 },
 | |
|   { "test_change_user", test_change_user },
 | |
|   { "test_bug30472", test_bug30472 },
 | |
|   { "test_bug20023", test_bug20023 },
 | |
|   { "test_bug45010", test_bug45010 },
 | |
|   { "test_bug53371", test_bug53371 },
 | |
|   { "test_bug31418", test_bug31418 },
 | |
|   { "test_bug31669", test_bug31669 },
 | |
|   { "test_bug28386", test_bug28386 },
 | |
|   { "test_wl4166_1", test_wl4166_1 },
 | |
|   { "test_wl4166_2", test_wl4166_2 },
 | |
|   { "test_wl4166_3", test_wl4166_3 },
 | |
|   { "test_wl4166_4", test_wl4166_4 },
 | |
|   { "test_bug36004", test_bug36004 },
 | |
|   { "test_wl4284_1", test_wl4284_1 },
 | |
|   { "test_wl4435",   test_wl4435 },
 | |
|   { "test_wl4435_2", test_wl4435_2 },
 | |
|   { "test_wl4435_3", test_wl4435_3 },
 | |
|   { "test_bug38486", test_bug38486 },
 | |
|   { "test_bug33831", test_bug33831 },
 | |
|   { "test_bug40365", test_bug40365 },
 | |
|   { "test_bug43560", test_bug43560 },
 | |
|   { "test_bug36326", test_bug36326 },
 | |
|   { "test_bug41078", test_bug41078 },
 | |
|   { "test_bug44495", test_bug44495 },
 | |
|   { "test_bug49972", test_bug49972 },
 | |
|   { "test_bug42373", test_bug42373 },
 | |
|   { "test_bug54041", test_bug54041 },
 | |
|   { "test_bug47485", test_bug47485 },
 | |
|   { "test_bug58036", test_bug58036 },
 | |
|   { "test_bug57058", test_bug57058 },
 | |
|   { "test_bug56976", test_bug56976 },
 | |
|   { "test_mdev3885", test_mdev3885 },
 | |
|   { "test_mdev4603", test_mdev4603 },
 | |
|   { "test_bug11766854", test_bug11766854 },
 | |
|   { "test_bug12337762", test_bug12337762 },
 | |
|   { "test_progress_reporting", test_progress_reporting },
 | |
|   { "test_bug11754979", test_bug11754979 },
 | |
|   { "test_bug13001491", test_bug13001491 },
 | |
|   { "test_mdev4326", test_mdev4326 },
 | |
|   { "test_ps_sp_out_params", test_ps_sp_out_params },
 | |
| #ifndef _WIN32
 | |
|   { "test_bug17512527", test_bug17512527},
 | |
| #endif
 | |
|   { "test_compressed_protocol", test_compressed_protocol },
 | |
|   { "test_big_packet", test_big_packet },
 | |
|   { "test_prepare_analyze", test_prepare_analyze },
 | |
|   { "test_mdev12579", test_mdev12579 },
 | |
|   { "test_mdev14013", test_mdev14013 },
 | |
|   { "test_mdev14013_1", test_mdev14013_1 },
 | |
|   { "test_mdev14454", test_mdev14454 },
 | |
| #ifndef EMBEDDED_LIBRARY
 | |
|   { "test_proxy_header", test_proxy_header},
 | |
|   { "test_bulk_autoinc", test_bulk_autoinc},
 | |
|   { "test_bulk_delete", test_bulk_delete },
 | |
|   { "test_bulk_replace", test_bulk_replace },
 | |
|   { "test_bulk_insert_returning", test_bulk_insert_returning },
 | |
|   { "test_bulk_delete_returning", test_bulk_delete_returning },
 | |
| #endif
 | |
|   { "test_ps_params_in_ctes", test_ps_params_in_ctes },
 | |
|   { "test_explain_meta", test_explain_meta },
 | |
| #ifndef EMBEDDED_LIBRARY
 | |
|   { "test_mdev19838", test_mdev19838 },
 | |
| #endif
 | |
|   { "test_mdev_16128", test_mdev_16128 },
 | |
|   { "test_mdev18408", test_mdev18408 },
 | |
|   { "test_mdev20261", test_mdev20261 },
 | |
|   { "test_mdev_30159", test_mdev_30159 },
 | |
|   { "test_connect_autocommit", test_connect_autocommit},
 | |
|   { "test_execute_direct", test_execute_direct },
 | |
|   { "test_cache_metadata", test_cache_metadata},
 | |
| #ifndef EMBEDDED_LIBRARY
 | |
|   { "test_mdev_24411", test_mdev_24411},
 | |
|   { "test_mdev_34718_bu", test_mdev_34718_bu },
 | |
|   { "test_mdev_34718_au", test_mdev_34718_au },
 | |
|   { "test_mdev_34718_bd", test_mdev_34718_bd },
 | |
|   { "test_mdev_34718_ad", test_mdev_34718_ad },
 | |
|   { "test_mdev_34958", test_mdev_34958 },
 | |
| #endif
 | |
|   { "test_mdev_10075", test_mdev_10075},
 | |
| #ifndef EMBEDDED_LIBRARY
 | |
|   { "test_mdev_36080", test_mdev_36080},
 | |
|   { "test_mdev35953", test_mdev35953 },
 | |
| #endif
 | |
|   { 0, 0 }
 | |
| };
 | |
| 
 | |
| 
 | |
| static struct my_tests_st *get_my_tests() { return my_tests; }
 | 
