MXS-852: Add PS response and command extraction functions
The mxs_mysql_extract_ps_response function extracts the binary protocol prepared statement components and stores them in a common structure. The mxs_mysql_get_command extracts the command byte from a GWBUF object containing a complete MySQL packet.
This commit is contained in:
@ -84,9 +84,13 @@ MXS_BEGIN_DECLS
|
|||||||
* [10-11] warning_count (2) -- number of warnings
|
* [10-11] warning_count (2) -- number of warnings
|
||||||
*/
|
*/
|
||||||
#define MYSQL_PS_ID_OFFSET MYSQL_HEADER_LEN + 1
|
#define MYSQL_PS_ID_OFFSET MYSQL_HEADER_LEN + 1
|
||||||
|
#define MYSQL_PS_ID_SIZE 4
|
||||||
#define MYSQL_PS_COLS_OFFSET MYSQL_HEADER_LEN + 5
|
#define MYSQL_PS_COLS_OFFSET MYSQL_HEADER_LEN + 5
|
||||||
|
#define MYSQL_PS_COLS_SIZE 2
|
||||||
#define MYSQL_PS_PARAMS_OFFSET MYSQL_HEADER_LEN + 7
|
#define MYSQL_PS_PARAMS_OFFSET MYSQL_HEADER_LEN + 7
|
||||||
|
#define MYSQL_PS_PARAMS_SIZE 2
|
||||||
#define MYSQL_PS_WARN_OFFSET MYSQL_HEADER_LEN + 10
|
#define MYSQL_PS_WARN_OFFSET MYSQL_HEADER_LEN + 10
|
||||||
|
#define MYSQL_PS_WARN_SIZE 2
|
||||||
|
|
||||||
/** Name of the default server side authentication plugin */
|
/** Name of the default server side authentication plugin */
|
||||||
#define DEFAULT_MYSQL_AUTH_PLUGIN "mysql_native_password"
|
#define DEFAULT_MYSQL_AUTH_PLUGIN "mysql_native_password"
|
||||||
@ -308,6 +312,14 @@ typedef struct
|
|||||||
#endif
|
#endif
|
||||||
} MySQLProtocol;
|
} MySQLProtocol;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
uint32_t id;
|
||||||
|
uint16_t columns;
|
||||||
|
uint16_t parameters;
|
||||||
|
uint16_t warnings;
|
||||||
|
} MXS_PS_RESPONSE;
|
||||||
|
|
||||||
/** Defines for response codes */
|
/** Defines for response codes */
|
||||||
#define MYSQL_REPLY_ERR 0xff
|
#define MYSQL_REPLY_ERR 0xff
|
||||||
#define MYSQL_REPLY_OK 0x00
|
#define MYSQL_REPLY_OK 0x00
|
||||||
@ -504,4 +516,24 @@ const char* mxs_mysql_get_current_db(MXS_SESSION* session);
|
|||||||
*/
|
*/
|
||||||
void mxs_mysql_set_current_db(MXS_SESSION* session, const char* db);
|
void mxs_mysql_set_current_db(MXS_SESSION* session, const char* db);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get the command byte
|
||||||
|
*
|
||||||
|
* @param buffer Buffer containing a complete MySQL packet
|
||||||
|
*
|
||||||
|
* @return The command byte
|
||||||
|
*/
|
||||||
|
uint8_t mxs_mysql_get_command(GWBUF* buffer);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Extract PS response values
|
||||||
|
*
|
||||||
|
* @param buffer Buffer containing a complete response to a binary protocol
|
||||||
|
* preparation of a prepared statement
|
||||||
|
* @param out Destination where the values are extracted
|
||||||
|
*
|
||||||
|
* @return True if values were extracted successfully
|
||||||
|
*/
|
||||||
|
bool mxs_mysql_extract_ps_response(GWBUF* buffer, MXS_PS_RESPONSE* out);
|
||||||
|
|
||||||
MXS_END_DECLS
|
MXS_END_DECLS
|
||||||
|
@ -629,26 +629,32 @@ static inline bool expecting_ps_response(MySQLProtocol *proto)
|
|||||||
static inline bool complete_ps_response(GWBUF *buffer)
|
static inline bool complete_ps_response(GWBUF *buffer)
|
||||||
{
|
{
|
||||||
ss_dassert(GWBUF_IS_CONTIGUOUS(buffer));
|
ss_dassert(GWBUF_IS_CONTIGUOUS(buffer));
|
||||||
uint16_t cols = gw_mysql_get_byte2(GWBUF_DATA(buffer) + MYSQL_PS_COLS_OFFSET);
|
MXS_PS_RESPONSE resp;
|
||||||
uint16_t params = gw_mysql_get_byte2(GWBUF_DATA(buffer) + MYSQL_PS_PARAMS_OFFSET);
|
bool rval = false;
|
||||||
int expected_eof = 0;
|
|
||||||
|
|
||||||
if (cols > 0)
|
if (mxs_mysql_extract_ps_response(buffer, &resp))
|
||||||
{
|
{
|
||||||
expected_eof++;
|
int expected_eof = 0;
|
||||||
|
|
||||||
|
if (resp.columns > 0)
|
||||||
|
{
|
||||||
|
expected_eof++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (resp.parameters > 0)
|
||||||
|
{
|
||||||
|
expected_eof++;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool more;
|
||||||
|
int n_eof = modutil_count_signal_packets(buffer, 0, &more);
|
||||||
|
|
||||||
|
MXS_DEBUG("Expecting %u EOF, have %u", n_eof, expected_eof);
|
||||||
|
|
||||||
|
rval = n_eof == expected_eof;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (params > 0)
|
return rval;
|
||||||
{
|
|
||||||
expected_eof++;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool more;
|
|
||||||
int n_eof = modutil_count_signal_packets(buffer, 0, &more);
|
|
||||||
|
|
||||||
MXS_DEBUG("Expecting %u EOF, have %u", n_eof, expected_eof);
|
|
||||||
|
|
||||||
return n_eof == expected_eof;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline bool collecting_resultset(MySQLProtocol *proto, uint64_t capabilities)
|
static inline bool collecting_resultset(MySQLProtocol *proto, uint64_t capabilities)
|
||||||
|
@ -1599,3 +1599,40 @@ void mxs_mysql_set_current_db(MXS_SESSION* session, const char* db)
|
|||||||
MYSQL_session* data = (MYSQL_session*)session->client_dcb->data;
|
MYSQL_session* data = (MYSQL_session*)session->client_dcb->data;
|
||||||
snprintf(data->db, sizeof(data->db), "%s", db);
|
snprintf(data->db, sizeof(data->db), "%s", db);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint8_t mxs_mysql_get_command(GWBUF* buffer)
|
||||||
|
{
|
||||||
|
if (GWBUF_LENGTH(buffer) > MYSQL_HEADER_LEN)
|
||||||
|
{
|
||||||
|
return GWBUF_DATA(buffer)[4];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
uint8_t command = 0;
|
||||||
|
gwbuf_copy_data(buffer, MYSQL_HEADER_LEN, 1, &command);
|
||||||
|
return command;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool mxs_mysql_extract_ps_response(GWBUF* buffer, MXS_PS_RESPONSE* out)
|
||||||
|
{
|
||||||
|
bool rval = false;
|
||||||
|
uint8_t id[MYSQL_PS_ID_SIZE];
|
||||||
|
uint8_t cols[MYSQL_PS_ID_SIZE];
|
||||||
|
uint8_t params[MYSQL_PS_ID_SIZE];
|
||||||
|
uint8_t warnings[MYSQL_PS_WARN_SIZE];
|
||||||
|
|
||||||
|
if (gwbuf_copy_data(buffer, MYSQL_PS_ID_OFFSET, sizeof(id), id) == sizeof(id) &&
|
||||||
|
gwbuf_copy_data(buffer, MYSQL_PS_COLS_OFFSET, sizeof(cols), cols) == sizeof(cols) &&
|
||||||
|
gwbuf_copy_data(buffer, MYSQL_PS_PARAMS_OFFSET, sizeof(params), params) == sizeof(params) &&
|
||||||
|
gwbuf_copy_data(buffer, MYSQL_PS_WARN_OFFSET, sizeof(warnings), warnings) == sizeof(warnings))
|
||||||
|
{
|
||||||
|
out->id = gw_mysql_get_byte4(id);
|
||||||
|
out->columns = gw_mysql_get_byte2(cols);
|
||||||
|
out->parameters = gw_mysql_get_byte2(params);
|
||||||
|
out->warnings = gw_mysql_get_byte2(warnings);
|
||||||
|
rval = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return rval;
|
||||||
|
}
|
||||||
|
Reference in New Issue
Block a user