read_query_result() 函数仅在你之前手动向 query 队列中添加了 query 的情况下,有结果集从服务器端返回的时候被调用。如果你没有对 query 队列进行过操作,该函数不会被调用。该函数仅具有一个入参,即结果包(在 lua 脚本中可以认为该包对应的是 injection 结构),其中包含了一系列属性:
id: 结果集 id ,其对应于 当 query 包被客户端向服务器提交时使用 append(id) 函数对 query 队列操作时设置的 id 值。你必须设置 resultset_is_needed 标志,以便当拦截到来自于服务器的返回结果集时,进行相应处理,之后再返回给客户端。参阅 proxy.queries 。
query: 原始 query 的文本内容。
query_time: 从 query 被发送到服务器,到接收到结果集的第一行时,所需要的微秒数。
response_time: 从 query 被发送到服务器,到接收到结果集的最后一行时,所需要的微秒数。
resultset: 结果集数据的内容。
通过对来自 mysql 服务器的返回结果信息的分析处理,可以提取出与你之前注入的 query 语句匹配的结果,并返回修改后的结果集(例如返回一个经过修改的 query 产生的结果),甚至创建属于你自己的结果集。
下面的 lua 脚本,将输出每一个发送到服务器的 query 对应的文本内容,以及 query 时间和 response 时间(即开始执行 query 的时刻和返回该 query 结果的时刻):
你可以通过 read_query_result() 函数获得返回结果中的 resultset 属性的 row 属性。例如,你可以使用下面的 lua 代码段来递归显示返回结果中所有行的第一列内容:
正如 read_query() 函数一样,read_query_result() 函数能够根据返回结果的内容,按需返回结果的不同值。例如,如果你之前注入了额外的 query 到 query 队列中,然后在获取返回的结果集后,移除与额外 query 对应的结果,仅返回与客户端发送的原始 query 对应的结果。
下面的例子注入额外的 select now() 语句到 query 队列中,并设置了一个与原始 query 不同的 id 值。在 read_query_result() 函数中,如果发现了与我们自己注入的 query 的 id 相匹配的结果,我们将显示结果的行内容,然后通过 return proxy.proxy_ignore_result 语句使该结果不会被返回给客户端。如果结果是由任何其他 query 产生,则打印出 query 相应的时间信息,并返回默认值,即返回不做任何修改的结果集给客户端。我们同样可以显式地使用 return proxy.proxy_ignore_result 来将结果返回给 mysql 客户端。