The read_query_result()
is called for each
result set returned by the server only if you have manually
injected queries into the query queue. If you have not
manipulated the query queue, this function is not called. The
function supports a single argument, the result packet, which
provides a number of properties:
id
: The ID of the result set, which corresponds to the ID that was set when the query packet was submitted to the server when usingappend(id)
on the query queue. You must have set theresultset_is_needed
flag toappend
to intercept the result set before it is returned to the client. See proxy.queries.query
: The text of the original query.query_time
: The number of microseconds required to receive the first row of a result set since the query was sent to the server.response_time
: The number of microseconds required to receive the last row of the result set since the query was sent to the server.resultset
: The content of the result set data.
By accessing the result information from the MySQL server, you can extract the results that match the queries that you injected, return different result sets (for example, from a modified query), and even create your own result sets.
The following Lua script, for example, will output the query, followed by the query time and response time (that is, the time to execute the query and the time to return the data for the query) for each query sent to the server:
function read_query( packet ) if packet:byte() == proxy.COM_QUERY then print("we got a normal query: " .. packet:sub(2)) proxy.queries:append(1, packet ) return proxy.PROXY_SEND_QUERY end end function read_query_result(inj) print("query-time: " .. (inj.query_time / 1000) .. "ms") print("response-time: " .. (inj.response_time / 1000) .. "ms") end
You can access the rows of returned results from the result set
by accessing the rows
property of the
resultset
property of the result that is
exposed through read_query_result()
. For
example, you can iterate over the results showing the first
column from each row using this Lua fragment:
for row in inj.resultset.rows do print("injected query returned: " .. row[1]) end
Just like read_query()
,
read_query_result()
can return different
values for each result according to the result returned. If you
have injected additional queries into the query queue, for
example, you will want to remove the results returned from those
additional queries and return only the results from the query
originally submitted by the client.
The following example injects additional SELECT
NOW()
statements into the query queue, giving them a
different ID to the ID of the original query. Within
read_query_result()
, if the ID for the
injected queries is identified, we display the result row, and
return the proxy.PROXY_IGNORE_RESULT
from the
function so that the result is not returned to the client. If
the result is from any other query, we print out the query time
information for the query and return the default, which passes
on the result set unchanged. We could also have explicitly
returned proxy.PROXY_IGNORE_RESULT
to the
MySQL client.
function read_query( packet ) if packet:byte() == proxy.COM_QUERY then proxy.queries:append(2, string.char(proxy.COM_QUERY) .. "SELECT NOW()", {resultset_is_needed = true} ) proxy.queries:append(1, packet, {resultset_is_needed = true}) proxy.queries:append(2, string.char(proxy.COM_QUERY) .. "SELECT NOW()", {resultset_is_needed = true} ) return proxy.PROXY_SEND_QUERY end end function read_query_result(inj) if inj.id == 2 then for row in inj.resultset.rows do print("injected query returned: " .. row[1]) end return proxy.PROXY_IGNORE_RESULT else print("query-time: " .. (inj.query_time / 1000) .. "ms") print("response-time: " .. (inj.response_time / 1000) .. "ms") end end
For further examples, see Section 14.6.5, “Using MySQL Proxy”.