Fix multi-statement execution in readwritesplit
A multi-statements can return multiple resultsets in one response. To accommodate for this, both the readwritesplit and modutil code must be altered. By ignoring complete resultsets in readwritesplit, the code can deduce whether a result is complete or not.
This commit is contained in:
@ -628,10 +628,9 @@ GWBUF* modutil_get_complete_packets(GWBUF **p_readbuf)
|
|||||||
return complete;
|
return complete;
|
||||||
}
|
}
|
||||||
|
|
||||||
int modutil_count_signal_packets(GWBUF *reply, int n_found, bool* more_dest, modutil_state* state)
|
int modutil_count_signal_packets(GWBUF *reply, int n_found, bool* more_out, modutil_state* state)
|
||||||
{
|
{
|
||||||
unsigned int len = gwbuf_length(reply);
|
unsigned int len = gwbuf_length(reply);
|
||||||
ss_debug(int real_offset = 0);
|
|
||||||
int eof = 0;
|
int eof = 0;
|
||||||
int err = 0;
|
int err = 0;
|
||||||
size_t offset = 0;
|
size_t offset = 0;
|
||||||
@ -661,18 +660,18 @@ int modutil_count_signal_packets(GWBUF *reply, int n_found, bool* more_dest, mod
|
|||||||
|
|
||||||
if (command == MYSQL_REPLY_ERR)
|
if (command == MYSQL_REPLY_ERR)
|
||||||
{
|
{
|
||||||
err++;
|
/** Any errors in the packet stream mean that the result set
|
||||||
|
* generation was aborted due to an error. No more results will
|
||||||
|
* follow after this. */
|
||||||
|
*more_out = false;
|
||||||
|
return 2;
|
||||||
}
|
}
|
||||||
else if (command == MYSQL_REPLY_EOF && pktlen == MYSQL_EOF_PACKET_LEN)
|
else if (command == MYSQL_REPLY_EOF && pktlen == MYSQL_EOF_PACKET_LEN)
|
||||||
{
|
{
|
||||||
eof++;
|
eof++;
|
||||||
}
|
}
|
||||||
else if (more && command == MYSQL_REPLY_OK)
|
else if (command == MYSQL_REPLY_OK && pktlen >= MYSQL_OK_PACKET_MIN_LEN)
|
||||||
{
|
{
|
||||||
// This should not be the first packet
|
|
||||||
ss_dassert(pktlen >= MYSQL_OK_PACKET_MIN_LEN);
|
|
||||||
ss_dassert(real_offset > 0);
|
|
||||||
|
|
||||||
uint8_t data[payloadlen - 1];
|
uint8_t data[payloadlen - 1];
|
||||||
gwbuf_copy_data(reply, offset + MYSQL_HEADER_LEN + 1, sizeof(data), data);
|
gwbuf_copy_data(reply, offset + MYSQL_HEADER_LEN + 1, sizeof(data), data);
|
||||||
|
|
||||||
@ -693,7 +692,6 @@ int modutil_count_signal_packets(GWBUF *reply, int n_found, bool* more_dest, mod
|
|||||||
}
|
}
|
||||||
|
|
||||||
offset += pktlen;
|
offset += pktlen;
|
||||||
ss_debug(real_offset += pktlen);
|
|
||||||
|
|
||||||
if (offset >= GWBUF_LENGTH(reply) && reply->next)
|
if (offset >= GWBUF_LENGTH(reply) && reply->next)
|
||||||
{
|
{
|
||||||
@ -709,7 +707,7 @@ int modutil_count_signal_packets(GWBUF *reply, int n_found, bool* more_dest, mod
|
|||||||
state->state = skip_next;
|
state->state = skip_next;
|
||||||
}
|
}
|
||||||
|
|
||||||
*more_dest = more;
|
*more_out = more;
|
||||||
return total;
|
return total;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -537,6 +537,16 @@ bool reply_is_complete(SRWBackend& backend, GWBUF *buffer)
|
|||||||
LOG_RS(backend, REPLY_STATE_DONE);
|
LOG_RS(backend, REPLY_STATE_DONE);
|
||||||
backend->set_reply_state(REPLY_STATE_DONE);
|
backend->set_reply_state(REPLY_STATE_DONE);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// This is an OK packet and more results will follow
|
||||||
|
ss_dassert(mxs_mysql_is_ok_packet(buffer) &&
|
||||||
|
mxs_mysql_more_results_after_ok(buffer));
|
||||||
|
|
||||||
|
LOG_RS(backend, REPLY_STATE_RSET_COLDEF);
|
||||||
|
backend->set_reply_state(REPLY_STATE_RSET_COLDEF);
|
||||||
|
return reply_is_complete(backend, buffer);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -546,6 +556,16 @@ bool reply_is_complete(SRWBackend& backend, GWBUF *buffer)
|
|||||||
int n_eof = modutil_count_signal_packets(buffer, n_old_eof, &more, &state);
|
int n_eof = modutil_count_signal_packets(buffer, n_old_eof, &more, &state);
|
||||||
backend->set_large_packet(state.state);
|
backend->set_large_packet(state.state);
|
||||||
|
|
||||||
|
if (n_eof > 2)
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* We have multiple results in the buffer, we only care about
|
||||||
|
* the state of the last one. Skip the complete result sets and act
|
||||||
|
* like we're processing a single result set.
|
||||||
|
*/
|
||||||
|
n_eof = n_eof % 2 ? 1 : 2;
|
||||||
|
}
|
||||||
|
|
||||||
if (n_eof == 0)
|
if (n_eof == 0)
|
||||||
{
|
{
|
||||||
/** Waiting for the EOF packet after the column definitions */
|
/** Waiting for the EOF packet after the column definitions */
|
||||||
|
Reference in New Issue
Block a user