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 then 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 using
append(id)
on the query queue. You must
have set the resultset_is_needed
flag to
append
to intercept the resultset
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.
response_time
— the number of
microseconds required to receive the last row of the result
set.
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 Lua script below, 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 resultset
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, then you will want to remove the results returned from
those additional queries and only return the results from the
query originally submitted by the client.
The example below 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 6.5, “Using MySQL Proxy”.