MySQL Proxy admin script

Developed In: Lua — Contributed by: Diego Medina

Use this script to get some information using the admin plugin for the MySQL Proxy

Use with http://forge.mysql.com/tools/tool.php?id=198


Diego Medina
Lua
  1. --[[ $%BEGINLICENSE%$
  2.  Copyright (C) 2009 MySQL AB, 2008 Sun Microsystems, Inc
  3.  
  4.  This program is free software; you can redistribute it and/or modify
  5.  it under the terms of the GNU General Public License as published by
  6.  the Free Software Foundation; version 2 of the License.
  7.  
  8.  This program is distributed in the hope that it will be useful,
  9.  but WITHOUT ANY WARRANTY; without even the implied warranty of
  10.  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11.  GNU General Public License for more details.
  12.  
  13.  You should have received a copy of the GNU General Public License
  14.  along with this program; if not, write to the Free Software
  15.  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  16.  
  17.  $%ENDLICENSE%$ --]]
  18.  
  19. -- admin-1.lua
  20.  
  21. --[[
  22.  
  23.   See http://forge.mysql.com/tools/tool.php?id=78
  24.   (Thanks to Jan Kneschke)
  25.   See http://www.chriscalender.com/?p=41
  26.   (Thanks to Chris Calender)
  27.   See http://datacharmer.blogspot.com/2009/01/mysql-proxy-is-back.html
  28.   (Thanks Giuseppe Maxia)
  29.  
  30. --]]
  31.  
  32.  
  33. function set_error(errmsg)
  34. proxy.response = {
  35. type = proxy.MYSQLD_PACKET_ERR,
  36. errmsg = errmsg or "error"
  37. }
  38. end
  39.  
  40. function read_query(packet)
  41. if packet:byte() ~= proxy.COM_QUERY then
  42. set_error("[admin] we only handle text-based queries (COM_QUERY)")
  43. return proxy.PROXY_SEND_RESULT
  44. end
  45.  
  46. local query = packet:sub(2)
  47. local rows = { }
  48. local fields = { }
  49.  
  50. -- try to match the string up to the first non-alphanum
  51. local f_s, f_e, command = string.find(packet, "^%s*(%w+)", 2)
  52. local option
  53.  
  54. if f_e then
  55. -- if that match, take the next sub-string as option
  56. f_s, f_e, option = string.find(packet, "^%s+(%w+)", f_e + 1)
  57. end
  58.  
  59. -- we got our commands, execute it
  60. if command == "show" and option == "querycounter" then
  61. ---
  62. -- proxy.PROXY_SEND_RESULT requires
  63. --
  64. -- proxy.response.type to be either
  65. -- * proxy.MYSQLD_PACKET_OK or
  66. -- * proxy.MYSQLD_PACKET_ERR
  67. --
  68. -- for proxy.MYSQLD_PACKET_OK you need a resultset
  69. -- * fields
  70. -- * rows
  71. --
  72. -- for proxy.MYSQLD_PACKET_ERR
  73. -- * errmsg
  74. proxy.response.type = proxy.MYSQLD_PACKET_OK
  75. proxy.response.resultset = {
  76. fields = {
  77. { type = proxy.MYSQL_TYPE_LONG, name = "query_counter", },
  78. },
  79. rows = {
  80. { proxy.global.query_counter }
  81. }
  82. }
  83.  
  84. -- we have our result, send it back
  85. return proxy.PROXY_SEND_RESULT
  86. elseif command == "show" and option == "myerror" then
  87. proxy.response.type = proxy.MYSQLD_PACKET_ERR
  88. proxy.response.errmsg = "my first error"
  89.  
  90. return proxy.PROXY_SEND_RESULT
  91.  
  92. elseif string.sub(packet, 2):lower() == 'select help' then
  93. return show_process_help()
  94.  
  95. elseif string.sub(packet, 2):lower() == 'show proxy processlist' then
  96. return show_process_table()
  97.  
  98. elseif query == "SELECT * FROM backends" then
  99. fields = {
  100. { name = "backend_ndx",
  101. type = proxy.MYSQL_TYPE_LONG },
  102.  
  103. { name = "address",
  104. type = proxy.MYSQL_TYPE_STRING },
  105. { name = "state",
  106. type = proxy.MYSQL_TYPE_STRING },
  107. { name = "type",
  108. type = proxy.MYSQL_TYPE_STRING },
  109. }
  110.  
  111. for i = 1, #proxy.global.backends do
  112. local b = proxy.global.backends[i]
  113.  
  114. rows[#rows + 1] = {
  115. i, b.dst.name, b.state, b.type
  116. }
  117. end
  118. else
  119. set_error()
  120. return proxy.PROXY_SEND_RESULT
  121. end
  122.  
  123. proxy.response = {
  124. type = proxy.MYSQLD_PACKET_OK,
  125. resultset = {
  126. fields = fields,
  127. rows = rows
  128. }
  129. }
  130. return proxy.PROXY_SEND_RESULT
  131. end
  132.  
  133.  
  134. function make_dataset (header, dataset)
  135. proxy.response.type = proxy.MYSQLD_PACKET_OK
  136.  
  137. proxy.response.resultset = {
  138. fields = {},
  139. rows = {}
  140. }
  141. for i,v in pairs (header) do
  142. table.insert(proxy.response.resultset.fields, {type = proxy.MYSQL_TYPE_STRING, name = v})
  143. end
  144. for i,v in pairs (dataset) do
  145. table.insert(proxy.response.resultset.rows, v )
  146. end
  147. return proxy.PROXY_SEND_RESULT
  148. end
  149.  
  150. function show_process_table()
  151. local dataset = {}
  152. local header = { 'Id', 'IP Address', 'Time' }
  153. local rows = {}
  154. for t_i, t_v in pairs (proxy.global.process) do
  155. for s_i, s_v in pairs ( t_v ) do
  156. table.insert(rows, { t_i, s_v.ip, os.date('%c',s_v.ts) })
  157. end
  158. end
  159. return make_dataset(header,rows)
  160. end
  161.  
  162. function show_process_help()
  163. local dataset = {}
  164. local header = { 'command', 'description' }
  165. local rows = {
  166. {'SELECT HELP', 'This command.'},
  167. {'SHOW PROXY PROCESSLIST', 'Show all connections and their true IP Address.'},
  168. }
  169. return make_dataset(header,rows)
  170. end
  171.  
  172. function dump_process_table()
  173. proxy.global.initialize_process_table()
  174. print('current contents of process table')
  175. for t_i, t_v in pairs (proxy.global.process) do
  176. print ('session id: ', t_i)
  177. for s_i, s_v in pairs ( t_v ) do
  178. print ( '\t', s_i, s_v.ip, s_v.ts )
  179. end
  180. end
  181. print ('---END PROCESS TABLE---')
  182. end
  183.  
  184.  
  185.  
  186.  
  187. --[[ Help
  188.  
  189. we use a simple string-match to split commands are word-boundaries
  190.  
  191. mysql> show querycounter
  192.  
  193. is split into
  194. command = "show"
  195. option = "querycounter"
  196.  
  197. spaces are ignored, the case has to be as is.
  198.  
  199. mysql> show myerror
  200.  
  201. returns a error-packet
  202.  
  203. --]]
  204.  
  205.  
  206.  

Current Tags

You must be logged in to tag this tool

No Comments yet

Votes

  • Rated 5.00 out of 5
Rated 5.00 out of 5 with 1 votes cast.
You must be logged in to vote.

Watches

1 members are watching this tool
You must be logged in to track this tool.

Provide Feedback

Please note:
HTML will be purified, but we allow for a number of HTML tags so that you have the flexibility to decorate your comment text to some extent. The comments allow the following HTML tags:

strong, b, em, blockquote, a, code, pre

To put code into your comment, simply encapsulate your code with
[code language="XXX"][/code], where XXX is any common language, for instance "PHP", "SQL", "C", etc.



You must be logged in to comment