diff --git a/include/maxscale/protocol/mysql.h b/include/maxscale/protocol/mysql.h index 01fdd1615..530f8bdaa 100644 --- a/include/maxscale/protocol/mysql.h +++ b/include/maxscale/protocol/mysql.h @@ -287,7 +287,9 @@ typedef struct /** Defines for response codes */ #define MYSQL_REPLY_ERR 0xff #define MYSQL_REPLY_OK 0x00 -#define MYSQL_REPLY_AUTHSWITCHREQUEST 0xfe +#define MYSQL_REPLY_EOF 0xfe +#define MYSQL_REPLY_LOCAL_INFILE 0xfb +#define MYSQL_REPLY_AUTHSWITCHREQUEST 0xfe /**< Only sent during authentication */ static inline mysql_server_cmd_t MYSQL_GET_COMMAND(const uint8_t* header) { @@ -399,4 +401,7 @@ int mxs_mysql_send_ok(DCB *dcb, int sequence, uint8_t affected_rows, const char* /** Check for OK packet */ bool mxs_mysql_is_ok_packet(GWBUF *buffer); +/** Check for result set */ +bool mxs_mysql_is_result_set(GWBUF *buffer); + MXS_END_DECLS diff --git a/include/maxscale/routing.h b/include/maxscale/routing.h index c16c2eb81..f9218c2fa 100644 --- a/include/maxscale/routing.h +++ b/include/maxscale/routing.h @@ -40,6 +40,8 @@ typedef enum routing_capability RCAP_TYPE_STMT_OUTPUT = 0x0010, /* 0b0000000000010000 */ /**< Each delivered buffer is contiguous; implies RCAP_TYPE_STMT_OUTPUT. */ RCAP_TYPE_CONTIGUOUS_OUTPUT = 0x0030, /* 0b0000000000110000 */ + /** Result sets are delivered in one buffer; implies RCAP_TYPE_STMT_OUTPUT. */ + RCAP_TYPE_RESULTSET_OUTPUT = 0x0050, /* 0b0000000001110000 */ } routing_capability_t; diff --git a/server/modules/protocol/MySQL/MySQLBackend/mysql_backend.c b/server/modules/protocol/MySQL/MySQLBackend/mysql_backend.c index 452721549..80389b0e3 100644 --- a/server/modules/protocol/MySQL/MySQLBackend/mysql_backend.c +++ b/server/modules/protocol/MySQL/MySQLBackend/mysql_backend.c @@ -787,6 +787,19 @@ gw_read_and_write(DCB *dcb) read_buffer = tmp; + if (rcap_type_required(capabilities, RCAP_TYPE_RESULTSET_OUTPUT)) + { + if (mxs_mysql_is_result_set(read_buffer)) + { + int more = 0; + if (modutil_count_signal_packets(read_buffer, 0, 0, &more) != 2) + { + dcb->dcb_readqueue = read_buffer; + return 0; + } + } + } + if (rcap_type_required(capabilities, RCAP_TYPE_CONTIGUOUS_OUTPUT)) { if ((tmp = gwbuf_make_contiguous(read_buffer))) @@ -862,7 +875,8 @@ gw_read_and_write(DCB *dcb) return 0; } } - else if (rcap_type_required(capabilities, RCAP_TYPE_STMT_OUTPUT)) + else if (rcap_type_required(capabilities, RCAP_TYPE_STMT_OUTPUT) && + !rcap_type_required(capabilities, RCAP_TYPE_RESULTSET_OUTPUT)) { stmt = modutil_get_next_MySQL_packet(&read_buffer); } diff --git a/server/modules/protocol/MySQL/mysql_common.c b/server/modules/protocol/MySQL/mysql_common.c index 04618cb68..314bba181 100644 --- a/server/modules/protocol/MySQL/mysql_common.c +++ b/server/modules/protocol/MySQL/mysql_common.c @@ -1559,3 +1559,31 @@ bool mxs_mysql_is_ok_packet(GWBUF *buffer) return rval; } + +bool mxs_mysql_is_result_set(GWBUF *buffer) +{ + bool rval = false; + uint8_t cmd; + + if (gwbuf_copy_data(buffer, MYSQL_HEADER_LEN, 1, &cmd)) + { + switch (cmd) + { + + case MYSQL_REPLY_OK: + case MYSQL_REPLY_ERR: + case MYSQL_REPLY_LOCAL_INFILE: + case MYSQL_REPLY_EOF: + /** Not a result set */ + break; + default: + if (gwbuf_copy_data(buffer, MYSQL_HEADER_LEN + 1, 1, &cmd) && cmd > 1) + { + rval = true; + } + break; + } + } + + return rval; +} diff --git a/server/modules/routing/binlogrouter/blr.c b/server/modules/routing/binlogrouter/blr.c index 9908b2701..1312cb44e 100644 --- a/server/modules/routing/binlogrouter/blr.c +++ b/server/modules/routing/binlogrouter/blr.c @@ -1846,7 +1846,7 @@ static void rses_end_locked_router_action(ROUTER_SLAVE *rses) static uint64_t getCapabilities(void) { - return RCAP_TYPE_NO_RSESSION | RCAP_TYPE_CONTIGUOUS_OUTPUT; + return RCAP_TYPE_NO_RSESSION | RCAP_TYPE_CONTIGUOUS_OUTPUT | RCAP_TYPE_RESULTSET_OUTPUT; } /**