Bug #80961 mysql_stmt_execute() will block if table empty
Submitted: 5 Apr 2016 14:45 Modified: 6 Apr 2016 18:06
Reporter: chen taosheng Email Updates:
Status: Verified Impact on me:
None 
Category:MySQL Server: C API (client library) Severity:S3 (Non-critical)
Version:5.7.11 OS:Windows (windows 7)
Assigned to: CPU Architecture:Any
Tags: CURSOR_TYPE_READ_ONLY, mysql_stmt_execute

[5 Apr 2016 14:45] chen taosheng
Description:
mysql_stmt_execute() will block:

#include <string.h>
#include <mysql.h>

int main(int argc, char **argv)
{
#define STRING_SIZE 50

#define SELECT_SAMPLE "call SP_TEST()"
	/*
	CREATE TABLE `test_table` (
	`col1`  int(10) UNSIGNED NOT NULL AUTO_INCREMENT ,
	`col2`  varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL ,
	`col3`  smallint(6) NULL DEFAULT NULL ,
	`col4`  timestamp(6) NULL DEFAULT NULL ,
	PRIMARY KEY (`col1`)
	)
	ENGINE=InnoDB
	DEFAULT CHARACTER SET=utf8 COLLATE=utf8_general_ci
	AUTO_INCREMENT=2
	ROW_FORMAT=DYNAMIC
	;
	*/

	/*
	CREATE DEFINER = `root`@`%` PROCEDURE `SP_TEST`()
	BEGIN
	SELECT col1, col2, col3, col4 FROM test_table;
	END;
	*/
	MYSQL *mysql;
	mysql = mysql_init(NULL);
	if (mysql == NULL)
	{
		fprintf(stderr, " mysql_init() error.\n");
		exit(0);
	}

	if (!mysql_real_connect(mysql, "127.0.0.1", "root", "root", "testdb", 3306, NULL, 0))
	{
		fprintf(stderr, " mysql_real_connect() error.\n");
		exit(0);
	}

	MYSQL_STMT    *stmt;
	MYSQL_BIND    bind[4];
	MYSQL_RES     *prepare_meta_result;
	MYSQL_TIME    ts;
	unsigned long length[4];
	int           param_count, column_count, row_count;
	short         small_data;
	int           int_data;
	char          str_data[STRING_SIZE];
	my_bool       is_null[4];
	my_bool       error[4];

	/* Prepare a SELECT query to fetch data from test_table */
	stmt = mysql_stmt_init(mysql);
	if (!stmt)
	{
		fprintf(stderr, " mysql_stmt_init(), out of memory\n");
		exit(0);
	}

	unsigned long type = (unsigned long)CURSOR_TYPE_READ_ONLY;
	unsigned long prefetch_rows = 50;
	mysql_stmt_attr_set(stmt, STMT_ATTR_CURSOR_TYPE, (void*)&type);
	if (mysql_stmt_attr_set(stmt, STMT_ATTR_PREFETCH_ROWS, (void*)&prefetch_rows))
	{
		fprintf(stderr, " %s\n", mysql_stmt_error(stmt));
		exit(0);
	}

	if (mysql_stmt_prepare(stmt, SELECT_SAMPLE, strlen(SELECT_SAMPLE)))
	{
		fprintf(stderr, " mysql_stmt_prepare(), SELECT failed\n");
		fprintf(stderr, " %s\n", mysql_stmt_error(stmt));
		exit(0);
	}
	fprintf(stdout, " prepare, SELECT successful\n");

	/* Execute the SELECT query */
	if (mysql_stmt_execute(stmt))
	{
		fprintf(stderr, " mysql_stmt_execute(), failed\n");
		fprintf(stderr, " %s\n", mysql_stmt_error(stmt));
		exit(0);
	}

	/* .... */

	/* Close the statement */
	if (mysql_stmt_close(stmt))
	{
		fprintf(stderr, " failed while closing the statement\n");
		fprintf(stderr, " %s\n", mysql_stmt_error(stmt));
		exit(0);
	}

	mysql_close(mysql);

	return 0;
}

How to repeat:
1) use procedure to query data
2) table empty
3) set CURSOR_TYPE_READ_ONLY
[6 Apr 2016 18:06] MySQL Verification Team
Thank you for the bug report. It hangs only with server 5.7.XX and not repeatable with server 5.6.XX even with the client compiled against 5.7 client library.

c:\tmp>c:\dbs\5.6\bin\mysql -uroot -p testdb
Enter password: ******
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 10
Server version: 5.6.29-log MySQL Community Server (GPL)

Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> select * from test_table;
Empty set (0.00 sec)

mysql> exit
Bye

c:\tmp>bug80961.exe
Connected to the server: 5.6.29-log
Client Info: 5.7.13
 prepare, SELECT successful
Done!!

c:\tmp>c:\dbs\5.7\bin\mysql -uroot --port=3307 -p testdb
Enter password: ******
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 18
Server version: 5.7.11-log MySQL Community Server (GPL)

Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> select * from test_table;
Empty set (0.00 sec)

mysql> exit
Bye

c:\tmp>bug80961.exe
Connected to the server: 5.7.11-log
Client Info: 5.7.13
 prepare, SELECT successful
^C
[6 Apr 2016 18:12] MySQL Verification Team
c:\tmp>c:\dbs\5.7\bin\mysql -uroot --port=3307 -p testdb -e "insert into test_table values (1,'a',1,NULL)"
Enter password: ******

c:\tmp>bug80961.exe
Connected to the server: 5.7.11-log
Client Info: 5.7.13
 prepare, SELECT successful
Done!!