Skip to content

MySQL: Support multiple result sets in prepared queries#825

Merged
asherkin merged 1 commit intoalliedmodders:masterfrom
peace-maker:mysql_prepared_statements_multi_result
Jun 5, 2018
Merged

MySQL: Support multiple result sets in prepared queries#825
asherkin merged 1 commit intoalliedmodders:masterfrom
peace-maker:mysql_prepared_statements_multi_result

Conversation

@peace-maker
Copy link
Member

Prepared statements can return multiple result sets in MySQL 5.5. That can happen when calling stored procedures using CALL x();.

This change removes the previous caching of result bindings, since the number of fields in a result can differ from result set to result set. This could potentially have a negative impact on performance of prepared statements always only returning one result set, since the result binding buffers are recreated everytime the statement is executed instead of once. That difference should be negligible though.

Fixes #823.

Usage is just like with normal queries:

// From https://dev.mysql.com/doc/refman/5.5/en/c-api-prepared-call-statements.html
public void OnPluginStart()
{
	char error[255];
	Database db = SQL_DefConnect(error, sizeof(error));
	if (db == null){
		PrintToServer("Could not connect: %s", error);
		return;
	}

	/*
	CREATE PROCEDURE p1(
	  IN p_in INT,
	  OUT p_out INT,
	  INOUT p_inout INT)
	BEGIN
	  SELECT p_in, p_out, p_inout;
	  SET p_in = 100, p_out = 200, p_inout = 300;
	  SELECT p_in, p_out, p_inout;
	END
	*/

	DBStatement hStmt = SQL_PrepareQuery(db, "CALL p1(?, ?, ?)", error, sizeof(error));
	if (!hStmt){
		PrintToServer(error);
		delete db;
		return;
	}
	
	/* assign values to parameters and execute statement */
	hStmt.BindInt(0, 10); /* p_in */
	hStmt.BindInt(1, 20); /* p_out */
	hStmt.BindInt(2, 30); /* p_inout */

	if (!SQL_Execute(hStmt)){
		SQL_GetError(hStmt, error, sizeof(error));
		PrintToServer(error);
		delete hStmt;
		delete db;
		return;
	}
	
	do 
	{
		int rows = SQL_GetRowCount(hStmt); 
		PrintToServer("Num rows: %d", rows);

		int num_fields = SQL_GetFieldCount(hStmt);
		while (SQL_FetchRow(hStmt))
		{
			for (int i = 0; i < num_fields; i++)
			{
				if (SQL_IsFieldNull(hStmt, i))
					PrintToServer("val[%d] = NULL", i);
				else
					PrintToServer("val[%d] = %d", i, SQL_FetchInt(hStmt, i));
			}
		}
	}
	while (SQL_FetchMoreResults(hStmt));

	delete hStmt;
	delete db;
}

Output:

Num rows: 1
val[0] = 10
val[1] = NULL
val[2] = 30
Num rows: 1
val[0] = 100
val[1] = 200
val[2] = 300
Num rows: 1
val[0] = 200
val[1] = 300

Prepared statements can return multiple result sets since MySQL 5.5. That can happen when calling stored procedures using `CALL x();`.

This change removes the previous caching of result bindings, since the number of fields in a result can differ from result set to result set. This could potentially have a negative impact on prepared statements always only returning one result set, since the result binding buffers are recreated everytime the statement is executed instead of once. That difference should be negligible.

Fixes alliedmodders#823.
Copy link
Member

@asherkin asherkin left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

image

@asherkin asherkin merged commit 6fcb411 into alliedmodders:master Jun 5, 2018
@peace-maker peace-maker deleted the mysql_prepared_statements_multi_result branch June 5, 2018 17:34
@Codes97
Copy link

Codes97 commented Jun 5, 2018

@asherkin When will we be able to use this? (since which version of sourcemod)

@asherkin
Copy link
Member

asherkin commented Jun 5, 2018

@Codes97 1.10 build 6287

@Codes97
Copy link

Codes97 commented Jun 5, 2018

@asherkin Sorry I still bothering, but which stable build would it be? And how's the process? how many dev builds do you do to make a stable one?It depends on changes? testing?

@Bara
Copy link
Contributor

Bara commented Jun 5, 2018

1.10 isn't the current dev-Version ( that's 1.9 ). So it could take some months. If you want that build you can download it here but only available for windows.

@Codes97
Copy link

Codes97 commented Jun 5, 2018

Thanks Bara, but I need it for linux, no problem, I'll wait

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants