diff options
Diffstat (limited to 'libmariadb/unittest/libmariadb/ps_bugs.c')
-rw-r--r-- | libmariadb/unittest/libmariadb/ps_bugs.c | 5846 |
1 files changed, 5846 insertions, 0 deletions
diff --git a/libmariadb/unittest/libmariadb/ps_bugs.c b/libmariadb/unittest/libmariadb/ps_bugs.c new file mode 100644 index 00000000..efe3d447 --- /dev/null +++ b/libmariadb/unittest/libmariadb/ps_bugs.c @@ -0,0 +1,5846 @@ +/* +Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. + +The MySQL Connector/C is licensed under the terms of the GPLv2 +<http://www.gnu.org/licenses/old-licenses/gpl-2.0.html>, like most +MySQL Connectors. There are special exceptions to the terms and +conditions of the GPLv2 as it is applied to this software, see the +FLOSS License Exception +<http://www.mysql.com/about/legal/licensing/foss-exception.html>. + +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 St, Fifth Floor, Boston, MA 02110-1301 USA +*/ +#include "my_test.h" +#include <math.h> + +#define MY_INT64_NUM_DECIMAL_DIGITS 21 +#define MAX_INDEXES 64 + +/* A workaround for Sun Forte 5.6 on Solaris x86 */ + +static int cmp_double(double *a, double *b) +{ + return *a == *b; + return OK; +} + +/* Test BUG#1115 (incorrect string parameter value allocation) */ + +static int test_conc67(MYSQL *mysql) +{ + MYSQL_STMT *stmt= mysql_stmt_init(mysql); + const char *query= "SELECT a,b FROM conc67 WHERE a=?"; + int rc, i; + MYSQL_BIND bind[2]; + char val[20]; + MYSQL_BIND rbind; + MYSQL_RES *res; + ulong prefetch_rows= 1000; + ulong cursor_type= CURSOR_TYPE_READ_ONLY; + + // https://jira.mariadb.org/browse/XPT-266 + if (IS_XPAND()) { + rc= mysql_query(mysql, "SET NAMES UTF8"); + check_mysql_rc(rc, mysql); + } + + rc= mysql_query(mysql, "DROP TABLE IF EXISTS conc67"); + check_mysql_rc(rc, mysql); + + rc= mysql_query(mysql, "CREATE TABLE conc67 (a int, b text)"); + check_mysql_rc(rc, mysql); + + rc= mysql_query(mysql, "INSERT INTO conc67 VALUES (1, 'foo')"); + check_mysql_rc(rc, mysql); + + rc= mysql_stmt_attr_set(stmt, STMT_ATTR_CURSOR_TYPE, &cursor_type); + check_stmt_rc(rc, stmt); + rc= mysql_stmt_attr_set(stmt, STMT_ATTR_PREFETCH_ROWS, &prefetch_rows); + check_stmt_rc(rc, stmt); + + rc= mysql_stmt_prepare(stmt, SL(query)); + check_stmt_rc(rc, stmt); + + memset(&rbind, 0, sizeof(MYSQL_BIND)); + i= 1; + rbind.buffer_type= MYSQL_TYPE_LONG; + rbind.buffer= &i; + rbind.buffer_length= 4; + mysql_stmt_bind_param(stmt, &rbind); + + rc= mysql_stmt_execute(stmt); + check_stmt_rc(rc, stmt); + + res= mysql_stmt_result_metadata(stmt); + mysql_free_result(res); + + memset(bind, 0, 2 * sizeof(MYSQL_BIND)); + + i= 0; + bind[0].buffer_type= MYSQL_TYPE_LONG; + bind[0].buffer= &i; + bind[0].buffer_length= 4; + bind[1].buffer_type= MYSQL_TYPE_STRING; + bind[1].buffer= &val; + bind[1].buffer_length= 20; + + mysql_stmt_bind_result(stmt, bind); + + rc= mysql_stmt_fetch(stmt); + check_stmt_rc(rc, stmt); + + FAIL_IF(i != 1, "expected value 1 for first row"); + + rc= mysql_stmt_fetch(stmt); + FAIL_IF(rc != MYSQL_NO_DATA, "Eof expected"); + + mysql_stmt_close(stmt); + rc= mysql_query(mysql, "DROP TABLE IF EXISTS conc67"); + check_mysql_rc(rc, mysql); + return OK; +} + +static int test_bug1115(MYSQL *mysql) +{ + MYSQL_STMT *stmt; + int rc, rowcount; + MYSQL_BIND my_bind[1]; + ulong length[1]; + char szData[11]; + char query[MAX_TEST_QUERY_LENGTH]; + + rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_select"); + check_mysql_rc(rc, mysql); + + 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)"); + check_mysql_rc(rc, mysql); + 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) "); + check_mysql_rc(rc, mysql); + 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)"); + check_mysql_rc(rc, mysql); + + strcpy(query, "SELECT * FROM test_select WHERE " + "CONVERT(session_id USING utf8)= ?"); + stmt= mysql_stmt_init(mysql); + FAIL_IF(!stmt, mysql_error(mysql)); + rc= mysql_stmt_prepare(stmt, SL(query)); + check_stmt_rc(rc, stmt); + + FAIL_IF(mysql_stmt_param_count(stmt) != 1, "Paramcount != 1"); + + memset(my_bind, '\0', sizeof(MYSQL_BIND)); + + strcpy(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_stmt_rc(rc, stmt); + + rc= mysql_stmt_execute(stmt); + check_stmt_rc(rc, stmt); + + rowcount= 0; + while (mysql_stmt_fetch(stmt) != MYSQL_NO_DATA) + rowcount++; + FAIL_IF(rowcount != 1, "rowcount=%d != 1"); + + strcpy(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_stmt_rc(rc, stmt); + + rc= mysql_stmt_execute(stmt); + check_stmt_rc(rc, stmt); + + rowcount= 0; + while (mysql_stmt_fetch(stmt) != MYSQL_NO_DATA) + rowcount++; + FAIL_IF(rowcount != 0, "rowcount != 0"); + + strcpy(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_stmt_rc(rc, stmt); + + rc= mysql_stmt_execute(stmt); + check_stmt_rc(rc, stmt); + + rowcount= 0; + while (mysql_stmt_fetch(stmt) != MYSQL_NO_DATA) + rowcount++; + FAIL_IF(rowcount != 1, "rowcount != 1"); + + mysql_stmt_close(stmt); + rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_select"); + check_mysql_rc(rc, mysql); + + return OK; +} +/* Test BUG#1180 (optimized away part of WHERE clause) */ + +static int test_bug1180(MYSQL *mysql) +{ + MYSQL_STMT *stmt; + int rc, rowcount; + MYSQL_BIND my_bind[1]; + ulong length[1]; + char szData[11]; + char query[MAX_TEST_QUERY_LENGTH]; + + // https://jira.mariadb.org/browse/XPT-266 + if (IS_XPAND()) { + rc= mysql_query(mysql, "SET NAMES UTF8"); + check_mysql_rc(rc, mysql); + } + + rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_select"); + check_mysql_rc(rc, mysql); + + rc= mysql_query(mysql, "CREATE TABLE test_select(session_id char(9) NOT NULL)"); + check_mysql_rc(rc, mysql); + rc= mysql_query(mysql, "INSERT INTO test_select VALUES (\"abc\")"); + check_mysql_rc(rc, mysql); + + strcpy(query, "SELECT * FROM test_select WHERE ?= \"1111\" and " + "session_id= \"abc\""); + stmt= mysql_stmt_init(mysql); + FAIL_IF(!stmt, mysql_error(mysql)); + rc= mysql_stmt_prepare(stmt, SL(query)); + check_stmt_rc(rc, stmt); + + FAIL_IF(mysql_stmt_param_count(stmt) != 1, "Paramcount != 1"); + + memset(my_bind, '\0', sizeof(MYSQL_BIND)); + + strcpy(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_stmt_rc(rc, stmt); + + rc= mysql_stmt_execute(stmt); + check_stmt_rc(rc, stmt); + + + rowcount= 0; + while (mysql_stmt_fetch(stmt) != MYSQL_NO_DATA) + rowcount++; + FAIL_IF(rowcount != 0, "rowcount != 0"); + + strcpy(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_stmt_rc(rc, stmt); + + rc= mysql_stmt_execute(stmt); + check_stmt_rc(rc, stmt); + + rowcount= 0; + while (mysql_stmt_fetch(stmt) != MYSQL_NO_DATA) + rowcount++; + FAIL_IF(rowcount != 1, "rowcount != 1"); + + strcpy(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_stmt_rc(rc, stmt); + + rc= mysql_stmt_execute(stmt); + check_stmt_rc(rc, stmt); + + rowcount= 0; + while (mysql_stmt_fetch(stmt) != MYSQL_NO_DATA) + rowcount++; + FAIL_IF(rowcount != 0, "rowcount != 0"); + + mysql_stmt_close(stmt); + rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_select"); + check_mysql_rc(rc, mysql); + + return OK; +} + + +/* + Test BUG#1644 (Insertion of more than 3 NULL columns with parameter + binding fails) +*/ + +static int test_bug1644(MYSQL *mysql) +{ + 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]; + + rc= mysql_query(mysql, "DROP TABLE IF EXISTS foo_dfr"); + check_mysql_rc(rc, mysql); + + rc= mysql_query(mysql, + "CREATE TABLE foo_dfr(col1 int, col2 int, col3 int, col4 int);"); + check_mysql_rc(rc, mysql); + + strcpy(query, "INSERT INTO foo_dfr VALUES (?, ?, ?, ? )"); + stmt= mysql_stmt_init(mysql); + FAIL_IF(!stmt, mysql_error(mysql)); + rc= mysql_stmt_prepare(stmt, SL(query)); + check_stmt_rc(rc, stmt); + + FAIL_IF(mysql_stmt_param_count(stmt) != 4, "Paramcount != 4"); + + memset(my_bind, '\0', sizeof(MYSQL_BIND) * 4); + + 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_stmt_rc(rc, stmt); + + rc= mysql_stmt_execute(stmt); + check_stmt_rc(rc, stmt); + + isnull= 1; + for (i= 0 ; i < 4 ; i++) + my_bind[i].is_null= &isnull; + + rc= mysql_stmt_bind_param(stmt, my_bind); + check_stmt_rc(rc, stmt); + + rc= mysql_stmt_execute(stmt); + check_stmt_rc(rc, stmt); + + 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_stmt_rc(rc, stmt); + + rc= mysql_stmt_execute(stmt); + check_stmt_rc(rc, stmt); + + mysql_stmt_close(stmt); + + rc= mysql_query(mysql, "SELECT * FROM foo_dfr"); + check_mysql_rc(rc, mysql); + + result= mysql_store_result(mysql); + FAIL_IF(!result, "Invalid resultset"); + + FAIL_IF(mysql_num_rows(result) != 3, "rowcount != 3"); + + mysql_data_seek(result, 0); + + row= mysql_fetch_row(result); + FAIL_IF(!row, "row = NULL"); + for (i= 0 ; i < 4 ; i++) + { + FAIL_UNLESS(strcmp(row[i], "22") == 0, "Wrong value"); + } + row= mysql_fetch_row(result); + FAIL_IF(!row, "Invalid row"); + for (i= 0 ; i < 4 ; i++) + { + FAIL_UNLESS(row[i] == 0, "row[i] != 0"); + } + row= mysql_fetch_row(result); + FAIL_IF(!row, "Invalid row"); + for (i= 0 ; i < 4 ; i++) + { + FAIL_UNLESS(strcmp(row[i], "88") == 0, "row[i] != 88"); + } + row= mysql_fetch_row(result); + FAIL_IF(row, "row != NULL"); + + mysql_free_result(result); + rc= mysql_query(mysql, "DROP TABLE IF EXISTS foo_dfr"); + check_mysql_rc(rc, mysql); + + return OK; +} + +static int test_bug11037(MYSQL *mysql) +{ + MYSQL_STMT *stmt; + int rc; + const char *stmt_text; + + rc= mysql_query(mysql, "drop table if exists t1"); + check_mysql_rc(rc, mysql); + + rc= mysql_query(mysql, "create table t1 (id int not null)"); + check_mysql_rc(rc, mysql); + + rc= mysql_query(mysql, "insert into t1 values (1)"); + check_mysql_rc(rc, mysql); + + stmt_text= "select id FROM t1"; + stmt= mysql_stmt_init(mysql); + FAIL_IF(!stmt, mysql_error(mysql)); + rc= mysql_stmt_prepare(stmt, SL(stmt_text)); + check_stmt_rc(rc, stmt); + + /* expected error */ + rc = mysql_stmt_fetch(stmt); + FAIL_UNLESS(rc==1, "Error expected"); + + rc= mysql_stmt_execute(stmt); + check_stmt_rc(rc, stmt); + + rc= mysql_stmt_fetch(stmt); + check_stmt_rc(rc, stmt); + + rc= mysql_stmt_fetch(stmt); + FAIL_UNLESS(rc==MYSQL_NO_DATA, "rc != MYSQL_NO_DATA"); + + rc= mysql_stmt_fetch(stmt); + FAIL_UNLESS(rc==MYSQL_NO_DATA, "rc != MYSQL_NO_DATA"); + + mysql_stmt_close(stmt); + rc= mysql_query(mysql, "drop table t1"); + check_mysql_rc(rc, mysql); + + return OK; +} + +/* Bug#11183 "mysql_stmt_reset() doesn't reset information about error" */ + +static int test_bug11183(MYSQL *mysql) +{ + int rc; + MYSQL_STMT *stmt; + char bug_statement[]= "insert into t1 values (1)"; + + rc= mysql_query(mysql, "drop table if exists t1"); + check_mysql_rc(rc, mysql); + rc= mysql_query(mysql, "create table t1 (a int)"); + check_mysql_rc(rc, mysql); + + stmt= mysql_stmt_init(mysql); + FAIL_IF(!stmt, mysql_error(mysql)); + + rc= mysql_stmt_prepare(stmt, SL(bug_statement)); + check_stmt_rc(rc, stmt); + + rc= mysql_query(mysql, "drop table t1"); + check_mysql_rc(rc, mysql); + + /* Trying to execute statement that should fail on execute stage */ + rc= mysql_stmt_execute(stmt); + FAIL_IF(!rc, "Error expected"); + + mysql_stmt_reset(stmt); + FAIL_IF(mysql_stmt_errno(stmt) != 0, "stmt->error != 0"); + + rc= mysql_query(mysql, "create table t1 (a int)"); + check_mysql_rc(rc, mysql); + + /* Trying to execute statement that should pass ok */ + if (mysql_stmt_execute(stmt)) + { + mysql_stmt_reset(stmt); + FAIL_IF(mysql_stmt_errno(stmt) == 0, "stmt->error != 0"); + } + + mysql_stmt_close(stmt); + + rc= mysql_query(mysql, "drop table t1"); + check_mysql_rc(rc, mysql); + + return OK; +} + +static int test_bug12744(MYSQL *mysql) +{ + MYSQL_STMT *stmt = NULL; + int rc; + + SKIP_MAXSCALE; + + stmt = mysql_stmt_init(mysql); + FAIL_IF(!stmt, mysql_error(mysql)); + rc= mysql_stmt_prepare(stmt, "SET @a:=1", 9); + check_stmt_rc(rc, stmt); + + rc= mysql_stmt_execute(stmt); + check_stmt_rc(rc, stmt); + + /* set reconnect, kill and ping to reconnect */ + rc= mysql_query(mysql, "SET @a:=1"); + check_mysql_rc(rc, mysql); + rc= mysql_options(mysql, MYSQL_OPT_RECONNECT, "1"); + check_mysql_rc(rc, mysql); + rc= mysql_kill(mysql, mysql_thread_id(mysql)); + + rc= mysql_ping(mysql); + check_mysql_rc(rc, mysql); + + rc= mysql_stmt_close(stmt); + check_stmt_rc(rc, stmt); + + return OK; +} + +static int test_bug1500(MYSQL *mysql) +{ + MYSQL_STMT *stmt; + MYSQL_BIND my_bind[3]; + int rc= 0; + int32 int_data[3]= {2, 3, 4}; + const char *data; + const char *query; + + // XPAND doesn't support AGAINST + SKIP_XPAND + + rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_bg1500"); + check_mysql_rc(rc, mysql); + + rc= mysql_query(mysql, "CREATE TABLE test_bg1500 (i INT)"); + check_mysql_rc(rc, mysql); + + rc= mysql_query(mysql, "INSERT INTO test_bg1500 VALUES (1), (2)"); + check_mysql_rc(rc, mysql); + + rc= mysql_commit(mysql); + check_mysql_rc(rc, mysql); + + query= "SELECT i FROM test_bg1500 WHERE i IN (?, ?, ?)"; + stmt= mysql_stmt_init(mysql); + FAIL_IF(!stmt, mysql_error(mysql)); + rc= mysql_stmt_prepare(stmt, SL(query)); + check_stmt_rc(rc, stmt); + + FAIL_IF(mysql_stmt_param_count(stmt) != 3, "paramcount != 3"); + + memset(my_bind, '\0', 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_stmt_rc(rc, stmt); + + rc= mysql_stmt_execute(stmt); + check_stmt_rc(rc, stmt); + + rc= 0; + while (mysql_stmt_fetch(stmt) != MYSQL_NO_DATA) + rc++; + FAIL_UNLESS(rc == 1, "rowcount != 1"); + + mysql_stmt_close(stmt); + + rc= mysql_query(mysql, "DROP TABLE test_bg1500"); + check_mysql_rc(rc, mysql); + + rc= mysql_query(mysql, "CREATE TABLE test_bg1500 (s VARCHAR(25), FULLTEXT(s)) engine=MyISAM"); + check_mysql_rc(rc, mysql); + + rc= mysql_query(mysql, + "INSERT INTO test_bg1500 VALUES ('Gravedigger'), ('Greed'), ('Hollow Dogs')"); + check_mysql_rc(rc, mysql); + + rc= mysql_commit(mysql); + check_mysql_rc(rc, mysql); + + query= "SELECT s FROM test_bg1500 WHERE MATCH (s) AGAINST (?)"; + stmt= mysql_stmt_init(mysql); + FAIL_IF(!stmt, mysql_error(mysql)); + rc= mysql_stmt_prepare(stmt, SL(query)); + check_stmt_rc(rc, stmt); + + FAIL_IF(mysql_stmt_param_count(stmt) != 1, "paramcount != 1"); + + data= "Dogs"; + my_bind[0].buffer_type= MYSQL_TYPE_STRING; + my_bind[0].buffer= (void *) data; + my_bind[0].buffer_length= (unsigned long)strlen(data); + my_bind[0].is_null= 0; + my_bind[0].length= 0; + + rc= mysql_stmt_bind_param(stmt, my_bind); + check_stmt_rc(rc, stmt); + + rc= mysql_stmt_execute(stmt); + check_stmt_rc(rc, stmt); + + rc= 0; + while (mysql_stmt_fetch(stmt) != MYSQL_NO_DATA) + rc++; + FAIL_UNLESS(rc == 1, "rowcount != 1"); + + mysql_stmt_close(stmt); + + /* This should work too */ + query= "SELECT s FROM test_bg1500 WHERE MATCH (s) AGAINST (CONCAT(?, 'digger'))"; + stmt= mysql_stmt_init(mysql); + FAIL_IF(!stmt, mysql_error(mysql)); + rc= mysql_stmt_prepare(stmt, SL(query)); + check_stmt_rc(rc, stmt); + + FAIL_IF(mysql_stmt_param_count(stmt) != 1, "paramcount != 1"); + + data= "Grave"; + my_bind[0].buffer_type= MYSQL_TYPE_STRING; + my_bind[0].buffer= (void *) data; + my_bind[0].buffer_length= (unsigned long)strlen(data); + + rc= mysql_stmt_bind_param(stmt, my_bind); + check_stmt_rc(rc, stmt); + + rc= mysql_stmt_execute(stmt); + check_stmt_rc(rc, stmt); + + rc= 0; + while (mysql_stmt_fetch(stmt) != MYSQL_NO_DATA) + rc++; + FAIL_UNLESS(rc == 1, "rowcount != 1"); + + mysql_stmt_close(stmt); + rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_bg1500"); + check_mysql_rc(rc, mysql); + + return OK; +} + +static int test_bug15510(MYSQL *mysql) +{ + MYSQL_STMT *stmt; + int rc; + const char *query= "select 1 from dual where 1/0"; + + SKIP_MYSQL(mysql); + + rc= mysql_query(mysql, "set @@sql_mode='ERROR_FOR_DIVISION_BY_ZERO'"); + check_mysql_rc(rc, mysql); + + stmt= mysql_stmt_init(mysql); + + rc= mysql_stmt_prepare(stmt, SL(query)); + check_stmt_rc(rc, stmt); + + rc= mysql_stmt_execute(stmt); + check_stmt_rc(rc, stmt); + + rc= mysql_stmt_fetch(stmt); + FAIL_UNLESS(mysql_warning_count(mysql), "Warning expected"); + + /* Cleanup */ + mysql_stmt_close(stmt); + rc= mysql_query(mysql, "set @@sql_mode=''"); + check_mysql_rc(rc, mysql); + + return OK; +} + +/* + Bug #15518 - Reusing a stmt that has failed during prepare + does not clear error +*/ + +static int test_bug15518(MYSQL *mysql) +{ + MYSQL_STMT *stmt; + int rc; + + stmt= mysql_stmt_init(mysql); + + /* + The prepare of foo should fail with errno 1064 since + it's not a valid query + */ + rc= mysql_stmt_prepare(stmt, "foo", 3); + FAIL_UNLESS(rc && mysql_stmt_errno(stmt) && mysql_errno(mysql), "Error expected"); + + /* + Use the same stmt and reprepare with another query that + succeeds + */ + rc= mysql_stmt_prepare(stmt, "SHOW STATUS", 12); + FAIL_UNLESS(!rc || mysql_stmt_errno(stmt) || mysql_errno(mysql), "Error not expected"); + + rc= mysql_stmt_close(stmt); + check_mysql_rc(rc, mysql); + /* + part2, when connection to server has been closed + after first prepare + */ + stmt= mysql_stmt_init(mysql); + rc= mysql_stmt_prepare(stmt, "foo", 3); + FAIL_UNLESS(rc && mysql_stmt_errno(stmt) && mysql_errno(mysql), "Error expected"); + + /* Close connection to server */ + mysql_close(mysql); + + /* + Use the same stmt and reprepare with another query that + succeeds. The prepare should fail with error 2013 since + connection to server has been closed. + */ + rc= mysql_stmt_prepare(stmt, "SHOW STATUS", 12); + FAIL_UNLESS(rc && mysql_stmt_errno(stmt), "Error expected"); + + mysql_stmt_close(stmt); + + return OK; +} + +/* + Bug #15613: "libmysqlclient API function mysql_stmt_prepare returns wrong + field length" +*/ + +static int test_bug15613(MYSQL *mysql) +{ + MYSQL_STMT *stmt; + const char *stmt_text; + MYSQL_RES *metadata; + MYSQL_FIELD *field; + int rc; + + //https://jira.mariadb.org/browse/XPT-273 + SKIP_XPAND; + + /* I. Prepare the table */ + rc= mysql_query(mysql, "set names latin1"); + check_mysql_rc(rc, mysql); + 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)"); + check_mysql_rc(rc, mysql); + + 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, SL(stmt_text)); + metadata= mysql_stmt_result_metadata(stmt); + field= mysql_fetch_fields(metadata); + FAIL_UNLESS(field[0].length == 65535, "length != 65535"); + FAIL_UNLESS(field[1].length == 255, "length != 255"); + FAIL_UNLESS(field[2].length == 16777215, "length != 166777215"); + FAIL_UNLESS(field[3].length == 4294967295UL, "length != 4294967295UL"); + FAIL_UNLESS(field[4].length == 255, "length != 255"); + FAIL_UNLESS(field[5].length == 255, "length != 255"); + FAIL_UNLESS(field[6].length == 255, "length != 255"); + mysql_free_result(metadata); + mysql_stmt_free_result(stmt); + + /* III. Cleanup */ + rc= mysql_query(mysql, "drop table t1"); + check_mysql_rc(rc, mysql); + rc= mysql_query(mysql, "set names default"); + check_mysql_rc(rc, mysql); + mysql_stmt_close(stmt); + + return OK; +} + +static int test_bug16144(MYSQL *mysql) +{ + const my_bool flag_orig= (my_bool) 0xde; + my_bool flag= flag_orig; + MYSQL_STMT *stmt; + + /* 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); + FAIL_UNLESS(flag == flag_orig, "flag != flag_orig"); + + mysql_stmt_close(stmt); + + return OK; +} + +/* + This tests for various mysql_stmt_send_long_data bugs described in #1664 +*/ + +static int test_bug1664(MYSQL *mysql) +{ + 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(?, ?)"; + + // https://jira.mariadb.org/browse/XPT-266 + if (IS_XPAND()) { + rc= mysql_query(mysql, "SET NAMES UTF8"); + check_mysql_rc(rc, mysql); + } + + rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_long_data"); + check_mysql_rc(rc, mysql); + + rc= mysql_query(mysql, "CREATE TABLE test_long_data(col1 int, col2 MEDIUMTEXT)"); + check_mysql_rc(rc, mysql); + + stmt= mysql_stmt_init(mysql); + rc= mysql_stmt_prepare(stmt, SL(query)); + check_stmt_rc(rc, stmt); + + FAIL_IF(mysql_stmt_param_count(stmt) != 2, "Param count != 2"); + + memset(my_bind, '\0', sizeof(my_bind)); + + my_bind[0].buffer_type= MYSQL_TYPE_STRING; + my_bind[0].buffer= (void *)str_data; + my_bind[0].buffer_length= (unsigned long)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_stmt_rc(rc, stmt); + + 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, SL(data)); + check_stmt_rc(rc, stmt); + + rc= mysql_stmt_execute(stmt); + check_stmt_rc(rc, stmt); + if (verify_col_data(mysql, "test_long_data", "col1", "1")) + goto error; + if (verify_col_data(mysql, "test_long_data", "col2", "")) + goto error; + rc= mysql_query(mysql, "DELETE FROM test_long_data"); + check_mysql_rc(rc, mysql); + + /* This should pass OK */ + data= (char *)"Data"; + rc= mysql_stmt_send_long_data(stmt, 0, SL(data)); + check_stmt_rc(rc, stmt); + + rc= mysql_stmt_execute(stmt); + check_stmt_rc(rc, stmt); + + if (verify_col_data(mysql, "test_long_data", "col1", "1")) + goto error; + if (verify_col_data(mysql, "test_long_data", "col2", "Data")) + goto error; + + /* clean up */ + rc= mysql_query(mysql, "DELETE FROM test_long_data"); + check_mysql_rc(rc, mysql); + + /* + 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_stmt_rc(rc, stmt); + + if (verify_col_data(mysql, "test_long_data", "col1", "2")) + goto error; + if (verify_col_data(mysql, "test_long_data", "col2", str_data)) + goto error; + + /* clean up */ + rc= mysql_query(mysql, "DELETE FROM test_long_data"); + check_mysql_rc(rc, mysql); + + /* + Now we are sending other long data. It should not be + concatenated to previous. + */ + + data= (char *)"SomeOtherData"; + rc= mysql_stmt_send_long_data(stmt, 0, SL(data)); + check_stmt_rc(rc, stmt); + + rc= mysql_stmt_execute(stmt); + check_stmt_rc(rc, stmt); + + if (verify_col_data(mysql, "test_long_data", "col1", "2")) + goto error; + if (verify_col_data(mysql, "test_long_data", "col2", "SomeOtherData")) + goto error; + + mysql_stmt_close(stmt); + + /* clean up */ + rc= mysql_query(mysql, "DELETE FROM test_long_data"); + check_mysql_rc(rc, mysql); + + /* Now let us test how mysql_stmt_reset works. */ + stmt= mysql_stmt_init(mysql); + rc= mysql_stmt_prepare(stmt, SL(query)); + check_stmt_rc(rc, stmt); + rc= mysql_stmt_bind_param(stmt, my_bind); + check_stmt_rc(rc, stmt); + + data= (char *)"SomeData"; + rc= mysql_stmt_send_long_data(stmt, 0, SL(data)); + check_stmt_rc(rc, stmt); + + rc= mysql_stmt_reset(stmt); + check_stmt_rc(rc, stmt); + + rc= mysql_stmt_execute(stmt); + check_stmt_rc(rc, stmt); + + if (verify_col_data(mysql, "test_long_data", "col1", "2")) + goto error; + if (verify_col_data(mysql, "test_long_data", "col2", str_data)) + goto error; + + mysql_stmt_close(stmt); + + /* Final clean up */ + rc= mysql_query(mysql, "DROP TABLE test_long_data"); + check_mysql_rc(rc, mysql); + + return OK; + +error: + mysql_stmt_close(stmt); + rc= mysql_query(mysql, "DROP TABLE test_long_data"); + return FAIL; +} +/* Test a misc bug */ + +static int test_ushort_bug(MYSQL *mysql) +{ + 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; + const char *query= "SELECT * FROM test_ushort"; + + rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_ushort"); + check_mysql_rc(rc, mysql); + + rc= mysql_query(mysql, "CREATE TABLE test_ushort(a smallint unsigned, \ + b smallint unsigned, \ + c smallint unsigned, \ + d smallint unsigned)"); + check_mysql_rc(rc, mysql); + + rc= mysql_query(mysql, + "INSERT INTO test_ushort VALUES(35999, 35999, 35999, 200)"); + check_mysql_rc(rc, mysql); + + stmt= mysql_stmt_init(mysql); + FAIL_IF(!stmt, mysql_error(mysql)); + rc= mysql_stmt_prepare(stmt, SL(query)); + check_stmt_rc(rc, stmt); + + rc= mysql_stmt_execute(stmt); + check_stmt_rc(rc, stmt); + + memset(my_bind, '\0', 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_stmt_rc(rc, stmt); + + rc= mysql_stmt_fetch(stmt); + check_stmt_rc(rc, stmt); + + FAIL_UNLESS(short_value == 35999, "short_value != 35999"); + FAIL_UNLESS(s_length == 2, "length != 2"); + + FAIL_UNLESS(long_value == 35999, "long_value != 35999"); + FAIL_UNLESS(l_length == 4, "length != 4"); + + FAIL_UNLESS(longlong_value == 35999, "longlong_value != 35999"); + FAIL_UNLESS(ll_length == 8, "length != 8"); + + FAIL_UNLESS(tiny_value == 200, "tiny_value != 200"); + FAIL_UNLESS(t_length == 1, "length != 1"); + + rc= mysql_stmt_fetch(stmt); + FAIL_UNLESS(rc == MYSQL_NO_DATA, "rc != MYSQL_NO_DATA"); + + mysql_stmt_close(stmt); + rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_ushort"); + check_mysql_rc(rc, mysql); + + return OK; +} + +static int test_bug1946(MYSQL *mysql) +{ + MYSQL_STMT *stmt; + int rc; + const char *query= "INSERT INTO prepare_command VALUES (?)"; + + + rc= mysql_query(mysql, "DROP TABLE IF EXISTS prepare_command"); + check_mysql_rc(rc, mysql); + + rc= mysql_query(mysql, "CREATE TABLE prepare_command(ID INT)"); + check_mysql_rc(rc, mysql); + + stmt= mysql_stmt_init(mysql); + FAIL_IF(!stmt, mysql_error(mysql)); + rc= mysql_stmt_prepare(stmt, SL(query)); + check_stmt_rc(rc, stmt); + + rc= mysql_real_query(mysql, SL(query)); + FAIL_IF(!rc, "Error expected"); + + mysql_stmt_close(stmt); + rc= mysql_query(mysql, "DROP TABLE prepare_command"); + check_mysql_rc(rc, mysql); + return OK; +} + +static int test_bug20152(MYSQL *mysql) +{ + MYSQL_BIND my_bind[1]; + MYSQL_STMT *stmt; + MYSQL_TIME tm; + int rc; + const char *query= "INSERT INTO t1 (f1) VALUES (?)"; + + + 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(MYSQL_TIME)); + + 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"); + check_mysql_rc(rc, mysql); + rc= mysql_query(mysql, "CREATE TABLE t1 (f1 DATE)"); + check_mysql_rc(rc, mysql); + + stmt= mysql_stmt_init(mysql); + rc= mysql_stmt_prepare(stmt, SL(query)); + check_stmt_rc(rc, stmt); + rc= mysql_stmt_bind_param(stmt, my_bind); + check_stmt_rc(rc, stmt); + rc= mysql_stmt_execute(stmt); + check_stmt_rc(rc, stmt); + rc= mysql_stmt_close(stmt); + check_stmt_rc(rc, stmt); + rc= mysql_query(mysql, "DROP TABLE t1"); + check_mysql_rc(rc, mysql); + FAIL_UNLESS(tm.hour == 14 && tm.minute == 9 && tm.second == 42, "time != 14:09:42"); + return OK; +} + +static int test_bug2247(MYSQL *mysql) +{ + 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 }; + + + /* create table and insert few rows */ + rc= mysql_query(mysql, drop); + check_mysql_rc(rc, mysql); + + rc= mysql_query(mysql, create); + check_mysql_rc(rc, mysql); + + stmt= mysql_stmt_init(mysql); + FAIL_IF(!stmt, mysql_error(mysql)); + rc= mysql_stmt_prepare(stmt, SL(insert)); + check_stmt_rc(rc, stmt); + for (i= 0; i < NUM_ROWS; ++i) + { + rc= mysql_stmt_execute(stmt); + check_stmt_rc(rc, stmt); + } + exp_count= mysql_stmt_affected_rows(stmt); + FAIL_UNLESS(exp_count == 1, "exp_count != 1"); + + rc= mysql_query(mysql, SELECT); + check_mysql_rc(rc, mysql); + /* + 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); + FAIL_IF(!res, "Invalid result set"); + + FAIL_UNLESS(mysql_affected_rows(mysql) == NUM_ROWS, "affected_rows != NUM_ROWS"); + FAIL_UNLESS(exp_count == mysql_stmt_affected_rows(stmt), "affected_rows != exp_count"); + + rc= mysql_query(mysql, update); + check_mysql_rc(rc, mysql); + FAIL_UNLESS(mysql_affected_rows(mysql) == NUM_ROWS, "affected_rows != NUM_ROWS"); + FAIL_UNLESS(exp_count == mysql_stmt_affected_rows(stmt), "affected_rows != exp_count"); + + mysql_free_result(res); + mysql_stmt_close(stmt); + + /* check that mysql_stmt_store_result modifies mysql_stmt_affected_rows */ + stmt= mysql_stmt_init(mysql); + FAIL_IF(!stmt, mysql_error(mysql)); + rc= mysql_stmt_prepare(stmt, SL(SELECT)); + check_stmt_rc(rc, stmt); + + rc= mysql_stmt_execute(stmt); + check_stmt_rc(rc, stmt); rc= mysql_stmt_store_result(stmt); + check_stmt_rc(rc, stmt); exp_count= mysql_stmt_affected_rows(stmt); + FAIL_UNLESS(exp_count == NUM_ROWS, "exp_count != NUM_ROWS"); + + rc= mysql_query(mysql, insert); + check_mysql_rc(rc, mysql); + FAIL_UNLESS(mysql_affected_rows(mysql) == 1, "affected_rows != 1"); + FAIL_UNLESS(exp_count == mysql_stmt_affected_rows(stmt), "affected_rows != exp_count"); + + mysql_stmt_close(stmt); + rc= mysql_query(mysql, drop); + check_mysql_rc(rc, mysql); + return OK; +} + +/* + Test for bug#2248 "mysql_fetch without prior mysql_stmt_execute hangs" +*/ + +static int test_bug2248(MYSQL *mysql) +{ + MYSQL_STMT *stmt; + int rc; + const char *query1= "SELECT DATABASE()"; + const char *query2= "INSERT INTO test_bug2248 VALUES (10)"; + + + rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_bug2248"); + check_mysql_rc(rc, mysql); + + rc= mysql_query(mysql, "CREATE TABLE test_bug2248 (id int)"); + check_mysql_rc(rc, mysql); + + stmt= mysql_stmt_init(mysql); + FAIL_IF(!stmt, mysql_error(mysql)); + rc= mysql_stmt_prepare(stmt, SL(query1)); + check_stmt_rc(rc, stmt); + + /* This should not hang */ + rc= mysql_stmt_fetch(stmt); + FAIL_IF(!rc, "Error expected"); + + /* And this too */ + rc= mysql_stmt_store_result(stmt); + FAIL_IF(!rc, "Error expected"); + + mysql_stmt_close(stmt); + + stmt= mysql_stmt_init(mysql); + FAIL_IF(!stmt, mysql_error(mysql)); + rc= mysql_stmt_prepare(stmt, SL(query2)); + check_stmt_rc(rc, stmt); + + rc= mysql_stmt_execute(stmt); + check_stmt_rc(rc, stmt); + /* This too should not hang but should return proper error */ + rc= mysql_stmt_fetch(stmt); + FAIL_UNLESS(rc == 1, "rc != 1"); + + /* This too should not hang but should not bark */ + rc= mysql_stmt_store_result(stmt); + check_stmt_rc(rc, stmt); + /* This should return proper error */ + rc= mysql_stmt_fetch(stmt); + FAIL_UNLESS(rc == 1, "rc != 1"); + + mysql_stmt_close(stmt); + + rc= mysql_query(mysql, "DROP TABLE test_bug2248"); + check_mysql_rc(rc, mysql); + return OK; +} + +/* + 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 int test_bug23383(MYSQL *mysql) +{ + 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; + unsigned long long row_count; + int rc; + + rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1"); + check_mysql_rc(rc, mysql); + + rc= mysql_query(mysql, "CREATE TABLE t1 (i INT UNIQUE)"); + check_mysql_rc(rc, mysql); + + rc= mysql_query(mysql, insert_query); + check_mysql_rc(rc, mysql); + row_count= mysql_affected_rows(mysql); + FAIL_UNLESS(row_count == 2, "row_count != 2"); + + rc= mysql_query(mysql, insert_query); + FAIL_IF(!rc, "Error expected"); + row_count= mysql_affected_rows(mysql); + FAIL_UNLESS(row_count == (unsigned long long)-1, "rowcount != -1"); + + rc= mysql_query(mysql, update_query); + check_mysql_rc(rc, mysql); + row_count= mysql_affected_rows(mysql); + FAIL_UNLESS(row_count == 0, ""); + + rc= mysql_query(mysql, "DELETE FROM t1"); + check_mysql_rc(rc, mysql); + + stmt= mysql_stmt_init(mysql); + FAIL_IF(!stmt, mysql_error(mysql)); + + rc= mysql_stmt_prepare(stmt, SL(insert_query)); + check_stmt_rc(rc, stmt); + rc= mysql_stmt_execute(stmt); + check_stmt_rc(rc, stmt); + row_count= mysql_stmt_affected_rows(stmt); + FAIL_UNLESS(row_count == 2, "row_count != 2"); + + rc= mysql_stmt_execute(stmt); + FAIL_UNLESS(rc != 0, ""); + row_count= mysql_stmt_affected_rows(stmt); + FAIL_UNLESS(row_count == (unsigned long long)-1, "rowcount != -1"); + + rc= mysql_stmt_prepare(stmt, SL(update_query)); + check_stmt_rc(rc, stmt); + rc= mysql_stmt_execute(stmt); + check_stmt_rc(rc, stmt); + row_count= mysql_stmt_affected_rows(stmt); + FAIL_UNLESS(row_count == 0, "rowcount != 0"); + + rc= mysql_stmt_close(stmt); + check_stmt_rc(rc, stmt); + rc= mysql_query(mysql, "DROP TABLE t1"); + check_mysql_rc(rc, mysql); + + return OK; +} + +/* + Bug#27592 (stack overrun when storing datetime value using prepared statements) +*/ + +static int test_bug27592(MYSQL *mysql) +{ + const int NUM_ITERATIONS= 40; + int i; + int rc; + MYSQL_STMT *stmt= NULL; + MYSQL_BIND bind[1]; + MYSQL_TIME time_val; + + mysql_query(mysql, "DROP TABLE IF EXISTS t1"); + mysql_query(mysql, "CREATE TABLE t1(c2 DATETIME)"); + + stmt= mysql_stmt_init(mysql); + FAIL_IF(!stmt, mysql_error(mysql)); + rc= mysql_stmt_prepare(stmt, SL("INSERT INTO t1 VALUES (?)")); + check_stmt_rc(rc, 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_stmt_rc(rc, stmt); + rc= mysql_stmt_execute(stmt); + check_stmt_rc(rc, stmt); + } + + mysql_stmt_close(stmt); + mysql_query(mysql, "DROP TABLE IF EXISTS t1"); + + return OK; +} + +/* + Bug#28934: server crash when receiving malformed com_execute packets +*/ + +static int test_bug28934(MYSQL *mysql) +{ + my_bool error= 0; + MYSQL_BIND bind[5]; + MYSQL_STMT *stmt; + int rc, cnt; + + rc= mysql_query(mysql, "drop table if exists t1"); + check_mysql_rc(rc, mysql); + rc= mysql_query(mysql, "create table t1(id int)"); + check_mysql_rc(rc, mysql); + + rc= mysql_query(mysql, "insert into t1 values(1),(2),(3),(4),(5)"); + check_mysql_rc(rc, mysql); + + stmt= mysql_stmt_init(mysql); + FAIL_IF(!stmt, mysql_error(mysql)); + rc= mysql_stmt_prepare(stmt, SL("select * from t1 where id in(?,?,?,?,?)")); + check_stmt_rc(rc, 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; + } + rc= mysql_stmt_bind_param(stmt, bind); + check_stmt_rc(rc, stmt); + + stmt->param_count=2; + error= mysql_stmt_execute(stmt); + FAIL_UNLESS(error != 0, "Error expected"); + mysql_stmt_close(stmt); + + rc= mysql_query(mysql, "drop table t1"); + check_mysql_rc(rc, mysql); + return OK; +} + +static int test_bug3035(MYSQL *mysql) +{ + 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; + + + stmt_text= "DROP TABLE IF EXISTS t1"; + rc= mysql_real_query(mysql, SL(stmt_text)); + check_mysql_rc(rc, mysql); + + 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, SL(stmt_text)); + check_mysql_rc(rc, mysql); + + memset(bind_array, '\0', 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_rc(rc, stmt); + + stmt_text= "INSERT INTO t1 (i8, ui8, i16, ui16, i32, ui32, i64, ui64) " + "VALUES (?, ?, ?, ?, ?, ?, ?, ?)"; + rc= mysql_stmt_prepare(stmt, SL(stmt_text)); + check_stmt_rc(rc, stmt); + 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_stmt_rc(rc, stmt); + 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_stmt_rc(rc, stmt); + 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, SL(stmt_text)); + check_stmt_rc(rc, stmt); + rc= mysql_stmt_execute(stmt); + check_stmt_rc(rc, stmt); + 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_stmt_rc(rc, stmt); + FAIL_UNLESS(int8_val == int8_min, "int8_val != int8_min"); + FAIL_UNLESS(uint8_val == uint8_min, "uint8_val != uint8_min"); + FAIL_UNLESS(int16_val == int16_min, "int16_val != int16_min"); + FAIL_UNLESS(uint16_val == uint16_min, "uint16_val != uint16_min"); + FAIL_UNLESS(int32_val == int32_min, "int32_val != int32_min"); + FAIL_UNLESS(uint32_val == uint32_min, "uint32_val != uint32_min"); + FAIL_UNLESS(int64_val == int64_min, "int64_val != int64_min"); + FAIL_UNLESS(uint64_val == uint64_min, "uint64_val != uint64_min"); + FAIL_UNLESS(double_val == (longlong) uint64_min, "double_val != uint64_min"); + double_tmp= ulonglong2double(uint64_val); + FAIL_UNLESS(cmp_double(&udouble_val,&double_tmp), "udouble_val != double_tmp"); + FAIL_UNLESS(!strcmp(longlong_as_string, "0"), "longlong_as_string != '0'"); + FAIL_UNLESS(!strcmp(ulonglong_as_string, "0"), "ulonglong_as_string != '0'"); + + rc= mysql_stmt_fetch(stmt); + + FAIL_UNLESS(rc == MYSQL_DATA_TRUNCATED || rc == 0, "rc != 0,MYSQL_DATA_TRUNCATED"); + + FAIL_UNLESS(int8_val == int8_max, "int8_val != int8_max"); + FAIL_UNLESS(uint8_val == uint8_max, "uint8_val != uint8_max"); + FAIL_UNLESS(int16_val == int16_max, "int16_val != int16_max"); + FAIL_UNLESS(uint16_val == uint16_max, "uint16_val != uint16_max"); + FAIL_UNLESS(int32_val == int32_max, "int32_val != int32_max"); + FAIL_UNLESS(uint32_val == uint32_max, "uint32_val != uint32_max"); + FAIL_UNLESS(int64_val == int64_max, "int64_val != int64_max"); + FAIL_UNLESS(uint64_val == uint64_max, "uint64_val != uint64_max"); + FAIL_UNLESS(double_val == (longlong) uint64_val, "double_val != uint64_val"); + double_tmp= ulonglong2double(uint64_val); + FAIL_UNLESS(cmp_double(&udouble_val,&double_tmp), "udouble_val != double_tmp"); + FAIL_UNLESS(!strcmp(longlong_as_string, "-1"), "longlong_as_string != '-1'"); + FAIL_UNLESS(!strcmp(ulonglong_as_string, "18446744073709551615"), "ulonglong_as_string != '18446744073709551615'"); + + rc= mysql_stmt_fetch(stmt); + FAIL_UNLESS(rc == MYSQL_NO_DATA, ""); + + mysql_stmt_close(stmt); + + stmt_text= "DROP TABLE t1"; + mysql_real_query(mysql, SL(stmt_text)); + return OK; +} + +/* + Test for BUG#3420 ("select id1, value1 from t where id= ? or value= ?" + returns all rows in the table) +*/ + +static int test_ps_conj_select(MYSQL *mysql) +{ + 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]; + + // https://jira.mariadb.org/browse/XPT-266 + if (IS_XPAND()) { + rc= mysql_query(mysql, "SET NAMES UTF8"); + check_mysql_rc(rc, mysql); + } + + rc= mysql_query(mysql, "drop table if exists t1"); + check_mysql_rc(rc, mysql); + + rc= mysql_query(mysql, "create table t1 (id1 int(11) NOT NULL default '0', " + "value2 varchar(100), value1 varchar(100))"); + check_mysql_rc(rc, mysql); + + rc= mysql_query(mysql, "insert into t1 values (1, 'hh', 'hh'), " + "(2, 'hh', 'hh'), (1, 'ii', 'ii'), (2, 'ii', 'ii')"); + check_mysql_rc(rc, mysql); + + strcpy(query, "select id1, value1 from t1 where id1= ? or " + "CONVERT(value1 USING utf8)= ?"); + stmt= mysql_stmt_init(mysql); + FAIL_IF(!stmt, mysql_error(mysql)); + rc= mysql_stmt_prepare(stmt, SL(query)); + check_stmt_rc(rc, stmt); + + FAIL_IF(mysql_stmt_param_count(stmt) != 2, "param_count != 2"); + + /* Always bzero all members of bind parameter */ + memset(my_bind, '\0', 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_stmt_rc(rc, stmt); + int_data= 1; + strcpy(str_data, "hh"); + str_length= (unsigned long)strlen(str_data); + + rc= mysql_stmt_execute(stmt); + check_stmt_rc(rc, stmt); + + rc=0; + while (mysql_stmt_fetch(stmt) != MYSQL_NO_DATA) + rc++; + FAIL_UNLESS(rc == 3, "rc != 3"); + + mysql_stmt_close(stmt); + rc= mysql_query(mysql, "drop table if exists t1"); + check_mysql_rc(rc, mysql); + return OK; +} + +/* Test for NULL as PS parameter (BUG#3367, BUG#3371) */ + +static int test_ps_null_param(MYSQL *mysql) +{ + 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; + + + rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_ps_nulls"); + check_mysql_rc(rc, mysql); + + rc= mysql_query(mysql, "CREATE TABLE test_ps_nulls(col1 int)"); + check_mysql_rc(rc, mysql); + + rc= mysql_query(mysql, "INSERT INTO test_ps_nulls values (1), (null)"); + check_mysql_rc(rc, mysql); + + /* Always bzero all members of bind parameter */ + memset(&in_bind, '\0', sizeof(in_bind)); + memset(&out_bind, '\0', 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]; + strcpy(query, *cur_query); + stmt= mysql_stmt_init(mysql); + FAIL_IF(!stmt, mysql_error(mysql)); + rc= mysql_stmt_prepare(stmt, SL(query)); + diag("statement: %s", query); + check_stmt_rc(rc, stmt); + FAIL_IF(mysql_stmt_param_count(stmt) != 1, "param_count != 1"); + + rc= mysql_stmt_bind_param(stmt, &in_bind); + check_stmt_rc(rc, stmt); + rc= mysql_stmt_bind_result(stmt, &out_bind); + check_stmt_rc(rc, stmt); + rc= mysql_stmt_execute(stmt); + check_stmt_rc(rc, stmt); + rc= mysql_stmt_fetch(stmt); + FAIL_UNLESS(rc != MYSQL_NO_DATA, "rc != MYSQL_NO_DATA"); + FAIL_UNLESS(out_is_null, "!out_is_null"); + rc= mysql_stmt_fetch(stmt); + FAIL_UNLESS(rc == MYSQL_NO_DATA, "rc != MYSQL_NO_DATA"); + mysql_stmt_close(stmt); + } + rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_ps_nulls"); + check_mysql_rc(rc, mysql); + return OK; +} + +/* + 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); \ + FAIL_UNLESS(r_metadata != NULL, ""); \ + rc= mysql_stmt_fetch(stmt); \ + check_stmt_rc(rc,stmt); \ + FAIL_UNLESS((r_int_data == i1) && (r_str_length == l1) && \ + (strcmp(r_str_data, s1) == 0), "test_ps_query_cache_result failure"); \ + rc= mysql_stmt_fetch(stmt); \ + check_stmt_rc(rc,stmt); \ + FAIL_UNLESS((r_int_data == i2) && (r_str_length == l2) && \ + (strcmp(r_str_data, s2) == 0), "test_ps_query_cache_result failure"); \ + rc= mysql_stmt_fetch(stmt); \ + check_stmt_rc(rc,stmt); \ + FAIL_UNLESS((r_int_data == i3) && (r_str_length == l3) && \ + (strcmp(r_str_data, s3) == 0), "test_ps_query_cache_result failure"); \ + rc= mysql_stmt_fetch(stmt); \ + FAIL_UNLESS(rc == MYSQL_NO_DATA, "rc != MYSQL_NO_DATA"); \ + mysql_free_result(r_metadata); + +/* reads Qcache_hits from server and returns its value */ +static int query_cache_hits(MYSQL *mysql) +{ + MYSQL_RES *res; + MYSQL_ROW row; + int rc; + uint result; + + rc= mysql_query(mysql, "show status like 'qcache_hits'"); + check_mysql_rc(rc, mysql); + res= mysql_use_result(mysql); + + row= mysql_fetch_row(res); + + result= atoi(row[1]); + mysql_free_result(res); + return result; +} + + +/* + Test that prepared statements make use of the query cache just as normal + statements (BUG#735). +*/ +static int test_ps_query_cache(MYSQL *mysql) +{ + 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; + + diag("test needs to be fixed"); + return SKIP; + /* prepare the table */ + + rc= mysql_query(mysql, "drop table if exists t1"); + check_mysql_rc(rc, mysql); + + rc= mysql_query(mysql, "create table t1 (id1 int(11) NOT NULL default '0', " + "value2 varchar(100), value1 varchar(100))"); + check_mysql_rc(rc, mysql); + + rc= mysql_query(mysql, "insert into t1 values (1, 'hh', 'hh'), " + "(2, 'hh', 'hh'), (1, 'ii', 'ii'), (2, 'ii', 'ii')"); + check_mysql_rc(rc, mysql); + + 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"); + check_mysql_rc(rc, mysql); + break; + case TEST_QCACHE_OFF_ON: + rc= mysql_query(lmysql, "set global query_cache_size=0"); + check_mysql_rc(rc, mysql); + break; + case TEST_QCACHE_ON_WITH_OTHER_CONN: + lmysql= test_connect(NULL); + FAIL_IF(!lmysql, "Opening new connection failed"); + break; + } + + strcpy(query, "select id1, value1 from t1 where id1= ? or " + "CONVERT(value1 USING utf8)= ?"); + stmt= mysql_stmt_init(lmysql); + FAIL_IF(!stmt, mysql_error(lmysql)); + rc= mysql_stmt_prepare(stmt, SL(query)); + check_stmt_rc(rc, stmt); + + FAIL_IF(mysql_stmt_param_count(stmt) != 2, "param_count != 2"); + + switch (iteration) { + case TEST_QCACHE_OFF_ON: + rc= mysql_query(lmysql, "set global query_cache_size=1000000"); + check_mysql_rc(rc, mysql); + break; + case TEST_QCACHE_ON_OFF: + rc= mysql_query(lmysql, "set global query_cache_size=0"); + check_mysql_rc(rc, mysql); + default: + break; + } + + memset(p_bind, '\0', 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_stmt_rc(rc, stmt); + p_int_data= 1; + strcpy(p_str_data, "hh"); + p_str_length= (unsigned long)strlen(p_str_data); + + memset(r_bind, '\0', 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_stmt_rc(rc, stmt); + rc= mysql_stmt_execute(stmt); + check_stmt_rc(rc, stmt); + test_ps_query_cache_result(1, "hh", 2, 2, "hh", 2, 1, "ii", 2); + r_metadata= mysql_stmt_result_metadata(stmt); + FAIL_UNLESS(r_metadata != NULL, ""); + rc= mysql_stmt_fetch(stmt); + check_stmt_rc(rc,stmt); + FAIL_UNLESS((r_int_data == 1) && (r_str_length == 2) && + (strcmp(r_str_data, "hh") == 0), "test_ps_query_cache_result failure"); \ + rc= mysql_stmt_fetch(stmt); + check_stmt_rc(rc,stmt); + FAIL_UNLESS((r_int_data == 2) && (r_str_length == 2) && + (strcmp(r_str_data, "hh") == 0), "test_ps_query_cache_result failure"); \ + rc= mysql_stmt_fetch(stmt); + check_stmt_rc(rc,stmt); + FAIL_UNLESS((r_int_data == 1) && (r_str_length == 2) && + (strcmp(r_str_data, "ii") == 0), "test_ps_query_cache_result failure"); \ + rc= mysql_stmt_fetch(stmt); + FAIL_UNLESS(rc == MYSQL_NO_DATA, "rc != MYSQL_NO_DATA"); + mysql_free_result(r_metadata); + + + /* now retry with the same parameter values and see qcache hits */ + hits1= query_cache_hits(lmysql); + rc= mysql_stmt_execute(stmt); + check_stmt_rc(rc, stmt); 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 */ + FAIL_UNLESS(hits2-hits1 == 1, "hits2 != hits1 + 1"); + break; + case TEST_QCACHE_OFF_ON: + case TEST_QCACHE_ON_OFF: /* should not have hit */ + FAIL_UNLESS(hits2-hits1 == 0, "hits2 != hits1"); + break; + } + + /* now modify parameter values and see qcache hits */ + strcpy(p_str_data, "ii"); + p_str_length= (unsigned long)strlen(p_str_data); + rc= mysql_stmt_execute(stmt); + check_stmt_rc(rc, stmt); + 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 */ + FAIL_UNLESS(hits2-hits1 == 0, "hits2 != hits1"); + break; + case TEST_QCACHE_ON_WITH_OTHER_CONN: /* should have hit */ + FAIL_UNLESS(hits1-hits2 == 1, "hits2 != hits1+1"); + break; + } + + rc= mysql_stmt_execute(stmt); + check_stmt_rc(rc, stmt); + 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 */ + FAIL_UNLESS(hits2-hits1 == 1, "hits2 != hits1+1"); + break; + case TEST_QCACHE_OFF_ON: + case TEST_QCACHE_ON_OFF: /* should not have hit */ + FAIL_UNLESS(hits2-hits1 == 0, "hits2 != hits1"); + break; + case TEST_QCACHE_ON_WITH_OTHER_CONN: /* should have hit */ + FAIL_UNLESS(hits2-hits1 == 1, "hits2 != hits1+1"); + break; + } + + } /* for(iteration=...) */ + + if (lmysql != mysql) + mysql_close(lmysql); + + rc= mysql_query(mysql, "set global query_cache_size=0"); + check_mysql_rc(rc, mysql); + return OK; +} + +static int test_bug3117(MYSQL *mysql) +{ + MYSQL_STMT *stmt; + MYSQL_BIND buffer; + longlong lii; + ulong length; + my_bool is_null; + int rc; + + rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1"); + check_mysql_rc(rc, mysql); + + rc= mysql_query(mysql, "CREATE TABLE t1 (id int auto_increment primary key)"); + check_mysql_rc(rc, mysql); + + stmt= mysql_stmt_init(mysql); + FAIL_IF(!stmt, mysql_error(mysql)); + rc= mysql_stmt_prepare(stmt, SL("SELECT LAST_INSERT_ID()")); + check_stmt_rc(rc, stmt); + + rc= mysql_query(mysql, "INSERT INTO t1 VALUES (NULL)"); + check_mysql_rc(rc, mysql); + + rc= mysql_stmt_execute(stmt); + check_stmt_rc(rc, stmt); + memset(&buffer, '\0', 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_stmt_rc(rc, stmt); + rc= mysql_stmt_store_result(stmt); + check_stmt_rc(rc, stmt); + rc= mysql_stmt_fetch(stmt); + check_stmt_rc(rc, stmt); + FAIL_UNLESS(is_null == 0 && lii == 1, "is_null != 0 || lii != 1"); + + rc= mysql_query(mysql, "INSERT INTO t1 VALUES (NULL)"); + check_mysql_rc(rc, mysql); + + rc= mysql_stmt_execute(stmt); + check_stmt_rc(rc, stmt); + rc= mysql_stmt_fetch(stmt); + check_stmt_rc(rc, stmt); + FAIL_UNLESS(is_null == 0 && lii == 2, "is_null != 0 || lii != 2"); + + mysql_stmt_close(stmt); + + rc= mysql_query(mysql, "DROP TABLE t1"); + check_mysql_rc(rc, mysql); + return OK; +} + +/** + Bug#36004 mysql_stmt_prepare resets the list of warnings +*/ + +static int test_bug36004(MYSQL *mysql) +{ + int rc, warning_count= 0; + MYSQL_STMT *stmt; + SKIP_MAXSCALE; + SKIP_MYSQL(mysql); // don't send expected warnings + + if (mysql_get_server_version(mysql) < 60000) { + diag("Test requires MySQL Server version 6.0 or above"); + return SKIP; + } + + rc= mysql_query(mysql, "drop table if exists inexistant"); + check_mysql_rc(rc, mysql); + + FAIL_UNLESS(mysql_warning_count(mysql) == 1, ""); + query_int_variable(mysql, "@@warning_count", &warning_count); + FAIL_UNLESS(warning_count, "Warning expected"); + + stmt= mysql_stmt_init(mysql); + FAIL_IF(!stmt, mysql_error(mysql)); + rc= mysql_stmt_prepare(stmt, SL("select 1")); + check_stmt_rc(rc, stmt); + + FAIL_UNLESS(mysql_warning_count(mysql) == 0, "No warning expected"); + query_int_variable(mysql, "@@warning_count", &warning_count); + FAIL_UNLESS(warning_count, "warning expected"); + + rc= mysql_stmt_execute(stmt); + check_stmt_rc(rc, stmt); + FAIL_UNLESS(mysql_warning_count(mysql) == 0, "No warning expected"); + mysql_stmt_close(stmt); + + query_int_variable(mysql, "@@warning_count", &warning_count); + FAIL_UNLESS(warning_count, "Warning expected"); + + stmt= mysql_stmt_init(mysql); + FAIL_IF(!stmt, mysql_error(mysql)); + rc= mysql_stmt_prepare(stmt, SL("drop table if exists inexistant")); + check_stmt_rc(rc, stmt); + + query_int_variable(mysql, "@@warning_count", &warning_count); + FAIL_UNLESS(warning_count == 0, "No warning expected"); + mysql_stmt_close(stmt); + + return OK; +} + +static int test_bug3796(MYSQL *mysql) +{ + 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; + + // https://jira.mariadb.org/browse/XPT-266 + if (IS_XPAND()) { + rc= mysql_query(mysql, "SET NAMES UTF8"); + check_mysql_rc(rc, mysql); + } + + /* Create and fill test table */ + stmt_text= "DROP TABLE IF EXISTS t1"; + rc= mysql_real_query(mysql, SL(stmt_text)); + check_mysql_rc(rc, mysql); + + stmt_text= "CREATE TABLE t1 (a INT, b VARCHAR(30))"; + rc= mysql_real_query(mysql, SL(stmt_text)); + check_mysql_rc(rc, mysql); + + stmt_text= "INSERT INTO t1 VALUES(1, 'ONE'), (2, 'TWO')"; + rc= mysql_real_query(mysql, SL(stmt_text)); + check_mysql_rc(rc, mysql); + + /* 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, SL(stmt_text)); + check_stmt_rc(rc, stmt); + /* Bind input buffers */ + memset(my_bind, '\0', sizeof(my_bind)); + my_bind[0].buffer_type= MYSQL_TYPE_STRING; + my_bind[0].buffer= (void *) concat_arg0; + my_bind[0].buffer_length= (unsigned long)strlen(concat_arg0); + + mysql_stmt_bind_param(stmt, my_bind); + + /* Execute the select statement */ + rc= mysql_stmt_execute(stmt); + check_stmt_rc(rc, stmt); + 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); + check_stmt_rc(rc, stmt); + strcpy(canonical_buff, concat_arg0); + strcat(canonical_buff, "ONE"); + FAIL_UNLESS(strlen(canonical_buff) == out_length && + strncmp(out_buff, canonical_buff, out_length) == 0, ""); + + rc= mysql_stmt_fetch(stmt); + check_stmt_rc(rc, stmt); + strcpy(canonical_buff + strlen(concat_arg0), "TWO"); + FAIL_UNLESS(strlen(canonical_buff) == out_length && + strncmp(out_buff, canonical_buff, out_length) == 0, ""); + + rc= mysql_stmt_fetch(stmt); + FAIL_UNLESS(rc == MYSQL_NO_DATA, "rc != MYSQL_NO_DATA"); + + mysql_stmt_close(stmt); + + stmt_text= "DROP TABLE IF EXISTS t1"; + rc= mysql_real_query(mysql, SL(stmt_text)); + check_mysql_rc(rc, mysql); + return OK; +} + +static int test_bug4026(MYSQL *mysql) +{ + 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; + + + /* 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, SL(stmt_text)); + check_stmt_rc(rc, stmt); + /* Bind input buffers */ + memset(my_bind, '\0', sizeof(MYSQL_BIND) * 2); + memset(&time_in, '\0', sizeof(MYSQL_TIME)); + memset(&time_out, '\0', sizeof(MYSQL_TIME)); + memset(&datetime_in, '\0', sizeof(MYSQL_TIME)); + memset(&datetime_out, '\0', sizeof(MYSQL_TIME)); + 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_stmt_rc(rc, stmt); + 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); + FAIL_UNLESS(rc == 0, "rc != 0"); + FAIL_UNLESS(memcmp(&time_in, &time_out, sizeof(time_in)) == 0, "time_in != time_out"); + FAIL_UNLESS(memcmp(&datetime_in, &datetime_out, sizeof(datetime_in)) == 0, "datetime_in != datetime_out"); + mysql_stmt_close(stmt); + + return OK; +} + +static int test_bug4030(MYSQL *mysql) +{ + 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; + + + /* 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, SL(stmt_text)); + check_stmt_rc(rc, stmt); + rc= mysql_stmt_execute(stmt); + check_stmt_rc(rc, stmt); + /* Bind output buffers */ + memset(my_bind, '\0', sizeof(my_bind)); + memset(&time_canonical, '\0', sizeof(time_canonical)); + memset(&time_out, '\0', sizeof(time_out)); + memset(&date_canonical, '\0', sizeof(date_canonical)); + memset(&date_out, '\0', sizeof(date_out)); + memset(&datetime_canonical, '\0', sizeof(datetime_canonical)); + memset(&datetime_out, '\0', 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); + FAIL_UNLESS(rc == 0, "rc != 0"); + FAIL_UNLESS(memcmp(&time_canonical, &time_out, sizeof(time_out)) == 0, "time_canonical != time_out"); + FAIL_UNLESS(memcmp(&date_canonical, &date_out, sizeof(date_out)) == 0, "date_canoncical != date_out"); + FAIL_UNLESS(memcmp(&datetime_canonical, &datetime_out, sizeof(datetime_out)) == 0, "datetime_canonical != datetime_out"); + mysql_stmt_close(stmt); + return OK; +} + +static int test_bug4079(MYSQL *mysql) +{ + MYSQL_STMT *stmt; + MYSQL_BIND my_bind[1]; + const char *stmt_text; + uint32 res; + int rc; + + /* 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, SL(stmt_text)); + check_stmt_rc(rc, stmt); + /* Execute the select statement */ + rc= mysql_stmt_execute(stmt); + check_stmt_rc(rc, stmt); + /* Bind input buffers */ + memset(my_bind, '\0', 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); + FAIL_UNLESS(rc == 1, "rc != 1"); + /* buggy version of libmysql hanged up here */ + mysql_stmt_close(stmt); + return OK; +} + +static int test_bug4172(MYSQL *mysql) +{ + 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; + + 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, SL(stmt_text)); + check_stmt_rc(rc, stmt); rc= mysql_stmt_execute(stmt); + check_stmt_rc(rc, stmt); + memset(my_bind, '\0', 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_stmt_rc(rc, stmt); + rc= mysql_real_query(mysql, SL(stmt_text)); + check_mysql_rc(rc, mysql); + res= mysql_store_result(mysql); + row= mysql_fetch_row(res); + + diag("expected %s %s %s", row[0], row[1], row[2]); + diag("fetched %s %s %s", f, d, e); + FAIL_UNLESS(!strcmp(f, row[0]) && !strcmp(d, row[1]) && !strcmp(e, row[2]), ""); + + mysql_free_result(res); + mysql_stmt_close(stmt); + return OK; +} + +static int test_bug4231(MYSQL *mysql) +{ + MYSQL_STMT *stmt; + MYSQL_BIND my_bind[2]; + MYSQL_TIME tm[2]; + const char *stmt_text; + int rc; + + + stmt_text= "DROP TABLE IF EXISTS t1"; + rc= mysql_real_query(mysql, SL(stmt_text)); + check_mysql_rc(rc, mysql); + + stmt_text= "CREATE TABLE t1 (a int)"; + rc= mysql_real_query(mysql, SL(stmt_text)); + check_mysql_rc(rc, mysql); + + stmt_text= "INSERT INTO t1 VALUES (1)"; + rc= mysql_real_query(mysql, SL(stmt_text)); + check_mysql_rc(rc, mysql); + + stmt= mysql_stmt_init(mysql); + stmt_text= "SELECT a FROM t1 WHERE ? = ?"; + rc= mysql_stmt_prepare(stmt, SL(stmt_text)); + check_stmt_rc(rc, stmt); + /* Bind input buffers */ + memset(my_bind, '\0', sizeof(my_bind)); memset(tm, '\0', 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_stmt_rc(rc, stmt); + /* + 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_stmt_rc(rc, stmt); + rc= mysql_stmt_fetch(stmt); + + /* binds are unequal, no rows should be returned */ + FAIL_UNLESS(rc == MYSQL_NO_DATA, "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); + FAIL_UNLESS(rc == 0, "rc != 0"); + + mysql_stmt_close(stmt); + stmt_text= "DROP TABLE t1"; + rc= mysql_real_query(mysql, SL(stmt_text)); + check_mysql_rc(rc, mysql); + return OK; +} + +static int test_bug4236(MYSQL *mysql) +{ + MYSQL_STMT *stmt; + const char *stmt_text; + int rc; + MYSQL_STMT backup; + + 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, SL(stmt_text)); + check_stmt_rc(rc, stmt); /* 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); + FAIL_IF(!rc, "Error expected"); + + /* Restore original statement id to be able to reprepare it */ + stmt->stmt_id= backup.stmt_id; + + mysql_stmt_close(stmt); + return OK; +} + +static int test_bug5126(MYSQL *mysql) +{ + MYSQL_STMT *stmt; + MYSQL_BIND my_bind[2]; + int32 c1, c2; + const char *stmt_text; + int rc; + + + stmt_text= "DROP TABLE IF EXISTS t1"; + rc= mysql_real_query(mysql, SL(stmt_text)); + check_mysql_rc(rc, mysql); + + stmt_text= "CREATE TABLE t1 (a mediumint, b int)"; + rc= mysql_real_query(mysql, SL(stmt_text)); + check_mysql_rc(rc, mysql); + + stmt_text= "INSERT INTO t1 VALUES (8386608, 1)"; + rc= mysql_real_query(mysql, SL(stmt_text)); + check_mysql_rc(rc, mysql); + + stmt= mysql_stmt_init(mysql); + stmt_text= "SELECT a, b FROM t1"; + rc= mysql_stmt_prepare(stmt, SL(stmt_text)); + check_stmt_rc(rc, stmt); + rc= mysql_stmt_execute(stmt); + check_stmt_rc(rc, stmt); + /* Bind output buffers */ + memset(my_bind, '\0', 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); + FAIL_UNLESS(rc == 0, "rc != 0"); + FAIL_UNLESS(c1 == 8386608 && c2 == 1, "c1 != 8386608 || c2 != 1"); + mysql_stmt_close(stmt); + return OK; +} + +static int test_bug5194(MYSQL *mysql) +{ + 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; + + SKIP_MAXSCALE; + + stmt_text= "drop table if exists t1"; + rc= mysql_real_query(mysql, SL(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, SL(stmt_text)); + check_mysql_rc(rc, mysql); + + 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); + + FAIL_IF(my_bind == 0 || query == 0 || param_str == 0, "Not enough memory"); + + 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= (int)strlen(param_str); + + /* setup bind array */ + memset(my_bind, '\0', 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 + (unsigned long)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) /* expected error */ + break; + + check_stmt_rc(rc, stmt); + + /* bind the parameter array and execute the query */ + rc= mysql_stmt_bind_param(stmt, my_bind); + check_stmt_rc(rc, stmt); + rc= mysql_stmt_execute(stmt); + check_stmt_rc(rc, stmt); + rc= mysql_stmt_reset(stmt); + } + + free(param_str); + free(query); + rc= mysql_stmt_close(stmt); + check_stmt_rc(rc, stmt); + free(my_bind); + stmt_text= "drop table t1"; + rc= mysql_real_query(mysql, SL(stmt_text)); + check_mysql_rc(rc, mysql); + return OK; +} + +static int test_bug5315(MYSQL *mysql) +{ + MYSQL_STMT *stmt; + const char *stmt_text; + int rc; + SKIP_MAXSCALE; + + if (!is_mariadb) + return SKIP; + + stmt_text= "SELECT 1"; + stmt= mysql_stmt_init(mysql); + rc= mysql_stmt_prepare(stmt, SL(stmt_text)); + check_stmt_rc(rc, stmt); + rc= mysql_change_user(mysql, username, password, schema); + check_mysql_rc(rc, mysql); + + rc= mysql_stmt_execute(stmt); + FAIL_UNLESS(rc != 0, "Error expected"); + + rc= mysql_stmt_close(stmt); + check_stmt_rc(rc, stmt); + + stmt= mysql_stmt_init(mysql); + rc= mysql_stmt_prepare(stmt, SL(stmt_text)); + check_stmt_rc(rc, stmt); + rc= mysql_stmt_execute(stmt); + check_stmt_rc(rc, stmt); + mysql_stmt_close(stmt); + return OK; +} + +static int test_bug5399(MYSQL *mysql) +{ + /* + 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; + + + memset(my_bind, '\0', 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, SL(buff)); + check_stmt_rc(rc, *stmt); mysql_stmt_bind_result(*stmt, my_bind); + } + + for (stmt= stmt_list; stmt != stmt_list + NUM_OF_USED_STMT; ++stmt) + { + rc= mysql_stmt_execute(*stmt); + check_stmt_rc(rc, *stmt); + rc= mysql_stmt_store_result(*stmt); + check_stmt_rc(rc, *stmt); + rc= mysql_stmt_fetch(*stmt); + FAIL_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 + return OK; +} + +static int test_bug6046(MYSQL *mysql) +{ + MYSQL_STMT *stmt; + const char *stmt_text; + int rc; + short b= 1; + MYSQL_BIND my_bind[1]; + + + stmt_text= "DROP TABLE IF EXISTS t1"; + rc= mysql_real_query(mysql, SL(stmt_text)); + check_mysql_rc(rc, mysql); + stmt_text= "CREATE TABLE t1 (a int, b int)"; + rc= mysql_real_query(mysql, SL(stmt_text)); + check_mysql_rc(rc, mysql); + stmt_text= "INSERT INTO t1 VALUES (1,1),(2,2),(3,1),(4,2)"; + rc= mysql_real_query(mysql, SL(stmt_text)); + check_mysql_rc(rc, mysql); + + 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, SL(stmt_text)); + check_stmt_rc(rc, stmt); + b= 1; + memset(my_bind, '\0', 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_stmt_rc(rc, stmt); + mysql_stmt_store_result(stmt); + + rc= mysql_stmt_execute(stmt); + check_stmt_rc(rc, stmt); + mysql_stmt_close(stmt); + return OK; +} + +static int test_bug6049(MYSQL *mysql) +{ + 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; + + + stmt_text= "SELECT MAKETIME(-25, 12, 12)"; + + rc= mysql_real_query(mysql, SL(stmt_text)); + check_mysql_rc(rc, mysql); + res= mysql_store_result(mysql); + row= mysql_fetch_row(res); + + stmt= mysql_stmt_init(mysql); + rc= mysql_stmt_prepare(stmt, SL(stmt_text)); + check_stmt_rc(rc, stmt); + rc= mysql_stmt_execute(stmt); + check_stmt_rc(rc, stmt); + memset(my_bind, '\0', 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); + check_stmt_rc(rc, stmt); + + FAIL_UNLESS(strcmp(row[0], (char*) buffer) == 0, "row[0] != buffer"); + + mysql_free_result(res); + mysql_stmt_close(stmt); + return OK; +} + +static int test_bug6058(MYSQL *mysql) +{ + 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; + + + stmt_text= "SELECT CAST('0000-00-00' AS DATE)"; + + rc= mysql_real_query(mysql, SL(stmt_text)); + check_mysql_rc(rc, mysql); + res= mysql_store_result(mysql); + row= mysql_fetch_row(res); + + stmt= mysql_stmt_init(mysql); + rc= mysql_stmt_prepare(stmt, SL(stmt_text)); + check_stmt_rc(rc, stmt); + rc= mysql_stmt_execute(stmt); + check_stmt_rc(rc, stmt); + memset(my_bind, '\0', 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); + check_stmt_rc(rc, stmt); + + FAIL_UNLESS(strcmp(row[0], buffer) == 0, "row[0] != buffer"); + + mysql_free_result(res); + mysql_stmt_close(stmt); + return OK; +} + + +static int test_bug6059(MYSQL *mysql) +{ + MYSQL_STMT *stmt; + const char *stmt_text; + int rc; + + SKIP_SKYSQL; + + stmt_text= "SELECT 'foo' INTO OUTFILE 'x.3'"; + + stmt= mysql_stmt_init(mysql); + rc= mysql_stmt_prepare(stmt, SL(stmt_text)); + check_stmt_rc(rc, stmt); + FAIL_UNLESS(mysql_stmt_field_count(stmt) == 0, ""); + mysql_stmt_close(stmt); + return OK; +} + +static int test_bug6096(MYSQL *mysql) +{ + 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; + + + stmt_text= "drop table if exists t1"; + rc= mysql_real_query(mysql, SL(stmt_text)); + check_mysql_rc(rc, mysql); + + 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, SL(stmt_text)); + check_mysql_rc(rc, mysql); + 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, SL(stmt_text)); + check_mysql_rc(rc, mysql); + + stmt_text= "select * from t1"; + + /* Run select in prepared and non-prepared mode and compare metadata */ + rc= mysql_real_query(mysql, SL(stmt_text)); + check_mysql_rc(rc, mysql); + query_result= mysql_store_result(mysql); + query_field_list= mysql_fetch_fields(query_result); + FAIL_IF(!query_field_list, "fetch_fields failed"); + query_field_count= mysql_num_fields(query_result); + + stmt= mysql_stmt_init(mysql); + rc= mysql_stmt_prepare(stmt, SL(stmt_text)); + check_stmt_rc(rc, stmt); rc= mysql_stmt_execute(stmt); + check_stmt_rc(rc, stmt); 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); + FAIL_UNLESS(stmt_field_count == query_field_count, ""); + + + /* Bind and fetch the data */ + + memset(my_bind, '\0', 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); + diag("rc=%d", rc); + check_stmt_rc(rc, stmt); + rc= mysql_stmt_fetch(stmt); + FAIL_UNLESS(rc == MYSQL_NO_DATA, "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, SL(stmt_text)); + check_mysql_rc(rc, mysql); + return OK; +} + +/* Bug#7990 - mysql_stmt_close doesn't reset mysql->net.last_error */ + +static int test_bug7990(MYSQL *mysql) +{ + MYSQL_STMT *stmt; + int rc; + + 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 + */ + FAIL_UNLESS(rc && mysql_stmt_errno(stmt) && mysql_errno(mysql), "Error expected"); + mysql_stmt_close(stmt); + return OK; +} + +/* Bug#8330 - mysql_stmt_execute crashes (libmysql) */ + +static int test_bug8330(MYSQL *mysql) +{ + 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]= {1,2}; + + stmt_text= "drop table if exists t1"; + /* in case some previous test failed */ + rc= mysql_real_query(mysql, SL(stmt_text)); + check_mysql_rc(rc, mysql); + stmt_text= "create table t1 (a int, b int)"; + rc= mysql_real_query(mysql, SL(stmt_text)); + check_mysql_rc(rc, mysql); + + memset(my_bind, '\0', sizeof(my_bind)); + for (i=0; i < 2; i++) + { + stmt[i]= mysql_stmt_init(mysql); + rc= mysql_stmt_prepare(stmt[i], SL(query)); + check_stmt_rc(rc, stmt[i]); + my_bind[i].buffer_type= MYSQL_TYPE_LONG; + 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_stmt_rc(rc, stmt[0]); + rc= mysql_stmt_execute(stmt[1]); + FAIL_UNLESS(rc && mysql_stmt_errno(stmt[1]) == CR_COMMANDS_OUT_OF_SYNC, "Error expected"); + rc= mysql_stmt_execute(stmt[0]); + check_stmt_rc(rc, stmt[0]); + mysql_stmt_close(stmt[0]); + mysql_stmt_close(stmt[1]); + + stmt_text= "drop table t1"; + rc= mysql_real_query(mysql, SL(stmt_text)); + check_mysql_rc(rc, mysql); + return OK; +} + +/* Test misc field information, bug: #74 */ + +static int test_field_misc(MYSQL *mysql) +{ + MYSQL_STMT *stmt; + MYSQL_RES *result; + int rc; + + + rc= mysql_query(mysql, "SELECT @@autocommit"); + check_mysql_rc(rc, mysql); + + result= mysql_store_result(mysql); + FAIL_IF(!result, "Invalid result set"); + + rc= 0; + while (mysql_fetch_row(result)) + rc++; + FAIL_UNLESS(rc == 1, "rowcount != 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_stmt_init(mysql); + FAIL_IF(!stmt, mysql_error(mysql)); + rc= mysql_stmt_prepare(stmt, SL("SELECT @@autocommit")); + check_stmt_rc(rc, stmt); + + rc= mysql_stmt_execute(stmt); + check_stmt_rc(rc, stmt); + + result= mysql_stmt_result_metadata(stmt); + FAIL_IF(!result, "Invalid result set"); + + rc= 0; + while (mysql_stmt_fetch(stmt) != MYSQL_NO_DATA) + rc++; + FAIL_UNLESS(rc == 1, "rowcount != 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); + + // XPAND doesn't support @@max_error_count + SKIP_XPAND + + stmt= mysql_stmt_init(mysql); + FAIL_IF(!stmt, mysql_error(mysql)); + rc= mysql_stmt_prepare(stmt, SL("SELECT @@max_error_count")); + check_stmt_rc(rc, stmt); + + result= mysql_stmt_result_metadata(stmt); + FAIL_IF(!result, "Invalid result set"); + + rc= mysql_stmt_execute(stmt); + check_stmt_rc(rc, stmt); + + rc= 0; + while (mysql_stmt_fetch(stmt) != MYSQL_NO_DATA) + rc++; + FAIL_UNLESS(rc == 1, "rowcount != 1"); + + if (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)) + goto error; + + mysql_free_result(result); + mysql_stmt_close(stmt); + + stmt= mysql_stmt_init(mysql); + FAIL_IF(!stmt, mysql_error(mysql)); + rc= mysql_stmt_prepare(stmt, SL("SELECT @@max_allowed_packet")); + check_stmt_rc(rc, stmt); + + result= mysql_stmt_result_metadata(stmt); + FAIL_IF(!result, "Invalid result set"); + + rc= mysql_stmt_execute(stmt); + check_stmt_rc(rc, stmt); + + rc= 0; + while (mysql_stmt_fetch(stmt) != MYSQL_NO_DATA) + rc++; + FAIL_UNLESS(rc == 1, "rowcount != 1"); + + if (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)) + goto error; + + mysql_free_result(result); + mysql_stmt_close(stmt); + + stmt= mysql_stmt_init(mysql); + FAIL_IF(!stmt, mysql_error(mysql)); + rc= mysql_stmt_prepare(stmt, SL("SELECT @@sql_warnings")); + check_stmt_rc(rc, stmt); + + result= mysql_stmt_result_metadata(stmt); + FAIL_IF(!result, "Invalid result set"); + + rc= mysql_stmt_execute(stmt); + check_stmt_rc(rc, stmt); + + rc= 0; + while (mysql_stmt_fetch(stmt) != MYSQL_NO_DATA) + rc++; + FAIL_UNLESS(rc == 1, "rowcount != 1"); + + if (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 */ + goto error; + + mysql_free_result(result); + mysql_stmt_close(stmt); + return OK; + +error: + mysql_free_result(result); + mysql_stmt_close(stmt); + return FAIL; +} + +/* Test a memory overrun bug */ + +static int test_mem_overun(MYSQL *mysql) +{ + char buffer[10000], field[12]; + MYSQL_STMT *stmt; + MYSQL_RES *field_res, *res; + int rc, i, length; + + /* + Test a memory overrun bug when a table had 1000 fields with + a row of data + */ + rc= mysql_query(mysql, "drop table if exists t_mem_overun"); + check_mysql_rc(rc, mysql); + + strcpy(buffer, "create table t_mem_overun("); + for (i= 0; i < 1000; i++) + { + snprintf(field, sizeof(field), "c%d int, ", i); + strcat(buffer, field); + } + length= (int)strlen(buffer); + buffer[length-2]= ')'; + buffer[--length]= '\0'; + + rc= mysql_real_query(mysql, buffer, length); + check_mysql_rc(rc, mysql); + + strcpy(buffer, "insert into t_mem_overun values("); + for (i= 0; i < 1000; i++) + { + strcat(buffer, "1, "); + } + length= (int)strlen(buffer); + buffer[length-2]= ')'; + buffer[--length]= '\0'; + + rc= mysql_real_query(mysql, buffer, length); + check_mysql_rc(rc, mysql); + + rc= mysql_query(mysql, "select * from t_mem_overun"); + check_mysql_rc(rc, mysql); + + res= mysql_store_result(mysql); + rc= 0; + while (mysql_fetch_row(res)) + rc++; + FAIL_UNLESS(rc == 1, "rowcount != 1"); + mysql_free_result(res); + + stmt= mysql_stmt_init(mysql); + FAIL_IF(!stmt, mysql_error(mysql)); + rc= mysql_stmt_prepare(stmt, SL("select * from t_mem_overun")); + check_stmt_rc(rc, stmt); + + rc= mysql_stmt_execute(stmt); + check_stmt_rc(rc, stmt); + + field_res= mysql_stmt_result_metadata(stmt); + FAIL_IF(!field_res, "Invalid result set"); + + FAIL_UNLESS( 1000 == mysql_num_fields(field_res), "fields != 1000"); + + rc= mysql_stmt_store_result(stmt); + check_stmt_rc(rc, stmt); + + rc= mysql_stmt_fetch(stmt); + check_stmt_rc(rc, stmt); + + rc= mysql_stmt_fetch(stmt); + FAIL_UNLESS(rc == MYSQL_NO_DATA, ""); + + mysql_free_result(field_res); + + mysql_stmt_close(stmt); + rc= mysql_query(mysql, "drop table if exists t_mem_overun"); + check_mysql_rc(rc, mysql); + return OK; +} + +static int test_bug8722(MYSQL *mysql) +{ + MYSQL_STMT *stmt; + int rc; + const char *stmt_text; + + /* Prepare test data */ + stmt_text= "drop table if exists t1"; + rc= mysql_real_query(mysql, SL(stmt_text)); + check_mysql_rc(rc, mysql); + stmt_text= "drop view if exists v1"; + rc= mysql_real_query(mysql, SL(stmt_text)); + check_mysql_rc(rc, mysql); + 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, SL(stmt_text)); + check_mysql_rc(rc, mysql); + stmt_text= "INSERT INTO t1 VALUES (1,2,3,4,5,6,7,8,9,10)"; + rc= mysql_real_query(mysql, SL(stmt_text)); + check_mysql_rc(rc, mysql); + stmt_text= "CREATE VIEW v1 AS SELECT * FROM t1"; + rc= mysql_real_query(mysql, SL(stmt_text)); + check_mysql_rc(rc, mysql); + + stmt= mysql_stmt_init(mysql); + stmt_text= "select * from v1"; + rc= mysql_stmt_prepare(stmt, SL(stmt_text)); + check_stmt_rc(rc, stmt); + mysql_stmt_close(stmt); + stmt_text= "drop table if exists t1, v1"; + rc= mysql_query(mysql, "DROP TABLE t1"); + check_mysql_rc(rc, mysql); + rc= mysql_query(mysql, "DROP VIEW v1"); + check_mysql_rc(rc, mysql); + return OK; +} + +/* Test DECIMAL conversion */ + +static int test_decimal_bug(MYSQL *mysql) +{ + MYSQL_STMT *stmt; + MYSQL_BIND my_bind[1]; + char data[30]; + int rc; + my_bool is_null; + + mysql_autocommit(mysql, TRUE); + + rc= mysql_query(mysql, "drop table if exists test_decimal_bug"); + check_mysql_rc(rc, mysql); + + rc= mysql_query(mysql, "create table test_decimal_bug(c1 decimal(10, 2))"); + check_mysql_rc(rc, mysql); + + rc= mysql_query(mysql, "insert into test_decimal_bug value(8), (10.22), (5.61)"); + check_mysql_rc(rc, mysql); + + stmt= mysql_stmt_init(mysql); + FAIL_IF(!stmt, mysql_error(mysql)); + rc= mysql_stmt_prepare(stmt, SL("select c1 from test_decimal_bug where c1=?")); + check_stmt_rc(rc, stmt); + + /* + We need to bzero bind structure because mysql_stmt_bind_param checks all + its members. + */ + memset(my_bind, '\0', sizeof(my_bind)); + + memset(data, 0, sizeof(data)); + 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_stmt_rc(rc, stmt); + + strcpy(data, "8.0"); + rc= mysql_stmt_execute(stmt); + check_stmt_rc(rc, stmt); + + data[0]= 0; + rc= mysql_stmt_bind_result(stmt, my_bind); + check_stmt_rc(rc, stmt); + + rc= mysql_stmt_fetch(stmt); + check_stmt_rc(rc, stmt); + + FAIL_UNLESS(strcmp(data, "8.00") == 0, "data != '8.00'"); + + rc= mysql_stmt_fetch(stmt); + FAIL_UNLESS(rc == MYSQL_NO_DATA, "rc != MYSQL_NO_DATA"); + + strcpy(data, "5.61"); + rc= mysql_stmt_execute(stmt); + check_stmt_rc(rc, stmt); + + data[0]= 0; + rc= mysql_stmt_bind_result(stmt, my_bind); + check_stmt_rc(rc, stmt); + + rc= mysql_stmt_fetch(stmt); + check_stmt_rc(rc, stmt); + + FAIL_UNLESS(strcmp(data, "5.61") == 0, "data != '5.61'"); + + rc= mysql_stmt_fetch(stmt); + FAIL_UNLESS(rc == MYSQL_NO_DATA, "rc != MYSQL_NO_DATA"); + + is_null= 1; + rc= mysql_stmt_execute(stmt); + check_stmt_rc(rc, stmt); + + rc= mysql_stmt_fetch(stmt); + FAIL_UNLESS(rc == MYSQL_NO_DATA, "rc != MYSQL_NO_DATA"); + + strcpy(data, "10.22"); is_null= 0; + rc= mysql_stmt_execute(stmt); + check_stmt_rc(rc, stmt); + + data[0]= 0; + rc= mysql_stmt_bind_result(stmt, my_bind); + check_stmt_rc(rc, stmt); + + rc= mysql_stmt_fetch(stmt); + check_stmt_rc(rc, stmt); + + FAIL_UNLESS(strcmp(data, "10.22") == 0, "data != '10.22'"); + + rc= mysql_stmt_fetch(stmt); + FAIL_UNLESS(rc == MYSQL_NO_DATA, "rc != MYSQL_NO_DATA"); + + mysql_stmt_close(stmt); + rc= mysql_query(mysql, "drop table if exists test_decimal_bug"); + check_mysql_rc(rc, mysql); + return OK; +} + +/* Test EXPLAIN bug (#115, reported by mark@mysql.com & georg@php.net). */ + +static int test_explain_bug(MYSQL *mysql) +{ + MYSQL_STMT *stmt; + MYSQL_RES *result; + int rc; + + if (!is_mariadb) + return SKIP; + + mysql_autocommit(mysql, TRUE); + + rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_explain"); + check_mysql_rc(rc, mysql); + + rc= mysql_query(mysql, "CREATE TABLE test_explain(id int, name char(2))"); + check_mysql_rc(rc, mysql); + + stmt= mysql_stmt_init(mysql); + FAIL_IF(!stmt, mysql_error(mysql)); + rc= mysql_stmt_prepare(stmt, SL("explain test_explain")); + check_stmt_rc(rc, stmt); + + rc= mysql_stmt_execute(stmt); + check_stmt_rc(rc, stmt); + + rc= 0; + while (!mysql_stmt_fetch(stmt)) + rc++; + FAIL_UNLESS(rc == 2, "rowcount != 2"); + + result= mysql_stmt_result_metadata(stmt); + FAIL_IF(!result, "Invalid result set"); + + FAIL_UNLESS(6 == mysql_num_fields(result), "fields != 6"); + + if (verify_prepare_field(result, 0, "Field", "COLUMN_NAME", + mysql_get_server_version(mysql) <= 50000 ? + MYSQL_TYPE_STRING : MYSQL_TYPE_VAR_STRING, + 0, 0, + mysql_get_server_version(mysql) <= 50400 ? "" : "information_schema", + 64, 0)) + goto error; + + if (verify_prepare_field(result, 1, "Type", "COLUMN_TYPE", MYSQL_TYPE_BLOB, + 0, 0, + mysql_get_server_version(mysql) <= 50400 ? "" : "information_schema", + 0, 0)) + goto error; + + if (verify_prepare_field(result, 2, "Null", "IS_NULLABLE", + mysql_get_server_version(mysql) <= 50000 ? + MYSQL_TYPE_STRING : MYSQL_TYPE_VAR_STRING, + 0, 0, + mysql_get_server_version(mysql) <= 50400 ? "" : "information_schema", + 3, 0)) + goto error; + + if (verify_prepare_field(result, 3, "Key", "COLUMN_KEY", + mysql_get_server_version(mysql) <= 50000 ? + MYSQL_TYPE_STRING : MYSQL_TYPE_VAR_STRING, + 0, 0, + mysql_get_server_version(mysql) <= 50400 ? "" : "information_schema", + 3, 0)) + goto error; + + if ( mysql_get_server_version(mysql) >= 50027 ) + { + /* The patch for bug#23037 changes column type of DEAULT to blob */ + if (verify_prepare_field(result, 4, "Default", "COLUMN_DEFAULT", + MYSQL_TYPE_BLOB, 0, 0, + mysql_get_server_version(mysql) <= 50400 ? "" : "information_schema", + 0, 0)) + goto error; + } + else + { + if (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, + mysql_get_server_version(mysql) <= 50400 ? "" : "information_schema", + mysql_get_server_version(mysql) >= 50027 ? 0 :64, 0)) + goto error; + } + + if (verify_prepare_field(result, 5, "Extra", "EXTRA", + mysql_get_server_version(mysql) <= 50000 ? + MYSQL_TYPE_STRING : MYSQL_TYPE_VAR_STRING, + 0, 0, + mysql_get_server_version(mysql) <= 50400 ? "" : "information_schema", + 27, 0)) + goto error; + + mysql_free_result(result); + mysql_stmt_close(stmt); + + stmt= mysql_stmt_init(mysql); + FAIL_IF(!stmt, mysql_error(mysql)); + rc= mysql_stmt_prepare(stmt, SL("explain select id, name FROM test_explain")); + check_stmt_rc(rc, stmt); + + rc= mysql_stmt_execute(stmt); + check_stmt_rc(rc, stmt); + + rc= 0; + while (!mysql_stmt_fetch(stmt)) + rc++; + FAIL_UNLESS(rc == 1, "rowcount != 1"); + + result= mysql_stmt_result_metadata(stmt); + FAIL_IF(!result, "Invalid result set"); + + FAIL_UNLESS(10 == mysql_num_fields(result), "fields != 10"); + + if (verify_prepare_field(result, 0, "id", "", MYSQL_TYPE_LONGLONG, "", "", "", 3, 0)) + goto error; + + if (verify_prepare_field(result, 1, "select_type", "", MYSQL_TYPE_VAR_STRING, "", "", "", 19, 0)) + goto error; + + if (verify_prepare_field(result, 2, "table", "", MYSQL_TYPE_VAR_STRING, "", "", "", NAME_CHAR_LEN, 0)) + goto error; + + if (verify_prepare_field(result, 3, "type", "", MYSQL_TYPE_VAR_STRING, "", "", "", 10, 0)) + goto error; + + if (verify_prepare_field(result, 4, "possible_keys", "", MYSQL_TYPE_VAR_STRING, "", "", "", NAME_CHAR_LEN*MAX_KEY, 0)) + goto error; + + if ( verify_prepare_field(result, 5, "key", "", MYSQL_TYPE_VAR_STRING, "", "", "", NAME_CHAR_LEN, 0)) + goto error; + + if (mysql_get_server_version(mysql) <= 50000) + { + if (verify_prepare_field(result, 6, "key_len", "", MYSQL_TYPE_LONGLONG, "", "", "", 3, 0)) + goto error; + } + else if (mysql_get_server_version(mysql) <= 60000) + { + if (verify_prepare_field(result, 6, "key_len", "", MYSQL_TYPE_VAR_STRING, "", "", "", NAME_CHAR_LEN*MAX_KEY, 0)) + goto error; + } + else + { + if (verify_prepare_field(result, 6, "key_len", "", MYSQL_TYPE_VAR_STRING, "", "", "", (MAX_KEY_LENGTH_DECIMAL_WIDTH + 1) * MAX_KEY, 0)) + goto error; + } + + if (verify_prepare_field(result, 7, "ref", "", MYSQL_TYPE_VAR_STRING, "", "", "", + NAME_CHAR_LEN*16, 0)) + goto error; + + if (verify_prepare_field(result, 8, "rows", "", MYSQL_TYPE_LONGLONG, "", "", "", 10, 0)) + goto error; + + if (verify_prepare_field(result, 9, "Extra", "", MYSQL_TYPE_VAR_STRING, "", "", "", 255, 0)) + goto error; + + mysql_free_result(result); + mysql_stmt_close(stmt); + rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_explain"); + check_mysql_rc(rc, mysql); + return OK; +error: + mysql_free_result(result); + mysql_stmt_close(stmt); + return FAIL; +} + +static int test_sshort_bug(MYSQL *mysql) +{ + 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; + + rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_sshort"); + check_mysql_rc(rc, mysql); + + rc= mysql_query(mysql, "CREATE TABLE test_sshort(a smallint signed, \ + b smallint signed, \ + c smallint unsigned, \ + d smallint unsigned)"); + check_mysql_rc(rc, mysql); + + rc= mysql_query(mysql, "INSERT INTO test_sshort VALUES(-5999, -5999, 35999, 200)"); + check_mysql_rc(rc, mysql); + + + stmt= mysql_stmt_init(mysql); + FAIL_IF(!stmt, mysql_error(mysql)); + rc= mysql_stmt_prepare(stmt, SL("SELECT * FROM test_sshort")); + check_stmt_rc(rc, stmt); + + rc= mysql_stmt_execute(stmt); + check_stmt_rc(rc, stmt); + + memset(my_bind, '\0', 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_stmt_rc(rc, stmt); + + rc= mysql_stmt_fetch(stmt); + check_stmt_rc(rc, stmt); + + FAIL_UNLESS(short_value == -5999, "sv != -5999"); + FAIL_UNLESS(s_length == 2, "s_length != 2"); + + FAIL_UNLESS(long_value == -5999, "l_v != -5999"); + FAIL_UNLESS(l_length == 4, "l_length != 4"); + + FAIL_UNLESS(longlong_value == 35999, "llv != 35999"); + FAIL_UNLESS(ll_length == 8, "ll_length != 8"); + + FAIL_UNLESS(tiny_value == 200, "t_v != 200"); + FAIL_UNLESS(t_length == 1, "t_length != 1"); + + rc= mysql_stmt_fetch(stmt); + FAIL_UNLESS(rc == MYSQL_NO_DATA, "rc != MYSQL_NO_DATA"); + + mysql_stmt_close(stmt); + rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_sshort"); + check_mysql_rc(rc, mysql); + return OK; +} + + +/* Test a misc tinyint-signed conversion bug */ + +static int test_stiny_bug(MYSQL *mysql) +{ + 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; + + rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_stiny"); + check_mysql_rc(rc, mysql); + + rc= mysql_query(mysql, "CREATE TABLE test_stiny(a tinyint signed, \ + b tinyint signed, \ + c tinyint unsigned, \ + d tinyint unsigned)"); + check_mysql_rc(rc, mysql); + + rc= mysql_query(mysql, "INSERT INTO test_stiny VALUES(-128, -127, 255, 0)"); + check_mysql_rc(rc, mysql); + + + stmt= mysql_stmt_init(mysql); + FAIL_IF(!stmt, mysql_error(mysql)); + rc= mysql_stmt_prepare(stmt, SL("SELECT * FROM test_stiny")); + check_stmt_rc(rc, stmt); + + rc= mysql_stmt_execute(stmt); + check_stmt_rc(rc, stmt); + + memset(my_bind, '\0', 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_stmt_rc(rc, stmt); + + rc= mysql_stmt_fetch(stmt); + check_stmt_rc(rc, stmt); + + FAIL_UNLESS(short_value == -128, "s_v != -128"); + FAIL_UNLESS(s_length == 2, "s_length != 2"); + + FAIL_UNLESS(long_value == -127, "l_v != -127"); + FAIL_UNLESS(l_length == 4, "l_length != 4"); + + FAIL_UNLESS(longlong_value == 255, "llv != 255"); + FAIL_UNLESS(ll_length == 8, "ll_length != 8"); + + FAIL_UNLESS(tiny_value == 0, "t_v != 0"); + FAIL_UNLESS(t_length == 1, "t_length != 1"); + + rc= mysql_stmt_fetch(stmt); + FAIL_UNLESS(rc == MYSQL_NO_DATA, "rc != MYSQL_NO_DATA"); + + mysql_stmt_close(stmt); + rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_stiny"); + check_mysql_rc(rc, mysql); + return OK; +} + +static int test_bug53311(MYSQL *mysql) +{ + int rc; + MYSQL_STMT *stmt; + int i; + const char *query= "INSERT INTO bug53311 VALUES (1)"; + SKIP_MAXSCALE; + SKIP_XPAND; + + rc= mysql_options(mysql, MYSQL_OPT_RECONNECT, "1"); + check_mysql_rc(rc, mysql); + + rc= mysql_query(mysql, "DROP TABLE IF EXISTS bug53311"); + check_mysql_rc(rc, mysql); + + rc= mysql_query(mysql, "CREATE TABLE bug53311 (a int)"); + check_mysql_rc(rc, mysql); + + stmt= mysql_stmt_init(mysql); + rc= mysql_stmt_prepare(stmt, SL(query)); + check_stmt_rc(rc, stmt); + + for (i=0; i < 2; i++) + { + rc= mysql_stmt_execute(stmt); + check_stmt_rc(rc, stmt); + } + + /* kill connection */ + rc= mysql_kill(mysql, mysql_thread_id(mysql)); + + rc= mysql_stmt_execute(stmt); + FAIL_IF(rc == 0, "Error expected"); + FAIL_IF(mysql_stmt_errno(stmt) == 0, "Errno != 0 expected"); + rc= mysql_stmt_close(stmt); + check_mysql_rc(rc, mysql); + rc= mysql_query(mysql, "DROP TABLE IF EXISTS bug53311"); + check_mysql_rc(rc, mysql); + + return OK; +} +#define PREPARE_SQL "EXPLAIN SELECT t1.*, t2.* FROM test AS t1, test AS t2" + +#ifdef NOT_IN_USE +static int test_metadata(MYSQL *mysql) +{ + int rc; + + rc= mysql_query(mysql, "DROP TABLE IF EXISTS test"); + check_mysql_rc(rc, mysql); + rc= mysql_query(mysql, "CREATE TABLE test(id INT, label CHAR(1), PRIMARY KEY(id)) ENGINE=MYISAM"); + check_mysql_rc(rc, mysql); + + rc= mysql_query(mysql, "INSERT INTO test(id, label) VALUES (1, 'a'), (2, 'b'), (3, 'c'), (4, 'd'), (5, 'e'), (6, 'f')"); + check_mysql_rc(rc, mysql); + printf("Client=%s\n", mysql_get_client_info()); + printf("Server=%s\n", mysql_get_server_info(mysql)); + + { + MYSQL_STMT * stmt = mysql_stmt_init(mysql); + if (!stmt) { + fprintf(stderr, "Failed to init stmt: Error: %s\n", mysql_error(mysql)); + goto end; + } + if (mysql_stmt_prepare(stmt, PREPARE_SQL, sizeof(PREPARE_SQL) - 1)) { + fprintf(stderr, "Failed to prepare stmt: Error: %s\n", mysql_stmt_error(stmt)); + goto end2; + } + if (mysql_stmt_execute(stmt)) { + fprintf(stderr, "Failed to execute stmt: Error: %s\n", mysql_stmt_error(stmt)); + goto end2; + } + { + MYSQL_FIELD * field = NULL; + MYSQL_RES * res = mysql_stmt_result_metadata(stmt); + if (!res) { + fprintf(stderr, "Failed to get metadata: Error: %s\n", mysql_stmt_error(stmt)); + goto end2; + } + while ((field = mysql_fetch_field(res))) { + printf("name=%s\n", field->name); + printf("catalog=%s\n", field->catalog); + } + mysql_free_result(res); + + } +end2: + mysql_stmt_close(stmt); + } +end: + return 0; +} +#endif + +static int test_conc_5(MYSQL *mysql) +{ + const char *query= "SELECT a FROM t1"; + MYSQL_RES *res; + MYSQL_STMT *stmt; + MYSQL_FIELD *fields; + int rc; + + rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1"); + check_mysql_rc(rc, mysql); + rc= mysql_query(mysql, "CREATE TABLE t1 (a int)"); + check_mysql_rc(rc, mysql); + rc= mysql_query(mysql, "INSERT INTO t1 VALUES (1)"); + check_mysql_rc(rc, mysql); + + stmt= mysql_stmt_init(mysql); + FAIL_IF(!stmt, "couldn't allocate memory"); + + rc= mysql_stmt_prepare(stmt, SL(query)); + check_stmt_rc(rc, stmt); + rc= mysql_stmt_execute(stmt); + check_stmt_rc(rc, stmt); + + res= mysql_stmt_result_metadata(stmt); + FAIL_IF(!res, "Can't obtain resultset"); + + fields= mysql_fetch_fields(res); + FAIL_IF(!fields, "Can't obtain fields"); + + FAIL_IF(strcmp("def", fields[0].catalog), "unexpected value for field->catalog"); + + mysql_free_result(res); + mysql_stmt_close(stmt); + return OK; +} + +static int test_conc141(MYSQL *mysql) +{ + int rc; + const char *query= "CALL p_conc141"; + MYSQL_STMT *stmt= mysql_stmt_init(mysql); + + rc= mysql_query(mysql, "DROP TABLE IF EXISTS conc141"); + check_mysql_rc(rc, mysql); + rc= mysql_query(mysql, "CREATE TABLE conc141 (KeyVal int not null primary key)"); + check_mysql_rc(rc, mysql); + rc= mysql_query(mysql, "INSERT INTO conc141 VALUES(1)"); + check_mysql_rc(rc, mysql); + rc= mysql_query(mysql, "DROP PROCEDURE IF EXISTS p_conc141"); + check_mysql_rc(rc, mysql); + rc= mysql_query(mysql, "CREATE PROCEDURE p_conc141()\n" + "BEGIN\n" + "select * from conc141;\n" + "insert into conc141(KeyVal) VALUES(1);\n" + "END"); + check_mysql_rc(rc, mysql); + + rc= mysql_stmt_prepare(stmt, SL(query)); + check_stmt_rc(rc, stmt); + + rc= mysql_stmt_execute(stmt); + check_stmt_rc(rc, stmt); + /* skip first result */ + rc= mysql_stmt_next_result(stmt); + FAIL_IF(rc==-1, "No more results and error expected"); + mysql_stmt_free_result(stmt); + FAIL_IF(mysql_stmt_errno(stmt), "No Error expected"); + rc= mysql_stmt_execute(stmt); + check_stmt_rc(rc, stmt); + mysql_stmt_close(stmt); + rc= mysql_query(mysql, "DROP TABLE IF EXISTS conc141"); + check_mysql_rc(rc, mysql); + rc= mysql_query(mysql, "DROP PROCEDURE IF EXISTS p_conc141"); + check_mysql_rc(rc, mysql); + return OK; +} + +static int test_conc154(MYSQL *mysql) +{ + MYSQL_STMT *stmt; + const char *stmtstr= "SELECT * FROM t1"; + int rc; + + /* 1st: empty result set without free_result */ + rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1"); + check_mysql_rc(rc, mysql); + rc= mysql_query(mysql, "CREATE TABLE t1 (a varchar(20))"); + check_mysql_rc(rc, mysql); + + stmt= mysql_stmt_init(mysql); + rc= mysql_stmt_prepare(stmt, SL(stmtstr)); + check_stmt_rc(rc, stmt); + + rc= mysql_stmt_execute(stmt); + check_stmt_rc(rc, stmt); + + rc= mysql_stmt_store_result(stmt); + check_stmt_rc(rc, stmt); + + rc= mysql_stmt_execute(stmt); + check_stmt_rc(rc, stmt); + + rc= mysql_stmt_store_result(stmt); + check_stmt_rc(rc, stmt); + + mysql_stmt_close(stmt); + + /* 2nd: empty result set with free_result */ + stmt= mysql_stmt_init(mysql); + rc= mysql_stmt_prepare(stmt, SL(stmtstr)); + check_stmt_rc(rc, stmt); + + rc= mysql_stmt_execute(stmt); + check_stmt_rc(rc, stmt); + + rc= mysql_stmt_store_result(stmt); + check_stmt_rc(rc, stmt); + + rc= mysql_stmt_free_result(stmt); + check_stmt_rc(rc, stmt); + + rc= mysql_stmt_execute(stmt); + check_stmt_rc(rc, stmt); + + rc= mysql_stmt_store_result(stmt); + check_stmt_rc(rc, stmt); + rc= mysql_stmt_free_result(stmt); + check_stmt_rc(rc, stmt); + + mysql_stmt_close(stmt); + + /* 3rd: non empty result without free_result */ + rc= mysql_query(mysql, "INSERT INTO t1 VALUES ('test_conc154')"); + check_mysql_rc(rc, mysql); + + stmt= mysql_stmt_init(mysql); + rc= mysql_stmt_prepare(stmt, SL(stmtstr)); + check_stmt_rc(rc, stmt); + + rc= mysql_stmt_execute(stmt); + check_stmt_rc(rc, stmt); + + rc= mysql_stmt_store_result(stmt); + check_stmt_rc(rc, stmt); + + rc= mysql_stmt_execute(stmt); + check_stmt_rc(rc, stmt); + + rc= mysql_stmt_store_result(stmt); + check_stmt_rc(rc, stmt); + + mysql_stmt_close(stmt); + + /* 4th non empty result set with free_result */ + stmt= mysql_stmt_init(mysql); + rc= mysql_stmt_prepare(stmt, SL(stmtstr)); + check_stmt_rc(rc, stmt); + + rc= mysql_stmt_execute(stmt); + check_stmt_rc(rc, stmt); + + rc= mysql_stmt_store_result(stmt); + check_stmt_rc(rc, stmt); + + rc= mysql_stmt_free_result(stmt); + check_stmt_rc(rc, stmt); + + rc= mysql_stmt_execute(stmt); + check_stmt_rc(rc, stmt); + + rc= mysql_stmt_store_result(stmt); + check_stmt_rc(rc, stmt); + rc= mysql_stmt_free_result(stmt); + check_stmt_rc(rc, stmt); + + mysql_stmt_close(stmt); + rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1"); + check_mysql_rc(rc, mysql); + + return OK; +} + +static int test_conc155(MYSQL *mysql) +{ + MYSQL_STMT *stmt; + MYSQL_BIND bind; + char buffer[50]; + int rc; + + rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1"); + check_mysql_rc(rc, mysql); + rc= mysql_query(mysql, "CREATE TABLE t1 (a TEXT)"); + check_mysql_rc(rc, mysql); + rc= mysql_query(mysql, "INSERT INTO t1 VALUES ('zero terminated string')"); + check_mysql_rc(rc, mysql); + + stmt= mysql_stmt_init(mysql); + rc= mysql_stmt_prepare(stmt, SL("SELECT a FROM t1")); + check_stmt_rc(rc, stmt); + + rc= mysql_stmt_execute(stmt); + check_stmt_rc(rc, stmt); + + memset(buffer, 'X', 50); + memset(&bind, 0, sizeof(MYSQL_BIND)); + + bind.buffer= buffer; + bind.buffer_length= 50; + bind.buffer_type= MYSQL_TYPE_STRING; + + rc= mysql_stmt_bind_result(stmt, &bind); + check_stmt_rc(rc, stmt); + + rc= mysql_stmt_fetch(stmt); + check_stmt_rc(rc, stmt); + + if (strlen(buffer) != strlen("zero terminated string")) + { + diag("Wrong buffer length"); + return FAIL; + } + + mysql_stmt_close(stmt); + rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1"); + check_mysql_rc(rc, mysql); + return OK; +} + +static int test_conc168(MYSQL *mysql) +{ + MYSQL_STMT *stmt= mysql_stmt_init(mysql); + + MYSQL_BIND bind; + char buffer[100]; + int rc; + + //https://jira.mariadb.org/browse/XPT-273 + SKIP_XPAND; + + rc= mysql_query(mysql, "DROP TABLE IF EXISTS conc168"); + check_mysql_rc(rc, mysql); + rc= mysql_query(mysql, "CREATE TABLE conc168(a datetime(3))"); + check_mysql_rc(rc, mysql); + rc= mysql_query(mysql, "INSERT INTO conc168 VALUES ('2016-03-09 07:51:49.000'),('2016-03-09 07:51:49.001'),('2016-03-09 07:51:49.010')"); + check_mysql_rc(rc, mysql); + + memset(&bind, 0, sizeof(MYSQL_BIND)); + bind.buffer= buffer; + bind.buffer_type= MYSQL_TYPE_STRING; + bind.buffer_length= 100; + + rc= mysql_stmt_prepare(stmt, SL("SELECT a FROM conc168")); + check_stmt_rc(rc, stmt); + + rc= mysql_stmt_execute(stmt); + check_stmt_rc(rc, stmt); + + rc= mysql_stmt_bind_result(stmt, &bind); + check_stmt_rc(rc, stmt); + + rc= mysql_stmt_fetch(stmt); + check_stmt_rc(rc, stmt); + FAIL_IF(strcmp(buffer, "2016-03-09 07:51:49.000"), "expected: 2016-03-09 07:51:49.000"); + + rc= mysql_stmt_fetch(stmt); + check_stmt_rc(rc, stmt); + FAIL_IF(strcmp(buffer, "2016-03-09 07:51:49.001"), "expected: 2016-03-09 07:51:49.001"); + + rc= mysql_stmt_fetch(stmt); + check_stmt_rc(rc, stmt); + FAIL_IF(strcmp(buffer, "2016-03-09 07:51:49.010"), "expected: 2016-03-09 07:51:49.010"); + + mysql_stmt_close(stmt); + rc= mysql_query(mysql, "DROP TABLE IF EXISTS conc168"); + check_mysql_rc(rc, mysql); + return OK; +} + +static int test_conc167(MYSQL *mysql) +{ + MYSQL_STMT *stmt= mysql_stmt_init(mysql); + + MYSQL_BIND bind[3]; + char buffer[100]; + int bit1=0, bit2=0; + int rc; + const char *stmt_str= "SELECT a,b,c FROM conc168"; + + rc= mysql_query(mysql, "DROP TABLE IF EXISTS conc168"); + check_mysql_rc(rc, mysql); + rc= mysql_query(mysql, "CREATE TABLE conc168(a bit, b bit, c varchar(10))"); + check_mysql_rc(rc, mysql); + rc= mysql_query(mysql, "INSERT INTO conc168 VALUES (1,0, 'test12345')"); + check_mysql_rc(rc, mysql); + + memset(bind, 0, 3 * sizeof(MYSQL_BIND)); + bind[0].buffer= &bit1; + bind[0].buffer_type= MYSQL_TYPE_BIT; + bind[0].buffer_length= sizeof(int); + bind[1].buffer= &bit2; + bind[1].buffer_type= MYSQL_TYPE_BIT; + bind[1].buffer_length= sizeof(int); + bind[2].buffer= buffer; + bind[2].buffer_type= MYSQL_TYPE_STRING; + bind[2].buffer_length= 100; + + rc= mysql_stmt_prepare(stmt, SL(stmt_str)); + check_stmt_rc(rc, stmt); + + rc= mysql_stmt_execute(stmt); + check_stmt_rc(rc, stmt); + + rc= mysql_stmt_bind_result(stmt, bind); + check_stmt_rc(rc, stmt); + + rc= mysql_stmt_store_result(stmt); + check_stmt_rc(rc, stmt); + + rc= mysql_stmt_fetch(stmt); + check_stmt_rc(rc, stmt); + + diag("bit=%d %d char=%s", bit1, bit2, buffer); + + mysql_stmt_close(stmt); + return OK; +} + +static int test_conc177(MYSQL *mysql) +{ + MYSQL_STMT *stmt; + int rc; + MYSQL_BIND bind[2]; + const char *stmt_str= "SELECT a,b FROM t1"; + char buf1[128], buf2[128]; + + // https://jira.mariadb.org/browse/XPT-286 + SKIP_XPAND + + rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1"); + check_mysql_rc(rc, mysql); + + rc= mysql_query(mysql, "CREATE TABLE t1 (a double zerofill default 8.8,b float zerofill default 8.8)"); + check_mysql_rc(rc, mysql); + rc= mysql_query(mysql, "INSERT INTO t1 VALUES (DEFAULT, DEFAULT)"); + check_mysql_rc(rc, mysql); + + stmt= mysql_stmt_init(mysql); + rc= mysql_stmt_prepare(stmt, SL(stmt_str)); + check_stmt_rc(rc, stmt); + rc= mysql_stmt_execute(stmt); + check_stmt_rc(rc, stmt); + + memset(bind, 0, 2 * sizeof(MYSQL_BIND)); + bind[0].buffer= &buf1; + bind[0].buffer_type= MYSQL_TYPE_STRING; + bind[0].buffer_length= 128; + bind[1].buffer= &buf2; + bind[1].buffer_type= MYSQL_TYPE_STRING; + bind[1].buffer_length= 128; + + rc= mysql_stmt_bind_result(stmt, bind); + check_stmt_rc(rc, stmt); + + rc= mysql_stmt_fetch(stmt); + mysql_stmt_close(stmt); + + diag("buf1 %s\nbuf2 %s", buf1, buf2); + + FAIL_IF(strcmp(buf1, "00000000000000000008.8"), "Expected 00000000000000000008.8"); + FAIL_IF(strcmp(buf2, "0000000008.8"), "Expected 0000000008.8"); + + rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1"); + check_mysql_rc(rc, mysql); + + rc= mysql_query(mysql, "CREATE TABLE t1 (a int(8) zerofill default 1, b int(4) zerofill default 1)"); + check_mysql_rc(rc, mysql); + rc= mysql_query(mysql, "INSERT INTO t1 VALUES (DEFAULT, DEFAULT)"); + check_mysql_rc(rc, mysql); + + stmt= mysql_stmt_init(mysql); + rc= mysql_stmt_prepare(stmt, SL(stmt_str)); + check_stmt_rc(rc, stmt); + rc= mysql_stmt_execute(stmt); + check_stmt_rc(rc, stmt); + + memset(bind, 0, 2 * sizeof(MYSQL_BIND)); + bind[0].buffer= &buf1; + bind[0].buffer_type= MYSQL_TYPE_STRING; + bind[0].buffer_length= 128; + bind[1].buffer= &buf2; + bind[1].buffer_type= MYSQL_TYPE_STRING; + bind[1].buffer_length= 128; + + rc= mysql_stmt_bind_result(stmt, bind); + check_stmt_rc(rc, stmt); + + rc= mysql_stmt_fetch(stmt); + mysql_stmt_close(stmt); + + diag("buf1 %s\nbuf2 %s", buf1, buf2); + + FAIL_IF(strcmp(buf1, "00000001"), "Expected 00000001"); + FAIL_IF(strcmp(buf2, "0001"), "Expected 0001"); + rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1"); + check_mysql_rc(rc, mysql); + return OK; +} + +static int test_conc179(MYSQL *mysql) +{ + MYSQL_STMT *stmt; + int rc; + const char *stmtstr= "select 1 as ' '"; + + stmt= mysql_stmt_init(mysql); + rc= mysql_stmt_prepare(stmt, SL(stmtstr)); + check_stmt_rc(rc, stmt); + + if (mysql_get_server_version(mysql) >= 100100) + { + FAIL_IF(mysql_warning_count(mysql) < 1, "expected 1 or more warnings"); + FAIL_IF(mysql_stmt_warning_count(stmt) < 1, "expected 1 or more warnings"); + } + + mysql_stmt_close(stmt); + rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1"); + check_mysql_rc(rc, mysql); + + return OK; +} + +static int test_conc182(MYSQL *mysql) +{ + MYSQL_STMT *stmt; + int rc; + MYSQL_BIND bind[2]; + char buf1[22]; + MYSQL_RES *result; + MYSQL_ROW row; + + stmt= mysql_stmt_init(mysql); + rc= mariadb_stmt_execute_direct(stmt, "DROP TABLE IF EXISTS t1", -1); + check_stmt_rc(rc, stmt); + rc= mariadb_stmt_execute_direct(stmt, "DROP TABLE IF EXISTS t1", -1); + check_stmt_rc(rc, stmt); + rc= mariadb_stmt_execute_direct(stmt, "SELECT 1", -1); + check_stmt_rc(rc, stmt); + rc= mariadb_stmt_execute_direct(stmt, "SELECT 1", -1); + check_stmt_rc(rc, stmt); + + rc= mysql_stmt_close(stmt); + check_stmt_rc(rc, stmt); + + rc= mysql_query(mysql, "SELECT row_count()"); + result= mysql_store_result(mysql); + row= mysql_fetch_row(result); + diag("buf: %s", row[0]); + mysql_free_result(result); + + + stmt= mysql_stmt_init(mysql); + rc= mysql_stmt_prepare(stmt, "SELECT row_count()", -1); + check_stmt_rc(rc, stmt); + rc= mysql_stmt_execute(stmt); + + memset(bind, 0, 2 * sizeof(MYSQL_BIND)); + bind[0].buffer= &buf1; + bind[0].buffer_length= bind[1].buffer_length= 20; + bind[0].buffer_type= bind[1].buffer_type= MYSQL_TYPE_STRING; + + rc= mysql_stmt_bind_result(stmt, bind); + + while(!mysql_stmt_fetch(stmt)) + diag("b1: %s", buf1); + rc= mysql_stmt_close(stmt); + rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1"); + check_mysql_rc(rc, mysql); + return OK; +} + +static int test_conc181(MYSQL *mysql) +{ + MYSQL_STMT *stmt; + int rc; + MYSQL_BIND bind; + const char *stmt_str= "SELECT a FROM t1"; + float f=1; + my_bool err= 0; + + rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1"); + check_mysql_rc(rc, mysql); + rc= mysql_query(mysql, "CREATE TABLE t1 (a int)"); + check_mysql_rc(rc, mysql); + rc= mysql_query(mysql, "INSERT INTO t1 VALUES(1073741825)"); + check_mysql_rc(rc, mysql); + + stmt= mysql_stmt_init(mysql); + rc= mysql_stmt_prepare(stmt, SL(stmt_str)); + check_stmt_rc(rc, stmt); + + rc= mysql_stmt_execute(stmt); + check_stmt_rc(rc, stmt); + + memset(&bind, 0, sizeof(MYSQL_BIND)); + bind.buffer= &f; + bind.error= &err; + bind.buffer_type= MYSQL_TYPE_FLOAT; + rc= mysql_stmt_bind_result(stmt, &bind); + check_stmt_rc(rc, stmt); + + rc= mysql_stmt_fetch(stmt); + diag("rc=%d err=%d float=%f, %d", rc, err, f, MYSQL_DATA_TRUNCATED); + + rc= mysql_stmt_close(stmt); + rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1"); + check_mysql_rc(rc, mysql); + return OK; +} + +static int test_conc198(MYSQL *mysql) +{ + MYSQL_STMT *stmt1, *stmt2; + MYSQL_BIND my_bind[1]; + int32 a; + int rc; + int num_rows= 0; + ulong type; + ulong prefetch_rows= 3; + + + 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)"); + check_mysql_rc(rc, mysql); + + stmt1= mysql_stmt_init(mysql); + stmt2= mysql_stmt_init(mysql); + /* Not implemented in 5.0 */ + type= (ulong) CURSOR_TYPE_SCROLLABLE; + rc= mysql_stmt_attr_set(stmt1, STMT_ATTR_CURSOR_TYPE, (void*) &type); + FAIL_UNLESS(rc, "Error expected"); + rc= mysql_stmt_attr_set(stmt2, STMT_ATTR_CURSOR_TYPE, (void*) &type); + FAIL_UNLESS(rc, "Error expected"); + + type= (ulong) CURSOR_TYPE_READ_ONLY; + rc= mysql_stmt_attr_set(stmt1, STMT_ATTR_CURSOR_TYPE, (void*) &type); + check_stmt_rc(rc, stmt1); + rc= mysql_stmt_attr_set(stmt2, STMT_ATTR_CURSOR_TYPE, (void*) &type); + check_stmt_rc(rc, stmt2); + rc= mysql_stmt_attr_set(stmt1, STMT_ATTR_PREFETCH_ROWS, + (void*) &prefetch_rows); + check_stmt_rc(rc, stmt1); + rc= mysql_stmt_attr_set(stmt2, STMT_ATTR_PREFETCH_ROWS, + (void*) &prefetch_rows); + check_stmt_rc(rc, stmt2); + rc= mysql_stmt_prepare(stmt1, "SELECT * FROM t1 ORDER by id ASC" , -1); + check_stmt_rc(rc, stmt1); + rc= mysql_stmt_prepare(stmt2, "SELECT * FROM t1 ORDER by id DESC", -1); + check_stmt_rc(rc, stmt2); + + rc= mysql_stmt_execute(stmt1); + check_stmt_rc(rc, stmt1); + rc= mysql_stmt_execute(stmt2); + check_stmt_rc(rc, stmt2); + + memset(my_bind, '\0', 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(stmt1, my_bind); + mysql_stmt_bind_result(stmt2, my_bind); + + while ((rc= mysql_stmt_fetch(stmt1)) == 0) + ++num_rows; + FAIL_UNLESS(num_rows == 9, "num_rows != 9"); + + num_rows= 0; + while ((rc= mysql_stmt_fetch(stmt2)) == 0) + ++num_rows; + FAIL_UNLESS(num_rows == 9, "num_rows != 9"); + + rc= mysql_stmt_close(stmt1); + rc= mysql_stmt_close(stmt2); + FAIL_UNLESS(rc == 0, ""); + + rc= mysql_query(mysql, "drop table t1"); + check_mysql_rc(rc, mysql); + return OK; +} + +static int test_conc205(MYSQL *mysql) +{ + MYSQL_STMT *stmt; + MYSQL_BIND my_bind[3]; + char data[8]; + ulong length[3]; + int rc, int_col; + short smint_col; + my_bool is_null[3]; + const char *query = "SELECT text_col, smint_col, int_col FROM test_conc205"; + + rc= mysql_query(mysql, "drop table if exists test_conc205"); + check_mysql_rc(rc, mysql); + rc= mysql_query(mysql, "CREATE TABLE test_conc205 (text_col TEXT, smint_col SMALLINT, int_col INT)"); + check_mysql_rc(rc, mysql); + rc= mysql_query(mysql, "INSERT INTO test_conc205 VALUES('data01', 21893, 1718038908), ('data2', -25734, -1857802040)"); + check_mysql_rc(rc, mysql); + + stmt= mysql_stmt_init(mysql); + FAIL_IF(!stmt, mysql_error(mysql)); + + rc= mysql_stmt_prepare(stmt, SL(query)); + check_stmt_rc(rc, stmt); + + memset(my_bind, '\0', sizeof(my_bind)); + my_bind[0].buffer_type= MYSQL_TYPE_STRING; + my_bind[0].buffer= (void *)data; + my_bind[0].buffer_length= sizeof(data); + my_bind[0].is_null= &is_null[0]; + my_bind[0].length= &length[0]; + + my_bind[1].buffer_type= MYSQL_TYPE_SHORT; + my_bind[1].buffer= &smint_col; + my_bind[1].buffer_length= 2; + my_bind[1].is_null= &is_null[1]; + my_bind[1].length= &length[1]; + + my_bind[2].buffer_type= MYSQL_TYPE_LONG; + my_bind[2].buffer= &int_col; + my_bind[2].buffer_length= 4; + my_bind[2].is_null= &is_null[2]; + my_bind[2].length= &length[2]; + + rc= mysql_stmt_execute(stmt); + check_stmt_rc(rc, stmt); + + rc= mysql_stmt_bind_result(stmt, my_bind); + check_stmt_rc(rc, stmt); + + rc= mysql_stmt_fetch(stmt); + check_stmt_rc(rc, stmt); + + FAIL_IF(length[0] != 6, "Wrong fetched string length"); + FAIL_IF(length[1] != 2, "Wrong fetched short length"); + FAIL_IF(length[2] != 4, "Wrong fetched int length"); + + FAIL_IF(strncmp(data, "data01", length[0] + 1) != 0, "Wrong string value"); + FAIL_IF(smint_col != 21893, "Expected 21893"); + FAIL_IF(int_col != 1718038908, "Expected 1718038908"); + + rc= mysql_stmt_fetch(stmt); + check_stmt_rc(rc, stmt); + + FAIL_IF(length[0] != 5, "Wrong fetched string length"); + FAIL_IF(length[1] != 2, "Wrong fetched short length"); + FAIL_IF(length[2] != 4, "Wrong fetched int length"); + + FAIL_IF(strncmp(data, "data2", length[0] + 1) != 0, "Wrong string value"); + FAIL_IF(smint_col != -25734, "Expected -25734"); + FAIL_IF(int_col != -1857802040, "Expected -1857802040"); + + rc= mysql_stmt_fetch(stmt); + FAIL_IF(rc != MYSQL_NO_DATA, "Expected MYSQL_NO_DATA"); + + mysql_stmt_close(stmt); + + rc= mysql_query(mysql, "drop table test_conc205"); + check_mysql_rc(rc, mysql); + + return OK; +} + +static int test_conc217(MYSQL *mysql) +{ + MYSQL_STMT *stmt= mysql_stmt_init(mysql); + int rc; + + SKIP_MAXSCALE; + rc= mariadb_stmt_execute_direct(stmt, "SELECT 1 FROM nonexisting_table", -1); + FAIL_IF(rc==0, "Expected error\n"); + rc= mysql_query(mysql, "drop table if exists t_count"); + check_mysql_rc(rc, mysql); + mysql_stmt_close(stmt); + check_mysql_rc(rc, mysql); + return OK; +} + +static int test_conc208(MYSQL *mysql) +{ + MYSQL_STMT *stmt= mysql_stmt_init(mysql); + int rc; + int data; + MYSQL_BIND bind; + + rc= mysql_stmt_prepare(stmt, "SELECT \"100\" UNION SELECT \"88\" UNION SELECT \"389789\"", -1); + check_stmt_rc(rc, stmt); + + memset(&bind, 0, sizeof(MYSQL_BIND)); + bind.buffer_type= MYSQL_TYPE_LONG; + bind.buffer= (void *)&data; + + rc= mysql_stmt_execute(stmt); + check_stmt_rc(rc, stmt); + + rc= mysql_stmt_bind_result(stmt, &bind); + + while (mysql_stmt_fetch(stmt) != MYSQL_NO_DATA) + { + diag("data=%d", data); + FAIL_IF(data != 100 && data != 88 && data != 389789, "Wrong value"); + } + mysql_stmt_close(stmt); + return OK; +} + +static int test_mdev14165(MYSQL *mysql) +{ + int rc; + MYSQL_STMT *stmt= mysql_stmt_init(mysql); + MYSQL_FIELD *fields; + MYSQL_RES *result; + my_bool val= 1; + MYSQL_BIND bind[1]; + char buf1[52]; + + rc= mysql_options(mysql, MYSQL_REPORT_DATA_TRUNCATION, &val); + + rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1"); + rc= mysql_query(mysql, "CREATE TABLE t1 (i INT(20) ZEROFILL)"); + check_mysql_rc(rc, mysql); + rc= mysql_query(mysql, "INSERT INTO t1 VALUES (2),(1)"); + check_mysql_rc(rc, mysql); + rc= mysql_stmt_prepare(stmt, "SELECT i FROM t1", -1); + check_stmt_rc(rc, stmt); + + rc= mysql_stmt_execute(stmt); + check_stmt_rc(rc, stmt); + + memset(bind, 0, sizeof(MYSQL_BIND)); + bind[0].buffer_type= MYSQL_TYPE_STRING; + bind[0].buffer_length= 51; + bind[0].buffer= buf1; + + mysql_stmt_bind_result(stmt, bind); + + rc= mysql_stmt_attr_set(stmt, STMT_ATTR_UPDATE_MAX_LENGTH, &val); + check_stmt_rc(rc, stmt); + rc= mysql_stmt_store_result(stmt); + check_stmt_rc(rc, stmt); + + result= mysql_stmt_result_metadata(stmt); + + fields= mysql_fetch_fields(result); + + FAIL_IF(fields[0].length < 20, "Expected length=20"); + FAIL_IF(fields[0].max_length < 20, "Expected max_length=20"); + + mysql_stmt_fetch(stmt); + + FAIL_UNLESS(strcmp(buf1, "00000000000000000002") == 0, "Wrong result"); + mysql_free_result(result); + + mysql_stmt_close(stmt); + + rc= mysql_query(mysql, "DROP TABLE t1"); + check_mysql_rc(rc, mysql); + return OK; +} + +static int test_compress(MYSQL *mysql) +{ + MYSQL_STMT *stmt= mysql_stmt_init(mysql); + int rc; + + rc= mariadb_stmt_execute_direct(stmt, SL("SELECT 1 FROM DUAL")); + check_stmt_rc(rc, stmt); + + mysql_stmt_close(stmt); + + return OK; +} + +static int equal_MYSQL_TIME(MYSQL_TIME *tm1, MYSQL_TIME *tm2) +{ + return tm1->day==tm2->day && tm1->hour==tm2->hour && tm1->minute==tm2->minute && + tm1->month==tm2->month && tm1->neg==tm2->neg && tm1->second==tm2->second && + tm1->second_part==tm2->second_part && tm1->time_type==tm2->time_type && tm1->year==tm2->year; +} + +static int test_str_to_int(MYSQL *mysql) +{ + int i; + struct st_atoi_test{ + const char *str_value; + int int_value; + int rc; + } atoi_tests[]= + { + {"0", 0, 0}, + {" 1",1, 0}, + {"123 ",123, 0}, + {"10.2",10, MYSQL_DATA_TRUNCATED}, + {"a", 0, MYSQL_DATA_TRUNCATED}, + {"1 2 3", 1, MYSQL_DATA_TRUNCATED}, + {NULL, 0, 0} + }; + + for(i=0; atoi_tests[i].str_value; i++) + { + int rc; + MYSQL_STMT *stmt; + MYSQL_BIND bind[1]; + struct st_atoi_test *test= &atoi_tests[i]; + char sql[256]; + int int_value; + + snprintf(sql, sizeof(sql), "SELECT '%s'",test->str_value); + + stmt= mysql_stmt_init(mysql); + + rc= mysql_stmt_prepare(stmt, sql, (ulong)strlen(sql)); + check_stmt_rc(rc, stmt); + rc= mysql_stmt_execute(stmt); + check_stmt_rc(rc, stmt); + rc= mysql_stmt_store_result(stmt); + + memset(bind, 0, sizeof(MYSQL_BIND)); + bind[0].buffer_type= MYSQL_TYPE_LONG; + bind[0].buffer= &int_value; + bind[0].buffer_length= sizeof(int_value); + + rc= mysql_stmt_bind_result(stmt, bind); + check_stmt_rc(rc, stmt); + rc= mysql_stmt_fetch(stmt); + + diag("test: str='%s', expected/returned value =%d/%d, expected/returned rc=%d/%d", + test->str_value, test->int_value, int_value, test->rc, rc); + FAIL_UNLESS(rc == test->rc, "unexpected return code"); + FAIL_UNLESS(int_value == test->int_value, "unexpected int value"); + mysql_stmt_close(stmt); + } + return OK; +} + + +static int test_codbc138(MYSQL *mysql) +{ + int rc; + MYSQL_STMT *stmt; + MYSQL_BIND bind[1]; + MYSQL_TIME tm; + int i= 0; + + struct st_time_test { + const char *statement; + MYSQL_TIME tm; + } time_test[]={ + { "SELECT DATE_ADD('2018-02-01', INTERVAL -188 DAY)", + { 2017,7,28,0,0,0,0L,0, MYSQL_TIMESTAMP_DATE } + }, + { "SELECT '2001-02-03 11:12:13.123456'", + { 2001,2,3,11,12,13,123456L,0, MYSQL_TIMESTAMP_DATETIME } + }, + { "SELECT '2001-02-03 11:12:13.123'", + { 2001,2,3,11,12,13,123000L,0, MYSQL_TIMESTAMP_DATETIME } + }, + { "SELECT '-11:12:13'", + { 0,0,0,11,12,13,0,1, MYSQL_TIMESTAMP_TIME } + }, + { "SELECT ' '", + { 0,0,0,0,0,0,0,0, MYSQL_TIMESTAMP_ERROR } + }, + { "SELECT '1--'", + { 0,0,0,0,0,0,0,0, MYSQL_TIMESTAMP_ERROR } + }, + { "SELECT '-2001-01-01'", + { 0,0,0,0,0,0,0,0, MYSQL_TIMESTAMP_ERROR } + }, + { "SELECT '-11:00'", + { 0,0,0,0,0,0,0,0, MYSQL_TIMESTAMP_ERROR } + }, + {"SELECT '1972-04-22'", + {1972,4,22, 0,0,0, 0,0,MYSQL_TIMESTAMP_DATE} + }, + {"SELECT ' 1972-04-22 '", + {1972,4,22, 0,0,0, 0,0,MYSQL_TIMESTAMP_DATE} + }, + {"SELECT '1972-04-22a'", + {1972,4,22, 0,0,0, 0,0,MYSQL_TIMESTAMP_DATE} + }, + {"SELECT '0000-00-00'", + {0,0,0, 0,0,0 ,0,0,MYSQL_TIMESTAMP_DATE} + }, + {"SELECT '1970-01-00'", + {1970,1,0, 0,0,0, 0,0, MYSQL_TIMESTAMP_DATE} + }, + {"SELECT '0069-12-31'", + {69,12,31, 0,0,0, 0,0, MYSQL_TIMESTAMP_DATE} + }, + {"SELECT '69-12-31'", + {2069,12,31, 0,0,0, 0,0, MYSQL_TIMESTAMP_DATE} + }, + {"SELECT '68-12-31'", + {2068,12,31, 0,0,0, 0,0, MYSQL_TIMESTAMP_DATE} + }, + {"SELECT '70-01-01'", + {1970,1,1, 0,0,0, 0,0, MYSQL_TIMESTAMP_DATE} + }, + {"SELECT '2010-1-1'", + {2010,1,1, 0,0,0, 0,0, MYSQL_TIMESTAMP_DATE} + }, + + {"SELECT '10000-01-01'", + {0,0,0, 0,0,0, 0,0, MYSQL_TIMESTAMP_ERROR} + }, + {"SELECT '1979-a-01'", + {0,0,0, 0,0,0, 0,0, MYSQL_TIMESTAMP_ERROR} + }, + {"SELECT '1979-01-32'", + {0,0,0, 0,0,0, 0,0, MYSQL_TIMESTAMP_ERROR} + }, + {"SELECT '1979-13-01'", + {0,0,0, 0,0,0, 0,0, MYSQL_TIMESTAMP_ERROR} + }, + {"SELECT '1YYY-01-01'", + {0,0,0, 0,0,0, 0,0, MYSQL_TIMESTAMP_ERROR} + }, + {"SELECT '1979-0M-01'", + {0,0,0, 0,0,0, 0,0, MYSQL_TIMESTAMP_ERROR} + }, + {"SELECT '1979-00-'", + {0,0,0, 0,0,0, 0,0, MYSQL_TIMESTAMP_ERROR} + }, + {"SELECT '1979-00'", + {0,0,0, 0,0,0, 0,0,MYSQL_TIMESTAMP_ERROR} + }, + {"SELECT '1979'", + {0,0,0, 0,0,0, 0,0, MYSQL_TIMESTAMP_ERROR} + }, + {"SELECT '79'", + {0,0,0, 0,0,0, 0,0, MYSQL_TIMESTAMP_ERROR} + }, + + {"SELECT '10:15:00'", + {0,0,0, 10,15,0, 0,0, MYSQL_TIMESTAMP_TIME} + }, + {"SELECT '10:15:01'", + {0,0,0, 10,15,1, 0,0, MYSQL_TIMESTAMP_TIME} + }, + {"SELECT '00:00:00'", + {0,0,0, 0,0,0, 0,0, MYSQL_TIMESTAMP_TIME} + }, + {"SELECT '0:0:0'", + {0,0,0, 0,0,0, 0,0, MYSQL_TIMESTAMP_TIME} + }, + {"SELECT '10:15:01.'", + {0,0,0, 10,15,1, 0,0, MYSQL_TIMESTAMP_TIME}, + }, + {"SELECT '25:59:59'", + {0,0,0, 25,59,59, 0,0, MYSQL_TIMESTAMP_TIME}, + }, + {"SELECT '838:59:59'", + {0,0,0, 838,59,59, 0,0, MYSQL_TIMESTAMP_TIME}, + }, + {"SELECT '-838:59:59'", + {0,0,0, 838,59,59, 0, 1, MYSQL_TIMESTAMP_TIME}, + }, + + {"SELECT '00:60:00'", + {0,0,0, 0,0,0, 0,0, MYSQL_TIMESTAMP_ERROR}, + }, + {"SELECT '839:00:00'", + {0,0,0, 0,0,0, 0,0, MYSQL_TIMESTAMP_ERROR}, + }, + {"SELECT '-839:00:00'", + {0,0,0, 0,0,0, 0,0, MYSQL_TIMESTAMP_ERROR}, + }, + {"SELECT '-10:15:a'", + { 0,0,0, 0,0,0, 0,0, MYSQL_TIMESTAMP_ERROR }, + }, + {"SELECT '1999-12-31 23:59:59.9999999'", + {1999,12,31, 23,59,59, 999999, 0, MYSQL_TIMESTAMP_DATETIME}, + }, + {"SELECT '00-08-11 8:46:40'", + {2000,8,11, 8,46,40, 0,0, MYSQL_TIMESTAMP_DATETIME}, + }, + {"SELECT '1999-12-31 25:59:59.999999'", + {0,0,0, 0,0,0, 0,0, MYSQL_TIMESTAMP_ERROR }, + }, + { NULL,{ 0 } } + }; + + while (time_test[i].statement) + { + stmt= mysql_stmt_init(mysql); + rc= mysql_stmt_prepare(stmt, SL(time_test[i].statement)); + check_stmt_rc(rc, stmt); + rc= mysql_stmt_execute(stmt); + check_stmt_rc(rc, stmt); + rc= mysql_stmt_store_result(stmt); + + memset(bind, 0, sizeof(MYSQL_BIND)); + bind[0].buffer_type= MYSQL_TYPE_DATETIME; + bind[0].buffer= &tm; + bind[0].buffer_length= sizeof(MYSQL_TIME); + + rc= mysql_stmt_bind_result(stmt, bind); + check_stmt_rc(rc, stmt); + rc= mysql_stmt_fetch(stmt); + check_stmt_rc(rc, stmt); + diag("test: %s %d %d", time_test[i].statement, tm.time_type, time_test[i].tm.time_type); + if (time_test[i].tm.time_type == MYSQL_TIMESTAMP_ERROR) + { + FAIL_UNLESS(tm.time_type == MYSQL_TIMESTAMP_ERROR, "MYSQL_TIMESTAMP_ERROR expected"); + } + else + FAIL_UNLESS(equal_MYSQL_TIME(&tm, &time_test[i].tm), "time_in != time_out"); + mysql_stmt_close(stmt); + i++; + } + + return OK; +} + +static int test_conc334(MYSQL *mysql) +{ + MYSQL_STMT *stmt= mysql_stmt_init(mysql); + MYSQL_RES *result; + MYSQL_FIELD *field; + int rc; + + rc= mysql_stmt_prepare(stmt, SL("SHOW ENGINES")); + check_stmt_rc(rc, stmt); + + rc= mysql_stmt_execute(stmt); + check_stmt_rc(rc, stmt); + + result= mysql_stmt_result_metadata(stmt); + if (!result) + { + diag("Couldn't retrieve result set"); + mysql_stmt_close(stmt); + return FAIL; + } + + mysql_field_seek(result, 0); + + while ((field= mysql_fetch_field(result))) + { + FAIL_IF(field->name_length == 0, "Invalid name length (0)"); + FAIL_IF(field->table_length == 0, "Invalid name length (0)"); + } + mysql_free_result(result); + mysql_stmt_close(stmt); + + return OK; +} +static int test_conc344(MYSQL *mysql) +{ + MYSQL_STMT *stmt= mysql_stmt_init(mysql); + int rc; + + rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1"); + check_mysql_rc(rc, mysql); + + rc= mysql_query(mysql, "CREATE TABLE t1 (a int, b int)"); + check_mysql_rc(rc, mysql); + rc= mysql_query(mysql, "INSERT INTO t1 VALUES (1,1), (2,2),(3,3),(4,4),(5,5)"); + check_mysql_rc(rc, mysql); + + rc= mysql_stmt_prepare(stmt, SL("SELECT * FROM t1 ORDER BY a")); + check_stmt_rc(rc, stmt); + + rc= mysql_stmt_execute(stmt); + check_stmt_rc(rc, stmt); + + while (!mysql_stmt_fetch(stmt)); + FAIL_IF(mysql_stmt_num_rows(stmt) != 5, "expected 5 rows"); + rc= mysql_stmt_execute(stmt); + check_stmt_rc(rc, stmt); + rc= mysql_stmt_fetch(stmt); + diag("num_rows: %lld", mysql_stmt_num_rows(stmt)); + FAIL_IF(mysql_stmt_num_rows(stmt) != 1, "expected 1 row"); + + mysql_stmt_close(stmt); + return OK; +} + + +static int test_conc_fraction(MYSQL *mysql) +{ + MYSQL_TIME tm; + MYSQL_BIND bind[1]; + char query[1024]; + int i; + MYSQL_STMT *stmt= mysql_stmt_init(mysql); + int rc; + unsigned long frac= 0; + + for (i=0; i < 10; i++, frac=frac*10+i) + { + unsigned long expected= 0; + sprintf(query, "SELECT '2018-11-05 22:25:59.%ld'", frac); + + diag("%d: %s", i, query); + + rc= mysql_stmt_prepare(stmt, SL(query)); + check_stmt_rc(rc, stmt); + + rc= mysql_stmt_execute(stmt); + check_stmt_rc(rc, stmt); + + rc = mysql_stmt_store_result(stmt); + check_stmt_rc(rc, stmt); + + memset(bind, 0, sizeof(MYSQL_BIND)); + bind[0].buffer_type= MYSQL_TYPE_DATETIME; + bind[0].buffer= &tm; + bind[0].buffer_length= sizeof(MYSQL_TIME); + + rc= mysql_stmt_bind_result(stmt, bind); + check_stmt_rc(rc, stmt); + rc= mysql_stmt_fetch(stmt); + check_stmt_rc(rc, stmt); + + diag("second_part: %ld", tm.second_part); + + expected= i > 6 ? 123456 : frac * (unsigned int)powl(10, (6 - i)); + + if (tm.second_part != expected) + { + diag("Error: tm.second_part=%ld expected=%ld", tm.second_part, expected); + return FAIL; + } + } + mysql_stmt_close(stmt); + return OK; +} + +static int test_zerofill_1byte(MYSQL *mysql) +{ + MYSQL_STMT *stmt= mysql_stmt_init(mysql); + int rc; + MYSQL_BIND bind; + char buffer[3]; + + rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1"); + check_mysql_rc(rc, mysql); + + rc= mysql_query(mysql, "CREATE TABLE t1 (a int zerofill)"); + check_mysql_rc(rc, mysql); + + rc= mysql_query(mysql, "INSERT INTO t1 VALUES(1)"); + check_mysql_rc(rc, mysql); + + rc= mysql_stmt_prepare(stmt, SL("SELECT a FROM t1")); + check_stmt_rc(rc, stmt); + + rc= mysql_stmt_execute(stmt); + check_stmt_rc(rc, stmt); + + memset(&bind, 0, sizeof(MYSQL_BIND)); + bind.buffer_type= MYSQL_TYPE_STRING; + bind.buffer= buffer; + bind.buffer_length= 1; + + rc= mysql_stmt_bind_result(stmt, &bind); + + rc= mysql_stmt_fetch(stmt); + FAIL_IF(rc != 101, "expected truncation warning"); + + mysql_stmt_close(stmt); + rc= mysql_query(mysql, "DROP TABLE t1"); + check_mysql_rc(rc, mysql); + + return OK; +} + +static int test_conc424(MYSQL *mysql) +{ + int rc; + MYSQL_STMT *stmt; + my_bool max_len= 1; + + rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_table1"); + check_mysql_rc(rc, mysql); + rc= mysql_query(mysql, "CREATE TABLE test_table1 (test_int INT, b int)"); + check_mysql_rc(rc, mysql); + rc= mysql_query(mysql, "INSERT INTO test_table1 values(10,11),(11,12)"); + check_mysql_rc(rc, mysql); + + rc= mysql_query(mysql, "DROP PROCEDURE IF EXISTS testCursor"); + check_mysql_rc(rc, mysql); + + rc= mysql_query(mysql, "CREATE PROCEDURE testCursor()\n" + "BEGIN\n" + "DECLARE test_int INT;\n" + "DECLARE b INT;\n" + "DECLARE done INT DEFAULT FALSE;\n" + "DECLARE testCursor CURSOR\n" + "FOR\n" + "SELECT test_int,b FROM test_table1;\n" + "DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;\n" + "OPEN testCursor;\n" + + " read_loop: LOOP\n" + " FETCH testCursor INTO test_int, b;\n" + " IF done THEN\n" + " LEAVE read_loop;\n" + " END IF;\n" + " SELECT test_int,b;" + " END LOOP;\n" + "CLOSE testCursor;\n" + "END"); + check_mysql_rc(rc, mysql); + + stmt= mysql_stmt_init(mysql); + rc= mysql_stmt_prepare(stmt, SL("CALL testCursor()")); + check_stmt_rc(rc, stmt); + + rc= mysql_stmt_attr_set(stmt, STMT_ATTR_UPDATE_MAX_LENGTH, &max_len); + check_stmt_rc(rc, stmt); + + rc= mysql_stmt_execute(stmt); + check_stmt_rc(rc, stmt); + + do { + if (mysql_stmt_field_count(stmt)) + { + MYSQL_RES *res= mysql_stmt_result_metadata(stmt); + rc= mysql_stmt_fetch(stmt); + FAIL_IF(rc, "Wrong return code"); + mysql_free_result(res); + } + rc= mysql_stmt_next_result(stmt); + + } while (!rc); + + mysql_stmt_close(stmt); + rc= mysql_query(mysql, "DROP PROCEDURE testCursor"); + check_mysql_rc(rc, mysql); + + rc= mysql_query(mysql, "DROP TABLE test_table1"); + check_mysql_rc(rc, mysql); + + return OK; +} + +static int test_maxparam(MYSQL *mysql) +{ + const char *query= "INSERT INTO t1 VALUES (?)"; + int rc; + char *buffer; + int i; + int val= 1; + size_t mem= strlen(query) + 1 + 4 * 65535 + 1; + MYSQL_STMT *stmt= mysql_stmt_init(mysql); + MYSQL_BIND* bind; + + bind = calloc(sizeof(MYSQL_BIND), 65535); + + rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1"); + check_mysql_rc(rc, mysql); + + rc= mysql_query(mysql, "CREATE TABLE t1 (a int)"); + check_mysql_rc(rc, mysql); + + buffer= calloc(1, mem); + strcpy(buffer, query); + for (i=0; i < 65534.; i++) + strcat(buffer, ",(?)"); + rc= mysql_stmt_prepare(stmt, SL(buffer)); + check_stmt_rc(rc, stmt); + + for (i=0; i < 65534; i++) + { + bind[i].buffer_type= MYSQL_TYPE_LONG; + bind[i].buffer= &val; + } + + rc= mysql_stmt_bind_param(stmt, bind); + check_stmt_rc(rc, stmt); + + rc= mysql_stmt_execute(stmt); + check_stmt_rc(rc, stmt); + + FAIL_IF(mysql_stmt_affected_rows(stmt) != 65535, "Expected affected_rows=65535"); + + strcat(buffer, ",(?)"); + rc= mysql_stmt_prepare(stmt, SL(buffer)); + free(buffer); + FAIL_IF(!rc, "Error expected"); + FAIL_IF(mysql_stmt_errno(stmt) != ER_PS_MANY_PARAM, "Expected ER_PS_MANY_PARAM error"); + + mysql_stmt_close(stmt); + free(bind); + return OK; +} + +static int test_mdev_21920(MYSQL *mysql) +{ + MYSQL_STMT *stmt= mysql_stmt_init(mysql); + MYSQL_BIND bind[1]; + int rc; + char buffer[128]; + + rc= mysql_stmt_prepare(stmt, SL("SELECT ''")); + check_stmt_rc(rc, stmt); + + rc= mysql_stmt_execute(stmt); + check_stmt_rc(rc, stmt); + + buffer[0]= 1; + + memset(bind, 0, sizeof(MYSQL_BIND)); + bind[0].buffer_type= MYSQL_TYPE_STRING; + bind[0].buffer= buffer; + bind[0].buffer_length= 127; + + rc= mysql_stmt_bind_result(stmt, bind); + check_stmt_rc(rc, stmt); + + rc= mysql_stmt_fetch(stmt); + check_stmt_rc(rc, stmt); + + FAIL_IF(buffer[0] != 0, "Expected empty string"); + + + mysql_stmt_close(stmt); + + return OK; +} + +static int test_returning(MYSQL *mysql) +{ + MYSQL_STMT *stmt= mysql_stmt_init(mysql); + MYSQL_RES *result; + int rc; + + diag("MDEV-23768 not fixed yet"); + mysql_stmt_close(stmt); + return SKIP; + + rc= mysql_query(mysql, "CREATE TEMPORARY TABLE t1 (a int not null auto_increment primary key, b json)"); + check_mysql_rc(rc, mysql); + + rc= mysql_query(mysql, "INSERT INTO t1 (a,b) VALUES (NULL, '[incorrect json]') RETURNING a"); + check_mysql_rc(rc, mysql); + + if (!rc) diag("should have fail"); + + result= mysql_store_result(mysql); + mysql_free_result(result); + + diag("Error: %s", mysql_error(mysql)); + + rc= mysql_stmt_prepare(stmt, SL("INSERT INTO t1 (a,b) VALUES (NULL, '[incorrect json]') RETURNING a")); + check_stmt_rc(rc, stmt); + + rc= mysql_stmt_execute(stmt); + check_stmt_rc(rc, stmt); + + rc= mysql_stmt_close(stmt); + + return OK; +} + +static int test_conc504(MYSQL *mysql) +{ + int rc; + MYSQL_STMT *stmt= mysql_stmt_init(mysql); + const char *sp= "CREATE PROCEDURE p1()\n" \ + "BEGIN\n"\ + " SELECT 1;\n"\ + " SELECT 2;\n"\ + " SELECT 3;\n"\ + "END"; + + rc= mysql_query(mysql, "DROP PROCEDURE IF EXISTS p1"); + check_mysql_rc(rc, mysql); + + rc= mysql_query(mysql, sp); + check_mysql_rc(rc, mysql); + + rc= mysql_stmt_prepare(stmt, SL("CALL p1()")); + check_stmt_rc(rc, stmt); + + rc= mysql_stmt_execute(stmt); + check_stmt_rc(rc, stmt); + + mysql_stmt_store_result(stmt); + FAIL_IF(mysql_stmt_num_rows(stmt) != 1, "Expected 1 row"); + + mysql_stmt_next_result(stmt); + mysql_stmt_store_result(stmt); + FAIL_IF(mysql_stmt_num_rows(stmt) != 1, "Expected 1 row"); + + mysql_stmt_next_result(stmt); + mysql_stmt_store_result(stmt); + FAIL_IF(mysql_stmt_num_rows(stmt) != 1, "Expected 1 row"); + + mysql_stmt_close(stmt); + + rc= mysql_query(mysql, "DROP PROCEDURE p1"); + check_mysql_rc(rc, mysql); + + return OK; +} + +static int test_conc512(MYSQL *mysql) +{ + int rc; + MYSQL_STMT *stmt; + MYSQL_BIND bind; + float f; + + rc= mysql_query(mysql, "drop table if exists t1"); + + rc= mysql_real_query(mysql, SL("CREATE TABLE t1 (a int)")); + + rc= mysql_real_query(mysql, SL("INSERT INTO t1 VALUES (1073741825)")); + + stmt= mysql_stmt_init(mysql); + rc= mysql_stmt_prepare(stmt, SL("SELECT a FROM t1")); + check_stmt_rc(rc, stmt); + + memset(&bind, 0, sizeof(MYSQL_BIND)); + bind.buffer= &f; + bind.buffer_type= MYSQL_TYPE_FLOAT; + + rc= mysql_stmt_execute(stmt); + check_stmt_rc(rc, stmt); + + rc= mysql_stmt_bind_result(stmt, &bind); + check_stmt_rc(rc, stmt); + + rc= mysql_stmt_fetch(stmt); + FAIL_IF(rc != 101, "Truncation expected"); + + mysql_stmt_close(stmt); + + rc= mysql_query(mysql, "DROP TABLE t1"); + check_mysql_rc(rc, mysql); + return OK; +} + +static int test_conc525(MYSQL *mysql) +{ + FILE *fp; + MYSQL_STMT *stmt; + int rc; + + rc= mysql_query(mysql, "create temporary table t1 (a blob)"); + check_mysql_rc(rc, mysql); + + /* create a dummy import file */ + if (!(fp= fopen("./test.csv", "w"))) + { + diag("couldn't create file './test.csv'"); + return FAIL; + } + fprintf(fp, "1\n2\n"); + fclose(fp); + + /* Test: prepare and execute + should fail due to non existing file */ + stmt= mysql_stmt_init(mysql); + + rc= mysql_stmt_prepare(stmt, SL("LOAD DATA LOCAL INFILE './test.notexist' INTO table t1")); + + if (rc && mysql_stmt_errno(stmt) == ER_UNSUPPORTED_PS) + { + diag("Server doesn't support LOAD LOCAL INFILE in binary protocol."); + mysql_stmt_close(stmt); + return SKIP; + } + + rc= mysql_stmt_execute(stmt); + FAIL_IF(!rc, "Error expected (file does not exist)"); + + mysql_stmt_close(stmt); + + /* Test: prepare and execute + 2 rows should be inserted */ + stmt= mysql_stmt_init(mysql); + + rc= mysql_stmt_prepare(stmt, SL("LOAD DATA LOCAL INFILE './test.csv' INTO table t1")); + check_stmt_rc(rc, stmt); + + rc= mysql_stmt_execute(stmt); + check_stmt_rc(rc, stmt); + + FAIL_IF(mysql_stmt_affected_rows(stmt) != 2, "Expected 2 inserted rows"); + + mysql_stmt_close(stmt); + stmt= mysql_stmt_init(mysql); + + /* Test: execute_direct + 2 rows should be inserted */ + rc= mariadb_stmt_execute_direct(stmt, SL("LOAD DATA LOCAL INFILE './test.csv' INTO table t1")); + check_stmt_rc(rc, stmt); + + FAIL_IF(mysql_stmt_affected_rows(stmt) != 2, "Expected 2 inserted rows"); + + /* Cleanup */ + mysql_stmt_close(stmt); + unlink("./test.csv"); + + return OK; +} + +static int test_conc566(MYSQL *mysql) +{ + int rc; + MYSQL_STMT *stmt = mysql_stmt_init(mysql); + unsigned long cursor = CURSOR_TYPE_READ_ONLY; + const char* query= "call sp()"; + + SKIP_SKYSQL; + + rc= mysql_query(mysql,"drop procedure if exists sp"); + check_mysql_rc(rc, mysql); + + rc= mysql_query(mysql,"create procedure sp() select 1"); + check_mysql_rc(rc, mysql); + + rc= mysql_stmt_prepare(stmt,query,-1); + check_stmt_rc(rc, stmt); + + rc= mysql_stmt_attr_set(stmt, STMT_ATTR_CURSOR_TYPE, &cursor); + check_stmt_rc(rc, stmt); + + rc= mysql_stmt_execute(stmt); + check_stmt_rc(rc, stmt); + + mysql_stmt_close(stmt); + + rc= mysql_query(mysql,"drop procedure sp"); + check_mysql_rc(rc, mysql); + return OK; +} + +#define MDEV19838_MAX_PARAM_COUNT 32 +#define MDEV19838_FIELDS_COUNT 17 + +static int test_mdev19838(MYSQL *mysql) +{ + int rc; + MYSQL_BIND bind[MDEV19838_MAX_PARAM_COUNT]; + unsigned int i, paramCount = 1; + char charvalue[] = "012345678901234567890123456789012345"; + MYSQL_STMT *stmt; + + SKIP_MAXSCALE; + // https://jira.mariadb.org/browse/XPT-266 + if (IS_XPAND()) { + rc= mysql_query(mysql, "SET NAMES UTF8"); + check_mysql_rc(rc, mysql); + } + + + rc = mysql_query(mysql, "CREATE temporary 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)" + ")"); + check_mysql_rc(rc, mysql); + + stmt = mysql_stmt_init(mysql); + + 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 = sizeof charvalue; + 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_stmt_rc(rc, stmt); + + 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 */ + FAIL_UNLESS(rc != 0, "rc!=0"); + + mysql_stmt_close(stmt); + stmt = mysql_stmt_init(mysql); + } + + 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 */ + FAIL_UNLESS(rc != 0, "rc!=0"); + mysql_stmt_close(stmt); + + stmt = mysql_stmt_init(mysql); + /* 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_stmt_rc(rc, stmt); + + /* 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); + + mysql_stmt_attr_set(stmt, STMT_ATTR_PREBIND_PARAMS, ¶mCount); + + rc = mysql_stmt_bind_param(stmt, bind); + + rc = mariadb_stmt_execute_direct(stmt, "INSERT INTO mdev19838" + "(f1, f2, f3, f4, f5, f6, f7, f8, f9)" + " VALUES " + "(?, ?, ?, ?, ?, ?, ?, ?, ?)", -1); + + /* Expecting an error */ + FAIL_UNLESS(rc != 0, "rc"); + } + + /* 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); + + mysql_stmt_attr_set(stmt, STMT_ATTR_PREBIND_PARAMS, ¶mCount); + + if (paramCount > 0) + { + rc = mysql_stmt_bind_param(stmt, bind); + check_stmt_rc(rc, stmt); + } + + 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. + */ + FAIL_UNLESS(rc == 0, ""); + } + + mysql_stmt_close(stmt); + return OK; +} + +my_bool conc623_param_callback(void *data __attribute((unused)), + MYSQL_BIND *bind __attribute((unused)), + unsigned int row_nr __attribute((unused))) +{ + return 1; +} + +static int test_conc623(MYSQL *mysql) +{ + int rc; + unsigned int paramcount= 1; + unsigned int array_size= 2; + MYSQL_BIND bind; + + MYSQL_STMT *stmt= mysql_stmt_init(mysql); + + rc= mysql_query(mysql, "CREATE TEMPORARY TABLE t1 (a int)"); + + rc= mysql_stmt_attr_set(stmt, STMT_ATTR_CB_USER_DATA, mysql); + check_stmt_rc(rc, stmt); + + rc= mysql_stmt_attr_set(stmt, STMT_ATTR_ARRAY_SIZE, &array_size); + check_stmt_rc(rc, stmt); + + rc= mysql_stmt_attr_set(stmt, STMT_ATTR_PREBIND_PARAMS, ¶mcount); + check_stmt_rc(rc, stmt); + + rc= mysql_stmt_attr_set(stmt, STMT_ATTR_CB_PARAM, conc623_param_callback); + check_stmt_rc(rc, stmt); + + bind.buffer_type= MYSQL_TYPE_LONG; + rc= mysql_stmt_bind_param(stmt, &bind); + check_stmt_rc(rc, stmt); + + rc= mysql_stmt_prepare(stmt, SL("INSERT INTO t1 VALUES (?)")); + check_stmt_rc(rc, stmt); + + rc= mysql_stmt_execute(stmt); + if (!rc) + { + diag("Error expected from callback function"); + mysql_stmt_close(stmt); + return FAIL; + } + + diag("Error (expected) %s", mysql_stmt_error(stmt)); + mysql_stmt_close(stmt); + return OK; +} + +static int test_conc627(MYSQL *mysql) +{ + MYSQL_STMT *stmt; + int rc; + + SKIP_MYSQL(mysql); + + stmt= mysql_stmt_init(mysql); + + rc= mysql_stmt_prepare(stmt, SL("show grants for mysqltest_8")); + check_stmt_rc(rc, stmt); + + rc= mysql_stmt_execute(stmt); + check_stmt_rc(rc, stmt); + + mysql_stmt_store_result(stmt); + FAIL_IF(!mysql_stmt_errno(stmt), "Expected error"); + FAIL_IF(strcmp(mysql_error(mysql), mysql_stmt_error(stmt)), "Error messages differ"); + + mysql_stmt_close(stmt); + + return OK; +} + +static int test_conc633(MYSQL *mysql) +{ + MYSQL_STMT *stmt; + MYSQL *my= NULL; + int ret= FAIL; + int rc; + + SKIP_MYSQL(mysql); + + stmt= mysql_stmt_init(mysql); + + if (!mariadb_stmt_execute_direct(stmt, SL("SÄLECT 1"))) + { + diag("Syntax error expected"); + goto end; + } + + if (mysql_errno(mysql) != mysql_stmt_errno(stmt)) + { + diag("Different error codes. mysql_errno= %d, mysql_stmt_errno=%d", + mysql_errno(mysql), mysql_stmt_errno(stmt)); + goto end; + } + + if ((long)stmt->stmt_id != -1) + { + diag("Error: expected stmt_id=-1"); + goto end; + } + + if (!(my= test_connect(NULL))) + { + diag("Can establish connection (%s)", mysql_error(my)); + goto end; + } + + rc= mysql_query(my, "CREATE OR REPLACE TABLE conc633 (a int)"); + check_mysql_rc(rc, mysql); + + rc= mysql_query(mysql, "SET @@lock_wait_timeout=3"); + + rc= mysql_query(my, "LOCK TABLES conc633 WRITE"); + check_mysql_rc(rc, mysql); + + rc= mysql_query(mysql, "SET @@lock_wait_timeout=3"); + check_mysql_rc(rc, mysql); + + if (!mariadb_stmt_execute_direct(stmt, SL("INSERT INTO conc633 VALUES (1)"))) + { + diag("lock wait timeout error expected"); + goto end; + } + + if (stmt->state != MYSQL_STMT_PREPARED) + { + diag("Error: stmt hasn't prepared status"); + goto end; + } + + if ((long)stmt->stmt_id == -1) + { + diag("Error: no stmt_id assigned"); + goto end; + } + + rc= mysql_query(my, "UNLOCK TABLES"); + check_mysql_rc(rc, mysql); + rc= mysql_query(my, "DROP TABLE conc633"); + check_mysql_rc(rc, mysql); + + ret= OK; + +end: + if (my) + mysql_close(my); + mysql_stmt_close(stmt); + return ret; +} + +struct my_tests_st my_tests[] = { + {"test_conc633", test_conc633, TEST_CONNECTION_DEFAULT, 0, NULL, NULL}, + {"test_conc623", test_conc623, TEST_CONNECTION_DEFAULT, 0, NULL, NULL}, + {"test_conc627", test_conc627, TEST_CONNECTION_DEFAULT, 0, NULL, NULL}, + {"test_mdev19838", test_mdev19838, TEST_CONNECTION_DEFAULT, 0, NULL, NULL}, + {"test_conc525", test_conc525, TEST_CONNECTION_DEFAULT, 0, NULL, NULL}, + {"test_conc566", test_conc566, TEST_CONNECTION_DEFAULT, 0, NULL, NULL}, + {"test_conc512", test_conc512, TEST_CONNECTION_DEFAULT, 0, NULL, NULL}, + {"test_conc504", test_conc504, TEST_CONNECTION_DEFAULT, 0, NULL, NULL}, + {"test_returning", test_returning, TEST_CONNECTION_DEFAULT, 0, NULL, NULL}, + {"test_mdev_21920", test_mdev_21920, TEST_CONNECTION_DEFAULT, 0, NULL, NULL}, + {"test_maxparam", test_maxparam, TEST_CONNECTION_NEW, 0, NULL, NULL}, + {"test_conc424", test_conc424, TEST_CONNECTION_NEW, 0, NULL, NULL}, + {"test_conc344", test_conc344, TEST_CONNECTION_NEW, 0, NULL, NULL}, + {"test_conc334", test_conc334, TEST_CONNECTION_NEW, 0, NULL, NULL}, + {"test_compress", test_compress, TEST_CONNECTION_NEW, CLIENT_COMPRESS, NULL, NULL}, + {"test_zerofill_1byte", test_zerofill_1byte, TEST_CONNECTION_DEFAULT, 0, NULL, NULL}, + {"test_codbc138", test_codbc138, TEST_CONNECTION_DEFAULT, 0, NULL, NULL}, + {"test_conc208", test_conc208, TEST_CONNECTION_DEFAULT, 0, NULL, NULL}, + {"test_mdev14165", test_mdev14165, TEST_CONNECTION_DEFAULT, 0, NULL, NULL}, + {"test_conc208", test_conc208, TEST_CONNECTION_DEFAULT, 0, NULL, NULL}, + {"test_conc217", test_conc217, TEST_CONNECTION_DEFAULT, 0, NULL, NULL}, + {"test_conc205", test_conc205, TEST_CONNECTION_DEFAULT, 0, NULL, NULL}, + {"test_conc198", test_conc198, TEST_CONNECTION_DEFAULT, 0, NULL, NULL}, + {"test_conc182", test_conc182, TEST_CONNECTION_DEFAULT, 0, NULL, NULL}, + {"test_conc181", test_conc181, TEST_CONNECTION_DEFAULT, 0, NULL, NULL}, + {"test_conc179", test_conc179, TEST_CONNECTION_DEFAULT, 0, NULL, NULL}, + {"test_conc177", test_conc177, TEST_CONNECTION_DEFAULT, 0, NULL, NULL}, + {"test_conc167", test_conc167, TEST_CONNECTION_DEFAULT, 0, NULL, NULL}, + {"test_conc168", test_conc168, TEST_CONNECTION_DEFAULT, 0, NULL, NULL}, + {"test_conc155", test_conc155, TEST_CONNECTION_DEFAULT, 0, NULL, NULL}, + {"test_conc154", test_conc154, TEST_CONNECTION_DEFAULT, 0, NULL , NULL}, + {"test_conc141", test_conc141, TEST_CONNECTION_NEW, 0, NULL , NULL}, + {"test_conc67", test_conc67, TEST_CONNECTION_DEFAULT, 0, NULL , NULL}, + {"test_conc_5", test_conc_5, TEST_CONNECTION_DEFAULT, 0, NULL , NULL}, + {"test_bug1115", test_bug1115, TEST_CONNECTION_DEFAULT, 0, NULL , NULL}, + {"test_bug1180", test_bug1180, TEST_CONNECTION_DEFAULT, 0, NULL , NULL}, + {"test_bug1644", test_bug1644, TEST_CONNECTION_DEFAULT, 0, NULL , NULL}, + {"test_bug11037", test_bug11037, TEST_CONNECTION_DEFAULT, 0, NULL , NULL}, + {"test_bug11183", test_bug11183, TEST_CONNECTION_DEFAULT, 0, NULL , NULL}, + {"test_bug12744", test_bug12744, TEST_CONNECTION_DEFAULT, 0, NULL , NULL}, + {"test_bug1500", test_bug1500, TEST_CONNECTION_DEFAULT, 0, NULL , NULL}, + {"test_bug15510", test_bug15510, TEST_CONNECTION_DEFAULT, 0, NULL , NULL}, + {"test_bug15518", test_bug15518, TEST_CONNECTION_NEW | TEST_CONNECTION_DONT_CLOSE, CLIENT_MULTI_STATEMENTS, NULL , NULL}, + {"test_bug15613", test_bug15613, TEST_CONNECTION_DEFAULT, 0, NULL , NULL}, + {"test_bug16144", test_bug16144, TEST_CONNECTION_DEFAULT, 0, NULL , NULL}, + {"test_bug1664", test_bug1664, TEST_CONNECTION_DEFAULT, 0, NULL , NULL}, + {"test_bug1946", test_bug1946, TEST_CONNECTION_DEFAULT, 0, NULL , NULL}, + {"test_bug2247", test_bug2247, TEST_CONNECTION_DEFAULT, 0, NULL , NULL}, + {"test_bug2248", test_bug2248, TEST_CONNECTION_DEFAULT, 0, NULL , NULL}, + {"test_bug20152", test_bug20152, TEST_CONNECTION_DEFAULT, 0, NULL , NULL}, + {"test_bug23383", test_bug23383, TEST_CONNECTION_DEFAULT, 0, NULL , NULL}, + {"test_bug27592", test_bug27592, TEST_CONNECTION_DEFAULT, 0, NULL , NULL}, + {"test_bug28934", test_bug28934, TEST_CONNECTION_DEFAULT, 0, NULL , NULL}, + {"test_bug36004", test_bug36004, TEST_CONNECTION_DEFAULT, 0, NULL , NULL}, + {"test_bug3035", test_bug3035, TEST_CONNECTION_DEFAULT, 0, NULL , NULL}, + {"test_bug3117", test_bug3117, TEST_CONNECTION_DEFAULT, 0, NULL , NULL}, + {"test_bug3796", test_bug3796, TEST_CONNECTION_DEFAULT, 0, NULL , NULL}, + {"test_bug4026", test_bug4026, TEST_CONNECTION_DEFAULT, 0, NULL , NULL}, + {"test_bug4030", test_bug4030, TEST_CONNECTION_DEFAULT, 0, NULL , NULL}, + {"test_bug4079", test_bug4079, TEST_CONNECTION_DEFAULT, 0, NULL , NULL}, + {"test_bug4172", test_bug4172, TEST_CONNECTION_DEFAULT, 0, NULL , NULL}, + {"test_bug4231", test_bug4231, TEST_CONNECTION_DEFAULT, 0, NULL , NULL}, + {"test_bug4236", test_bug4236, TEST_CONNECTION_DEFAULT, 0, NULL , NULL}, + {"test_bug5126", test_bug5126, TEST_CONNECTION_DEFAULT, 0, NULL , NULL}, + {"test_bug5194", test_bug5194, TEST_CONNECTION_DEFAULT, 0, NULL , NULL}, + {"test_bug5315", test_bug5315, TEST_CONNECTION_DEFAULT, 0, NULL , NULL}, + {"test_bug5399", test_bug5399, TEST_CONNECTION_DEFAULT, 0, NULL , NULL}, + {"test_bug6046", test_bug6046, TEST_CONNECTION_DEFAULT, 0, NULL , NULL}, + {"test_bug6049", test_bug6049, TEST_CONNECTION_DEFAULT, 0, NULL , NULL}, + {"test_bug6058", test_bug6058, TEST_CONNECTION_DEFAULT, 0, NULL , NULL}, + {"test_bug6059", test_bug6059, TEST_CONNECTION_DEFAULT, 0, NULL , NULL}, + {"test_bug6096", test_bug6096, TEST_CONNECTION_DEFAULT, 0, NULL , NULL}, + {"test_bug7990", test_bug7990, TEST_CONNECTION_DEFAULT, 0, NULL , NULL}, + {"test_bug8330", test_bug8330, TEST_CONNECTION_DEFAULT, 0, NULL , NULL}, + {"test_bug8722", test_bug8722, TEST_CONNECTION_DEFAULT, 0, NULL , NULL}, + {"test_ps_conj_select", test_ps_conj_select, TEST_CONNECTION_DEFAULT, 0, NULL , NULL}, + {"test_ps_null_param", test_ps_null_param, TEST_CONNECTION_DEFAULT, 0, NULL , NULL}, + {"test_ps_query_cache", test_ps_query_cache, TEST_CONNECTION_DEFAULT, 0, NULL , NULL}, + {"test_ushort_bug", test_ushort_bug, TEST_CONNECTION_DEFAULT, 0, NULL , NULL}, + {"test_field_misc", test_field_misc, TEST_CONNECTION_DEFAULT, 0, NULL , NULL}, + {"test_mem_overun", test_mem_overun, TEST_CONNECTION_DEFAULT, 0, NULL , NULL}, + {"test_decimal_bug", test_decimal_bug, TEST_CONNECTION_DEFAULT, 0, NULL , NULL}, + {"test_explain_bug", test_explain_bug, TEST_CONNECTION_DEFAULT, 0, NULL , NULL}, + {"test_sshort_bug", test_sshort_bug, TEST_CONNECTION_DEFAULT, 0, NULL , NULL}, + {"test_stiny_bug", test_stiny_bug, TEST_CONNECTION_DEFAULT, 0, NULL , NULL}, + {"test_bug53311", test_bug53311, TEST_CONNECTION_NEW, 0, NULL , NULL}, + {"test_conc_fraction", test_conc_fraction, TEST_CONNECTION_DEFAULT, 0, NULL , NULL}, + {"test_str_to_int", test_str_to_int, TEST_CONNECTION_DEFAULT, 0, NULL, NULL}, + {NULL, NULL, 0, 0, NULL, NULL} +}; + +int main(int argc, char **argv) +{ + if (argc > 1) + get_options(argc, argv); + + get_envvars(); + + run_tests(my_tests); + + return(exit_status()); +} |