Decouple binary protocol from prepared statements

Registered by Vlad Lesin on 2014-07-07

Implement possibility to use binary answer without "prepare" stage.

The similar approach is described here: http://dev.mysql.com/worklog/task/?id=4627

Blueprint information

Status:
Started
Approver:
Laurynas Biveinis
Priority:
Medium
Drafter:
Vlad Lesin
Direction:
Approved
Assignee:
Vlad Lesin
Definition:
Drafting
Series goal:
Accepted for 5.6
Implementation:
Needs Code Review
Milestone target:
None
Started by
Laurynas Biveinis on 2014-07-15

Sprints

Whiteboard

The task can be splitted in server and client parts.

Server-side.

If we look into mysqld_stmt_prepare() function we can see the code like this:

Protocol *save_protocol= thd->protocol;
thd->protocol= &thd->protocol_binary;
stmt->prepare(...);
thd->protocol= save_protocol;

The THD class contains this members:

Protocol *protocol; // Current protocol
Protocol_text protocol_text; // Normal protocol
Protocol_binary protocol_binary; // Binary protocol

So for server-side is enough to add new command COM_STMT_QUERY which would do absolutely the same things as COM_QUERY does but with replacing thd->protocol with &thd->protocol_binary before processing and restore protocol pointer after processing.

Client side.

Standard C API has already have all necessary infrastructure to parse binary protocol. So the task is to use this infrastructure. The idea is to add new function mysql_stmt_query() which would send COM_STMT_QUERY to server, initialize MYSQL_STMT object to use it for parsing result with standard functions for parsing the result of "execute prepared statement". As well mysql_stmt_query_bind_result() is necessary to initialize certain MYSQL_STMT fields which are usually initialized inside of mysql_stmt_prepare() and to invoke standard mysql_stmt_bind_result() function to describe the result data.

There are two functions to execute prepared and non-prepared queries correspondingly: mysql_stmt_execute() and mysql_real_query(). Both functions use the same function cli_read_query_result() to get information about fields count, their names. So this part of result parsing is the same. But rows parsing is absolutely different. For non-prepared query mysql_fetch_row()->read_one_row() calls just set pointers in array of rows to the certain values in read packet. As all values are in the text format we have the array of pointers to null-terminated strings as the output of the function. But when binary data are parsed in mysql_stmt_fetch()->stmt_fetch_row() the functions use information about field types from MYSQL_STMT::bind array. For each element of this array mysql_stmt_bind_result()->setup_one_fetch_function() sets the pointer to the function which parses binary data of corresponding type to the buffer. For example fetch_result_int32() is set up for MYSQL_TYPE_LONG data type.

The task is to mix these two functions (mysql_stmt_execute() and mysql_real_query()) to get mysql_stmt_query().

The sequence of C API calls to send query and receive and parse binary answer would look like this:

MYSQL *con = mysql_init(...);
mysql_real_connect(...)

MYSQL_BIND stmt_result[n];
/* fill result info here */
...

MYSQL_STMT *stmt = mysql_stmt_init(con);
mysql_stmt_query_bind_result(stmt, stmt_result, n);
mysql_stmt_query(stmt, "SELECT 1"));
mysql_stmt_store_result(stmt);
while(!mysql_stmt_fetch (stmt))
{
...
}

mysql_stmt_free_result(stmt);
mysql_stmt_close(stmt);
mysql_close(con);

UPD: mysql_stmt_query() and mysql_stmt_query_bind_result() should be renamed to mysql_stmt_execute_immediate() and mysql_stmt_bind_immediate(), COM_STMT_QUERY should be renamed to COM_STMT_EXECUTE_IMMEDIATE as this is more suitable naming and this corresponds to this worklog http://dev.mysql.com/worklog/task/?id=4627.

(?)

Work Items

This blueprint contains Public information 
Everyone can see this information.

Subscribers

No subscribers.